##// END OF EJS Templates
clean Rayleigh funcionando, tiempo de ejecución elevado usando todos los pares
joabAM -
r1391:fba03565a781
parent child
Show More
@@ -1,693 +1,695
1 # Copyright (c) 2012-2020 Jicamarca Radio Observatory
1 # Copyright (c) 2012-2020 Jicamarca Radio Observatory
2 # All rights reserved.
2 # All rights reserved.
3 #
3 #
4 # Distributed under the terms of the BSD 3-clause license.
4 # Distributed under the terms of the BSD 3-clause license.
5 """Base class to create plot operations
5 """Base class to create plot operations
6
6
7 """
7 """
8
8
9 import os
9 import os
10 import sys
10 import sys
11 import zmq
11 import zmq
12 import time
12 import time
13 import numpy
13 import numpy
14 import datetime
14 import datetime
15 from collections import deque
15 from collections import deque
16 from functools import wraps
16 from functools import wraps
17 from threading import Thread
17 from threading import Thread
18 import matplotlib
18 import matplotlib
19
19
20 if 'BACKEND' in os.environ:
20 if 'BACKEND' in os.environ:
21 matplotlib.use(os.environ['BACKEND'])
21 matplotlib.use(os.environ['BACKEND'])
22 elif 'linux' in sys.platform:
22 elif 'linux' in sys.platform:
23 matplotlib.use("TkAgg")
23 matplotlib.use("TkAgg")
24 elif 'darwin' in sys.platform:
24 elif 'darwin' in sys.platform:
25 matplotlib.use('MacOSX')
25 matplotlib.use('MacOSX')
26 else:
26 else:
27 from schainpy.utils import log
27 from schainpy.utils import log
28 log.warning('Using default Backend="Agg"', 'INFO')
28 log.warning('Using default Backend="Agg"', 'INFO')
29 matplotlib.use('Agg')
29 matplotlib.use('Agg')
30
30
31 import matplotlib.pyplot as plt
31 import matplotlib.pyplot as plt
32 from matplotlib.patches import Polygon
32 from matplotlib.patches import Polygon
33 from mpl_toolkits.axes_grid1 import make_axes_locatable
33 from mpl_toolkits.axes_grid1 import make_axes_locatable
34 from matplotlib.ticker import FuncFormatter, LinearLocator, MultipleLocator
34 from matplotlib.ticker import FuncFormatter, LinearLocator, MultipleLocator
35
35
36 from schainpy.model.data.jrodata import PlotterData
36 from schainpy.model.data.jrodata import PlotterData
37 from schainpy.model.proc.jroproc_base import ProcessingUnit, Operation, MPDecorator
37 from schainpy.model.proc.jroproc_base import ProcessingUnit, Operation, MPDecorator
38 from schainpy.utils import log
38 from schainpy.utils import log
39
39
40 jet_values = matplotlib.pyplot.get_cmap('jet', 100)(numpy.arange(100))[10:90]
40 jet_values = matplotlib.pyplot.get_cmap('jet', 100)(numpy.arange(100))[10:90]
41 blu_values = matplotlib.pyplot.get_cmap(
41 blu_values = matplotlib.pyplot.get_cmap(
42 'seismic_r', 20)(numpy.arange(20))[10:15]
42 'seismic_r', 20)(numpy.arange(20))[10:15]
43 ncmap = matplotlib.colors.LinearSegmentedColormap.from_list(
43 ncmap = matplotlib.colors.LinearSegmentedColormap.from_list(
44 'jro', numpy.vstack((blu_values, jet_values)))
44 'jro', numpy.vstack((blu_values, jet_values)))
45 matplotlib.pyplot.register_cmap(cmap=ncmap)
45 matplotlib.pyplot.register_cmap(cmap=ncmap)
46
46
47 CMAPS = [plt.get_cmap(s) for s in ('jro', 'jet', 'viridis',
47 CMAPS = [plt.get_cmap(s) for s in ('jro', 'jet', 'viridis',
48 'plasma', 'inferno', 'Greys', 'seismic', 'bwr', 'coolwarm')]
48 'plasma', 'inferno', 'Greys', 'seismic', 'bwr', 'coolwarm')]
49
49
50 EARTH_RADIUS = 6.3710e3
50 EARTH_RADIUS = 6.3710e3
51
51
52 def ll2xy(lat1, lon1, lat2, lon2):
52 def ll2xy(lat1, lon1, lat2, lon2):
53
53
54 p = 0.017453292519943295
54 p = 0.017453292519943295
55 a = 0.5 - numpy.cos((lat2 - lat1) * p)/2 + numpy.cos(lat1 * p) * \
55 a = 0.5 - numpy.cos((lat2 - lat1) * p)/2 + numpy.cos(lat1 * p) * \
56 numpy.cos(lat2 * p) * (1 - numpy.cos((lon2 - lon1) * p)) / 2
56 numpy.cos(lat2 * p) * (1 - numpy.cos((lon2 - lon1) * p)) / 2
57 r = 12742 * numpy.arcsin(numpy.sqrt(a))
57 r = 12742 * numpy.arcsin(numpy.sqrt(a))
58 theta = numpy.arctan2(numpy.sin((lon2-lon1)*p)*numpy.cos(lat2*p), numpy.cos(lat1*p)
58 theta = numpy.arctan2(numpy.sin((lon2-lon1)*p)*numpy.cos(lat2*p), numpy.cos(lat1*p)
59 * numpy.sin(lat2*p)-numpy.sin(lat1*p)*numpy.cos(lat2*p)*numpy.cos((lon2-lon1)*p))
59 * numpy.sin(lat2*p)-numpy.sin(lat1*p)*numpy.cos(lat2*p)*numpy.cos((lon2-lon1)*p))
60 theta = -theta + numpy.pi/2
60 theta = -theta + numpy.pi/2
61 return r*numpy.cos(theta), r*numpy.sin(theta)
61 return r*numpy.cos(theta), r*numpy.sin(theta)
62
62
63
63
64 def km2deg(km):
64 def km2deg(km):
65 '''
65 '''
66 Convert distance in km to degrees
66 Convert distance in km to degrees
67 '''
67 '''
68
68
69 return numpy.rad2deg(km/EARTH_RADIUS)
69 return numpy.rad2deg(km/EARTH_RADIUS)
70
70
71
71
72 def figpause(interval):
72 def figpause(interval):
73 backend = plt.rcParams['backend']
73 backend = plt.rcParams['backend']
74 if backend in matplotlib.rcsetup.interactive_bk:
74 if backend in matplotlib.rcsetup.interactive_bk:
75 figManager = matplotlib._pylab_helpers.Gcf.get_active()
75 figManager = matplotlib._pylab_helpers.Gcf.get_active()
76 if figManager is not None:
76 if figManager is not None:
77 canvas = figManager.canvas
77 canvas = figManager.canvas
78 if canvas.figure.stale:
78 if canvas.figure.stale:
79 canvas.draw()
79 canvas.draw()
80 try:
80 try:
81 canvas.start_event_loop(interval)
81 canvas.start_event_loop(interval)
82 except:
82 except:
83 pass
83 pass
84 return
84 return
85
85
86 def popup(message):
86 def popup(message):
87 '''
87 '''
88 '''
88 '''
89
89
90 fig = plt.figure(figsize=(12, 8), facecolor='r')
90 fig = plt.figure(figsize=(12, 8), facecolor='r')
91 text = '\n'.join([s.strip() for s in message.split(':')])
91 text = '\n'.join([s.strip() for s in message.split(':')])
92 fig.text(0.01, 0.5, text, ha='left', va='center',
92 fig.text(0.01, 0.5, text, ha='left', va='center',
93 size='20', weight='heavy', color='w')
93 size='20', weight='heavy', color='w')
94 fig.show()
94 fig.show()
95 figpause(1000)
95 figpause(1000)
96
96
97
97
98 class Throttle(object):
98 class Throttle(object):
99 '''
99 '''
100 Decorator that prevents a function from being called more than once every
100 Decorator that prevents a function from being called more than once every
101 time period.
101 time period.
102 To create a function that cannot be called more than once a minute, but
102 To create a function that cannot be called more than once a minute, but
103 will sleep until it can be called:
103 will sleep until it can be called:
104 @Throttle(minutes=1)
104 @Throttle(minutes=1)
105 def foo():
105 def foo():
106 pass
106 pass
107
107
108 for i in range(10):
108 for i in range(10):
109 foo()
109 foo()
110 print "This function has run %s times." % i
110 print "This function has run %s times." % i
111 '''
111 '''
112
112
113 def __init__(self, seconds=0, minutes=0, hours=0):
113 def __init__(self, seconds=0, minutes=0, hours=0):
114 self.throttle_period = datetime.timedelta(
114 self.throttle_period = datetime.timedelta(
115 seconds=seconds, minutes=minutes, hours=hours
115 seconds=seconds, minutes=minutes, hours=hours
116 )
116 )
117
117
118 self.time_of_last_call = datetime.datetime.min
118 self.time_of_last_call = datetime.datetime.min
119
119
120 def __call__(self, fn):
120 def __call__(self, fn):
121 @wraps(fn)
121 @wraps(fn)
122 def wrapper(*args, **kwargs):
122 def wrapper(*args, **kwargs):
123 coerce = kwargs.pop('coerce', None)
123 coerce = kwargs.pop('coerce', None)
124 if coerce:
124 if coerce:
125 self.time_of_last_call = datetime.datetime.now()
125 self.time_of_last_call = datetime.datetime.now()
126 return fn(*args, **kwargs)
126 return fn(*args, **kwargs)
127 else:
127 else:
128 now = datetime.datetime.now()
128 now = datetime.datetime.now()
129 time_since_last_call = now - self.time_of_last_call
129 time_since_last_call = now - self.time_of_last_call
130 time_left = self.throttle_period - time_since_last_call
130 time_left = self.throttle_period - time_since_last_call
131
131
132 if time_left > datetime.timedelta(seconds=0):
132 if time_left > datetime.timedelta(seconds=0):
133 return
133 return
134
134
135 self.time_of_last_call = datetime.datetime.now()
135 self.time_of_last_call = datetime.datetime.now()
136 return fn(*args, **kwargs)
136 return fn(*args, **kwargs)
137
137
138 return wrapper
138 return wrapper
139
139
140 def apply_throttle(value):
140 def apply_throttle(value):
141
141
142 @Throttle(seconds=value)
142 @Throttle(seconds=value)
143 def fnThrottled(fn):
143 def fnThrottled(fn):
144 fn()
144 fn()
145
145
146 return fnThrottled
146 return fnThrottled
147
147
148
148
149 @MPDecorator
149 @MPDecorator
150 class Plot(Operation):
150 class Plot(Operation):
151 """Base class for Schain plotting operations
151 """Base class for Schain plotting operations
152
152
153 This class should never be use directtly you must subclass a new operation,
153 This class should never be use directtly you must subclass a new operation,
154 children classes must be defined as follow:
154 children classes must be defined as follow:
155
155
156 ExamplePlot(Plot):
156 ExamplePlot(Plot):
157
157
158 CODE = 'code'
158 CODE = 'code'
159 colormap = 'jet'
159 colormap = 'jet'
160 plot_type = 'pcolor' # options are ('pcolor', 'pcolorbuffer', 'scatter', 'scatterbuffer')
160 plot_type = 'pcolor' # options are ('pcolor', 'pcolorbuffer', 'scatter', 'scatterbuffer')
161
161
162 def setup(self):
162 def setup(self):
163 pass
163 pass
164
164
165 def plot(self):
165 def plot(self):
166 pass
166 pass
167
167
168 """
168 """
169
169
170 CODE = 'Figure'
170 CODE = 'Figure'
171 colormap = 'jet'
171 colormap = 'jet'
172 bgcolor = 'white'
172 bgcolor = 'white'
173 buffering = True
173 buffering = True
174 __missing = 1E30
174 __missing = 1E30
175
175
176 __attrs__ = ['show', 'save', 'ymin', 'ymax', 'zmin', 'zmax', 'title',
176 __attrs__ = ['show', 'save', 'ymin', 'ymax', 'zmin', 'zmax', 'title',
177 'showprofile']
177 'showprofile']
178
178
179 def __init__(self):
179 def __init__(self):
180
180
181 Operation.__init__(self)
181 Operation.__init__(self)
182 self.isConfig = False
182 self.isConfig = False
183 self.isPlotConfig = False
183 self.isPlotConfig = False
184 self.save_time = 0
184 self.save_time = 0
185 self.sender_time = 0
185 self.sender_time = 0
186 self.data = None
186 self.data = None
187 self.firsttime = True
187 self.firsttime = True
188 self.sender_queue = deque(maxlen=10)
188 self.sender_queue = deque(maxlen=10)
189 self.plots_adjust = {'left': 0.125, 'right': 0.9, 'bottom': 0.15, 'top': 0.9, 'wspace': 0.2, 'hspace': 0.2}
189 self.plots_adjust = {'left': 0.125, 'right': 0.9, 'bottom': 0.15, 'top': 0.9, 'wspace': 0.2, 'hspace': 0.2}
190
190
191 def __fmtTime(self, x, pos):
191 def __fmtTime(self, x, pos):
192 '''
192 '''
193 '''
193 '''
194
194
195 return '{}'.format(self.getDateTime(x).strftime('%H:%M'))
195 return '{}'.format(self.getDateTime(x).strftime('%H:%M'))
196
196
197 def __setup(self, **kwargs):
197 def __setup(self, **kwargs):
198 '''
198 '''
199 Initialize variables
199 Initialize variables
200 '''
200 '''
201
201
202 self.figures = []
202 self.figures = []
203 self.axes = []
203 self.axes = []
204 self.cb_axes = []
204 self.cb_axes = []
205 self.pf_axes = []
205 self.localtime = kwargs.pop('localtime', True)
206 self.localtime = kwargs.pop('localtime', True)
206 self.show = kwargs.get('show', True)
207 self.show = kwargs.get('show', True)
207 self.save = kwargs.get('save', False)
208 self.save = kwargs.get('save', False)
208 self.save_period = kwargs.get('save_period', 0)
209 self.save_period = kwargs.get('save_period', 0)
209 self.colormap = kwargs.get('colormap', self.colormap)
210 self.colormap = kwargs.get('colormap', self.colormap)
210 self.colormap_coh = kwargs.get('colormap_coh', 'jet')
211 self.colormap_coh = kwargs.get('colormap_coh', 'jet')
211 self.colormap_phase = kwargs.get('colormap_phase', 'RdBu_r')
212 self.colormap_phase = kwargs.get('colormap_phase', 'RdBu_r')
212 self.colormaps = kwargs.get('colormaps', None)
213 self.colormaps = kwargs.get('colormaps', None)
213 self.bgcolor = kwargs.get('bgcolor', self.bgcolor)
214 self.bgcolor = kwargs.get('bgcolor', self.bgcolor)
214 self.showprofile = kwargs.get('showprofile', False)
215 self.showprofile = kwargs.get('showprofile', False)
215 self.title = kwargs.get('wintitle', self.CODE.upper())
216 self.title = kwargs.get('wintitle', self.CODE.upper())
216 self.cb_label = kwargs.get('cb_label', None)
217 self.cb_label = kwargs.get('cb_label', None)
217 self.cb_labels = kwargs.get('cb_labels', None)
218 self.cb_labels = kwargs.get('cb_labels', None)
218 self.labels = kwargs.get('labels', None)
219 self.labels = kwargs.get('labels', None)
219 self.xaxis = kwargs.get('xaxis', 'frequency')
220 self.xaxis = kwargs.get('xaxis', 'frequency')
220 self.zmin = kwargs.get('zmin', None)
221 self.zmin = kwargs.get('zmin', None)
221 self.zmax = kwargs.get('zmax', None)
222 self.zmax = kwargs.get('zmax', None)
222 self.zlimits = kwargs.get('zlimits', None)
223 self.zlimits = kwargs.get('zlimits', None)
223 self.xmin = kwargs.get('xmin', None)
224 self.xmin = kwargs.get('xmin', None)
224 self.xmax = kwargs.get('xmax', None)
225 self.xmax = kwargs.get('xmax', None)
225 self.xrange = kwargs.get('xrange', 12)
226 self.xrange = kwargs.get('xrange', 12)
226 self.xscale = kwargs.get('xscale', None)
227 self.xscale = kwargs.get('xscale', None)
227 self.ymin = kwargs.get('ymin', None)
228 self.ymin = kwargs.get('ymin', None)
228 self.ymax = kwargs.get('ymax', None)
229 self.ymax = kwargs.get('ymax', None)
229 self.yscale = kwargs.get('yscale', None)
230 self.yscale = kwargs.get('yscale', None)
230 self.xlabel = kwargs.get('xlabel', None)
231 self.xlabel = kwargs.get('xlabel', None)
231 self.attr_time = kwargs.get('attr_time', 'utctime')
232 self.attr_time = kwargs.get('attr_time', 'utctime')
232 self.attr_data = kwargs.get('attr_data', 'data_param')
233 self.attr_data = kwargs.get('attr_data', 'data_param')
233 self.decimation = kwargs.get('decimation', None)
234 self.decimation = kwargs.get('decimation', None)
234 self.oneFigure = kwargs.get('oneFigure', True)
235 self.oneFigure = kwargs.get('oneFigure', True)
235 self.width = kwargs.get('width', None)
236 self.width = kwargs.get('width', None)
236 self.height = kwargs.get('height', None)
237 self.height = kwargs.get('height', None)
237 self.colorbar = kwargs.get('colorbar', True)
238 self.colorbar = kwargs.get('colorbar', True)
238 self.factors = kwargs.get('factors', [1, 1, 1, 1, 1, 1, 1, 1])
239 self.factors = kwargs.get('factors', [1, 1, 1, 1, 1, 1, 1, 1])
239 self.channels = kwargs.get('channels', None)
240 self.channels = kwargs.get('channels', None)
240 self.titles = kwargs.get('titles', [])
241 self.titles = kwargs.get('titles', [])
241 self.polar = False
242 self.polar = False
242 self.type = kwargs.get('type', 'iq')
243 self.type = kwargs.get('type', 'iq')
243 self.grid = kwargs.get('grid', False)
244 self.grid = kwargs.get('grid', False)
244 self.pause = kwargs.get('pause', False)
245 self.pause = kwargs.get('pause', False)
245 self.save_code = kwargs.get('save_code', self.CODE)
246 self.save_code = kwargs.get('save_code', self.CODE)
246 self.throttle = kwargs.get('throttle', 0)
247 self.throttle = kwargs.get('throttle', 0)
247 self.exp_code = kwargs.get('exp_code', None)
248 self.exp_code = kwargs.get('exp_code', None)
248 self.server = kwargs.get('server', False)
249 self.server = kwargs.get('server', False)
249 self.sender_period = kwargs.get('sender_period', 60)
250 self.sender_period = kwargs.get('sender_period', 60)
250 self.tag = kwargs.get('tag', '')
251 self.tag = kwargs.get('tag', '')
251 self.height_index = kwargs.get('height_index', None)
252 self.height_index = kwargs.get('height_index', None)
252 self.__throttle_plot = apply_throttle(self.throttle)
253 self.__throttle_plot = apply_throttle(self.throttle)
253 code = self.attr_data if self.attr_data else self.CODE
254 code = self.attr_data if self.attr_data else self.CODE
254 self.data = PlotterData(self.CODE, self.exp_code, self.localtime)
255 self.data = PlotterData(self.CODE, self.exp_code, self.localtime)
256 self.tmin = kwargs.get('tmin', None)
255
257
256 if self.server:
258 if self.server:
257 if not self.server.startswith('tcp://'):
259 if not self.server.startswith('tcp://'):
258 self.server = 'tcp://{}'.format(self.server)
260 self.server = 'tcp://{}'.format(self.server)
259 log.success(
261 log.success(
260 'Sending to server: {}'.format(self.server),
262 'Sending to server: {}'.format(self.server),
261 self.name
263 self.name
262 )
264 )
263
265
264 if isinstance(self.attr_data, str):
266 if isinstance(self.attr_data, str):
265 self.attr_data = [self.attr_data]
267 self.attr_data = [self.attr_data]
266
268
267 def __setup_plot(self):
269 def __setup_plot(self):
268 '''
270 '''
269 Common setup for all figures, here figures and axes are created
271 Common setup for all figures, here figures and axes are created
270 '''
272 '''
271
273
272 self.setup()
274 self.setup()
273
275
274 self.time_label = 'LT' if self.localtime else 'UTC'
276 self.time_label = 'LT' if self.localtime else 'UTC'
275
277
276 if self.width is None:
278 if self.width is None:
277 self.width = 8
279 self.width = 8
278
280
279 self.figures = []
281 self.figures = []
280 self.axes = []
282 self.axes = []
281 self.cb_axes = []
283 self.cb_axes = []
282 self.pf_axes = []
284 self.pf_axes = []
283 self.cmaps = []
285 self.cmaps = []
284
286
285 size = '15%' if self.ncols == 1 else '30%'
287 size = '15%' if self.ncols == 1 else '30%'
286 pad = '4%' if self.ncols == 1 else '8%'
288 pad = '4%' if self.ncols == 1 else '8%'
287
289
288 if self.oneFigure:
290 if self.oneFigure:
289 if self.height is None:
291 if self.height is None:
290 self.height = 1.4 * self.nrows + 1
292 self.height = 1.4 * self.nrows + 1
291 fig = plt.figure(figsize=(self.width, self.height),
293 fig = plt.figure(figsize=(self.width, self.height),
292 edgecolor='k',
294 edgecolor='k',
293 facecolor='w')
295 facecolor='w')
294 self.figures.append(fig)
296 self.figures.append(fig)
295 for n in range(self.nplots):
297 for n in range(self.nplots):
296 ax = fig.add_subplot(self.nrows, self.ncols,
298 ax = fig.add_subplot(self.nrows, self.ncols,
297 n + 1, polar=self.polar)
299 n + 1, polar=self.polar)
298 ax.tick_params(labelsize=8)
300 ax.tick_params(labelsize=8)
299 ax.firsttime = True
301 ax.firsttime = True
300 ax.index = 0
302 ax.index = 0
301 ax.press = None
303 ax.press = None
302 self.axes.append(ax)
304 self.axes.append(ax)
303 if self.showprofile:
305 if self.showprofile:
304 cax = self.__add_axes(ax, size=size, pad=pad)
306 cax = self.__add_axes(ax, size=size, pad=pad)
305 cax.tick_params(labelsize=8)
307 cax.tick_params(labelsize=8)
306 self.pf_axes.append(cax)
308 self.pf_axes.append(cax)
307 else:
309 else:
308 if self.height is None:
310 if self.height is None:
309 self.height = 3
311 self.height = 3
310 for n in range(self.nplots):
312 for n in range(self.nplots):
311 fig = plt.figure(figsize=(self.width, self.height),
313 fig = plt.figure(figsize=(self.width, self.height),
312 edgecolor='k',
314 edgecolor='k',
313 facecolor='w')
315 facecolor='w')
314 ax = fig.add_subplot(1, 1, 1, polar=self.polar)
316 ax = fig.add_subplot(1, 1, 1, polar=self.polar)
315 ax.tick_params(labelsize=8)
317 ax.tick_params(labelsize=8)
316 ax.firsttime = True
318 ax.firsttime = True
317 ax.index = 0
319 ax.index = 0
318 ax.press = None
320 ax.press = None
319 self.figures.append(fig)
321 self.figures.append(fig)
320 self.axes.append(ax)
322 self.axes.append(ax)
321 if self.showprofile:
323 if self.showprofile:
322 cax = self.__add_axes(ax, size=size, pad=pad)
324 cax = self.__add_axes(ax, size=size, pad=pad)
323 cax.tick_params(labelsize=8)
325 cax.tick_params(labelsize=8)
324 self.pf_axes.append(cax)
326 self.pf_axes.append(cax)
325
327
326 for n in range(self.nrows):
328 for n in range(self.nrows):
327 if self.colormaps is not None:
329 if self.colormaps is not None:
328 cmap = plt.get_cmap(self.colormaps[n])
330 cmap = plt.get_cmap(self.colormaps[n])
329 else:
331 else:
330 cmap = plt.get_cmap(self.colormap)
332 cmap = plt.get_cmap(self.colormap)
331 cmap.set_bad(self.bgcolor, 1.)
333 cmap.set_bad(self.bgcolor, 1.)
332 self.cmaps.append(cmap)
334 self.cmaps.append(cmap)
333
335
334 def __add_axes(self, ax, size='30%', pad='8%'):
336 def __add_axes(self, ax, size='30%', pad='8%'):
335 '''
337 '''
336 Add new axes to the given figure
338 Add new axes to the given figure
337 '''
339 '''
338 divider = make_axes_locatable(ax)
340 divider = make_axes_locatable(ax)
339 nax = divider.new_horizontal(size=size, pad=pad)
341 nax = divider.new_horizontal(size=size, pad=pad)
340 ax.figure.add_axes(nax)
342 ax.figure.add_axes(nax)
341 return nax
343 return nax
342
344
343 def fill_gaps(self, x_buffer, y_buffer, z_buffer):
345 def fill_gaps(self, x_buffer, y_buffer, z_buffer):
344 '''
346 '''
345 Create a masked array for missing data
347 Create a masked array for missing data
346 '''
348 '''
347 if x_buffer.shape[0] < 2:
349 if x_buffer.shape[0] < 2:
348 return x_buffer, y_buffer, z_buffer
350 return x_buffer, y_buffer, z_buffer
349
351
350 deltas = x_buffer[1:] - x_buffer[0:-1]
352 deltas = x_buffer[1:] - x_buffer[0:-1]
351 x_median = numpy.median(deltas)
353 x_median = numpy.median(deltas)
352
354
353 index = numpy.where(deltas > 5 * x_median)
355 index = numpy.where(deltas > 5 * x_median)
354
356
355 if len(index[0]) != 0:
357 if len(index[0]) != 0:
356 z_buffer[::, index[0], ::] = self.__missing
358 z_buffer[::, index[0], ::] = self.__missing
357 z_buffer = numpy.ma.masked_inside(z_buffer,
359 z_buffer = numpy.ma.masked_inside(z_buffer,
358 0.99 * self.__missing,
360 0.99 * self.__missing,
359 1.01 * self.__missing)
361 1.01 * self.__missing)
360
362
361 return x_buffer, y_buffer, z_buffer
363 return x_buffer, y_buffer, z_buffer
362
364
363 def decimate(self):
365 def decimate(self):
364
366
365 # dx = int(len(self.x)/self.__MAXNUMX) + 1
367 # dx = int(len(self.x)/self.__MAXNUMX) + 1
366 dy = int(len(self.y) / self.decimation) + 1
368 dy = int(len(self.y) / self.decimation) + 1
367
369
368 # x = self.x[::dx]
370 # x = self.x[::dx]
369 x = self.x
371 x = self.x
370 y = self.y[::dy]
372 y = self.y[::dy]
371 z = self.z[::, ::, ::dy]
373 z = self.z[::, ::, ::dy]
372
374
373 return x, y, z
375 return x, y, z
374
376
375 def format(self):
377 def format(self):
376 '''
378 '''
377 Set min and max values, labels, ticks and titles
379 Set min and max values, labels, ticks and titles
378 '''
380 '''
379
381
380 for n, ax in enumerate(self.axes):
382 for n, ax in enumerate(self.axes):
381 if ax.firsttime:
383 if ax.firsttime:
382 if self.xaxis != 'time':
384 if self.xaxis != 'time':
383 xmin = self.xmin
385 xmin = self.xmin
384 xmax = self.xmax
386 xmax = self.xmax
385 else:
387 else:
386 xmin = self.tmin
388 xmin = self.tmin
387 xmax = self.tmin + self.xrange*60*60
389 xmax = self.tmin + self.xrange*60*60
388 ax.xaxis.set_major_formatter(FuncFormatter(self.__fmtTime))
390 ax.xaxis.set_major_formatter(FuncFormatter(self.__fmtTime))
389 ax.xaxis.set_major_locator(LinearLocator(9))
391 ax.xaxis.set_major_locator(LinearLocator(9))
390 ymin = self.ymin if self.ymin is not None else numpy.nanmin(self.y[numpy.isfinite(self.y)])
392 ymin = self.ymin if self.ymin is not None else numpy.nanmin(self.y[numpy.isfinite(self.y)])
391 ymax = self.ymax if self.ymax is not None else numpy.nanmax(self.y[numpy.isfinite(self.y)])
393 ymax = self.ymax if self.ymax is not None else numpy.nanmax(self.y[numpy.isfinite(self.y)])
392 ax.set_facecolor(self.bgcolor)
394 ax.set_facecolor(self.bgcolor)
393 if self.xscale:
395 if self.xscale:
394 ax.xaxis.set_major_formatter(FuncFormatter(
396 ax.xaxis.set_major_formatter(FuncFormatter(
395 lambda x, pos: '{0:g}'.format(x*self.xscale)))
397 lambda x, pos: '{0:g}'.format(x*self.xscale)))
396 if self.yscale:
398 if self.yscale:
397 ax.yaxis.set_major_formatter(FuncFormatter(
399 ax.yaxis.set_major_formatter(FuncFormatter(
398 lambda x, pos: '{0:g}'.format(x*self.yscale)))
400 lambda x, pos: '{0:g}'.format(x*self.yscale)))
399 if self.xlabel is not None:
401 if self.xlabel is not None:
400 ax.set_xlabel(self.xlabel)
402 ax.set_xlabel(self.xlabel)
401 if self.ylabel is not None:
403 if self.ylabel is not None:
402 ax.set_ylabel(self.ylabel)
404 ax.set_ylabel(self.ylabel)
403 if self.showprofile:
405 if self.showprofile:
404 self.pf_axes[n].set_ylim(ymin, ymax)
406 self.pf_axes[n].set_ylim(ymin, ymax)
405 self.pf_axes[n].set_xlim(self.zmin, self.zmax)
407 self.pf_axes[n].set_xlim(self.zmin, self.zmax)
406 self.pf_axes[n].set_xlabel('dB')
408 self.pf_axes[n].set_xlabel('dB')
407 self.pf_axes[n].grid(b=True, axis='x')
409 self.pf_axes[n].grid(b=True, axis='x')
408 [tick.set_visible(False)
410 [tick.set_visible(False)
409 for tick in self.pf_axes[n].get_yticklabels()]
411 for tick in self.pf_axes[n].get_yticklabels()]
410 if self.colorbar:
412 if self.colorbar:
411 ax.cbar = plt.colorbar(
413 ax.cbar = plt.colorbar(
412 ax.plt, ax=ax, fraction=0.05, pad=0.02, aspect=10)
414 ax.plt, ax=ax, fraction=0.05, pad=0.02, aspect=10)
413 ax.cbar.ax.tick_params(labelsize=8)
415 ax.cbar.ax.tick_params(labelsize=8)
414 ax.cbar.ax.press = None
416 ax.cbar.ax.press = None
415 if self.cb_label:
417 if self.cb_label:
416 ax.cbar.set_label(self.cb_label, size=8)
418 ax.cbar.set_label(self.cb_label, size=8)
417 elif self.cb_labels:
419 elif self.cb_labels:
418 ax.cbar.set_label(self.cb_labels[n], size=8)
420 ax.cbar.set_label(self.cb_labels[n], size=8)
419 else:
421 else:
420 ax.cbar = None
422 ax.cbar = None
421 ax.set_xlim(xmin, xmax)
423 ax.set_xlim(xmin, xmax)
422 ax.set_ylim(ymin, ymax)
424 ax.set_ylim(ymin, ymax)
423 ax.firsttime = False
425 ax.firsttime = False
424 if self.grid:
426 if self.grid:
425 ax.grid(True)
427 ax.grid(True)
426 if not self.polar:
428 if not self.polar:
427 ax.set_title('{} {} {}'.format(
429 ax.set_title('{} {} {}'.format(
428 self.titles[n],
430 self.titles[n],
429 self.getDateTime(self.data.max_time).strftime(
431 self.getDateTime(self.data.max_time).strftime(
430 '%Y-%m-%d %H:%M:%S'),
432 '%Y-%m-%d %H:%M:%S'),
431 self.time_label),
433 self.time_label),
432 size=8)
434 size=8)
433 else:
435 else:
434 ax.set_title('{}'.format(self.titles[n]), size=8)
436 ax.set_title('{}'.format(self.titles[n]), size=8)
435 ax.set_ylim(0, 90)
437 ax.set_ylim(0, 90)
436 ax.set_yticks(numpy.arange(0, 90, 20))
438 ax.set_yticks(numpy.arange(0, 90, 20))
437 ax.yaxis.labelpad = 40
439 ax.yaxis.labelpad = 40
438
440
439 if self.firsttime:
441 if self.firsttime:
440 for n, fig in enumerate(self.figures):
442 for n, fig in enumerate(self.figures):
441 fig.subplots_adjust(**self.plots_adjust)
443 fig.subplots_adjust(**self.plots_adjust)
442 self.firsttime = False
444 self.firsttime = False
443
445
444 def clear_figures(self):
446 def clear_figures(self):
445 '''
447 '''
446 Reset axes for redraw plots
448 Reset axes for redraw plots
447 '''
449 '''
448
450
449 for ax in self.axes+self.pf_axes+self.cb_axes:
451 for ax in self.axes+self.pf_axes+self.cb_axes:
450 ax.clear()
452 ax.clear()
451 ax.firsttime = True
453 ax.firsttime = True
452 if hasattr(ax, 'cbar') and ax.cbar:
454 if hasattr(ax, 'cbar') and ax.cbar:
453 ax.cbar.remove()
455 ax.cbar.remove()
454
456
455 def __plot(self):
457 def __plot(self):
456 '''
458 '''
457 Main function to plot, format and save figures
459 Main function to plot, format and save figures
458 '''
460 '''
459
461
460 self.plot()
462 self.plot()
461 self.format()
463 self.format()
462
464
463 for n, fig in enumerate(self.figures):
465 for n, fig in enumerate(self.figures):
464 if self.nrows == 0 or self.nplots == 0:
466 if self.nrows == 0 or self.nplots == 0:
465 log.warning('No data', self.name)
467 log.warning('No data', self.name)
466 fig.text(0.5, 0.5, 'No Data', fontsize='large', ha='center')
468 fig.text(0.5, 0.5, 'No Data', fontsize='large', ha='center')
467 fig.canvas.manager.set_window_title(self.CODE)
469 fig.canvas.manager.set_window_title(self.CODE)
468 continue
470 continue
469
471
470 fig.canvas.manager.set_window_title('{} - {}'.format(self.title,
472 fig.canvas.manager.set_window_title('{} - {}'.format(self.title,
471 self.getDateTime(self.data.max_time).strftime('%Y/%m/%d')))
473 self.getDateTime(self.data.max_time).strftime('%Y/%m/%d')))
472 fig.canvas.draw()
474 fig.canvas.draw()
473 if self.show:
475 if self.show:
474 fig.show()
476 fig.show()
475 figpause(0.01)
477 figpause(0.01)
476
478
477 if self.save:
479 if self.save:
478 self.save_figure(n)
480 self.save_figure(n)
479
481
480 if self.server:
482 if self.server:
481 self.send_to_server()
483 self.send_to_server()
482
484
483 def __update(self, dataOut, timestamp):
485 def __update(self, dataOut, timestamp):
484 '''
486 '''
485 '''
487 '''
486
488
487 metadata = {
489 metadata = {
488 'yrange': dataOut.heightList,
490 'yrange': dataOut.heightList,
489 'interval': dataOut.timeInterval,
491 'interval': dataOut.timeInterval,
490 'channels': dataOut.channelList
492 'channels': dataOut.channelList
491 }
493 }
492
494
493 data, meta = self.update(dataOut)
495 data, meta = self.update(dataOut)
494 metadata.update(meta)
496 metadata.update(meta)
495 self.data.update(data, timestamp, metadata)
497 self.data.update(data, timestamp, metadata)
496
498
497 def save_figure(self, n):
499 def save_figure(self, n):
498 '''
500 '''
499 '''
501 '''
500
502
501 if (self.data.max_time - self.save_time) <= self.save_period:
503 if (self.data.max_time - self.save_time) <= self.save_period:
502 return
504 return
503
505
504 self.save_time = self.data.max_time
506 self.save_time = self.data.max_time
505
507
506 fig = self.figures[n]
508 fig = self.figures[n]
507
509
508 if self.throttle == 0:
510 if self.throttle == 0:
509 figname = os.path.join(
511 figname = os.path.join(
510 self.save,
512 self.save,
511 self.save_code,
513 self.save_code,
512 '{}_{}.png'.format(
514 '{}_{}.png'.format(
513 self.save_code,
515 self.save_code,
514 self.getDateTime(self.data.max_time).strftime(
516 self.getDateTime(self.data.max_time).strftime(
515 '%Y%m%d_%H%M%S'
517 '%Y%m%d_%H%M%S'
516 ),
518 ),
517 )
519 )
518 )
520 )
519 log.log('Saving figure: {}'.format(figname), self.name)
521 log.log('Saving figure: {}'.format(figname), self.name)
520 if not os.path.isdir(os.path.dirname(figname)):
522 if not os.path.isdir(os.path.dirname(figname)):
521 os.makedirs(os.path.dirname(figname))
523 os.makedirs(os.path.dirname(figname))
522 fig.savefig(figname)
524 fig.savefig(figname)
523
525
524 figname = os.path.join(
526 figname = os.path.join(
525 self.save,
527 self.save,
526 '{}_{}.png'.format(
528 '{}_{}.png'.format(
527 self.save_code,
529 self.save_code,
528 self.getDateTime(self.data.min_time).strftime(
530 self.getDateTime(self.data.min_time).strftime(
529 '%Y%m%d'
531 '%Y%m%d'
530 ),
532 ),
531 )
533 )
532 )
534 )
533
535
534 log.log('Saving figure: {}'.format(figname), self.name)
536 log.log('Saving figure: {}'.format(figname), self.name)
535 if not os.path.isdir(os.path.dirname(figname)):
537 if not os.path.isdir(os.path.dirname(figname)):
536 os.makedirs(os.path.dirname(figname))
538 os.makedirs(os.path.dirname(figname))
537 fig.savefig(figname)
539 fig.savefig(figname)
538
540
539 def send_to_server(self):
541 def send_to_server(self):
540 '''
542 '''
541 '''
543 '''
542
544
543 if self.exp_code == None:
545 if self.exp_code == None:
544 log.warning('Missing `exp_code` skipping sending to server...')
546 log.warning('Missing `exp_code` skipping sending to server...')
545
547
546 last_time = self.data.max_time
548 last_time = self.data.max_time
547 interval = last_time - self.sender_time
549 interval = last_time - self.sender_time
548 if interval < self.sender_period:
550 if interval < self.sender_period:
549 return
551 return
550
552
551 self.sender_time = last_time
553 self.sender_time = last_time
552
554
553 attrs = ['titles', 'zmin', 'zmax', 'tag', 'ymin', 'ymax']
555 attrs = ['titles', 'zmin', 'zmax', 'tag', 'ymin', 'ymax']
554 for attr in attrs:
556 for attr in attrs:
555 value = getattr(self, attr)
557 value = getattr(self, attr)
556 if value:
558 if value:
557 if isinstance(value, (numpy.float32, numpy.float64)):
559 if isinstance(value, (numpy.float32, numpy.float64)):
558 value = round(float(value), 2)
560 value = round(float(value), 2)
559 self.data.meta[attr] = value
561 self.data.meta[attr] = value
560 if self.colormap == 'jet':
562 if self.colormap == 'jet':
561 self.data.meta['colormap'] = 'Jet'
563 self.data.meta['colormap'] = 'Jet'
562 elif 'RdBu' in self.colormap:
564 elif 'RdBu' in self.colormap:
563 self.data.meta['colormap'] = 'RdBu'
565 self.data.meta['colormap'] = 'RdBu'
564 else:
566 else:
565 self.data.meta['colormap'] = 'Viridis'
567 self.data.meta['colormap'] = 'Viridis'
566 self.data.meta['interval'] = int(interval)
568 self.data.meta['interval'] = int(interval)
567
569
568 self.sender_queue.append(last_time)
570 self.sender_queue.append(last_time)
569
571
570 while True:
572 while True:
571 try:
573 try:
572 tm = self.sender_queue.popleft()
574 tm = self.sender_queue.popleft()
573 except IndexError:
575 except IndexError:
574 break
576 break
575 msg = self.data.jsonify(tm, self.save_code, self.plot_type)
577 msg = self.data.jsonify(tm, self.save_code, self.plot_type)
576 self.socket.send_string(msg)
578 self.socket.send_string(msg)
577 socks = dict(self.poll.poll(2000))
579 socks = dict(self.poll.poll(2000))
578 if socks.get(self.socket) == zmq.POLLIN:
580 if socks.get(self.socket) == zmq.POLLIN:
579 reply = self.socket.recv_string()
581 reply = self.socket.recv_string()
580 if reply == 'ok':
582 if reply == 'ok':
581 log.log("Response from server ok", self.name)
583 log.log("Response from server ok", self.name)
582 time.sleep(0.1)
584 time.sleep(0.1)
583 continue
585 continue
584 else:
586 else:
585 log.warning(
587 log.warning(
586 "Malformed reply from server: {}".format(reply), self.name)
588 "Malformed reply from server: {}".format(reply), self.name)
587 else:
589 else:
588 log.warning(
590 log.warning(
589 "No response from server, retrying...", self.name)
591 "No response from server, retrying...", self.name)
590 self.sender_queue.appendleft(tm)
592 self.sender_queue.appendleft(tm)
591 self.socket.setsockopt(zmq.LINGER, 0)
593 self.socket.setsockopt(zmq.LINGER, 0)
592 self.socket.close()
594 self.socket.close()
593 self.poll.unregister(self.socket)
595 self.poll.unregister(self.socket)
594 self.socket = self.context.socket(zmq.REQ)
596 self.socket = self.context.socket(zmq.REQ)
595 self.socket.connect(self.server)
597 self.socket.connect(self.server)
596 self.poll.register(self.socket, zmq.POLLIN)
598 self.poll.register(self.socket, zmq.POLLIN)
597 break
599 break
598
600
599 def setup(self):
601 def setup(self):
600 '''
602 '''
601 This method should be implemented in the child class, the following
603 This method should be implemented in the child class, the following
602 attributes should be set:
604 attributes should be set:
603
605
604 self.nrows: number of rows
606 self.nrows: number of rows
605 self.ncols: number of cols
607 self.ncols: number of cols
606 self.nplots: number of plots (channels or pairs)
608 self.nplots: number of plots (channels or pairs)
607 self.ylabel: label for Y axes
609 self.ylabel: label for Y axes
608 self.titles: list of axes title
610 self.titles: list of axes title
609
611
610 '''
612 '''
611 raise NotImplementedError
613 raise NotImplementedError
612
614
613 def plot(self):
615 def plot(self):
614 '''
616 '''
615 Must be defined in the child class, the actual plotting method
617 Must be defined in the child class, the actual plotting method
616 '''
618 '''
617 raise NotImplementedError
619 raise NotImplementedError
618
620
619 def update(self, dataOut):
621 def update(self, dataOut):
620 '''
622 '''
621 Must be defined in the child class, update self.data with new data
623 Must be defined in the child class, update self.data with new data
622 '''
624 '''
623
625
624 data = {
626 data = {
625 self.CODE: getattr(dataOut, 'data_{}'.format(self.CODE))
627 self.CODE: getattr(dataOut, 'data_{}'.format(self.CODE))
626 }
628 }
627 meta = {}
629 meta = {}
628
630
629 return data, meta
631 return data, meta
630
632
631 def run(self, dataOut, **kwargs):
633 def run(self, dataOut, **kwargs):
632 '''
634 '''
633 Main plotting routine
635 Main plotting routine
634 '''
636 '''
635
637
636 if self.isConfig is False:
638 if self.isConfig is False:
637 self.__setup(**kwargs)
639 self.__setup(**kwargs)
638
640
639 if self.localtime:
641 if self.localtime:
640 self.getDateTime = datetime.datetime.fromtimestamp
642 self.getDateTime = datetime.datetime.fromtimestamp
641 else:
643 else:
642 self.getDateTime = datetime.datetime.utcfromtimestamp
644 self.getDateTime = datetime.datetime.utcfromtimestamp
643
645
644 self.data.setup()
646 self.data.setup()
645 self.isConfig = True
647 self.isConfig = True
646 if self.server:
648 if self.server:
647 self.context = zmq.Context()
649 self.context = zmq.Context()
648 self.socket = self.context.socket(zmq.REQ)
650 self.socket = self.context.socket(zmq.REQ)
649 self.socket.connect(self.server)
651 self.socket.connect(self.server)
650 self.poll = zmq.Poller()
652 self.poll = zmq.Poller()
651 self.poll.register(self.socket, zmq.POLLIN)
653 self.poll.register(self.socket, zmq.POLLIN)
652
654
653 tm = getattr(dataOut, self.attr_time)
655 tm = getattr(dataOut, self.attr_time)
654
656
655 if self.data and 'time' in self.xaxis and (tm - self.tmin) >= self.xrange*60*60:
657 if self.data and 'time' in self.xaxis and (tm - self.tmin) >= self.xrange*60*60:
656 self.save_time = tm
658 self.save_time = tm
657 self.__plot()
659 self.__plot()
658 self.tmin += self.xrange*60*60
660 self.tmin += self.xrange*60*60
659 self.data.setup()
661 self.data.setup()
660 self.clear_figures()
662 self.clear_figures()
661
663
662 self.__update(dataOut, tm)
664 self.__update(dataOut, tm)
663
665
664 if self.isPlotConfig is False:
666 if self.isPlotConfig is False:
665 self.__setup_plot()
667 self.__setup_plot()
666 self.isPlotConfig = True
668 self.isPlotConfig = True
667 if self.xaxis == 'time':
669 if self.xaxis == 'time':
668 dt = self.getDateTime(tm)
670 dt = self.getDateTime(tm)
669 if self.xmin is None:
671 if self.xmin is None:
670 self.tmin = tm
672 self.tmin = tm
671 self.xmin = dt.hour
673 self.xmin = dt.hour
672 minutes = (self.xmin-int(self.xmin)) * 60
674 minutes = (self.xmin-int(self.xmin)) * 60
673 seconds = (minutes - int(minutes)) * 60
675 seconds = (minutes - int(minutes)) * 60
674 self.tmin = (dt.replace(hour=int(self.xmin), minute=int(minutes), second=int(seconds)) -
676 self.tmin = (dt.replace(hour=int(self.xmin), minute=int(minutes), second=int(seconds)) -
675 datetime.datetime(1970, 1, 1)).total_seconds()
677 datetime.datetime(1970, 1, 1)).total_seconds()
676 if self.localtime:
678 if self.localtime:
677 self.tmin += time.timezone
679 self.tmin += time.timezone
678
680
679 if self.xmin is not None and self.xmax is not None:
681 if self.xmin is not None and self.xmax is not None:
680 self.xrange = self.xmax - self.xmin
682 self.xrange = self.xmax - self.xmin
681
683
682 if self.throttle == 0:
684 if self.throttle == 0:
683 self.__plot()
685 self.__plot()
684 else:
686 else:
685 self.__throttle_plot(self.__plot)#, coerce=coerce)
687 self.__throttle_plot(self.__plot)#, coerce=coerce)
686
688
687 def close(self):
689 def close(self):
688
690
689 if self.data and not self.data.flagNoData:
691 if self.data and not self.data.flagNoData:
690 self.save_time = 0
692 self.save_time = 0
691 self.__plot()
693 self.__plot()
692 if self.data and not self.data.flagNoData and self.pause:
694 if self.data and not self.data.flagNoData and self.pause:
693 figpause(10)
695 figpause(10)
@@ -1,357 +1,356
1 import os
1 import os
2 import datetime
2 import datetime
3 import numpy
3 import numpy
4
4
5 from schainpy.model.graphics.jroplot_base import Plot, plt
5 from schainpy.model.graphics.jroplot_base import Plot, plt
6 from schainpy.model.graphics.jroplot_spectra import SpectraPlot, RTIPlot, CoherencePlot
6 from schainpy.model.graphics.jroplot_spectra import SpectraPlot, RTIPlot, CoherencePlot
7 from schainpy.utils import log
7 from schainpy.utils import log
8
8
9 EARTH_RADIUS = 6.3710e3
9 EARTH_RADIUS = 6.3710e3
10
10
11
11
12 def ll2xy(lat1, lon1, lat2, lon2):
12 def ll2xy(lat1, lon1, lat2, lon2):
13
13
14 p = 0.017453292519943295
14 p = 0.017453292519943295
15 a = 0.5 - numpy.cos((lat2 - lat1) * p)/2 + numpy.cos(lat1 * p) * \
15 a = 0.5 - numpy.cos((lat2 - lat1) * p)/2 + numpy.cos(lat1 * p) * \
16 numpy.cos(lat2 * p) * (1 - numpy.cos((lon2 - lon1) * p)) / 2
16 numpy.cos(lat2 * p) * (1 - numpy.cos((lon2 - lon1) * p)) / 2
17 r = 12742 * numpy.arcsin(numpy.sqrt(a))
17 r = 12742 * numpy.arcsin(numpy.sqrt(a))
18 theta = numpy.arctan2(numpy.sin((lon2-lon1)*p)*numpy.cos(lat2*p), numpy.cos(lat1*p)
18 theta = numpy.arctan2(numpy.sin((lon2-lon1)*p)*numpy.cos(lat2*p), numpy.cos(lat1*p)
19 * numpy.sin(lat2*p)-numpy.sin(lat1*p)*numpy.cos(lat2*p)*numpy.cos((lon2-lon1)*p))
19 * numpy.sin(lat2*p)-numpy.sin(lat1*p)*numpy.cos(lat2*p)*numpy.cos((lon2-lon1)*p))
20 theta = -theta + numpy.pi/2
20 theta = -theta + numpy.pi/2
21 return r*numpy.cos(theta), r*numpy.sin(theta)
21 return r*numpy.cos(theta), r*numpy.sin(theta)
22
22
23
23
24 def km2deg(km):
24 def km2deg(km):
25 '''
25 '''
26 Convert distance in km to degrees
26 Convert distance in km to degrees
27 '''
27 '''
28
28
29 return numpy.rad2deg(km/EARTH_RADIUS)
29 return numpy.rad2deg(km/EARTH_RADIUS)
30
30
31
31
32
32
33 class SpectralMomentsPlot(SpectraPlot):
33 class SpectralMomentsPlot(SpectraPlot):
34 '''
34 '''
35 Plot for Spectral Moments
35 Plot for Spectral Moments
36 '''
36 '''
37 CODE = 'spc_moments'
37 CODE = 'spc_moments'
38 colormap = 'jet'
38 colormap = 'jet'
39 plot_type = 'pcolor'
39 plot_type = 'pcolor'
40
40
41
41
42 class SnrPlot(RTIPlot):
42 class SnrPlot(RTIPlot):
43 '''
43 '''
44 Plot for SNR Data
44 Plot for SNR Data
45 '''
45 '''
46
46
47 CODE = 'snr'
47 CODE = 'snr'
48 colormap = 'jet'
48 colormap = 'jet'
49
49
50 def update(self, dataOut):
50 def update(self, dataOut):
51
51
52 data = {
52 data = {
53 'snr': 10*numpy.log10(dataOut.data_snr)
53 'snr': 10*numpy.log10(dataOut.data_snr)
54 }
54 }
55
55
56 return data, {}
56 return data, {}
57
57
58 class DopplerPlot(RTIPlot):
58 class DopplerPlot(RTIPlot):
59 '''
59 '''
60 Plot for DOPPLER Data (1st moment)
60 Plot for DOPPLER Data (1st moment)
61 '''
61 '''
62
62
63 CODE = 'dop'
63 CODE = 'dop'
64 colormap = 'jet'
64 colormap = 'jet'
65
65
66 def update(self, dataOut):
66 def update(self, dataOut):
67
67
68 data = {
68 data = {
69 'dop': 10*numpy.log10(dataOut.data_dop)
69 'dop': 10*numpy.log10(dataOut.data_dop)
70 }
70 }
71
71
72 return data, {}
72 return data, {}
73
73
74 class PowerPlot(RTIPlot):
74 class PowerPlot(RTIPlot):
75 '''
75 '''
76 Plot for Power Data (0 moment)
76 Plot for Power Data (0 moment)
77 '''
77 '''
78
78
79 CODE = 'pow'
79 CODE = 'pow'
80 colormap = 'jet'
80 colormap = 'jet'
81
81
82 def update(self, dataOut):
82 def update(self, dataOut):
83
83
84 data = {
84 data = {
85 'pow': 10*numpy.log10(dataOut.data_pow)
85 'pow': 10*numpy.log10(dataOut.data_pow)
86 }
86 }
87
87 print("data",data)
88 return data, {}
88 return data, {}
89
89
90 class SpectralWidthPlot(RTIPlot):
90 class SpectralWidthPlot(RTIPlot):
91 '''
91 '''
92 Plot for Spectral Width Data (2nd moment)
92 Plot for Spectral Width Data (2nd moment)
93 '''
93 '''
94
94
95 CODE = 'width'
95 CODE = 'width'
96 colormap = 'jet'
96 colormap = 'jet'
97
97
98 def update(self, dataOut):
98 def update(self, dataOut):
99
99
100 data = {
100 data = {
101 'width': dataOut.data_width
101 'width': dataOut.data_width
102 }
102 }
103
103
104 return data, {}
104 return data, {}
105
105
106 class SkyMapPlot(Plot):
106 class SkyMapPlot(Plot):
107 '''
107 '''
108 Plot for meteors detection data
108 Plot for meteors detection data
109 '''
109 '''
110
110
111 CODE = 'param'
111 CODE = 'param'
112
112
113 def setup(self):
113 def setup(self):
114
114
115 self.ncols = 1
115 self.ncols = 1
116 self.nrows = 1
116 self.nrows = 1
117 self.width = 7.2
117 self.width = 7.2
118 self.height = 7.2
118 self.height = 7.2
119 self.nplots = 1
119 self.nplots = 1
120 self.xlabel = 'Zonal Zenith Angle (deg)'
120 self.xlabel = 'Zonal Zenith Angle (deg)'
121 self.ylabel = 'Meridional Zenith Angle (deg)'
121 self.ylabel = 'Meridional Zenith Angle (deg)'
122 self.polar = True
122 self.polar = True
123 self.ymin = -180
123 self.ymin = -180
124 self.ymax = 180
124 self.ymax = 180
125 self.colorbar = False
125 self.colorbar = False
126
126
127 def plot(self):
127 def plot(self):
128
128
129 arrayParameters = numpy.concatenate(self.data['param'])
129 arrayParameters = numpy.concatenate(self.data['param'])
130 error = arrayParameters[:, -1]
130 error = arrayParameters[:, -1]
131 indValid = numpy.where(error == 0)[0]
131 indValid = numpy.where(error == 0)[0]
132 finalMeteor = arrayParameters[indValid, :]
132 finalMeteor = arrayParameters[indValid, :]
133 finalAzimuth = finalMeteor[:, 3]
133 finalAzimuth = finalMeteor[:, 3]
134 finalZenith = finalMeteor[:, 4]
134 finalZenith = finalMeteor[:, 4]
135
135
136 x = finalAzimuth * numpy.pi / 180
136 x = finalAzimuth * numpy.pi / 180
137 y = finalZenith
137 y = finalZenith
138
138
139 ax = self.axes[0]
139 ax = self.axes[0]
140
140
141 if ax.firsttime:
141 if ax.firsttime:
142 ax.plot = ax.plot(x, y, 'bo', markersize=5)[0]
142 ax.plot = ax.plot(x, y, 'bo', markersize=5)[0]
143 else:
143 else:
144 ax.plot.set_data(x, y)
144 ax.plot.set_data(x, y)
145
145
146 dt1 = self.getDateTime(self.data.min_time).strftime('%y/%m/%d %H:%M:%S')
146 dt1 = self.getDateTime(self.data.min_time).strftime('%y/%m/%d %H:%M:%S')
147 dt2 = self.getDateTime(self.data.max_time).strftime('%y/%m/%d %H:%M:%S')
147 dt2 = self.getDateTime(self.data.max_time).strftime('%y/%m/%d %H:%M:%S')
148 title = 'Meteor Detection Sky Map\n %s - %s \n Number of events: %5.0f\n' % (dt1,
148 title = 'Meteor Detection Sky Map\n %s - %s \n Number of events: %5.0f\n' % (dt1,
149 dt2,
149 dt2,
150 len(x))
150 len(x))
151 self.titles[0] = title
151 self.titles[0] = title
152
152
153
153
154 class GenericRTIPlot(Plot):
154 class GenericRTIPlot(Plot):
155 '''
155 '''
156 Plot for data_xxxx object
156 Plot for data_xxxx object
157 '''
157 '''
158
158
159 CODE = 'param'
159 CODE = 'param'
160 colormap = 'viridis'
160 colormap = 'viridis'
161 plot_type = 'pcolorbuffer'
161 plot_type = 'pcolorbuffer'
162
162
163 def setup(self):
163 def setup(self):
164 self.xaxis = 'time'
164 self.xaxis = 'time'
165 self.ncols = 1
165 self.ncols = 1
166 self.nrows = self.data.shape('param')[0]
166 self.nrows = self.data.shape('param')[0]
167 self.nplots = self.nrows
167 self.nplots = self.nrows
168 self.plots_adjust.update({'hspace':0.8, 'left': 0.1, 'bottom': 0.08, 'right':0.95, 'top': 0.95})
168 self.plots_adjust.update({'hspace':0.8, 'left': 0.1, 'bottom': 0.08, 'right':0.95, 'top': 0.95})
169
169
170 if not self.xlabel:
170 if not self.xlabel:
171 self.xlabel = 'Time'
171 self.xlabel = 'Time'
172
172
173 self.ylabel = 'Height [km]'
173 self.ylabel = 'Height [km]'
174 if not self.titles:
174 if not self.titles:
175 self.titles = ['Param {}'.format(x) for x in range(self.nrows)]
175 self.titles = ['Param {}'.format(x) for x in range(self.nrows)]
176
176
177 def update(self, dataOut):
177 def update(self, dataOut):
178
178
179 data = {
179 data = {
180 'param' : numpy.concatenate([getattr(dataOut, attr) for attr in self.attr_data], axis=0)
180 'param' : numpy.concatenate([getattr(dataOut, attr) for attr in self.attr_data], axis=0)
181 }
181 }
182
182
183 meta = {}
183 meta = {}
184
184
185 return data, meta
185 return data, meta
186
186
187 def plot(self):
187 def plot(self):
188 # self.data.normalize_heights()
188 # self.data.normalize_heights()
189 self.x = self.data.times
189 self.x = self.data.times
190 self.y = self.data.yrange
190 self.y = self.data.yrange
191 self.z = self.data['param']
191 self.z = self.data['param']
192
192
193 self.z = numpy.ma.masked_invalid(self.z)
193 self.z = numpy.ma.masked_invalid(self.z)
194
194
195 if self.decimation is None:
195 if self.decimation is None:
196 x, y, z = self.fill_gaps(self.x, self.y, self.z)
196 x, y, z = self.fill_gaps(self.x, self.y, self.z)
197 else:
197 else:
198 x, y, z = self.fill_gaps(*self.decimate())
198 x, y, z = self.fill_gaps(*self.decimate())
199
199
200 for n, ax in enumerate(self.axes):
200 for n, ax in enumerate(self.axes):
201
201
202 self.zmax = self.zmax if self.zmax is not None else numpy.max(
202 self.zmax = self.zmax if self.zmax is not None else numpy.max(
203 self.z[n])
203 self.z[n])
204 self.zmin = self.zmin if self.zmin is not None else numpy.min(
204 self.zmin = self.zmin if self.zmin is not None else numpy.min(
205 self.z[n])
205 self.z[n])
206
206
207 if ax.firsttime:
207 if ax.firsttime:
208 if self.zlimits is not None:
208 if self.zlimits is not None:
209 self.zmin, self.zmax = self.zlimits[n]
209 self.zmin, self.zmax = self.zlimits[n]
210
210
211 ax.plt = ax.pcolormesh(x, y, z[n].T * self.factors[n],
211 ax.plt = ax.pcolormesh(x, y, z[n].T * self.factors[n],
212 vmin=self.zmin,
212 vmin=self.zmin,
213 vmax=self.zmax,
213 vmax=self.zmax,
214 cmap=self.cmaps[n]
214 cmap=self.cmaps[n]
215 )
215 )
216 else:
216 else:
217 if self.zlimits is not None:
217 if self.zlimits is not None:
218 self.zmin, self.zmax = self.zlimits[n]
218 self.zmin, self.zmax = self.zlimits[n]
219 ax.collections.remove(ax.collections[0])
219 ax.collections.remove(ax.collections[0])
220 ax.plt = ax.pcolormesh(x, y, z[n].T * self.factors[n],
220 ax.plt = ax.pcolormesh(x, y, z[n].T * self.factors[n],
221 vmin=self.zmin,
221 vmin=self.zmin,
222 vmax=self.zmax,
222 vmax=self.zmax,
223 cmap=self.cmaps[n]
223 cmap=self.cmaps[n]
224 )
224 )
225
225
226
226
227 class PolarMapPlot(Plot):
227 class PolarMapPlot(Plot):
228 '''
228 '''
229 Plot for weather radar
229 Plot for weather radar
230 '''
230 '''
231
231
232 CODE = 'param'
232 CODE = 'param'
233 colormap = 'seismic'
233 colormap = 'seismic'
234
234
235 def setup(self):
235 def setup(self):
236 self.ncols = 1
236 self.ncols = 1
237 self.nrows = 1
237 self.nrows = 1
238 self.width = 9
238 self.width = 9
239 self.height = 8
239 self.height = 8
240 self.mode = self.data.meta['mode']
240 self.mode = self.data.meta['mode']
241 if self.channels is not None:
241 if self.channels is not None:
242 self.nplots = len(self.channels)
242 self.nplots = len(self.channels)
243 self.nrows = len(self.channels)
243 self.nrows = len(self.channels)
244 else:
244 else:
245 self.nplots = self.data.shape(self.CODE)[0]
245 self.nplots = self.data.shape(self.CODE)[0]
246 self.nrows = self.nplots
246 self.nrows = self.nplots
247 self.channels = list(range(self.nplots))
247 self.channels = list(range(self.nplots))
248 if self.mode == 'E':
248 if self.mode == 'E':
249 self.xlabel = 'Longitude'
249 self.xlabel = 'Longitude'
250 self.ylabel = 'Latitude'
250 self.ylabel = 'Latitude'
251 else:
251 else:
252 self.xlabel = 'Range (km)'
252 self.xlabel = 'Range (km)'
253 self.ylabel = 'Height (km)'
253 self.ylabel = 'Height (km)'
254 self.bgcolor = 'white'
254 self.bgcolor = 'white'
255 self.cb_labels = self.data.meta['units']
255 self.cb_labels = self.data.meta['units']
256 self.lat = self.data.meta['latitude']
256 self.lat = self.data.meta['latitude']
257 self.lon = self.data.meta['longitude']
257 self.lon = self.data.meta['longitude']
258 self.xmin, self.xmax = float(
258 self.xmin, self.xmax = float(
259 km2deg(self.xmin) + self.lon), float(km2deg(self.xmax) + self.lon)
259 km2deg(self.xmin) + self.lon), float(km2deg(self.xmax) + self.lon)
260 self.ymin, self.ymax = float(
260 self.ymin, self.ymax = float(
261 km2deg(self.ymin) + self.lat), float(km2deg(self.ymax) + self.lat)
261 km2deg(self.ymin) + self.lat), float(km2deg(self.ymax) + self.lat)
262 # self.polar = True
262 # self.polar = True
263
263
264 def plot(self):
264 def plot(self):
265
265
266 for n, ax in enumerate(self.axes):
266 for n, ax in enumerate(self.axes):
267 data = self.data['param'][self.channels[n]]
267 data = self.data['param'][self.channels[n]]
268
268
269 zeniths = numpy.linspace(
269 zeniths = numpy.linspace(
270 0, self.data.meta['max_range'], data.shape[1])
270 0, self.data.meta['max_range'], data.shape[1])
271 if self.mode == 'E':
271 if self.mode == 'E':
272 azimuths = -numpy.radians(self.data.yrange)+numpy.pi/2
272 azimuths = -numpy.radians(self.data.yrange)+numpy.pi/2
273 r, theta = numpy.meshgrid(zeniths, azimuths)
273 r, theta = numpy.meshgrid(zeniths, azimuths)
274 x, y = r*numpy.cos(theta)*numpy.cos(numpy.radians(self.data.meta['elevation'])), r*numpy.sin(
274 x, y = r*numpy.cos(theta)*numpy.cos(numpy.radians(self.data.meta['elevation'])), r*numpy.sin(
275 theta)*numpy.cos(numpy.radians(self.data.meta['elevation']))
275 theta)*numpy.cos(numpy.radians(self.data.meta['elevation']))
276 x = km2deg(x) + self.lon
276 x = km2deg(x) + self.lon
277 y = km2deg(y) + self.lat
277 y = km2deg(y) + self.lat
278 else:
278 else:
279 azimuths = numpy.radians(self.data.yrange)
279 azimuths = numpy.radians(self.data.yrange)
280 r, theta = numpy.meshgrid(zeniths, azimuths)
280 r, theta = numpy.meshgrid(zeniths, azimuths)
281 x, y = r*numpy.cos(theta), r*numpy.sin(theta)
281 x, y = r*numpy.cos(theta), r*numpy.sin(theta)
282 self.y = zeniths
282 self.y = zeniths
283
283
284 if ax.firsttime:
284 if ax.firsttime:
285 if self.zlimits is not None:
285 if self.zlimits is not None:
286 self.zmin, self.zmax = self.zlimits[n]
286 self.zmin, self.zmax = self.zlimits[n]
287 ax.plt = ax.pcolormesh( # r, theta, numpy.ma.array(data, mask=numpy.isnan(data)),
287 ax.plt = ax.pcolormesh( # r, theta, numpy.ma.array(data, mask=numpy.isnan(data)),
288 x, y, numpy.ma.array(data, mask=numpy.isnan(data)),
288 x, y, numpy.ma.array(data, mask=numpy.isnan(data)),
289 vmin=self.zmin,
289 vmin=self.zmin,
290 vmax=self.zmax,
290 vmax=self.zmax,
291 cmap=self.cmaps[n])
291 cmap=self.cmaps[n])
292 else:
292 else:
293 if self.zlimits is not None:
293 if self.zlimits is not None:
294 self.zmin, self.zmax = self.zlimits[n]
294 self.zmin, self.zmax = self.zlimits[n]
295 ax.collections.remove(ax.collections[0])
295 ax.collections.remove(ax.collections[0])
296 ax.plt = ax.pcolormesh( # r, theta, numpy.ma.array(data, mask=numpy.isnan(data)),
296 ax.plt = ax.pcolormesh( # r, theta, numpy.ma.array(data, mask=numpy.isnan(data)),
297 x, y, numpy.ma.array(data, mask=numpy.isnan(data)),
297 x, y, numpy.ma.array(data, mask=numpy.isnan(data)),
298 vmin=self.zmin,
298 vmin=self.zmin,
299 vmax=self.zmax,
299 vmax=self.zmax,
300 cmap=self.cmaps[n])
300 cmap=self.cmaps[n])
301
301
302 if self.mode == 'A':
302 if self.mode == 'A':
303 continue
303 continue
304
304
305 # plot district names
305 # plot district names
306 f = open('/data/workspace/schain_scripts/distrito.csv')
306 f = open('/data/workspace/schain_scripts/distrito.csv')
307 for line in f:
307 for line in f:
308 label, lon, lat = [s.strip() for s in line.split(',') if s]
308 label, lon, lat = [s.strip() for s in line.split(',') if s]
309 lat = float(lat)
309 lat = float(lat)
310 lon = float(lon)
310 lon = float(lon)
311 # ax.plot(lon, lat, '.b', ms=2)
311 # ax.plot(lon, lat, '.b', ms=2)
312 ax.text(lon, lat, label.decode('utf8'), ha='center',
312 ax.text(lon, lat, label.decode('utf8'), ha='center',
313 va='bottom', size='8', color='black')
313 va='bottom', size='8', color='black')
314
314
315 # plot limites
315 # plot limites
316 limites = []
316 limites = []
317 tmp = []
317 tmp = []
318 for line in open('/data/workspace/schain_scripts/lima.csv'):
318 for line in open('/data/workspace/schain_scripts/lima.csv'):
319 if '#' in line:
319 if '#' in line:
320 if tmp:
320 if tmp:
321 limites.append(tmp)
321 limites.append(tmp)
322 tmp = []
322 tmp = []
323 continue
323 continue
324 values = line.strip().split(',')
324 values = line.strip().split(',')
325 tmp.append((float(values[0]), float(values[1])))
325 tmp.append((float(values[0]), float(values[1])))
326 for points in limites:
326 for points in limites:
327 ax.add_patch(
327 ax.add_patch(
328 Polygon(points, ec='k', fc='none', ls='--', lw=0.5))
328 Polygon(points, ec='k', fc='none', ls='--', lw=0.5))
329
329
330 # plot Cuencas
330 # plot Cuencas
331 for cuenca in ('rimac', 'lurin', 'mala', 'chillon', 'chilca', 'chancay-huaral'):
331 for cuenca in ('rimac', 'lurin', 'mala', 'chillon', 'chilca', 'chancay-huaral'):
332 f = open('/data/workspace/schain_scripts/{}.csv'.format(cuenca))
332 f = open('/data/workspace/schain_scripts/{}.csv'.format(cuenca))
333 values = [line.strip().split(',') for line in f]
333 values = [line.strip().split(',') for line in f]
334 points = [(float(s[0]), float(s[1])) for s in values]
334 points = [(float(s[0]), float(s[1])) for s in values]
335 ax.add_patch(Polygon(points, ec='b', fc='none'))
335 ax.add_patch(Polygon(points, ec='b', fc='none'))
336
336
337 # plot grid
337 # plot grid
338 for r in (15, 30, 45, 60):
338 for r in (15, 30, 45, 60):
339 ax.add_artist(plt.Circle((self.lon, self.lat),
339 ax.add_artist(plt.Circle((self.lon, self.lat),
340 km2deg(r), color='0.6', fill=False, lw=0.2))
340 km2deg(r), color='0.6', fill=False, lw=0.2))
341 ax.text(
341 ax.text(
342 self.lon + (km2deg(r))*numpy.cos(60*numpy.pi/180),
342 self.lon + (km2deg(r))*numpy.cos(60*numpy.pi/180),
343 self.lat + (km2deg(r))*numpy.sin(60*numpy.pi/180),
343 self.lat + (km2deg(r))*numpy.sin(60*numpy.pi/180),
344 '{}km'.format(r),
344 '{}km'.format(r),
345 ha='center', va='bottom', size='8', color='0.6', weight='heavy')
345 ha='center', va='bottom', size='8', color='0.6', weight='heavy')
346
346
347 if self.mode == 'E':
347 if self.mode == 'E':
348 title = 'El={}$^\circ$'.format(self.data.meta['elevation'])
348 title = 'El={}$^\circ$'.format(self.data.meta['elevation'])
349 label = 'E{:02d}'.format(int(self.data.meta['elevation']))
349 label = 'E{:02d}'.format(int(self.data.meta['elevation']))
350 else:
350 else:
351 title = 'Az={}$^\circ$'.format(self.data.meta['azimuth'])
351 title = 'Az={}$^\circ$'.format(self.data.meta['azimuth'])
352 label = 'A{:02d}'.format(int(self.data.meta['azimuth']))
352 label = 'A{:02d}'.format(int(self.data.meta['azimuth']))
353
353
354 self.save_labels = ['{}-{}'.format(lbl, label) for lbl in self.labels]
354 self.save_labels = ['{}-{}'.format(lbl, label) for lbl in self.labels]
355 self.titles = ['{} {}'.format(
355 self.titles = ['{} {}'.format(
356 self.data.parameters[x], title) for x in self.channels]
356 self.data.parameters[x], title) for x in self.channels]
357
@@ -1,711 +1,712
1 # Copyright (c) 2012-2020 Jicamarca Radio Observatory
1 # Copyright (c) 2012-2020 Jicamarca Radio Observatory
2 # All rights reserved.
2 # All rights reserved.
3 #
3 #
4 # Distributed under the terms of the BSD 3-clause license.
4 # Distributed under the terms of the BSD 3-clause license.
5 """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 channelList = None
24 channelList = []
25
25
26 def setup(self):
26 def setup(self):
27 self.nplots = len(self.data.channels)
27 self.nplots = len(self.data.channels)
28 self.ncols = int(numpy.sqrt(self.nplots) + 0.9)
28 self.ncols = int(numpy.sqrt(self.nplots) + 0.9)
29 self.nrows = int((1.0 * self.nplots / self.ncols) + 0.9)
29 self.nrows = int((1.0 * self.nplots / self.ncols) + 0.9)
30 self.height = 2.6 * self.nrows
30 self.height = 2.6 * self.nrows
31
31
32 self.cb_label = 'dB'
32 self.cb_label = 'dB'
33 if self.showprofile:
33 if self.showprofile:
34 self.width = 4 * self.ncols
34 self.width = 4 * self.ncols
35 else:
35 else:
36 self.width = 3.5 * self.ncols
36 self.width = 3.5 * self.ncols
37 self.plots_adjust.update({'wspace': 0.4, 'hspace':0.4, 'left': 0.1, 'right': 0.9, 'bottom': 0.08})
37 self.plots_adjust.update({'wspace': 0.4, 'hspace':0.4, 'left': 0.1, 'right': 0.9, 'bottom': 0.08})
38 self.ylabel = 'Range [km]'
38 self.ylabel = 'Range [km]'
39
39
40 def update(self, dataOut):
40 def update(self, dataOut):
41 if self.channelList == None:
41 if self.channelList == None:
42 self.channelList = dataOut.channelList
42 self.channelList = dataOut.channelList
43 data = {}
43 data = {}
44 meta = {}
44 meta = {}
45 spc = 10*numpy.log10(dataOut.data_spc/dataOut.normFactor)
45 spc = 10*numpy.log10(dataOut.data_spc/dataOut.normFactor)
46 data['spc'] = spc
46 data['spc'] = spc
47 data['rti'] = dataOut.getPower()
47 data['rti'] = dataOut.getPower()
48 data['noise'] = 10*numpy.log10(dataOut.getNoise()/dataOut.normFactor)
48 data['noise'] = 10*numpy.log10(dataOut.getNoise()/dataOut.normFactor)
49 meta['xrange'] = (dataOut.getFreqRange(1)/1000., dataOut.getAcfRange(1), dataOut.getVelRange(1))
49 meta['xrange'] = (dataOut.getFreqRange(1)/1000., dataOut.getAcfRange(1), dataOut.getVelRange(1))
50 if self.CODE == 'spc_moments':
50 if self.CODE == 'spc_moments':
51 data['moments'] = dataOut.moments
51 data['moments'] = dataOut.moments
52
52
53 return data, meta
53 return data, meta
54
54
55 def plot(self):
55 def plot(self):
56 if self.xaxis == "frequency":
56 if self.xaxis == "frequency":
57 x = self.data.xrange[0]
57 x = self.data.xrange[0]
58 self.xlabel = "Frequency (kHz)"
58 self.xlabel = "Frequency (kHz)"
59 elif self.xaxis == "time":
59 elif self.xaxis == "time":
60 x = self.data.xrange[1]
60 x = self.data.xrange[1]
61 self.xlabel = "Time (ms)"
61 self.xlabel = "Time (ms)"
62 else:
62 else:
63 x = self.data.xrange[2]
63 x = self.data.xrange[2]
64 self.xlabel = "Velocity (m/s)"
64 self.xlabel = "Velocity (m/s)"
65
65
66 if self.CODE == 'spc_moments':
66 if self.CODE == 'spc_moments':
67 x = self.data.xrange[2]
67 x = self.data.xrange[2]
68 self.xlabel = "Velocity (m/s)"
68 self.xlabel = "Velocity (m/s)"
69
69
70 self.titles = []
70 self.titles = []
71
71
72 y = self.data.yrange
72 y = self.data.yrange
73 self.y = y
73 self.y = y
74
74
75 data = self.data[-1]
75 data = self.data[-1]
76 z = data['spc']
76 z = data['spc']
77
77
78 for n, ax in enumerate(self.axes):
78 for n, ax in enumerate(self.axes):
79 noise = data['noise'][n]
79 noise = data['noise'][n]
80 if self.CODE == 'spc_moments':
80 if self.CODE == 'spc_moments':
81 mean = data['moments'][n, 1]
81 mean = data['moments'][n, 1]
82 if ax.firsttime:
82 if ax.firsttime:
83 self.xmax = self.xmax if self.xmax else numpy.nanmax(x)
83 self.xmax = self.xmax if self.xmax else numpy.nanmax(x)
84 self.xmin = self.xmin if self.xmin else -self.xmax
84 self.xmin = self.xmin if self.xmin else -self.xmax
85 self.zmin = self.zmin if self.zmin else numpy.nanmin(z)
85 self.zmin = self.zmin if self.zmin else numpy.nanmin(z)
86 self.zmax = self.zmax if self.zmax else numpy.nanmax(z)
86 self.zmax = self.zmax if self.zmax else numpy.nanmax(z)
87 ax.plt = ax.pcolormesh(x, y, z[n].T,
87 ax.plt = ax.pcolormesh(x, y, z[n].T,
88 vmin=self.zmin,
88 vmin=self.zmin,
89 vmax=self.zmax,
89 vmax=self.zmax,
90 cmap=plt.get_cmap(self.colormap)
90 cmap=plt.get_cmap(self.colormap)
91 )
91 )
92
92
93 if self.showprofile:
93 if self.showprofile:
94 ax.plt_profile = self.pf_axes[n].plot(
94 ax.plt_profile = self.pf_axes[n].plot(
95 data['rti'][n], y)[0]
95 data['rti'][n], y)[0]
96 ax.plt_noise = self.pf_axes[n].plot(numpy.repeat(noise, len(y)), y,
96 ax.plt_noise = self.pf_axes[n].plot(numpy.repeat(noise, len(y)), y,
97 color="k", linestyle="dashed", lw=1)[0]
97 color="k", linestyle="dashed", lw=1)[0]
98 if self.CODE == 'spc_moments':
98 if self.CODE == 'spc_moments':
99 ax.plt_mean = ax.plot(mean, y, color='k')[0]
99 ax.plt_mean = ax.plot(mean, y, color='k')[0]
100 else:
100 else:
101 ax.plt.set_array(z[n].T.ravel())
101 ax.plt.set_array(z[n].T.ravel())
102 if self.showprofile:
102 if self.showprofile:
103 ax.plt_profile.set_data(data['rti'][n], y)
103 ax.plt_profile.set_data(data['rti'][n], y)
104 ax.plt_noise.set_data(numpy.repeat(noise, len(y)), y)
104 ax.plt_noise.set_data(numpy.repeat(noise, len(y)), y)
105 if self.CODE == 'spc_moments':
105 if self.CODE == 'spc_moments':
106 ax.plt_mean.set_data(mean, y)
106 ax.plt_mean.set_data(mean, y)
107 self.titles.append('CH {}: {:3.2f}dB'.format(self.channelList[n], noise))
107 self.titles.append('CH {}: {:3.2f}dB'.format(self.channelList[n], noise))
108
108
109
109
110 class CrossSpectraPlot(Plot):
110 class CrossSpectraPlot(Plot):
111
111
112 CODE = 'cspc'
112 CODE = 'cspc'
113 colormap = 'jet'
113 colormap = 'jet'
114 plot_type = 'pcolor'
114 plot_type = 'pcolor'
115 zmin_coh = None
115 zmin_coh = None
116 zmax_coh = None
116 zmax_coh = None
117 zmin_phase = None
117 zmin_phase = None
118 zmax_phase = None
118 zmax_phase = None
119
119
120 def setup(self):
120 def setup(self):
121
121
122 self.ncols = 4
122 self.ncols = 4
123 self.nplots = len(self.data.pairs) * 2
123 self.nplots = len(self.data.pairs) * 2
124 self.nrows = int((1.0 * self.nplots / self.ncols) + 0.9)
124 self.nrows = int((1.0 * self.nplots / self.ncols) + 0.9)
125 self.width = 3.1 * self.ncols
125 self.width = 3.1 * self.ncols
126 self.height = 2.6 * self.nrows
126 self.height = 2.6 * self.nrows
127 self.ylabel = 'Range [km]'
127 self.ylabel = 'Range [km]'
128 self.showprofile = False
128 self.showprofile = False
129 self.plots_adjust.update({'left': 0.08, 'right': 0.92, 'wspace': 0.5, 'hspace':0.4, 'top':0.95, 'bottom': 0.08})
129 self.plots_adjust.update({'left': 0.08, 'right': 0.92, 'wspace': 0.5, 'hspace':0.4, 'top':0.95, 'bottom': 0.08})
130
130
131 def update(self, dataOut):
131 def update(self, dataOut):
132
132
133 data = {}
133 data = {}
134 meta = {}
134 meta = {}
135
135
136 spc = dataOut.data_spc
136 spc = dataOut.data_spc
137 cspc = dataOut.data_cspc
137 cspc = dataOut.data_cspc
138 meta['xrange'] = (dataOut.getFreqRange(1)/1000., dataOut.getAcfRange(1), dataOut.getVelRange(1))
138 meta['xrange'] = (dataOut.getFreqRange(1)/1000., dataOut.getAcfRange(1), dataOut.getVelRange(1))
139 meta['pairs'] = dataOut.pairsList
139 meta['pairs'] = dataOut.pairsList
140
140
141 tmp = []
141 tmp = []
142
142
143 for n, pair in enumerate(meta['pairs']):
143 for n, pair in enumerate(meta['pairs']):
144 out = cspc[n] / numpy.sqrt(spc[pair[0]] * spc[pair[1]])
144 out = cspc[n] / numpy.sqrt(spc[pair[0]] * spc[pair[1]])
145 coh = numpy.abs(out)
145 coh = numpy.abs(out)
146 phase = numpy.arctan2(out.imag, out.real) * 180 / numpy.pi
146 phase = numpy.arctan2(out.imag, out.real) * 180 / numpy.pi
147 tmp.append(coh)
147 tmp.append(coh)
148 tmp.append(phase)
148 tmp.append(phase)
149
149
150 data['cspc'] = numpy.array(tmp)
150 data['cspc'] = numpy.array(tmp)
151
151
152 return data, meta
152 return data, meta
153
153
154 def plot(self):
154 def plot(self):
155
155
156 if self.xaxis == "frequency":
156 if self.xaxis == "frequency":
157 x = self.data.xrange[0]
157 x = self.data.xrange[0]
158 self.xlabel = "Frequency (kHz)"
158 self.xlabel = "Frequency (kHz)"
159 elif self.xaxis == "time":
159 elif self.xaxis == "time":
160 x = self.data.xrange[1]
160 x = self.data.xrange[1]
161 self.xlabel = "Time (ms)"
161 self.xlabel = "Time (ms)"
162 else:
162 else:
163 x = self.data.xrange[2]
163 x = self.data.xrange[2]
164 self.xlabel = "Velocity (m/s)"
164 self.xlabel = "Velocity (m/s)"
165
165
166 self.titles = []
166 self.titles = []
167
167
168 y = self.data.yrange
168 y = self.data.yrange
169 self.y = y
169 self.y = y
170
170
171 data = self.data[-1]
171 data = self.data[-1]
172 cspc = data['cspc']
172 cspc = data['cspc']
173
173
174 for n in range(len(self.data.pairs)):
174 for n in range(len(self.data.pairs)):
175 pair = self.data.pairs[n]
175 pair = self.data.pairs[n]
176 coh = cspc[n*2]
176 coh = cspc[n*2]
177 phase = cspc[n*2+1]
177 phase = cspc[n*2+1]
178 ax = self.axes[2 * n]
178 ax = self.axes[2 * n]
179 if ax.firsttime:
179 if ax.firsttime:
180 ax.plt = ax.pcolormesh(x, y, coh.T,
180 ax.plt = ax.pcolormesh(x, y, coh.T,
181 vmin=0,
181 vmin=0,
182 vmax=1,
182 vmax=1,
183 cmap=plt.get_cmap(self.colormap_coh)
183 cmap=plt.get_cmap(self.colormap_coh)
184 )
184 )
185 else:
185 else:
186 ax.plt.set_array(coh.T.ravel())
186 ax.plt.set_array(coh.T.ravel())
187 self.titles.append(
187 self.titles.append(
188 'Coherence Ch{} * Ch{}'.format(pair[0], pair[1]))
188 'Coherence Ch{} * Ch{}'.format(pair[0], pair[1]))
189
189
190 ax = self.axes[2 * n + 1]
190 ax = self.axes[2 * n + 1]
191 if ax.firsttime:
191 if ax.firsttime:
192 ax.plt = ax.pcolormesh(x, y, phase.T,
192 ax.plt = ax.pcolormesh(x, y, phase.T,
193 vmin=-180,
193 vmin=-180,
194 vmax=180,
194 vmax=180,
195 cmap=plt.get_cmap(self.colormap_phase)
195 cmap=plt.get_cmap(self.colormap_phase)
196 )
196 )
197 else:
197 else:
198 ax.plt.set_array(phase.T.ravel())
198 ax.plt.set_array(phase.T.ravel())
199 self.titles.append('Phase CH{} * CH{}'.format(pair[0], pair[1]))
199 self.titles.append('Phase CH{} * CH{}'.format(pair[0], pair[1]))
200
200
201
201
202 class RTIPlot(Plot):
202 class RTIPlot(Plot):
203 '''
203 '''
204 Plot for RTI data
204 Plot for RTI data
205 '''
205 '''
206
206
207 CODE = 'rti'
207 CODE = 'rti'
208 colormap = 'jet'
208 colormap = 'jet'
209 plot_type = 'pcolorbuffer'
209 plot_type = 'pcolorbuffer'
210 titles = None
210 titles = None
211 channelList = None
211 channelList = []
212
212
213 def setup(self):
213 def setup(self):
214 self.xaxis = 'time'
214 self.xaxis = 'time'
215 self.ncols = 1
215 self.ncols = 1
216 print("dataChannels ",self.data.channels)
216 self.nrows = len(self.data.channels)
217 self.nrows = len(self.data.channels)
217 self.nplots = len(self.data.channels)
218 self.nplots = len(self.data.channels)
218 self.ylabel = 'Range [km]'
219 self.ylabel = 'Range [km]'
219 self.xlabel = 'Time'
220 self.xlabel = 'Time'
220 self.cb_label = 'dB'
221 self.cb_label = 'dB'
221 self.plots_adjust.update({'hspace':0.8, 'left': 0.1, 'bottom': 0.08, 'right':0.95})
222 self.plots_adjust.update({'hspace':0.8, 'left': 0.1, 'bottom': 0.08, 'right':0.95})
222 self.titles = ['{} Channel {}'.format(
223 self.titles = ['{} Channel {}'.format(
223 self.CODE.upper(), x) for x in range(self.nplots)]
224 self.CODE.upper(), x) for x in range(self.nplots)]
224
225 print("SETUP")
225 def update(self, dataOut):
226 def update(self, dataOut):
226 if self.channelList == None:
227 if len(self.channelList) == 0:
227 self.channelList = dataOut.channelList
228 self.channelList = dataOut.channelList
228 data = {}
229 data = {}
229 meta = {}
230 meta = {}
230 data['rti'] = dataOut.getPower()
231 data['rti'] = dataOut.getPower()
231 data['noise'] = 10*numpy.log10(dataOut.getNoise()/dataOut.normFactor)
232 data['noise'] = 10*numpy.log10(dataOut.getNoise()/dataOut.normFactor)
232
233
233 return data, meta
234 return data, meta
234
235
235 def plot(self):
236 def plot(self):
236 self.x = self.data.times
237 self.x = self.data.times
237 self.y = self.data.yrange
238 self.y = self.data.yrange
238 self.z = self.data[self.CODE]
239 self.z = self.data[self.CODE]
239 self.z = numpy.ma.masked_invalid(self.z)
240 self.z = numpy.ma.masked_invalid(self.z)
240 if self.channelList != None:
241 if self.channelList != None:
241 self.titles = ['{} Channel {}'.format(
242 self.titles = ['{} Channel {}'.format(
242 self.CODE.upper(), x) for x in self.channelList]
243 self.CODE.upper(), x) for x in self.channelList]
243
244
244 if self.decimation is None:
245 if self.decimation is None:
245 x, y, z = self.fill_gaps(self.x, self.y, self.z)
246 x, y, z = self.fill_gaps(self.x, self.y, self.z)
246 else:
247 else:
247 x, y, z = self.fill_gaps(*self.decimate())
248 x, y, z = self.fill_gaps(*self.decimate())
248
249
249 for n, ax in enumerate(self.axes):
250 for n, ax in enumerate(self.axes):
250 self.zmin = self.zmin if self.zmin else numpy.min(self.z)
251 self.zmin = self.zmin if self.zmin else numpy.min(self.z)
251 self.zmax = self.zmax if self.zmax else numpy.max(self.z)
252 self.zmax = self.zmax if self.zmax else numpy.max(self.z)
252 data = self.data[-1]
253 data = self.data[-1]
253 if ax.firsttime:
254 if ax.firsttime:
254 ax.plt = ax.pcolormesh(x, y, z[n].T,
255 ax.plt = ax.pcolormesh(x, y, z[n].T,
255 vmin=self.zmin,
256 vmin=self.zmin,
256 vmax=self.zmax,
257 vmax=self.zmax,
257 cmap=plt.get_cmap(self.colormap)
258 cmap=plt.get_cmap(self.colormap)
258 )
259 )
259 if self.showprofile:
260 if self.showprofile:
260 ax.plot_profile = self.pf_axes[n].plot(
261 ax.plot_profile = self.pf_axes[n].plot(
261 data['rti'][n], self.y)[0]
262 data['rti'][n], self.y)[0]
262 ax.plot_noise = self.pf_axes[n].plot(numpy.repeat(data['noise'][n], len(self.y)), self.y,
263 ax.plot_noise = self.pf_axes[n].plot(numpy.repeat(data['noise'][n], len(self.y)), self.y,
263 color="k", linestyle="dashed", lw=1)[0]
264 color="k", linestyle="dashed", lw=1)[0]
264 else:
265 else:
265 ax.collections.remove(ax.collections[0])
266 ax.collections.remove(ax.collections[0])
266 ax.plt = ax.pcolormesh(x, y, z[n].T,
267 ax.plt = ax.pcolormesh(x, y, z[n].T,
267 vmin=self.zmin,
268 vmin=self.zmin,
268 vmax=self.zmax,
269 vmax=self.zmax,
269 cmap=plt.get_cmap(self.colormap)
270 cmap=plt.get_cmap(self.colormap)
270 )
271 )
271 if self.showprofile:
272 if self.showprofile:
272 ax.plot_profile.set_data(data['rti'][n], self.y)
273 ax.plot_profile.set_data(data['rti'][n], self.y)
273 ax.plot_noise.set_data(numpy.repeat(
274 ax.plot_noise.set_data(numpy.repeat(
274 data['noise'][n], len(self.y)), self.y)
275 data['noise'][n], len(self.y)), self.y)
275
276
276
277
277 class CoherencePlot(RTIPlot):
278 class CoherencePlot(RTIPlot):
278 '''
279 '''
279 Plot for Coherence data
280 Plot for Coherence data
280 '''
281 '''
281
282
282 CODE = 'coh'
283 CODE = 'coh'
283
284
284 def setup(self):
285 def setup(self):
285 self.xaxis = 'time'
286 self.xaxis = 'time'
286 self.ncols = 1
287 self.ncols = 1
287 self.nrows = len(self.data.pairs)
288 self.nrows = len(self.data.pairs)
288 self.nplots = len(self.data.pairs)
289 self.nplots = len(self.data.pairs)
289 self.ylabel = 'Range [km]'
290 self.ylabel = 'Range [km]'
290 self.xlabel = 'Time'
291 self.xlabel = 'Time'
291 self.plots_adjust.update({'hspace':0.6, 'left': 0.1, 'bottom': 0.1,'right':0.95})
292 self.plots_adjust.update({'hspace':0.6, 'left': 0.1, 'bottom': 0.1,'right':0.95})
292 if self.CODE == 'coh':
293 if self.CODE == 'coh':
293 self.cb_label = ''
294 self.cb_label = ''
294 self.titles = [
295 self.titles = [
295 'Coherence Map Ch{} * Ch{}'.format(x[0], x[1]) for x in self.data.pairs]
296 'Coherence Map Ch{} * Ch{}'.format(x[0], x[1]) for x in self.data.pairs]
296 else:
297 else:
297 self.cb_label = 'Degrees'
298 self.cb_label = 'Degrees'
298 self.titles = [
299 self.titles = [
299 'Phase Map Ch{} * Ch{}'.format(x[0], x[1]) for x in self.data.pairs]
300 'Phase Map Ch{} * Ch{}'.format(x[0], x[1]) for x in self.data.pairs]
300
301
301 def update(self, dataOut):
302 def update(self, dataOut):
302
303
303 data = {}
304 data = {}
304 meta = {}
305 meta = {}
305 data['coh'] = dataOut.getCoherence()
306 data['coh'] = dataOut.getCoherence()
306 meta['pairs'] = dataOut.pairsList
307 meta['pairs'] = dataOut.pairsList
307
308
308 return data, meta
309 return data, meta
309
310
310 class PhasePlot(CoherencePlot):
311 class PhasePlot(CoherencePlot):
311 '''
312 '''
312 Plot for Phase map data
313 Plot for Phase map data
313 '''
314 '''
314
315
315 CODE = 'phase'
316 CODE = 'phase'
316 colormap = 'seismic'
317 colormap = 'seismic'
317
318
318 def update(self, dataOut):
319 def update(self, dataOut):
319
320
320 data = {}
321 data = {}
321 meta = {}
322 meta = {}
322 data['phase'] = dataOut.getCoherence(phase=True)
323 data['phase'] = dataOut.getCoherence(phase=True)
323 meta['pairs'] = dataOut.pairsList
324 meta['pairs'] = dataOut.pairsList
324
325
325 return data, meta
326 return data, meta
326
327
327 class NoisePlot(Plot):
328 class NoisePlot(Plot):
328 '''
329 '''
329 Plot for noise
330 Plot for noise
330 '''
331 '''
331
332
332 CODE = 'noise'
333 CODE = 'noise'
333 plot_type = 'scatterbuffer'
334 plot_type = 'scatterbuffer'
334
335
335 def setup(self):
336 def setup(self):
336 self.xaxis = 'time'
337 self.xaxis = 'time'
337 self.ncols = 1
338 self.ncols = 1
338 self.nrows = 1
339 self.nrows = 1
339 self.nplots = 1
340 self.nplots = 1
340 self.ylabel = 'Intensity [dB]'
341 self.ylabel = 'Intensity [dB]'
341 self.xlabel = 'Time'
342 self.xlabel = 'Time'
342 self.titles = ['Noise']
343 self.titles = ['Noise']
343 self.colorbar = False
344 self.colorbar = False
344 self.plots_adjust.update({'right': 0.85 })
345 self.plots_adjust.update({'right': 0.85 })
345
346
346 def update(self, dataOut):
347 def update(self, dataOut):
347
348
348 data = {}
349 data = {}
349 meta = {}
350 meta = {}
350 data['noise'] = 10*numpy.log10(dataOut.getNoise()/dataOut.normFactor).reshape(dataOut.nChannels, 1)
351 data['noise'] = 10*numpy.log10(dataOut.getNoise()/dataOut.normFactor).reshape(dataOut.nChannels, 1)
351 meta['yrange'] = numpy.array([])
352 meta['yrange'] = numpy.array([])
352
353
353 return data, meta
354 return data, meta
354
355
355 def plot(self):
356 def plot(self):
356
357
357 x = self.data.times
358 x = self.data.times
358 xmin = self.data.min_time
359 xmin = self.data.min_time
359 xmax = xmin + self.xrange * 60 * 60
360 xmax = xmin + self.xrange * 60 * 60
360 Y = self.data['noise']
361 Y = self.data['noise']
361
362
362 if self.axes[0].firsttime:
363 if self.axes[0].firsttime:
363 self.ymin = numpy.nanmin(Y) - 5
364 self.ymin = numpy.nanmin(Y) - 5
364 self.ymax = numpy.nanmax(Y) + 5
365 self.ymax = numpy.nanmax(Y) + 5
365 for ch in self.data.channels:
366 for ch in self.data.channels:
366 y = Y[ch]
367 y = Y[ch]
367 self.axes[0].plot(x, y, lw=1, label='Ch{}'.format(ch))
368 self.axes[0].plot(x, y, lw=1, label='Ch{}'.format(ch))
368 plt.legend(bbox_to_anchor=(1.18, 1.0))
369 plt.legend(bbox_to_anchor=(1.18, 1.0))
369 else:
370 else:
370 for ch in self.data.channels:
371 for ch in self.data.channels:
371 y = Y[ch]
372 y = Y[ch]
372 self.axes[0].lines[ch].set_data(x, y)
373 self.axes[0].lines[ch].set_data(x, y)
373
374
374
375
375 class PowerProfilePlot(Plot):
376 class PowerProfilePlot(Plot):
376
377
377 CODE = 'pow_profile'
378 CODE = 'pow_profile'
378 plot_type = 'scatter'
379 plot_type = 'scatter'
379
380
380 def setup(self):
381 def setup(self):
381
382
382 self.ncols = 1
383 self.ncols = 1
383 self.nrows = 1
384 self.nrows = 1
384 self.nplots = 1
385 self.nplots = 1
385 self.height = 4
386 self.height = 4
386 self.width = 3
387 self.width = 3
387 self.ylabel = 'Range [km]'
388 self.ylabel = 'Range [km]'
388 self.xlabel = 'Intensity [dB]'
389 self.xlabel = 'Intensity [dB]'
389 self.titles = ['Power Profile']
390 self.titles = ['Power Profile']
390 self.colorbar = False
391 self.colorbar = False
391
392
392 def update(self, dataOut):
393 def update(self, dataOut):
393
394
394 data = {}
395 data = {}
395 meta = {}
396 meta = {}
396 data[self.CODE] = dataOut.getPower()
397 data[self.CODE] = dataOut.getPower()
397
398
398 return data, meta
399 return data, meta
399
400
400 def plot(self):
401 def plot(self):
401
402
402 y = self.data.yrange
403 y = self.data.yrange
403 self.y = y
404 self.y = y
404
405
405 x = self.data[-1][self.CODE]
406 x = self.data[-1][self.CODE]
406
407
407 if self.xmin is None: self.xmin = numpy.nanmin(x)*0.9
408 if self.xmin is None: self.xmin = numpy.nanmin(x)*0.9
408 if self.xmax is None: self.xmax = numpy.nanmax(x)*1.1
409 if self.xmax is None: self.xmax = numpy.nanmax(x)*1.1
409
410
410 if self.axes[0].firsttime:
411 if self.axes[0].firsttime:
411 for ch in self.data.channels:
412 for ch in self.data.channels:
412 self.axes[0].plot(x[ch], y, lw=1, label='Ch{}'.format(ch))
413 self.axes[0].plot(x[ch], y, lw=1, label='Ch{}'.format(ch))
413 plt.legend()
414 plt.legend()
414 else:
415 else:
415 for ch in self.data.channels:
416 for ch in self.data.channels:
416 self.axes[0].lines[ch].set_data(x[ch], y)
417 self.axes[0].lines[ch].set_data(x[ch], y)
417
418
418
419
419 class SpectraCutPlot(Plot):
420 class SpectraCutPlot(Plot):
420
421
421 CODE = 'spc_cut'
422 CODE = 'spc_cut'
422 plot_type = 'scatter'
423 plot_type = 'scatter'
423 buffering = False
424 buffering = False
424
425
425 def setup(self):
426 def setup(self):
426
427
427 self.nplots = len(self.data.channels)
428 self.nplots = len(self.data.channels)
428 self.ncols = int(numpy.sqrt(self.nplots) + 0.9)
429 self.ncols = int(numpy.sqrt(self.nplots) + 0.9)
429 self.nrows = int((1.0 * self.nplots / self.ncols) + 0.9)
430 self.nrows = int((1.0 * self.nplots / self.ncols) + 0.9)
430 self.width = 3.4 * self.ncols + 1.5
431 self.width = 3.4 * self.ncols + 1.5
431 self.height = 3 * self.nrows
432 self.height = 3 * self.nrows
432 self.ylabel = 'Power [dB]'
433 self.ylabel = 'Power [dB]'
433 self.colorbar = False
434 self.colorbar = False
434 self.plots_adjust.update({'left':0.1, 'hspace':0.3, 'right': 0.75, 'bottom':0.08})
435 self.plots_adjust.update({'left':0.1, 'hspace':0.3, 'right': 0.75, 'bottom':0.08})
435
436
436 def update(self, dataOut):
437 def update(self, dataOut):
437
438
438 data = {}
439 data = {}
439 meta = {}
440 meta = {}
440 spc = 10*numpy.log10(dataOut.data_spc/dataOut.normFactor)
441 spc = 10*numpy.log10(dataOut.data_spc/dataOut.normFactor)
441 data['spc'] = spc
442 data['spc'] = spc
442 meta['xrange'] = (dataOut.getFreqRange(1)/1000., dataOut.getAcfRange(1), dataOut.getVelRange(1))
443 meta['xrange'] = (dataOut.getFreqRange(1)/1000., dataOut.getAcfRange(1), dataOut.getVelRange(1))
443
444
444 return data, meta
445 return data, meta
445
446
446 def plot(self):
447 def plot(self):
447 if self.xaxis == "frequency":
448 if self.xaxis == "frequency":
448 x = self.data.xrange[0][1:]
449 x = self.data.xrange[0][1:]
449 self.xlabel = "Frequency (kHz)"
450 self.xlabel = "Frequency (kHz)"
450 elif self.xaxis == "time":
451 elif self.xaxis == "time":
451 x = self.data.xrange[1]
452 x = self.data.xrange[1]
452 self.xlabel = "Time (ms)"
453 self.xlabel = "Time (ms)"
453 else:
454 else:
454 x = self.data.xrange[2]
455 x = self.data.xrange[2]
455 self.xlabel = "Velocity (m/s)"
456 self.xlabel = "Velocity (m/s)"
456
457
457 self.titles = []
458 self.titles = []
458
459
459 y = self.data.yrange
460 y = self.data.yrange
460 z = self.data[-1]['spc']
461 z = self.data[-1]['spc']
461
462
462 if self.height_index:
463 if self.height_index:
463 index = numpy.array(self.height_index)
464 index = numpy.array(self.height_index)
464 else:
465 else:
465 index = numpy.arange(0, len(y), int((len(y))/9))
466 index = numpy.arange(0, len(y), int((len(y))/9))
466
467
467 for n, ax in enumerate(self.axes):
468 for n, ax in enumerate(self.axes):
468 if ax.firsttime:
469 if ax.firsttime:
469 self.xmax = self.xmax if self.xmax else numpy.nanmax(x)
470 self.xmax = self.xmax if self.xmax else numpy.nanmax(x)
470 self.xmin = self.xmin if self.xmin else -self.xmax
471 self.xmin = self.xmin if self.xmin else -self.xmax
471 self.ymin = self.ymin if self.ymin else numpy.nanmin(z)
472 self.ymin = self.ymin if self.ymin else numpy.nanmin(z)
472 self.ymax = self.ymax if self.ymax else numpy.nanmax(z)
473 self.ymax = self.ymax if self.ymax else numpy.nanmax(z)
473 ax.plt = ax.plot(x, z[n, :, index].T)
474 ax.plt = ax.plot(x, z[n, :, index].T)
474 labels = ['Range = {:2.1f}km'.format(y[i]) for i in index]
475 labels = ['Range = {:2.1f}km'.format(y[i]) for i in index]
475 self.figures[0].legend(ax.plt, labels, loc='center right')
476 self.figures[0].legend(ax.plt, labels, loc='center right')
476 else:
477 else:
477 for i, line in enumerate(ax.plt):
478 for i, line in enumerate(ax.plt):
478 line.set_data(x, z[n, :, index[i]])
479 line.set_data(x, z[n, :, index[i]])
479 self.titles.append('CH {}'.format(n))
480 self.titles.append('CH {}'.format(n))
480
481
481
482
482 class BeaconPhase(Plot):
483 class BeaconPhase(Plot):
483
484
484 __isConfig = None
485 __isConfig = None
485 __nsubplots = None
486 __nsubplots = None
486
487
487 PREFIX = 'beacon_phase'
488 PREFIX = 'beacon_phase'
488
489
489 def __init__(self):
490 def __init__(self):
490 Plot.__init__(self)
491 Plot.__init__(self)
491 self.timerange = 24*60*60
492 self.timerange = 24*60*60
492 self.isConfig = False
493 self.isConfig = False
493 self.__nsubplots = 1
494 self.__nsubplots = 1
494 self.counter_imagwr = 0
495 self.counter_imagwr = 0
495 self.WIDTH = 800
496 self.WIDTH = 800
496 self.HEIGHT = 400
497 self.HEIGHT = 400
497 self.WIDTHPROF = 120
498 self.WIDTHPROF = 120
498 self.HEIGHTPROF = 0
499 self.HEIGHTPROF = 0
499 self.xdata = None
500 self.xdata = None
500 self.ydata = None
501 self.ydata = None
501
502
502 self.PLOT_CODE = BEACON_CODE
503 self.PLOT_CODE = BEACON_CODE
503
504
504 self.FTP_WEI = None
505 self.FTP_WEI = None
505 self.EXP_CODE = None
506 self.EXP_CODE = None
506 self.SUB_EXP_CODE = None
507 self.SUB_EXP_CODE = None
507 self.PLOT_POS = None
508 self.PLOT_POS = None
508
509
509 self.filename_phase = None
510 self.filename_phase = None
510
511
511 self.figfile = None
512 self.figfile = None
512
513
513 self.xmin = None
514 self.xmin = None
514 self.xmax = None
515 self.xmax = None
515
516
516 def getSubplots(self):
517 def getSubplots(self):
517
518
518 ncol = 1
519 ncol = 1
519 nrow = 1
520 nrow = 1
520
521
521 return nrow, ncol
522 return nrow, ncol
522
523
523 def setup(self, id, nplots, wintitle, showprofile=True, show=True):
524 def setup(self, id, nplots, wintitle, showprofile=True, show=True):
524
525
525 self.__showprofile = showprofile
526 self.__showprofile = showprofile
526 self.nplots = nplots
527 self.nplots = nplots
527
528
528 ncolspan = 7
529 ncolspan = 7
529 colspan = 6
530 colspan = 6
530 self.__nsubplots = 2
531 self.__nsubplots = 2
531
532
532 self.createFigure(id = id,
533 self.createFigure(id = id,
533 wintitle = wintitle,
534 wintitle = wintitle,
534 widthplot = self.WIDTH+self.WIDTHPROF,
535 widthplot = self.WIDTH+self.WIDTHPROF,
535 heightplot = self.HEIGHT+self.HEIGHTPROF,
536 heightplot = self.HEIGHT+self.HEIGHTPROF,
536 show=show)
537 show=show)
537
538
538 nrow, ncol = self.getSubplots()
539 nrow, ncol = self.getSubplots()
539
540
540 self.addAxes(nrow, ncol*ncolspan, 0, 0, colspan, 1)
541 self.addAxes(nrow, ncol*ncolspan, 0, 0, colspan, 1)
541
542
542 def save_phase(self, filename_phase):
543 def save_phase(self, filename_phase):
543 f = open(filename_phase,'w+')
544 f = open(filename_phase,'w+')
544 f.write('\n\n')
545 f.write('\n\n')
545 f.write('JICAMARCA RADIO OBSERVATORY - Beacon Phase \n')
546 f.write('JICAMARCA RADIO OBSERVATORY - Beacon Phase \n')
546 f.write('DD MM YYYY HH MM SS pair(2,0) pair(2,1) pair(2,3) pair(2,4)\n\n' )
547 f.write('DD MM YYYY HH MM SS pair(2,0) pair(2,1) pair(2,3) pair(2,4)\n\n' )
547 f.close()
548 f.close()
548
549
549 def save_data(self, filename_phase, data, data_datetime):
550 def save_data(self, filename_phase, data, data_datetime):
550 f=open(filename_phase,'a')
551 f=open(filename_phase,'a')
551 timetuple_data = data_datetime.timetuple()
552 timetuple_data = data_datetime.timetuple()
552 day = str(timetuple_data.tm_mday)
553 day = str(timetuple_data.tm_mday)
553 month = str(timetuple_data.tm_mon)
554 month = str(timetuple_data.tm_mon)
554 year = str(timetuple_data.tm_year)
555 year = str(timetuple_data.tm_year)
555 hour = str(timetuple_data.tm_hour)
556 hour = str(timetuple_data.tm_hour)
556 minute = str(timetuple_data.tm_min)
557 minute = str(timetuple_data.tm_min)
557 second = str(timetuple_data.tm_sec)
558 second = str(timetuple_data.tm_sec)
558 f.write(day+' '+month+' '+year+' '+hour+' '+minute+' '+second+' '+str(data[0])+' '+str(data[1])+' '+str(data[2])+' '+str(data[3])+'\n')
559 f.write(day+' '+month+' '+year+' '+hour+' '+minute+' '+second+' '+str(data[0])+' '+str(data[1])+' '+str(data[2])+' '+str(data[3])+'\n')
559 f.close()
560 f.close()
560
561
561 def plot(self):
562 def plot(self):
562 log.warning('TODO: Not yet implemented...')
563 log.warning('TODO: Not yet implemented...')
563
564
564 def run(self, dataOut, id, wintitle="", pairsList=None, showprofile='True',
565 def run(self, dataOut, id, wintitle="", pairsList=None, showprofile='True',
565 xmin=None, xmax=None, ymin=None, ymax=None, hmin=None, hmax=None,
566 xmin=None, xmax=None, ymin=None, ymax=None, hmin=None, hmax=None,
566 timerange=None,
567 timerange=None,
567 save=False, figpath='./', figfile=None, show=True, ftp=False, wr_period=1,
568 save=False, figpath='./', figfile=None, show=True, ftp=False, wr_period=1,
568 server=None, folder=None, username=None, password=None,
569 server=None, folder=None, username=None, password=None,
569 ftp_wei=0, exp_code=0, sub_exp_code=0, plot_pos=0):
570 ftp_wei=0, exp_code=0, sub_exp_code=0, plot_pos=0):
570
571
571 if dataOut.flagNoData:
572 if dataOut.flagNoData:
572 return dataOut
573 return dataOut
573
574
574 if not isTimeInHourRange(dataOut.datatime, xmin, xmax):
575 if not isTimeInHourRange(dataOut.datatime, xmin, xmax):
575 return
576 return
576
577
577 if pairsList == None:
578 if pairsList == None:
578 pairsIndexList = dataOut.pairsIndexList[:10]
579 pairsIndexList = dataOut.pairsIndexList[:10]
579 else:
580 else:
580 pairsIndexList = []
581 pairsIndexList = []
581 for pair in pairsList:
582 for pair in pairsList:
582 if pair not in dataOut.pairsList:
583 if pair not in dataOut.pairsList:
583 raise ValueError("Pair %s is not in dataOut.pairsList" %(pair))
584 raise ValueError("Pair %s is not in dataOut.pairsList" %(pair))
584 pairsIndexList.append(dataOut.pairsList.index(pair))
585 pairsIndexList.append(dataOut.pairsList.index(pair))
585
586
586 if pairsIndexList == []:
587 if pairsIndexList == []:
587 return
588 return
588
589
589 # if len(pairsIndexList) > 4:
590 # if len(pairsIndexList) > 4:
590 # pairsIndexList = pairsIndexList[0:4]
591 # pairsIndexList = pairsIndexList[0:4]
591
592
592 hmin_index = None
593 hmin_index = None
593 hmax_index = None
594 hmax_index = None
594
595
595 if hmin != None and hmax != None:
596 if hmin != None and hmax != None:
596 indexes = numpy.arange(dataOut.nHeights)
597 indexes = numpy.arange(dataOut.nHeights)
597 hmin_list = indexes[dataOut.heightList >= hmin]
598 hmin_list = indexes[dataOut.heightList >= hmin]
598 hmax_list = indexes[dataOut.heightList <= hmax]
599 hmax_list = indexes[dataOut.heightList <= hmax]
599
600
600 if hmin_list.any():
601 if hmin_list.any():
601 hmin_index = hmin_list[0]
602 hmin_index = hmin_list[0]
602
603
603 if hmax_list.any():
604 if hmax_list.any():
604 hmax_index = hmax_list[-1]+1
605 hmax_index = hmax_list[-1]+1
605
606
606 x = dataOut.getTimeRange()
607 x = dataOut.getTimeRange()
607
608
608 thisDatetime = dataOut.datatime
609 thisDatetime = dataOut.datatime
609
610
610 title = wintitle + " Signal Phase" # : %s" %(thisDatetime.strftime("%d-%b-%Y"))
611 title = wintitle + " Signal Phase" # : %s" %(thisDatetime.strftime("%d-%b-%Y"))
611 xlabel = "Local Time"
612 xlabel = "Local Time"
612 ylabel = "Phase (degrees)"
613 ylabel = "Phase (degrees)"
613
614
614 update_figfile = False
615 update_figfile = False
615
616
616 nplots = len(pairsIndexList)
617 nplots = len(pairsIndexList)
617 #phase = numpy.zeros((len(pairsIndexList),len(dataOut.beacon_heiIndexList)))
618 #phase = numpy.zeros((len(pairsIndexList),len(dataOut.beacon_heiIndexList)))
618 phase_beacon = numpy.zeros(len(pairsIndexList))
619 phase_beacon = numpy.zeros(len(pairsIndexList))
619 for i in range(nplots):
620 for i in range(nplots):
620 pair = dataOut.pairsList[pairsIndexList[i]]
621 pair = dataOut.pairsList[pairsIndexList[i]]
621 ccf = numpy.average(dataOut.data_cspc[pairsIndexList[i], :, hmin_index:hmax_index], axis=0)
622 ccf = numpy.average(dataOut.data_cspc[pairsIndexList[i], :, hmin_index:hmax_index], axis=0)
622 powa = numpy.average(dataOut.data_spc[pair[0], :, hmin_index:hmax_index], axis=0)
623 powa = numpy.average(dataOut.data_spc[pair[0], :, hmin_index:hmax_index], axis=0)
623 powb = numpy.average(dataOut.data_spc[pair[1], :, hmin_index:hmax_index], axis=0)
624 powb = numpy.average(dataOut.data_spc[pair[1], :, hmin_index:hmax_index], axis=0)
624 avgcoherenceComplex = ccf/numpy.sqrt(powa*powb)
625 avgcoherenceComplex = ccf/numpy.sqrt(powa*powb)
625 phase = numpy.arctan2(avgcoherenceComplex.imag, avgcoherenceComplex.real)*180/numpy.pi
626 phase = numpy.arctan2(avgcoherenceComplex.imag, avgcoherenceComplex.real)*180/numpy.pi
626
627
627 if dataOut.beacon_heiIndexList:
628 if dataOut.beacon_heiIndexList:
628 phase_beacon[i] = numpy.average(phase[dataOut.beacon_heiIndexList])
629 phase_beacon[i] = numpy.average(phase[dataOut.beacon_heiIndexList])
629 else:
630 else:
630 phase_beacon[i] = numpy.average(phase)
631 phase_beacon[i] = numpy.average(phase)
631
632
632 if not self.isConfig:
633 if not self.isConfig:
633
634
634 nplots = len(pairsIndexList)
635 nplots = len(pairsIndexList)
635
636
636 self.setup(id=id,
637 self.setup(id=id,
637 nplots=nplots,
638 nplots=nplots,
638 wintitle=wintitle,
639 wintitle=wintitle,
639 showprofile=showprofile,
640 showprofile=showprofile,
640 show=show)
641 show=show)
641
642
642 if timerange != None:
643 if timerange != None:
643 self.timerange = timerange
644 self.timerange = timerange
644
645
645 self.xmin, self.xmax = self.getTimeLim(x, xmin, xmax, timerange)
646 self.xmin, self.xmax = self.getTimeLim(x, xmin, xmax, timerange)
646
647
647 if ymin == None: ymin = 0
648 if ymin == None: ymin = 0
648 if ymax == None: ymax = 360
649 if ymax == None: ymax = 360
649
650
650 self.FTP_WEI = ftp_wei
651 self.FTP_WEI = ftp_wei
651 self.EXP_CODE = exp_code
652 self.EXP_CODE = exp_code
652 self.SUB_EXP_CODE = sub_exp_code
653 self.SUB_EXP_CODE = sub_exp_code
653 self.PLOT_POS = plot_pos
654 self.PLOT_POS = plot_pos
654
655
655 self.name = thisDatetime.strftime("%Y%m%d_%H%M%S")
656 self.name = thisDatetime.strftime("%Y%m%d_%H%M%S")
656 self.isConfig = True
657 self.isConfig = True
657 self.figfile = figfile
658 self.figfile = figfile
658 self.xdata = numpy.array([])
659 self.xdata = numpy.array([])
659 self.ydata = numpy.array([])
660 self.ydata = numpy.array([])
660
661
661 update_figfile = True
662 update_figfile = True
662
663
663 #open file beacon phase
664 #open file beacon phase
664 path = '%s%03d' %(self.PREFIX, self.id)
665 path = '%s%03d' %(self.PREFIX, self.id)
665 beacon_file = os.path.join(path,'%s.txt'%self.name)
666 beacon_file = os.path.join(path,'%s.txt'%self.name)
666 self.filename_phase = os.path.join(figpath,beacon_file)
667 self.filename_phase = os.path.join(figpath,beacon_file)
667 #self.save_phase(self.filename_phase)
668 #self.save_phase(self.filename_phase)
668
669
669
670
670 #store data beacon phase
671 #store data beacon phase
671 #self.save_data(self.filename_phase, phase_beacon, thisDatetime)
672 #self.save_data(self.filename_phase, phase_beacon, thisDatetime)
672
673
673 self.setWinTitle(title)
674 self.setWinTitle(title)
674
675
675
676
676 title = "Phase Plot %s" %(thisDatetime.strftime("%Y/%m/%d %H:%M:%S"))
677 title = "Phase Plot %s" %(thisDatetime.strftime("%Y/%m/%d %H:%M:%S"))
677
678
678 legendlabels = ["Pair (%d,%d)"%(pair[0], pair[1]) for pair in dataOut.pairsList]
679 legendlabels = ["Pair (%d,%d)"%(pair[0], pair[1]) for pair in dataOut.pairsList]
679
680
680 axes = self.axesList[0]
681 axes = self.axesList[0]
681
682
682 self.xdata = numpy.hstack((self.xdata, x[0:1]))
683 self.xdata = numpy.hstack((self.xdata, x[0:1]))
683
684
684 if len(self.ydata)==0:
685 if len(self.ydata)==0:
685 self.ydata = phase_beacon.reshape(-1,1)
686 self.ydata = phase_beacon.reshape(-1,1)
686 else:
687 else:
687 self.ydata = numpy.hstack((self.ydata, phase_beacon.reshape(-1,1)))
688 self.ydata = numpy.hstack((self.ydata, phase_beacon.reshape(-1,1)))
688
689
689
690
690 axes.pmultilineyaxis(x=self.xdata, y=self.ydata,
691 axes.pmultilineyaxis(x=self.xdata, y=self.ydata,
691 xmin=self.xmin, xmax=self.xmax, ymin=ymin, ymax=ymax,
692 xmin=self.xmin, xmax=self.xmax, ymin=ymin, ymax=ymax,
692 xlabel=xlabel, ylabel=ylabel, title=title, legendlabels=legendlabels, marker='x', markersize=8, linestyle="solid",
693 xlabel=xlabel, ylabel=ylabel, title=title, legendlabels=legendlabels, marker='x', markersize=8, linestyle="solid",
693 XAxisAsTime=True, grid='both'
694 XAxisAsTime=True, grid='both'
694 )
695 )
695
696
696 self.draw()
697 self.draw()
697
698
698 if dataOut.ltctime >= self.xmax:
699 if dataOut.ltctime >= self.xmax:
699 self.counter_imagwr = wr_period
700 self.counter_imagwr = wr_period
700 self.isConfig = False
701 self.isConfig = False
701 update_figfile = True
702 update_figfile = True
702
703
703 self.save(figpath=figpath,
704 self.save(figpath=figpath,
704 figfile=figfile,
705 figfile=figfile,
705 save=save,
706 save=save,
706 ftp=ftp,
707 ftp=ftp,
707 wr_period=wr_period,
708 wr_period=wr_period,
708 thisDatetime=thisDatetime,
709 thisDatetime=thisDatetime,
709 update_figfile=update_figfile)
710 update_figfile=update_figfile)
710
711
711 return dataOut
712 return dataOut
@@ -1,1575 +1,1575
1 """
1 """
2 Created on Jul 2, 2014
2 Created on Jul 2, 2014
3
3
4 @author: roj-idl71
4 @author: roj-idl71
5 """
5 """
6 import os
6 import os
7 import sys
7 import sys
8 import glob
8 import glob
9 import time
9 import time
10 import numpy
10 import numpy
11 import fnmatch
11 import fnmatch
12 import inspect
12 import inspect
13 import time
13 import time
14 import datetime
14 import datetime
15 import zmq
15 import zmq
16
16
17 from schainpy.model.proc.jroproc_base import Operation, MPDecorator
17 from schainpy.model.proc.jroproc_base import Operation, MPDecorator
18 from schainpy.model.data.jroheaderIO import PROCFLAG, BasicHeader, SystemHeader, RadarControllerHeader, ProcessingHeader
18 from schainpy.model.data.jroheaderIO import PROCFLAG, BasicHeader, SystemHeader, RadarControllerHeader, ProcessingHeader
19 from schainpy.model.data.jroheaderIO import get_dtype_index, get_numpy_dtype, get_procflag_dtype, get_dtype_width
19 from schainpy.model.data.jroheaderIO import get_dtype_index, get_numpy_dtype, get_procflag_dtype, get_dtype_width
20 from schainpy.utils import log
20 from schainpy.utils import log
21 import schainpy.admin
21 import schainpy.admin
22
22
23 LOCALTIME = True
23 LOCALTIME = True
24 DT_DIRECTIVES = {
24 DT_DIRECTIVES = {
25 '%Y': 4,
25 '%Y': 4,
26 '%y': 2,
26 '%y': 2,
27 '%m': 2,
27 '%m': 2,
28 '%d': 2,
28 '%d': 2,
29 '%j': 3,
29 '%j': 3,
30 '%H': 2,
30 '%H': 2,
31 '%M': 2,
31 '%M': 2,
32 '%S': 2,
32 '%S': 2,
33 '%f': 6
33 '%f': 6
34 }
34 }
35
35
36
36
37 def isNumber(cad):
37 def isNumber(cad):
38 """
38 """
39 Chequea si el conjunto de caracteres que componen un string puede ser convertidos a un numero.
39 Chequea si el conjunto de caracteres que componen un string puede ser convertidos a un numero.
40
40
41 Excepciones:
41 Excepciones:
42 Si un determinado string no puede ser convertido a numero
42 Si un determinado string no puede ser convertido a numero
43 Input:
43 Input:
44 str, string al cual se le analiza para determinar si convertible a un numero o no
44 str, string al cual se le analiza para determinar si convertible a un numero o no
45
45
46 Return:
46 Return:
47 True : si el string es uno numerico
47 True : si el string es uno numerico
48 False : no es un string numerico
48 False : no es un string numerico
49 """
49 """
50 try:
50 try:
51 float(cad)
51 float(cad)
52 return True
52 return True
53 except:
53 except:
54 return False
54 return False
55
55
56
56
57 def isFileInEpoch(filename, startUTSeconds, endUTSeconds):
57 def isFileInEpoch(filename, startUTSeconds, endUTSeconds):
58 """
58 """
59 Esta funcion determina si un archivo de datos se encuentra o no dentro del rango de fecha especificado.
59 Esta funcion determina si un archivo de datos se encuentra o no dentro del rango de fecha especificado.
60
60
61 Inputs:
61 Inputs:
62 filename : nombre completo del archivo de datos en formato Jicamarca (.r)
62 filename : nombre completo del archivo de datos en formato Jicamarca (.r)
63
63
64 startUTSeconds : fecha inicial del rango seleccionado. La fecha esta dada en
64 startUTSeconds : fecha inicial del rango seleccionado. La fecha esta dada en
65 segundos contados desde 01/01/1970.
65 segundos contados desde 01/01/1970.
66 endUTSeconds : fecha final del rango seleccionado. La fecha esta dada en
66 endUTSeconds : fecha final del rango seleccionado. La fecha esta dada en
67 segundos contados desde 01/01/1970.
67 segundos contados desde 01/01/1970.
68
68
69 Return:
69 Return:
70 Boolean : Retorna True si el archivo de datos contiene datos en el rango de
70 Boolean : Retorna True si el archivo de datos contiene datos en el rango de
71 fecha especificado, de lo contrario retorna False.
71 fecha especificado, de lo contrario retorna False.
72
72
73 Excepciones:
73 Excepciones:
74 Si el archivo no existe o no puede ser abierto
74 Si el archivo no existe o no puede ser abierto
75 Si la cabecera no puede ser leida.
75 Si la cabecera no puede ser leida.
76
76
77 """
77 """
78 basicHeaderObj = BasicHeader(LOCALTIME)
78 basicHeaderObj = BasicHeader(LOCALTIME)
79
79
80 try:
80 try:
81 fp = open(filename, 'rb')
81 fp = open(filename, 'rb')
82 except IOError:
82 except IOError:
83 print("The file %s can't be opened" % (filename))
83 print("The file %s can't be opened" % (filename))
84 return 0
84 return 0
85
85
86 sts = basicHeaderObj.read(fp)
86 sts = basicHeaderObj.read(fp)
87 fp.close()
87 fp.close()
88
88
89 if not(sts):
89 if not(sts):
90 print("Skipping the file %s because it has not a valid header" % (filename))
90 print("Skipping the file %s because it has not a valid header" % (filename))
91 return 0
91 return 0
92
92
93 if not ((startUTSeconds <= basicHeaderObj.utc) and (endUTSeconds > basicHeaderObj.utc)):
93 if not ((startUTSeconds <= basicHeaderObj.utc) and (endUTSeconds > basicHeaderObj.utc)):
94 return 0
94 return 0
95
95
96 return 1
96 return 1
97
97
98
98
99 def isTimeInRange(thisTime, startTime, endTime):
99 def isTimeInRange(thisTime, startTime, endTime):
100 if endTime >= startTime:
100 if endTime >= startTime:
101 if (thisTime < startTime) or (thisTime > endTime):
101 if (thisTime < startTime) or (thisTime > endTime):
102 return 0
102 return 0
103 return 1
103 return 1
104 else:
104 else:
105 if (thisTime < startTime) and (thisTime > endTime):
105 if (thisTime < startTime) and (thisTime > endTime):
106 return 0
106 return 0
107 return 1
107 return 1
108
108
109
109
110 def isFileInTimeRange(filename, startDate, endDate, startTime, endTime):
110 def isFileInTimeRange(filename, startDate, endDate, startTime, endTime):
111 """
111 """
112 Retorna 1 si el archivo de datos se encuentra dentro del rango de horas especificado.
112 Retorna 1 si el archivo de datos se encuentra dentro del rango de horas especificado.
113
113
114 Inputs:
114 Inputs:
115 filename : nombre completo del archivo de datos en formato Jicamarca (.r)
115 filename : nombre completo del archivo de datos en formato Jicamarca (.r)
116
116
117 startDate : fecha inicial del rango seleccionado en formato datetime.date
117 startDate : fecha inicial del rango seleccionado en formato datetime.date
118
118
119 endDate : fecha final del rango seleccionado en formato datetime.date
119 endDate : fecha final del rango seleccionado en formato datetime.date
120
120
121 startTime : tiempo inicial del rango seleccionado en formato datetime.time
121 startTime : tiempo inicial del rango seleccionado en formato datetime.time
122
122
123 endTime : tiempo final del rango seleccionado en formato datetime.time
123 endTime : tiempo final del rango seleccionado en formato datetime.time
124
124
125 Return:
125 Return:
126 Boolean : Retorna True si el archivo de datos contiene datos en el rango de
126 Boolean : Retorna True si el archivo de datos contiene datos en el rango de
127 fecha especificado, de lo contrario retorna False.
127 fecha especificado, de lo contrario retorna False.
128
128
129 Excepciones:
129 Excepciones:
130 Si el archivo no existe o no puede ser abierto
130 Si el archivo no existe o no puede ser abierto
131 Si la cabecera no puede ser leida.
131 Si la cabecera no puede ser leida.
132
132
133 """
133 """
134
134
135 try:
135 try:
136 fp = open(filename, 'rb')
136 fp = open(filename, 'rb')
137 except IOError:
137 except IOError:
138 print("The file %s can't be opened" % (filename))
138 print("The file %s can't be opened" % (filename))
139 return None
139 return None
140
140
141 firstBasicHeaderObj = BasicHeader(LOCALTIME)
141 firstBasicHeaderObj = BasicHeader(LOCALTIME)
142 systemHeaderObj = SystemHeader()
142 systemHeaderObj = SystemHeader()
143 radarControllerHeaderObj = RadarControllerHeader()
143 radarControllerHeaderObj = RadarControllerHeader()
144 processingHeaderObj = ProcessingHeader()
144 processingHeaderObj = ProcessingHeader()
145
145
146 lastBasicHeaderObj = BasicHeader(LOCALTIME)
146 lastBasicHeaderObj = BasicHeader(LOCALTIME)
147
147
148 sts = firstBasicHeaderObj.read(fp)
148 sts = firstBasicHeaderObj.read(fp)
149
149
150 if not(sts):
150 if not(sts):
151 print("[Reading] Skipping the file %s because it has not a valid header" % (filename))
151 print("[Reading] Skipping the file %s because it has not a valid header" % (filename))
152 return None
152 return None
153
153
154 if not systemHeaderObj.read(fp):
154 if not systemHeaderObj.read(fp):
155 return None
155 return None
156
156
157 if not radarControllerHeaderObj.read(fp):
157 if not radarControllerHeaderObj.read(fp):
158 return None
158 return None
159
159
160 if not processingHeaderObj.read(fp):
160 if not processingHeaderObj.read(fp):
161 return None
161 return None
162
162
163 filesize = os.path.getsize(filename)
163 filesize = os.path.getsize(filename)
164
164
165 offset = processingHeaderObj.blockSize + 24 # header size
165 offset = processingHeaderObj.blockSize + 24 # header size
166
166
167 if filesize <= offset:
167 if filesize <= offset:
168 print("[Reading] %s: This file has not enough data" % filename)
168 print("[Reading] %s: This file has not enough data" % filename)
169 return None
169 return None
170
170
171 fp.seek(-offset, 2)
171 fp.seek(-offset, 2)
172
172
173 sts = lastBasicHeaderObj.read(fp)
173 sts = lastBasicHeaderObj.read(fp)
174
174
175 fp.close()
175 fp.close()
176
176
177 thisDatetime = lastBasicHeaderObj.datatime
177 thisDatetime = lastBasicHeaderObj.datatime
178 thisTime_last_block = thisDatetime.time()
178 thisTime_last_block = thisDatetime.time()
179
179
180 thisDatetime = firstBasicHeaderObj.datatime
180 thisDatetime = firstBasicHeaderObj.datatime
181 thisDate = thisDatetime.date()
181 thisDate = thisDatetime.date()
182 thisTime_first_block = thisDatetime.time()
182 thisTime_first_block = thisDatetime.time()
183
183
184 # General case
184 # General case
185 # o>>>>>>>>>>>>>><<<<<<<<<<<<<<o
185 # o>>>>>>>>>>>>>><<<<<<<<<<<<<<o
186 #-----------o----------------------------o-----------
186 #-----------o----------------------------o-----------
187 # startTime endTime
187 # startTime endTime
188
188
189 if endTime >= startTime:
189 if endTime >= startTime:
190 if (thisTime_last_block < startTime) or (thisTime_first_block > endTime):
190 if (thisTime_last_block < startTime) or (thisTime_first_block > endTime):
191 return None
191 return None
192
192
193 return thisDatetime
193 return thisDatetime
194
194
195 # If endTime < startTime then endTime belongs to the next day
195 # If endTime < startTime then endTime belongs to the next day
196
196
197 #<<<<<<<<<<<o o>>>>>>>>>>>
197 #<<<<<<<<<<<o o>>>>>>>>>>>
198 #-----------o----------------------------o-----------
198 #-----------o----------------------------o-----------
199 # endTime startTime
199 # endTime startTime
200
200
201 if (thisDate == startDate) and (thisTime_last_block < startTime):
201 if (thisDate == startDate) and (thisTime_last_block < startTime):
202 return None
202 return None
203
203
204 if (thisDate == endDate) and (thisTime_first_block > endTime):
204 if (thisDate == endDate) and (thisTime_first_block > endTime):
205 return None
205 return None
206
206
207 if (thisTime_last_block < startTime) and (thisTime_first_block > endTime):
207 if (thisTime_last_block < startTime) and (thisTime_first_block > endTime):
208 return None
208 return None
209
209
210 return thisDatetime
210 return thisDatetime
211
211
212
212
213 def isFolderInDateRange(folder, startDate=None, endDate=None):
213 def isFolderInDateRange(folder, startDate=None, endDate=None):
214 """
214 """
215 Retorna 1 si el archivo de datos se encuentra dentro del rango de horas especificado.
215 Retorna 1 si el archivo de datos se encuentra dentro del rango de horas especificado.
216
216
217 Inputs:
217 Inputs:
218 folder : nombre completo del directorio.
218 folder : nombre completo del directorio.
219 Su formato deberia ser "/path_root/?YYYYDDD"
219 Su formato deberia ser "/path_root/?YYYYDDD"
220
220
221 siendo:
221 siendo:
222 YYYY : Anio (ejemplo 2015)
222 YYYY : Anio (ejemplo 2015)
223 DDD : Dia del anio (ejemplo 305)
223 DDD : Dia del anio (ejemplo 305)
224
224
225 startDate : fecha inicial del rango seleccionado en formato datetime.date
225 startDate : fecha inicial del rango seleccionado en formato datetime.date
226
226
227 endDate : fecha final del rango seleccionado en formato datetime.date
227 endDate : fecha final del rango seleccionado en formato datetime.date
228
228
229 Return:
229 Return:
230 Boolean : Retorna True si el archivo de datos contiene datos en el rango de
230 Boolean : Retorna True si el archivo de datos contiene datos en el rango de
231 fecha especificado, de lo contrario retorna False.
231 fecha especificado, de lo contrario retorna False.
232 Excepciones:
232 Excepciones:
233 Si el directorio no tiene el formato adecuado
233 Si el directorio no tiene el formato adecuado
234 """
234 """
235
235
236 basename = os.path.basename(folder)
236 basename = os.path.basename(folder)
237
237
238 if not isRadarFolder(basename):
238 if not isRadarFolder(basename):
239 print("The folder %s has not the rigth format" % folder)
239 print("The folder %s has not the rigth format" % folder)
240 return 0
240 return 0
241
241
242 if startDate and endDate:
242 if startDate and endDate:
243 thisDate = getDateFromRadarFolder(basename)
243 thisDate = getDateFromRadarFolder(basename)
244
244
245 if thisDate < startDate:
245 if thisDate < startDate:
246 return 0
246 return 0
247
247
248 if thisDate > endDate:
248 if thisDate > endDate:
249 return 0
249 return 0
250
250
251 return 1
251 return 1
252
252
253
253
254 def isFileInDateRange(filename, startDate=None, endDate=None):
254 def isFileInDateRange(filename, startDate=None, endDate=None):
255 """
255 """
256 Retorna 1 si el archivo de datos se encuentra dentro del rango de horas especificado.
256 Retorna 1 si el archivo de datos se encuentra dentro del rango de horas especificado.
257
257
258 Inputs:
258 Inputs:
259 filename : nombre completo del archivo de datos en formato Jicamarca (.r)
259 filename : nombre completo del archivo de datos en formato Jicamarca (.r)
260
260
261 Su formato deberia ser "?YYYYDDDsss"
261 Su formato deberia ser "?YYYYDDDsss"
262
262
263 siendo:
263 siendo:
264 YYYY : Anio (ejemplo 2015)
264 YYYY : Anio (ejemplo 2015)
265 DDD : Dia del anio (ejemplo 305)
265 DDD : Dia del anio (ejemplo 305)
266 sss : set
266 sss : set
267
267
268 startDate : fecha inicial del rango seleccionado en formato datetime.date
268 startDate : fecha inicial del rango seleccionado en formato datetime.date
269
269
270 endDate : fecha final del rango seleccionado en formato datetime.date
270 endDate : fecha final del rango seleccionado en formato datetime.date
271
271
272 Return:
272 Return:
273 Boolean : Retorna True si el archivo de datos contiene datos en el rango de
273 Boolean : Retorna True si el archivo de datos contiene datos en el rango de
274 fecha especificado, de lo contrario retorna False.
274 fecha especificado, de lo contrario retorna False.
275 Excepciones:
275 Excepciones:
276 Si el archivo no tiene el formato adecuado
276 Si el archivo no tiene el formato adecuado
277 """
277 """
278
278
279 basename = os.path.basename(filename)
279 basename = os.path.basename(filename)
280
280
281 if not isRadarFile(basename):
281 if not isRadarFile(basename):
282 print("The filename %s has not the rigth format" % filename)
282 print("The filename %s has not the rigth format" % filename)
283 return 0
283 return 0
284
284
285 if startDate and endDate:
285 if startDate and endDate:
286 thisDate = getDateFromRadarFile(basename)
286 thisDate = getDateFromRadarFile(basename)
287
287
288 if thisDate < startDate:
288 if thisDate < startDate:
289 return 0
289 return 0
290
290
291 if thisDate > endDate:
291 if thisDate > endDate:
292 return 0
292 return 0
293
293
294 return 1
294 return 1
295
295
296
296
297 def getFileFromSet(path, ext, set):
297 def getFileFromSet(path, ext, set):
298 validFilelist = []
298 validFilelist = []
299 fileList = os.listdir(path)
299 fileList = os.listdir(path)
300
300
301 # 0 1234 567 89A BCDE
301 # 0 1234 567 89A BCDE
302 # H YYYY DDD SSS .ext
302 # H YYYY DDD SSS .ext
303
303
304 for thisFile in fileList:
304 for thisFile in fileList:
305 try:
305 try:
306 year = int(thisFile[1:5])
306 year = int(thisFile[1:5])
307 doy = int(thisFile[5:8])
307 doy = int(thisFile[5:8])
308 except:
308 except:
309 continue
309 continue
310
310
311 if (os.path.splitext(thisFile)[-1].lower() != ext.lower()):
311 if (os.path.splitext(thisFile)[-1].lower() != ext.lower()):
312 continue
312 continue
313
313
314 validFilelist.append(thisFile)
314 validFilelist.append(thisFile)
315
315
316 myfile = fnmatch.filter(
316 myfile = fnmatch.filter(
317 validFilelist, '*%4.4d%3.3d%3.3d*' % (year, doy, set))
317 validFilelist, '*%4.4d%3.3d%3.3d*' % (year, doy, set))
318
318
319 if len(myfile) != 0:
319 if len(myfile) != 0:
320 return myfile[0]
320 return myfile[0]
321 else:
321 else:
322 filename = '*%4.4d%3.3d%3.3d%s' % (year, doy, set, ext.lower())
322 filename = '*%4.4d%3.3d%3.3d%s' % (year, doy, set, ext.lower())
323 print('the filename %s does not exist' % filename)
323 print('the filename %s does not exist' % filename)
324 print('...going to the last file: ')
324 print('...going to the last file: ')
325
325
326 if validFilelist:
326 if validFilelist:
327 validFilelist = sorted(validFilelist, key=str.lower)
327 validFilelist = sorted(validFilelist, key=str.lower)
328 return validFilelist[-1]
328 return validFilelist[-1]
329
329
330 return None
330 return None
331
331
332
332
333 def getlastFileFromPath(path, ext):
333 def getlastFileFromPath(path, ext):
334 """
334 """
335 Depura el fileList dejando solo los que cumplan el formato de "PYYYYDDDSSS.ext"
335 Depura el fileList dejando solo los que cumplan el formato de "PYYYYDDDSSS.ext"
336 al final de la depuracion devuelve el ultimo file de la lista que quedo.
336 al final de la depuracion devuelve el ultimo file de la lista que quedo.
337
337
338 Input:
338 Input:
339 fileList : lista conteniendo todos los files (sin path) que componen una determinada carpeta
339 fileList : lista conteniendo todos los files (sin path) que componen una determinada carpeta
340 ext : extension de los files contenidos en una carpeta
340 ext : extension de los files contenidos en una carpeta
341
341
342 Return:
342 Return:
343 El ultimo file de una determinada carpeta, no se considera el path.
343 El ultimo file de una determinada carpeta, no se considera el path.
344 """
344 """
345 validFilelist = []
345 validFilelist = []
346 fileList = os.listdir(path)
346 fileList = os.listdir(path)
347
347
348 # 0 1234 567 89A BCDE
348 # 0 1234 567 89A BCDE
349 # H YYYY DDD SSS .ext
349 # H YYYY DDD SSS .ext
350
350
351 for thisFile in fileList:
351 for thisFile in fileList:
352
352
353 year = thisFile[1:5]
353 year = thisFile[1:5]
354 if not isNumber(year):
354 if not isNumber(year):
355 continue
355 continue
356
356
357 doy = thisFile[5:8]
357 doy = thisFile[5:8]
358 if not isNumber(doy):
358 if not isNumber(doy):
359 continue
359 continue
360
360
361 year = int(year)
361 year = int(year)
362 doy = int(doy)
362 doy = int(doy)
363
363
364 if (os.path.splitext(thisFile)[-1].lower() != ext.lower()):
364 if (os.path.splitext(thisFile)[-1].lower() != ext.lower()):
365 continue
365 continue
366
366
367 validFilelist.append(thisFile)
367 validFilelist.append(thisFile)
368
368
369 if validFilelist:
369 if validFilelist:
370 validFilelist = sorted(validFilelist, key=str.lower)
370 validFilelist = sorted(validFilelist, key=str.lower)
371 return validFilelist[-1]
371 return validFilelist[-1]
372
372
373 return None
373 return None
374
374
375
375
376 def isRadarFolder(folder):
376 def isRadarFolder(folder):
377 try:
377 try:
378 year = int(folder[1:5])
378 year = int(folder[1:5])
379 doy = int(folder[5:8])
379 doy = int(folder[5:8])
380 except:
380 except:
381 return 0
381 return 0
382
382
383 return 1
383 return 1
384
384
385
385
386 def isRadarFile(file):
386 def isRadarFile(file):
387 try:
387 try:
388 year = int(file[1:5])
388 year = int(file[1:5])
389 doy = int(file[5:8])
389 doy = int(file[5:8])
390 set = int(file[8:11])
390 set = int(file[8:11])
391 except:
391 except:
392 return 0
392 return 0
393
393
394 return 1
394 return 1
395
395
396
396
397 def getDateFromRadarFile(file):
397 def getDateFromRadarFile(file):
398 try:
398 try:
399 year = int(file[1:5])
399 year = int(file[1:5])
400 doy = int(file[5:8])
400 doy = int(file[5:8])
401 set = int(file[8:11])
401 set = int(file[8:11])
402 except:
402 except:
403 return None
403 return None
404
404
405 thisDate = datetime.date(year, 1, 1) + datetime.timedelta(doy - 1)
405 thisDate = datetime.date(year, 1, 1) + datetime.timedelta(doy - 1)
406 return thisDate
406 return thisDate
407
407
408
408
409 def getDateFromRadarFolder(folder):
409 def getDateFromRadarFolder(folder):
410 try:
410 try:
411 year = int(folder[1:5])
411 year = int(folder[1:5])
412 doy = int(folder[5:8])
412 doy = int(folder[5:8])
413 except:
413 except:
414 return None
414 return None
415
415
416 thisDate = datetime.date(year, 1, 1) + datetime.timedelta(doy - 1)
416 thisDate = datetime.date(year, 1, 1) + datetime.timedelta(doy - 1)
417 return thisDate
417 return thisDate
418
418
419 def parse_format(s, fmt):
419 def parse_format(s, fmt):
420
420
421 for i in range(fmt.count('%')):
421 for i in range(fmt.count('%')):
422 x = fmt.index('%')
422 x = fmt.index('%')
423 d = DT_DIRECTIVES[fmt[x:x+2]]
423 d = DT_DIRECTIVES[fmt[x:x+2]]
424 fmt = fmt.replace(fmt[x:x+2], s[x:x+d])
424 fmt = fmt.replace(fmt[x:x+2], s[x:x+d])
425 return fmt
425 return fmt
426
426
427 class Reader(object):
427 class Reader(object):
428
428
429 c = 3E8
429 c = 3E8
430 isConfig = False
430 isConfig = False
431 dtype = None
431 dtype = None
432 pathList = []
432 pathList = []
433 filenameList = []
433 filenameList = []
434 datetimeList = []
434 datetimeList = []
435 filename = None
435 filename = None
436 ext = None
436 ext = None
437 flagIsNewFile = 1
437 flagIsNewFile = 1
438 flagDiscontinuousBlock = 0
438 flagDiscontinuousBlock = 0
439 flagIsNewBlock = 0
439 flagIsNewBlock = 0
440 flagNoMoreFiles = 0
440 flagNoMoreFiles = 0
441 fp = None
441 fp = None
442 firstHeaderSize = 0
442 firstHeaderSize = 0
443 basicHeaderSize = 24
443 basicHeaderSize = 24
444 versionFile = 1103
444 versionFile = 1103
445 fileSize = None
445 fileSize = None
446 fileSizeByHeader = None
446 fileSizeByHeader = None
447 fileIndex = -1
447 fileIndex = -1
448 profileIndex = None
448 profileIndex = None
449 blockIndex = 0
449 blockIndex = 0
450 nTotalBlocks = 0
450 nTotalBlocks = 0
451 maxTimeStep = 30
451 maxTimeStep = 30
452 lastUTTime = None
452 lastUTTime = None
453 datablock = None
453 datablock = None
454 dataOut = None
454 dataOut = None
455 getByBlock = False
455 getByBlock = False
456 path = None
456 path = None
457 startDate = None
457 startDate = None
458 endDate = None
458 endDate = None
459 startTime = datetime.time(0, 0, 0)
459 startTime = datetime.time(0, 0, 0)
460 endTime = datetime.time(23, 59, 59)
460 endTime = datetime.time(23, 59, 59)
461 set = None
461 set = None
462 expLabel = ""
462 expLabel = ""
463 online = False
463 online = False
464 delay = 60
464 delay = 60
465 nTries = 3 # quantity tries
465 nTries = 3 # quantity tries
466 nFiles = 3 # number of files for searching
466 nFiles = 3 # number of files for searching
467 walk = True
467 walk = True
468 getblock = False
468 getblock = False
469 nTxs = 1
469 nTxs = 1
470 realtime = False
470 realtime = False
471 blocksize = 0
471 blocksize = 0
472 blocktime = None
472 blocktime = None
473 warnings = True
473 warnings = True
474 verbose = True
474 verbose = True
475 server = None
475 server = None
476 format = None
476 format = None
477 oneDDict = None
477 oneDDict = None
478 twoDDict = None
478 twoDDict = None
479 independentParam = None
479 independentParam = None
480 filefmt = None
480 filefmt = None
481 folderfmt = None
481 folderfmt = None
482 open_file = open
482 open_file = open
483 open_mode = 'rb'
483 open_mode = 'rb'
484
484
485 def run(self):
485 def run(self):
486
486
487 raise NotImplementedError
487 raise NotImplementedError
488
488
489 def getAllowedArgs(self):
489 def getAllowedArgs(self):
490 if hasattr(self, '__attrs__'):
490 if hasattr(self, '__attrs__'):
491 return self.__attrs__
491 return self.__attrs__
492 else:
492 else:
493 return inspect.getargspec(self.run).args
493 return inspect.getargspec(self.run).args
494
494
495 def set_kwargs(self, **kwargs):
495 def set_kwargs(self, **kwargs):
496
496
497 for key, value in kwargs.items():
497 for key, value in kwargs.items():
498 setattr(self, key, value)
498 setattr(self, key, value)
499
499
500 def find_folders(self, path, startDate, endDate, folderfmt, last=False):
500 def find_folders(self, path, startDate, endDate, folderfmt, last=False):
501
501
502 folders = [x for f in path.split(',')
502 folders = [x for f in path.split(',')
503 for x in os.listdir(f) if os.path.isdir(os.path.join(f, x))]
503 for x in os.listdir(f) if os.path.isdir(os.path.join(f, x))]
504 folders.sort()
504 folders.sort()
505
505
506 if last:
506 if last:
507 folders = [folders[-1]]
507 folders = [folders[-1]]
508
508
509 for folder in folders:
509 for folder in folders:
510 try:
510 try:
511 dt = datetime.datetime.strptime(parse_format(folder, folderfmt), folderfmt).date()
511 dt = datetime.datetime.strptime(parse_format(folder, folderfmt), folderfmt).date()
512 if dt >= startDate and dt <= endDate:
512 if dt >= startDate and dt <= endDate:
513 yield os.path.join(path, folder)
513 yield os.path.join(path, folder)
514 else:
514 else:
515 log.log('Skiping folder {}'.format(folder), self.name)
515 log.log('Skiping folder {}'.format(folder), self.name)
516 except Exception as e:
516 except Exception as e:
517 log.log('Skiping folder {}'.format(folder), self.name)
517 log.log('Skiping folder {}'.format(folder), self.name)
518 continue
518 continue
519 return
519 return
520
520
521 def find_files(self, folders, ext, filefmt, startDate=None, endDate=None,
521 def find_files(self, folders, ext, filefmt, startDate=None, endDate=None,
522 expLabel='', last=False):
522 expLabel='', last=False):
523
523
524 for path in folders:
524 for path in folders:
525 files = glob.glob1(path, '*{}'.format(ext))
525 files = glob.glob1(path, '*{}'.format(ext))
526 files.sort()
526 files.sort()
527 if last:
527 if last:
528 if files:
528 if files:
529 fo = files[-1]
529 fo = files[-1]
530 try:
530 try:
531 dt = datetime.datetime.strptime(parse_format(fo, filefmt), filefmt).date()
531 dt = datetime.datetime.strptime(parse_format(fo, filefmt), filefmt).date()
532 yield os.path.join(path, expLabel, fo)
532 yield os.path.join(path, expLabel, fo)
533 except Exception as e:
533 except Exception as e:
534 pass
534 pass
535 return
535 return
536 else:
536 else:
537 return
537 return
538
538
539 for fo in files:
539 for fo in files:
540 try:
540 try:
541 dt = datetime.datetime.strptime(parse_format(fo, filefmt), filefmt).date()
541 dt = datetime.datetime.strptime(parse_format(fo, filefmt), filefmt).date()
542 if dt >= startDate and dt <= endDate:
542 if dt >= startDate and dt <= endDate:
543 yield os.path.join(path, expLabel, fo)
543 yield os.path.join(path, expLabel, fo)
544 else:
544 else:
545 log.log('Skiping file {}'.format(fo), self.name)
545 log.log('Skiping file {}'.format(fo), self.name)
546 except Exception as e:
546 except Exception as e:
547 log.log('Skiping file {}'.format(fo), self.name)
547 log.log('Skiping file {}'.format(fo), self.name)
548 continue
548 continue
549
549
550 def searchFilesOffLine(self, path, startDate, endDate,
550 def searchFilesOffLine(self, path, startDate, endDate,
551 expLabel, ext, walk,
551 expLabel, ext, walk,
552 filefmt, folderfmt):
552 filefmt, folderfmt):
553 """Search files in offline mode for the given arguments
553 """Search files in offline mode for the given arguments
554
554
555 Return:
555 Return:
556 Generator of files
556 Generator of files
557 """
557 """
558
558
559 if walk:
559 if walk:
560 folders = self.find_folders(
560 folders = self.find_folders(
561 path, startDate, endDate, folderfmt)
561 path, startDate, endDate, folderfmt)
562 else:
562 else:
563 folders = path.split(',')
563 folders = path.split(',')
564
564
565 return self.find_files(
565 return self.find_files(
566 folders, ext, filefmt, startDate, endDate, expLabel)
566 folders, ext, filefmt, startDate, endDate, expLabel)
567
567
568 def searchFilesOnLine(self, path, startDate, endDate,
568 def searchFilesOnLine(self, path, startDate, endDate,
569 expLabel, ext, walk,
569 expLabel, ext, walk,
570 filefmt, folderfmt):
570 filefmt, folderfmt):
571 """Search for the last file of the last folder
571 """Search for the last file of the last folder
572
572
573 Arguments:
573 Arguments:
574 path : carpeta donde estan contenidos los files que contiene data
574 path : carpeta donde estan contenidos los files que contiene data
575 expLabel : Nombre del subexperimento (subfolder)
575 expLabel : Nombre del subexperimento (subfolder)
576 ext : extension de los files
576 ext : extension de los files
577 walk : Si es habilitado no realiza busquedas dentro de los ubdirectorios (doypath)
577 walk : Si es habilitado no realiza busquedas dentro de los ubdirectorios (doypath)
578
578
579 Return:
579 Return:
580 generator with the full path of last filename
580 generator with the full path of last filename
581 """
581 """
582
582
583 if walk:
583 if walk:
584 folders = self.find_folders(
584 folders = self.find_folders(
585 path, startDate, endDate, folderfmt, last=True)
585 path, startDate, endDate, folderfmt, last=True)
586 else:
586 else:
587 folders = path.split(',')
587 folders = path.split(',')
588
588
589 return self.find_files(
589 return self.find_files(
590 folders, ext, filefmt, startDate, endDate, expLabel, last=True)
590 folders, ext, filefmt, startDate, endDate, expLabel, last=True)
591
591
592 def setNextFile(self):
592 def setNextFile(self):
593 """Set the next file to be readed open it and parse de file header"""
593 """Set the next file to be readed open it and parse de file header"""
594
594
595 while True:
595 while True:
596 if self.fp != None:
596 if self.fp != None:
597 self.fp.close()
597 self.fp.close()
598
598
599 if self.online:
599 if self.online:
600 newFile = self.setNextFileOnline()
600 newFile = self.setNextFileOnline()
601 else:
601 else:
602 newFile = self.setNextFileOffline()
602 newFile = self.setNextFileOffline()
603
603
604 if not(newFile):
604 if not(newFile):
605 if self.online:
605 if self.online:
606 raise schainpy.admin.SchainError('Time to wait for new files reach')
606 raise schainpy.admin.SchainError('Time to wait for new files reach')
607 else:
607 else:
608 if self.fileIndex == -1:
608 if self.fileIndex == -1:
609 raise schainpy.admin.SchainWarning('No files found in the given path')
609 raise schainpy.admin.SchainWarning('No files found in the given path')
610 else:
610 else:
611 raise schainpy.admin.SchainWarning('No more files to read')
611 raise schainpy.admin.SchainWarning('No more files to read')
612
612
613 if self.verifyFile(self.filename):
613 if self.verifyFile(self.filename):
614 break
614 break
615
615
616 log.log('Opening file: %s' % self.filename, self.name)
616 log.log('Opening file: %s' % self.filename, self.name)
617
617
618 self.readFirstHeader()
618 self.readFirstHeader()
619 self.nReadBlocks = 0
619 self.nReadBlocks = 0
620
620
621 def setNextFileOnline(self):
621 def setNextFileOnline(self):
622 """Check for the next file to be readed in online mode.
622 """Check for the next file to be readed in online mode.
623
623
624 Set:
624 Set:
625 self.filename
625 self.filename
626 self.fp
626 self.fp
627 self.filesize
627 self.filesize
628
628
629 Return:
629 Return:
630 boolean
630 boolean
631
631
632 """
632 """
633 nextFile = True
633 nextFile = True
634 nextDay = False
634 nextDay = False
635
635
636 for nFiles in range(self.nFiles+1):
636 for nFiles in range(self.nFiles+1):
637 for nTries in range(self.nTries):
637 for nTries in range(self.nTries):
638 fullfilename, filename = self.checkForRealPath(nextFile, nextDay)
638 fullfilename, filename = self.checkForRealPath(nextFile, nextDay)
639 if fullfilename is not None:
639 if fullfilename is not None:
640 break
640 break
641 log.warning(
641 log.warning(
642 "Waiting %0.2f sec for the next file: \"%s\" , try %02d ..." % (self.delay, filename, nTries + 1),
642 "Waiting %0.2f sec for the next file: \"%s\" , try %02d ..." % (self.delay, filename, nTries + 1),
643 self.name)
643 self.name)
644 time.sleep(self.delay)
644 time.sleep(self.delay)
645 nextFile = False
645 nextFile = False
646 continue
646 continue
647
647
648 if fullfilename is not None:
648 if fullfilename is not None:
649 break
649 break
650
650
651 self.nTries = 1
651 self.nTries = 1
652 nextFile = True
652 nextFile = True
653
653
654 if nFiles == (self.nFiles - 1):
654 if nFiles == (self.nFiles - 1):
655 log.log('Trying with next day...', self.name)
655 log.log('Trying with next day...', self.name)
656 nextDay = True
656 nextDay = True
657 self.nTries = 3
657 self.nTries = 3
658
658
659 if fullfilename:
659 if fullfilename:
660 self.fileSize = os.path.getsize(fullfilename)
660 self.fileSize = os.path.getsize(fullfilename)
661 self.filename = fullfilename
661 self.filename = fullfilename
662 self.flagIsNewFile = 1
662 self.flagIsNewFile = 1
663 if self.fp != None:
663 if self.fp != None:
664 self.fp.close()
664 self.fp.close()
665 self.fp = self.open_file(fullfilename, self.open_mode)
665 self.fp = self.open_file(fullfilename, self.open_mode)
666 self.flagNoMoreFiles = 0
666 self.flagNoMoreFiles = 0
667 self.fileIndex += 1
667 self.fileIndex += 1
668 return 1
668 return 1
669 else:
669 else:
670 return 0
670 return 0
671
671
672 def setNextFileOffline(self):
672 def setNextFileOffline(self):
673 """Open the next file to be readed in offline mode"""
673 """Open the next file to be readed in offline mode"""
674
674
675 try:
675 try:
676 filename = next(self.filenameList)
676 filename = next(self.filenameList)
677 self.fileIndex +=1
677 self.fileIndex +=1
678 except StopIteration:
678 except StopIteration:
679 self.flagNoMoreFiles = 1
679 self.flagNoMoreFiles = 1
680 return 0
680 return 0
681
681
682 self.filename = filename
682 self.filename = filename
683 self.fileSize = os.path.getsize(filename)
683 self.fileSize = os.path.getsize(filename)
684 self.fp = self.open_file(filename, self.open_mode)
684 self.fp = self.open_file(filename, self.open_mode)
685 self.flagIsNewFile = 1
685 self.flagIsNewFile = 1
686
686
687 return 1
687 return 1
688
688
689 @staticmethod
689 @staticmethod
690 def isDateTimeInRange(dt, startDate, endDate, startTime, endTime):
690 def isDateTimeInRange(dt, startDate, endDate, startTime, endTime):
691 """Check if the given datetime is in range"""
691 """Check if the given datetime is in range"""
692 startDateTime= datetime.datetime.combine(startDate,startTime)
692 startDateTime= datetime.datetime.combine(startDate,startTime)
693 endDateTime = datetime.datetime.combine(endDate,endTime)
693 endDateTime = datetime.datetime.combine(endDate,endTime)
694 if startDateTime <= dt <= endDateTime:
694 if startDateTime <= dt <= endDateTime:
695 return True
695 return True
696 return False
696 return False
697
697
698 def verifyFile(self, filename):
698 def verifyFile(self, filename):
699 """Check for a valid file
699 """Check for a valid file
700
700
701 Arguments:
701 Arguments:
702 filename -- full path filename
702 filename -- full path filename
703
703
704 Return:
704 Return:
705 boolean
705 boolean
706 """
706 """
707
707
708 return True
708 return True
709
709
710 def checkForRealPath(self, nextFile, nextDay):
710 def checkForRealPath(self, nextFile, nextDay):
711 """Check if the next file to be readed exists"""
711 """Check if the next file to be readed exists"""
712
712
713 raise NotImplementedError
713 raise NotImplementedError
714
714
715 def readFirstHeader(self):
715 def readFirstHeader(self):
716 """Parse the file header"""
716 """Parse the file header"""
717
717
718 pass
718 pass
719
719
720 def waitDataBlock(self, pointer_location, blocksize=None):
720 def waitDataBlock(self, pointer_location, blocksize=None):
721 """
721 """
722 """
722 """
723
723
724 currentPointer = pointer_location
724 currentPointer = pointer_location
725 if blocksize is None:
725 if blocksize is None:
726 neededSize = self.processingHeaderObj.blockSize # + self.basicHeaderSize
726 neededSize = self.processingHeaderObj.blockSize # + self.basicHeaderSize
727 else:
727 else:
728 neededSize = blocksize
728 neededSize = blocksize
729
729
730 for nTries in range(self.nTries):
730 for nTries in range(self.nTries):
731 self.fp.close()
731 self.fp.close()
732 self.fp = open(self.filename, 'rb')
732 self.fp = open(self.filename, 'rb')
733 self.fp.seek(currentPointer)
733 self.fp.seek(currentPointer)
734
734
735 self.fileSize = os.path.getsize(self.filename)
735 self.fileSize = os.path.getsize(self.filename)
736 currentSize = self.fileSize - currentPointer
736 currentSize = self.fileSize - currentPointer
737
737
738 if (currentSize >= neededSize):
738 if (currentSize >= neededSize):
739 return 1
739 return 1
740
740
741 log.warning(
741 log.warning(
742 "Waiting %0.2f seconds for the next block, try %03d ..." % (self.delay, nTries + 1),
742 "Waiting %0.2f seconds for the next block, try %03d ..." % (self.delay, nTries + 1),
743 self.name
743 self.name
744 )
744 )
745 time.sleep(self.delay)
745 time.sleep(self.delay)
746
746
747 return 0
747 return 0
748
748
749 class JRODataReader(Reader):
749 class JRODataReader(Reader):
750
750
751 utc = 0
751 utc = 0
752 nReadBlocks = 0
752 nReadBlocks = 0
753 foldercounter = 0
753 foldercounter = 0
754 firstHeaderSize = 0
754 firstHeaderSize = 0
755 basicHeaderSize = 24
755 basicHeaderSize = 24
756 __isFirstTimeOnline = 1
756 __isFirstTimeOnline = 1
757 filefmt = "*%Y%j***"
757 filefmt = "*%Y%j***"
758 folderfmt = "*%Y%j"
758 folderfmt = "*%Y%j"
759 __attrs__ = ['path', 'startDate', 'endDate', 'startTime', 'endTime', 'online', 'delay', 'walk']
759 __attrs__ = ['path', 'startDate', 'endDate', 'startTime', 'endTime', 'online', 'delay', 'walk']
760
760
761 def getDtypeWidth(self):
761 def getDtypeWidth(self):
762
762
763 dtype_index = get_dtype_index(self.dtype)
763 dtype_index = get_dtype_index(self.dtype)
764 dtype_width = get_dtype_width(dtype_index)
764 dtype_width = get_dtype_width(dtype_index)
765
765
766 return dtype_width
766 return dtype_width
767
767
768 def checkForRealPath(self, nextFile, nextDay):
768 def checkForRealPath(self, nextFile, nextDay):
769 """Check if the next file to be readed exists.
769 """Check if the next file to be readed exists.
770
770
771 Example :
771 Example :
772 nombre correcto del file es .../.../D2009307/P2009307367.ext
772 nombre correcto del file es .../.../D2009307/P2009307367.ext
773
773
774 Entonces la funcion prueba con las siguientes combinaciones
774 Entonces la funcion prueba con las siguientes combinaciones
775 .../.../y2009307367.ext
775 .../.../y2009307367.ext
776 .../.../Y2009307367.ext
776 .../.../Y2009307367.ext
777 .../.../x2009307/y2009307367.ext
777 .../.../x2009307/y2009307367.ext
778 .../.../x2009307/Y2009307367.ext
778 .../.../x2009307/Y2009307367.ext
779 .../.../X2009307/y2009307367.ext
779 .../.../X2009307/y2009307367.ext
780 .../.../X2009307/Y2009307367.ext
780 .../.../X2009307/Y2009307367.ext
781 siendo para este caso, la ultima combinacion de letras, identica al file buscado
781 siendo para este caso, la ultima combinacion de letras, identica al file buscado
782
782
783 Return:
783 Return:
784 str -- fullpath of the file
784 str -- fullpath of the file
785 """
785 """
786
786
787
787
788 if nextFile:
788 if nextFile:
789 self.set += 1
789 self.set += 1
790 if nextDay:
790 if nextDay:
791 self.set = 0
791 self.set = 0
792 self.doy += 1
792 self.doy += 1
793 foldercounter = 0
793 foldercounter = 0
794 prefixDirList = [None, 'd', 'D']
794 prefixDirList = [None, 'd', 'D']
795 if self.ext.lower() == ".r": # voltage
795 if self.ext.lower() == ".r": # voltage
796 prefixFileList = ['d', 'D']
796 prefixFileList = ['d', 'D']
797 elif self.ext.lower() == ".pdata": # spectra
797 elif self.ext.lower() == ".pdata": # spectra
798 prefixFileList = ['p', 'P']
798 prefixFileList = ['p', 'P']
799
799
800 # barrido por las combinaciones posibles
800 # barrido por las combinaciones posibles
801 for prefixDir in prefixDirList:
801 for prefixDir in prefixDirList:
802 thispath = self.path
802 thispath = self.path
803 if prefixDir != None:
803 if prefixDir != None:
804 # formo el nombre del directorio xYYYYDDD (x=d o x=D)
804 # formo el nombre del directorio xYYYYDDD (x=d o x=D)
805 if foldercounter == 0:
805 if foldercounter == 0:
806 thispath = os.path.join(self.path, "%s%04d%03d" %
806 thispath = os.path.join(self.path, "%s%04d%03d" %
807 (prefixDir, self.year, self.doy))
807 (prefixDir, self.year, self.doy))
808 else:
808 else:
809 thispath = os.path.join(self.path, "%s%04d%03d_%02d" % (
809 thispath = os.path.join(self.path, "%s%04d%03d_%02d" % (
810 prefixDir, self.year, self.doy, foldercounter))
810 prefixDir, self.year, self.doy, foldercounter))
811 for prefixFile in prefixFileList: # barrido por las dos combinaciones posibles de "D"
811 for prefixFile in prefixFileList: # barrido por las dos combinaciones posibles de "D"
812 # formo el nombre del file xYYYYDDDSSS.ext
812 # formo el nombre del file xYYYYDDDSSS.ext
813 filename = "%s%04d%03d%03d%s" % (prefixFile, self.year, self.doy, self.set, self.ext)
813 filename = "%s%04d%03d%03d%s" % (prefixFile, self.year, self.doy, self.set, self.ext)
814 fullfilename = os.path.join(
814 fullfilename = os.path.join(
815 thispath, filename)
815 thispath, filename)
816
816
817 if os.path.exists(fullfilename):
817 if os.path.exists(fullfilename):
818 return fullfilename, filename
818 return fullfilename, filename
819
819
820 return None, filename
820 return None, filename
821
821
822 def __waitNewBlock(self):
822 def __waitNewBlock(self):
823 """
823 """
824 Return 1 si se encontro un nuevo bloque de datos, 0 de otra forma.
824 Return 1 si se encontro un nuevo bloque de datos, 0 de otra forma.
825
825
826 Si el modo de lectura es OffLine siempre retorn 0
826 Si el modo de lectura es OffLine siempre retorn 0
827 """
827 """
828 if not self.online:
828 if not self.online:
829 return 0
829 return 0
830
830
831 if (self.nReadBlocks >= self.processingHeaderObj.dataBlocksPerFile):
831 if (self.nReadBlocks >= self.processingHeaderObj.dataBlocksPerFile):
832 return 0
832 return 0
833
833
834 currentPointer = self.fp.tell()
834 currentPointer = self.fp.tell()
835
835
836 neededSize = self.processingHeaderObj.blockSize + self.basicHeaderSize
836 neededSize = self.processingHeaderObj.blockSize + self.basicHeaderSize
837
837
838 for nTries in range(self.nTries):
838 for nTries in range(self.nTries):
839
839
840 self.fp.close()
840 self.fp.close()
841 self.fp = open(self.filename, 'rb')
841 self.fp = open(self.filename, 'rb')
842 self.fp.seek(currentPointer)
842 self.fp.seek(currentPointer)
843
843
844 self.fileSize = os.path.getsize(self.filename)
844 self.fileSize = os.path.getsize(self.filename)
845 currentSize = self.fileSize - currentPointer
845 currentSize = self.fileSize - currentPointer
846
846
847 if (currentSize >= neededSize):
847 if (currentSize >= neededSize):
848 self.basicHeaderObj.read(self.fp)
848 self.basicHeaderObj.read(self.fp)
849 return 1
849 return 1
850
850
851 if self.fileSize == self.fileSizeByHeader:
851 if self.fileSize == self.fileSizeByHeader:
852 # self.flagEoF = True
852 # self.flagEoF = True
853 return 0
853 return 0
854
854
855 print("[Reading] Waiting %0.2f seconds for the next block, try %03d ..." % (self.delay, nTries + 1))
855 print("[Reading] Waiting %0.2f seconds for the next block, try %03d ..." % (self.delay, nTries + 1))
856 time.sleep(self.delay)
856 time.sleep(self.delay)
857
857
858 return 0
858 return 0
859
859
860 def __setNewBlock(self):
860 def __setNewBlock(self):
861
861
862 if self.fp == None:
862 if self.fp == None:
863 return 0
863 return 0
864
864
865 if self.flagIsNewFile:
865 if self.flagIsNewFile:
866 self.lastUTTime = self.basicHeaderObj.utc
866 self.lastUTTime = self.basicHeaderObj.utc
867 return 1
867 return 1
868
868
869 if self.realtime:
869 if self.realtime:
870 self.flagDiscontinuousBlock = 1
870 self.flagDiscontinuousBlock = 1
871 if not(self.setNextFile()):
871 if not(self.setNextFile()):
872 return 0
872 return 0
873 else:
873 else:
874 return 1
874 return 1
875
875
876 currentSize = self.fileSize - self.fp.tell()
876 currentSize = self.fileSize - self.fp.tell()
877 neededSize = self.processingHeaderObj.blockSize + self.basicHeaderSize
877 neededSize = self.processingHeaderObj.blockSize + self.basicHeaderSize
878
878
879 if (currentSize >= neededSize):
879 if (currentSize >= neededSize):
880 self.basicHeaderObj.read(self.fp)
880 self.basicHeaderObj.read(self.fp)
881 self.lastUTTime = self.basicHeaderObj.utc
881 self.lastUTTime = self.basicHeaderObj.utc
882 return 1
882 return 1
883
883
884 if self.__waitNewBlock():
884 if self.__waitNewBlock():
885 self.lastUTTime = self.basicHeaderObj.utc
885 self.lastUTTime = self.basicHeaderObj.utc
886 return 1
886 return 1
887
887
888 if not(self.setNextFile()):
888 if not(self.setNextFile()):
889 return 0
889 return 0
890
890
891 deltaTime = self.basicHeaderObj.utc - self.lastUTTime
891 deltaTime = self.basicHeaderObj.utc - self.lastUTTime
892 self.lastUTTime = self.basicHeaderObj.utc
892 self.lastUTTime = self.basicHeaderObj.utc
893
893
894 self.flagDiscontinuousBlock = 0
894 self.flagDiscontinuousBlock = 0
895
895
896 if deltaTime > self.maxTimeStep:
896 if deltaTime > self.maxTimeStep:
897 self.flagDiscontinuousBlock = 1
897 self.flagDiscontinuousBlock = 1
898
898
899 return 1
899 return 1
900
900
901 def readNextBlock(self):
901 def readNextBlock(self):
902
902
903 while True:
903 while True:
904 if not(self.__setNewBlock()):
904 if not(self.__setNewBlock()):
905 continue
905 continue
906
906
907 if not(self.readBlock()):
907 if not(self.readBlock()):
908 return 0
908 return 0
909
909
910 self.getBasicHeader()
910 self.getBasicHeader()
911
911
912 if not self.isDateTimeInRange(self.dataOut.datatime, self.startDate, self.endDate, self.startTime, self.endTime):
912 if not self.isDateTimeInRange(self.dataOut.datatime, self.startDate, self.endDate, self.startTime, self.endTime):
913 print("[Reading] Block No. %d/%d -> %s [Skipping]" % (self.nReadBlocks,
913 print("[Reading] Block No. %d/%d -> %s [Skipping]" % (self.nReadBlocks,
914 self.processingHeaderObj.dataBlocksPerFile,
914 self.processingHeaderObj.dataBlocksPerFile,
915 self.dataOut.datatime.ctime()))
915 self.dataOut.datatime.ctime()))
916 continue
916 continue
917
917
918 break
918 break
919
919
920 if self.verbose:
920 if self.verbose:
921 print("[Reading] Block No. %d/%d -> %s" % (self.nReadBlocks,
921 print("[Reading] Block No. %d/%d -> %s" % (self.nReadBlocks,
922 self.processingHeaderObj.dataBlocksPerFile,
922 self.processingHeaderObj.dataBlocksPerFile,
923 self.dataOut.datatime.ctime()))
923 self.dataOut.datatime.ctime()))
924 return 1
924 return 1
925
925
926 def readFirstHeader(self):
926 def readFirstHeader(self):
927
927
928 self.basicHeaderObj.read(self.fp)
928 self.basicHeaderObj.read(self.fp)
929 self.systemHeaderObj.read(self.fp)
929 self.systemHeaderObj.read(self.fp)
930 self.radarControllerHeaderObj.read(self.fp)
930 self.radarControllerHeaderObj.read(self.fp)
931 self.processingHeaderObj.read(self.fp)
931 self.processingHeaderObj.read(self.fp)
932 self.firstHeaderSize = self.basicHeaderObj.size
932 self.firstHeaderSize = self.basicHeaderObj.size
933
933
934 datatype = int(numpy.log2((self.processingHeaderObj.processFlags &
934 datatype = int(numpy.log2((self.processingHeaderObj.processFlags &
935 PROCFLAG.DATATYPE_MASK)) - numpy.log2(PROCFLAG.DATATYPE_CHAR))
935 PROCFLAG.DATATYPE_MASK)) - numpy.log2(PROCFLAG.DATATYPE_CHAR))
936 if datatype == 0:
936 if datatype == 0:
937 datatype_str = numpy.dtype([('real', '<i1'), ('imag', '<i1')])
937 datatype_str = numpy.dtype([('real', '<i1'), ('imag', '<i1')])
938 elif datatype == 1:
938 elif datatype == 1:
939 datatype_str = numpy.dtype([('real', '<i2'), ('imag', '<i2')])
939 datatype_str = numpy.dtype([('real', '<i2'), ('imag', '<i2')])
940 elif datatype == 2:
940 elif datatype == 2:
941 datatype_str = numpy.dtype([('real', '<i4'), ('imag', '<i4')])
941 datatype_str = numpy.dtype([('real', '<i4'), ('imag', '<i4')])
942 elif datatype == 3:
942 elif datatype == 3:
943 datatype_str = numpy.dtype([('real', '<i8'), ('imag', '<i8')])
943 datatype_str = numpy.dtype([('real', '<i8'), ('imag', '<i8')])
944 elif datatype == 4:
944 elif datatype == 4:
945 datatype_str = numpy.dtype([('real', '<f4'), ('imag', '<f4')])
945 datatype_str = numpy.dtype([('real', '<f4'), ('imag', '<f4')])
946 elif datatype == 5:
946 elif datatype == 5:
947 datatype_str = numpy.dtype([('real', '<f8'), ('imag', '<f8')])
947 datatype_str = numpy.dtype([('real', '<f8'), ('imag', '<f8')])
948 else:
948 else:
949 raise ValueError('Data type was not defined')
949 raise ValueError('Data type was not defined')
950
950
951 self.dtype = datatype_str
951 self.dtype = datatype_str
952 #self.ippSeconds = 2 * 1000 * self.radarControllerHeaderObj.ipp / self.c
952 #self.ippSeconds = 2 * 1000 * self.radarControllerHeaderObj.ipp / self.c
953 self.fileSizeByHeader = self.processingHeaderObj.dataBlocksPerFile * self.processingHeaderObj.blockSize + \
953 self.fileSizeByHeader = self.processingHeaderObj.dataBlocksPerFile * self.processingHeaderObj.blockSize + \
954 self.firstHeaderSize + self.basicHeaderSize * \
954 self.firstHeaderSize + self.basicHeaderSize * \
955 (self.processingHeaderObj.dataBlocksPerFile - 1)
955 (self.processingHeaderObj.dataBlocksPerFile - 1)
956 # self.dataOut.channelList = numpy.arange(self.systemHeaderObj.numChannels)
956 # self.dataOut.channelList = numpy.arange(self.systemHeaderObj.numChannels)
957 # self.dataOut.channelIndexList = numpy.arange(self.systemHeaderObj.numChannels)
957 # self.dataOut.channelIndexList = numpy.arange(self.systemHeaderObj.numChannels)
958 self.getBlockDimension()
958 self.getBlockDimension()
959
959
960 def verifyFile(self, filename):
960 def verifyFile(self, filename):
961
961
962 flag = True
962 flag = True
963
963
964 try:
964 try:
965 fp = open(filename, 'rb')
965 fp = open(filename, 'rb')
966 except IOError:
966 except IOError:
967 log.error("File {} can't be opened".format(filename), self.name)
967 log.error("File {} can't be opened".format(filename), self.name)
968 return False
968 return False
969
969
970 if self.online and self.waitDataBlock(0):
970 if self.online and self.waitDataBlock(0):
971 pass
971 pass
972
972
973 basicHeaderObj = BasicHeader(LOCALTIME)
973 basicHeaderObj = BasicHeader(LOCALTIME)
974 systemHeaderObj = SystemHeader()
974 systemHeaderObj = SystemHeader()
975 radarControllerHeaderObj = RadarControllerHeader()
975 radarControllerHeaderObj = RadarControllerHeader()
976 processingHeaderObj = ProcessingHeader()
976 processingHeaderObj = ProcessingHeader()
977
977
978 if not(basicHeaderObj.read(fp)):
978 if not(basicHeaderObj.read(fp)):
979 flag = False
979 flag = False
980 if not(systemHeaderObj.read(fp)):
980 if not(systemHeaderObj.read(fp)):
981 flag = False
981 flag = False
982 if not(radarControllerHeaderObj.read(fp)):
982 if not(radarControllerHeaderObj.read(fp)):
983 flag = False
983 flag = False
984 if not(processingHeaderObj.read(fp)):
984 if not(processingHeaderObj.read(fp)):
985 flag = False
985 flag = False
986 if not self.online:
986 if not self.online:
987 dt1 = basicHeaderObj.datatime
987 dt1 = basicHeaderObj.datatime
988 pos = self.fileSize-processingHeaderObj.blockSize-24
988 pos = self.fileSize-processingHeaderObj.blockSize-24
989 if pos<0:
989 if pos<0:
990 flag = False
990 flag = False
991 log.error('Invalid size for file: {}'.format(self.filename), self.name)
991 log.error('Invalid size for file: {}'.format(self.filename), self.name)
992 else:
992 else:
993 fp.seek(pos)
993 fp.seek(pos)
994 if not(basicHeaderObj.read(fp)):
994 if not(basicHeaderObj.read(fp)):
995 flag = False
995 flag = False
996 dt2 = basicHeaderObj.datatime
996 dt2 = basicHeaderObj.datatime
997 if not self.isDateTimeInRange(dt1, self.startDate, self.endDate, self.startTime, self.endTime) and not \
997 if not self.isDateTimeInRange(dt1, self.startDate, self.endDate, self.startTime, self.endTime) and not \
998 self.isDateTimeInRange(dt2, self.startDate, self.endDate, self.startTime, self.endTime):
998 self.isDateTimeInRange(dt2, self.startDate, self.endDate, self.startTime, self.endTime):
999 flag = False
999 flag = False
1000
1000
1001 fp.close()
1001 fp.close()
1002 return flag
1002 return flag
1003
1003
1004 def findDatafiles(self, path, startDate=None, endDate=None, expLabel='', ext='.r', walk=True, include_path=False):
1004 def findDatafiles(self, path, startDate=None, endDate=None, expLabel='', ext='.r', walk=True, include_path=False):
1005
1005
1006 path_empty = True
1006 path_empty = True
1007
1007
1008 dateList = []
1008 dateList = []
1009 pathList = []
1009 pathList = []
1010
1010
1011 multi_path = path.split(',')
1011 multi_path = path.split(',')
1012
1012
1013 if not walk:
1013 if not walk:
1014
1014
1015 for single_path in multi_path:
1015 for single_path in multi_path:
1016
1016
1017 if not os.path.isdir(single_path):
1017 if not os.path.isdir(single_path):
1018 continue
1018 continue
1019
1019
1020 fileList = glob.glob1(single_path, "*" + ext)
1020 fileList = glob.glob1(single_path, "*" + ext)
1021
1021
1022 if not fileList:
1022 if not fileList:
1023 continue
1023 continue
1024
1024
1025 path_empty = False
1025 path_empty = False
1026
1026
1027 fileList.sort()
1027 fileList.sort()
1028
1028
1029 for thisFile in fileList:
1029 for thisFile in fileList:
1030
1030
1031 if not os.path.isfile(os.path.join(single_path, thisFile)):
1031 if not os.path.isfile(os.path.join(single_path, thisFile)):
1032 continue
1032 continue
1033
1033
1034 if not isRadarFile(thisFile):
1034 if not isRadarFile(thisFile):
1035 continue
1035 continue
1036
1036
1037 if not isFileInDateRange(thisFile, startDate, endDate):
1037 if not isFileInDateRange(thisFile, startDate, endDate):
1038 continue
1038 continue
1039
1039
1040 thisDate = getDateFromRadarFile(thisFile)
1040 thisDate = getDateFromRadarFile(thisFile)
1041
1041
1042 if thisDate in dateList or single_path in pathList:
1042 if thisDate in dateList or single_path in pathList:
1043 continue
1043 continue
1044
1044
1045 dateList.append(thisDate)
1045 dateList.append(thisDate)
1046 pathList.append(single_path)
1046 pathList.append(single_path)
1047
1047
1048 else:
1048 else:
1049 for single_path in multi_path:
1049 for single_path in multi_path:
1050
1050
1051 if not os.path.isdir(single_path):
1051 if not os.path.isdir(single_path):
1052 continue
1052 continue
1053
1053
1054 dirList = []
1054 dirList = []
1055
1055
1056 for thisPath in os.listdir(single_path):
1056 for thisPath in os.listdir(single_path):
1057
1057
1058 if not os.path.isdir(os.path.join(single_path, thisPath)):
1058 if not os.path.isdir(os.path.join(single_path, thisPath)):
1059 continue
1059 continue
1060
1060
1061 if not isRadarFolder(thisPath):
1061 if not isRadarFolder(thisPath):
1062 continue
1062 continue
1063
1063
1064 if not isFolderInDateRange(thisPath, startDate, endDate):
1064 if not isFolderInDateRange(thisPath, startDate, endDate):
1065 continue
1065 continue
1066
1066
1067 dirList.append(thisPath)
1067 dirList.append(thisPath)
1068
1068
1069 if not dirList:
1069 if not dirList:
1070 continue
1070 continue
1071
1071
1072 dirList.sort()
1072 dirList.sort()
1073
1073
1074 for thisDir in dirList:
1074 for thisDir in dirList:
1075
1075
1076 datapath = os.path.join(single_path, thisDir, expLabel)
1076 datapath = os.path.join(single_path, thisDir, expLabel)
1077 fileList = glob.glob1(datapath, "*" + ext)
1077 fileList = glob.glob1(datapath, "*" + ext)
1078
1078
1079 if not fileList:
1079 if not fileList:
1080 continue
1080 continue
1081
1081
1082 path_empty = False
1082 path_empty = False
1083
1083
1084 thisDate = getDateFromRadarFolder(thisDir)
1084 thisDate = getDateFromRadarFolder(thisDir)
1085
1085
1086 pathList.append(datapath)
1086 pathList.append(datapath)
1087 dateList.append(thisDate)
1087 dateList.append(thisDate)
1088
1088
1089 dateList.sort()
1089 dateList.sort()
1090
1090
1091 if walk:
1091 if walk:
1092 pattern_path = os.path.join(multi_path[0], "[dYYYYDDD]", expLabel)
1092 pattern_path = os.path.join(multi_path[0], "[dYYYYDDD]", expLabel)
1093 else:
1093 else:
1094 pattern_path = multi_path[0]
1094 pattern_path = multi_path[0]
1095
1095
1096 if path_empty:
1096 if path_empty:
1097 raise schainpy.admin.SchainError("[Reading] No *%s files in %s for %s to %s" % (ext, pattern_path, startDate, endDate))
1097 raise schainpy.admin.SchainError("[Reading] No *%s files in %s for %s to %s" % (ext, pattern_path, startDate, endDate))
1098 else:
1098 else:
1099 if not dateList:
1099 if not dateList:
1100 raise schainpy.admin.SchainError("[Reading] Date range selected invalid [%s - %s]: No *%s files in %s)" % (startDate, endDate, ext, path))
1100 raise schainpy.admin.SchainError("[Reading] Date range selected invalid [%s - %s]: No *%s files in %s)" % (startDate, endDate, ext, path))
1101
1101
1102 if include_path:
1102 if include_path:
1103 return dateList, pathList
1103 return dateList, pathList
1104
1104
1105 return dateList
1105 return dateList
1106
1106
1107 def setup(self, **kwargs):
1107 def setup(self, **kwargs):
1108
1108
1109 self.set_kwargs(**kwargs)
1109 self.set_kwargs(**kwargs)
1110 if not self.ext.startswith('.'):
1110 if not self.ext.startswith('.'):
1111 self.ext = '.{}'.format(self.ext)
1111 self.ext = '.{}'.format(self.ext)
1112
1112
1113 if self.server is not None:
1113 if self.server is not None:
1114 if 'tcp://' in self.server:
1114 if 'tcp://' in self.server:
1115 address = server
1115 address = server
1116 else:
1116 else:
1117 address = 'ipc:///tmp/%s' % self.server
1117 address = 'ipc:///tmp/%s' % self.server
1118 self.server = address
1118 self.server = address
1119 self.context = zmq.Context()
1119 self.context = zmq.Context()
1120 self.receiver = self.context.socket(zmq.PULL)
1120 self.receiver = self.context.socket(zmq.PULL)
1121 self.receiver.connect(self.server)
1121 self.receiver.connect(self.server)
1122 time.sleep(0.5)
1122 time.sleep(0.5)
1123 print('[Starting] ReceiverData from {}'.format(self.server))
1123 print('[Starting] ReceiverData from {}'.format(self.server))
1124 else:
1124 else:
1125 self.server = None
1125 self.server = None
1126 if self.path == None:
1126 if self.path == None:
1127 raise ValueError("[Reading] The path is not valid")
1127 raise ValueError("[Reading] The path is not valid")
1128
1128
1129 if self.online:
1129 if self.online:
1130 log.log("[Reading] Searching files in online mode...", self.name)
1130 log.log("[Reading] Searching files in online mode...", self.name)
1131
1131
1132 for nTries in range(self.nTries):
1132 for nTries in range(self.nTries):
1133 fullpath = self.searchFilesOnLine(self.path, self.startDate,
1133 fullpath = self.searchFilesOnLine(self.path, self.startDate,
1134 self.endDate, self.expLabel, self.ext, self.walk,
1134 self.endDate, self.expLabel, self.ext, self.walk,
1135 self.filefmt, self.folderfmt)
1135 self.filefmt, self.folderfmt)
1136
1136
1137 try:
1137 try:
1138 fullpath = next(fullpath)
1138 fullpath = next(fullpath)
1139 except:
1139 except:
1140 fullpath = None
1140 fullpath = None
1141
1141
1142 if fullpath:
1142 if fullpath:
1143 break
1143 break
1144
1144
1145 log.warning(
1145 log.warning(
1146 'Waiting {} sec for a valid file in {}: try {} ...'.format(
1146 'Waiting {} sec for a valid file in {}: try {} ...'.format(
1147 self.delay, self.path, nTries + 1),
1147 self.delay, self.path, nTries + 1),
1148 self.name)
1148 self.name)
1149 time.sleep(self.delay)
1149 time.sleep(self.delay)
1150
1150
1151 if not(fullpath):
1151 if not(fullpath):
1152 raise schainpy.admin.SchainError(
1152 raise schainpy.admin.SchainError(
1153 'There isn\'t any valid file in {}'.format(self.path))
1153 'There isn\'t any valid file in {}'.format(self.path))
1154
1154
1155 pathname, filename = os.path.split(fullpath)
1155 pathname, filename = os.path.split(fullpath)
1156 self.year = int(filename[1:5])
1156 self.year = int(filename[1:5])
1157 self.doy = int(filename[5:8])
1157 self.doy = int(filename[5:8])
1158 self.set = int(filename[8:11]) - 1
1158 self.set = int(filename[8:11]) - 1
1159 else:
1159 else:
1160 log.log("Searching files in {}".format(self.path), self.name)
1160 log.log("Searching files in {}".format(self.path), self.name)
1161 self.filenameList = self.searchFilesOffLine(self.path, self.startDate,
1161 self.filenameList = self.searchFilesOffLine(self.path, self.startDate,
1162 self.endDate, self.expLabel, self.ext, self.walk, self.filefmt, self.folderfmt)
1162 self.endDate, self.expLabel, self.ext, self.walk, self.filefmt, self.folderfmt)
1163
1163
1164 self.setNextFile()
1164 self.setNextFile()
1165
1165
1166 return
1166 return
1167
1167
1168 def getBasicHeader(self):
1168 def getBasicHeader(self):
1169
1169
1170 self.dataOut.utctime = self.basicHeaderObj.utc + self.basicHeaderObj.miliSecond / \
1170 self.dataOut.utctime = self.basicHeaderObj.utc + self.basicHeaderObj.miliSecond / \
1171 1000. + self.profileIndex * self.radarControllerHeaderObj.ippSeconds
1171 1000. + self.profileIndex * self.radarControllerHeaderObj.ippSeconds
1172
1172
1173 self.dataOut.flagDiscontinuousBlock = self.flagDiscontinuousBlock
1173 self.dataOut.flagDiscontinuousBlock = self.flagDiscontinuousBlock
1174
1174
1175 self.dataOut.timeZone = self.basicHeaderObj.timeZone
1175 self.dataOut.timeZone = self.basicHeaderObj.timeZone
1176
1176
1177 self.dataOut.dstFlag = self.basicHeaderObj.dstFlag
1177 self.dataOut.dstFlag = self.basicHeaderObj.dstFlag
1178
1178
1179 self.dataOut.errorCount = self.basicHeaderObj.errorCount
1179 self.dataOut.errorCount = self.basicHeaderObj.errorCount
1180
1180
1181 self.dataOut.useLocalTime = self.basicHeaderObj.useLocalTime
1181 self.dataOut.useLocalTime = self.basicHeaderObj.useLocalTime
1182
1182
1183 self.dataOut.ippSeconds = self.radarControllerHeaderObj.ippSeconds / self.nTxs
1183 self.dataOut.ippSeconds = self.radarControllerHeaderObj.ippSeconds / self.nTxs
1184
1184
1185 def getFirstHeader(self):
1185 def getFirstHeader(self):
1186
1186
1187 raise NotImplementedError
1187 raise NotImplementedError
1188
1188
1189 def getData(self):
1189 def getData(self):
1190
1190
1191 raise NotImplementedError
1191 raise NotImplementedError
1192
1192
1193 def hasNotDataInBuffer(self):
1193 def hasNotDataInBuffer(self):
1194
1194
1195 raise NotImplementedError
1195 raise NotImplementedError
1196
1196
1197 def readBlock(self):
1197 def readBlock(self):
1198
1198
1199 raise NotImplementedError
1199 raise NotImplementedError
1200
1200
1201 def isEndProcess(self):
1201 def isEndProcess(self):
1202
1202
1203 return self.flagNoMoreFiles
1203 return self.flagNoMoreFiles
1204
1204
1205 def printReadBlocks(self):
1205 def printReadBlocks(self):
1206
1206
1207 print("[Reading] Number of read blocks per file %04d" % self.nReadBlocks)
1207 print("[Reading] Number of read blocks per file %04d" % self.nReadBlocks)
1208
1208
1209 def printTotalBlocks(self):
1209 def printTotalBlocks(self):
1210
1210
1211 print("[Reading] Number of read blocks %04d" % self.nTotalBlocks)
1211 print("[Reading] Number of read blocks %04d" % self.nTotalBlocks)
1212
1212
1213 def run(self, **kwargs):
1213 def run(self, **kwargs):
1214 """
1214 """
1215
1215
1216 Arguments:
1216 Arguments:
1217 path :
1217 path :
1218 startDate :
1218 startDate :
1219 endDate :
1219 endDate :
1220 startTime :
1220 startTime :
1221 endTime :
1221 endTime :
1222 set :
1222 set :
1223 expLabel :
1223 expLabel :
1224 ext :
1224 ext :
1225 online :
1225 online :
1226 delay :
1226 delay :
1227 walk :
1227 walk :
1228 getblock :
1228 getblock :
1229 nTxs :
1229 nTxs :
1230 realtime :
1230 realtime :
1231 blocksize :
1231 blocksize :
1232 blocktime :
1232 blocktime :
1233 skip :
1233 skip :
1234 cursor :
1234 cursor :
1235 warnings :
1235 warnings :
1236 server :
1236 server :
1237 verbose :
1237 verbose :
1238 format :
1238 format :
1239 oneDDict :
1239 oneDDict :
1240 twoDDict :
1240 twoDDict :
1241 independentParam :
1241 independentParam :
1242 """
1242 """
1243
1243
1244 if not(self.isConfig):
1244 if not(self.isConfig):
1245 self.setup(**kwargs)
1245 self.setup(**kwargs)
1246 self.isConfig = True
1246 self.isConfig = True
1247 if self.server is None:
1247 if self.server is None:
1248 self.getData()
1248 self.getData()
1249 else:
1249 else:
1250 self.getFromServer()
1250 self.getFromServer()
1251
1251
1252
1252
1253 class JRODataWriter(Reader):
1253 class JRODataWriter(Reader):
1254
1254
1255 """
1255 """
1256 Esta clase permite escribir datos a archivos procesados (.r o ,pdata). La escritura
1256 Esta clase permite escribir datos a archivos procesados (.r o ,pdata). La escritura
1257 de los datos siempre se realiza por bloques.
1257 de los datos siempre se realiza por bloques.
1258 """
1258 """
1259
1259
1260 setFile = None
1260 setFile = None
1261 profilesPerBlock = None
1261 profilesPerBlock = None
1262 blocksPerFile = None
1262 blocksPerFile = None
1263 nWriteBlocks = 0
1263 nWriteBlocks = 0
1264 fileDate = None
1264 fileDate = None
1265
1265
1266 def __init__(self, dataOut=None):
1266 def __init__(self, dataOut=None):
1267 raise NotImplementedError
1267 raise NotImplementedError
1268
1268
1269 def hasAllDataInBuffer(self):
1269 def hasAllDataInBuffer(self):
1270 raise NotImplementedError
1270 raise NotImplementedError
1271
1271
1272 def setBlockDimension(self):
1272 def setBlockDimension(self):
1273 raise NotImplementedError
1273 raise NotImplementedError
1274
1274
1275 def writeBlock(self):
1275 def writeBlock(self):
1276 raise NotImplementedError
1276 raise NotImplementedError
1277
1277
1278 def putData(self):
1278 def putData(self):
1279 raise NotImplementedError
1279 raise NotImplementedError
1280
1280
1281 def getDtypeWidth(self):
1281 def getDtypeWidth(self):
1282
1282
1283 dtype_index = get_dtype_index(self.dtype)
1283 dtype_index = get_dtype_index(self.dtype)
1284 dtype_width = get_dtype_width(dtype_index)
1284 dtype_width = get_dtype_width(dtype_index)
1285
1285
1286 return dtype_width
1286 return dtype_width
1287
1287
1288 def getProcessFlags(self):
1288 def getProcessFlags(self):
1289
1289
1290 processFlags = 0
1290 processFlags = 0
1291
1291
1292 dtype_index = get_dtype_index(self.dtype)
1292 dtype_index = get_dtype_index(self.dtype)
1293 procflag_dtype = get_procflag_dtype(dtype_index)
1293 procflag_dtype = get_procflag_dtype(dtype_index)
1294
1294
1295 processFlags += procflag_dtype
1295 processFlags += procflag_dtype
1296
1296
1297 if self.dataOut.flagDecodeData:
1297 if self.dataOut.flagDecodeData:
1298 processFlags += PROCFLAG.DECODE_DATA
1298 processFlags += PROCFLAG.DECODE_DATA
1299
1299
1300 if self.dataOut.flagDeflipData:
1300 if self.dataOut.flagDeflipData:
1301 processFlags += PROCFLAG.DEFLIP_DATA
1301 processFlags += PROCFLAG.DEFLIP_DATA
1302
1302
1303 if self.dataOut.code is not None:
1303 if self.dataOut.code is not None:
1304 processFlags += PROCFLAG.DEFINE_PROCESS_CODE
1304 processFlags += PROCFLAG.DEFINE_PROCESS_CODE
1305
1305
1306 if self.dataOut.nCohInt > 1:
1306 if self.dataOut.nCohInt > 1:
1307 processFlags += PROCFLAG.COHERENT_INTEGRATION
1307 processFlags += PROCFLAG.COHERENT_INTEGRATION
1308
1308
1309 if self.dataOut.type == "Spectra":
1309 if self.dataOut.type == "Spectra":
1310 if self.dataOut.nIncohInt > 1:
1310 if self.dataOut.nIncohInt > 1:
1311 processFlags += PROCFLAG.INCOHERENT_INTEGRATION
1311 processFlags += PROCFLAG.INCOHERENT_INTEGRATION
1312
1312
1313 if self.dataOut.data_dc is not None:
1313 if self.dataOut.data_dc is not None:
1314 processFlags += PROCFLAG.SAVE_CHANNELS_DC
1314 processFlags += PROCFLAG.SAVE_CHANNELS_DC
1315
1315
1316 if self.dataOut.flagShiftFFT:
1316 if self.dataOut.flagShiftFFT:
1317 processFlags += PROCFLAG.SHIFT_FFT_DATA
1317 processFlags += PROCFLAG.SHIFT_FFT_DATA
1318
1318
1319 return processFlags
1319 return processFlags
1320
1320
1321 def setBasicHeader(self):
1321 def setBasicHeader(self):
1322
1322
1323 self.basicHeaderObj.size = self.basicHeaderSize # bytes
1323 self.basicHeaderObj.size = self.basicHeaderSize # bytes
1324 self.basicHeaderObj.version = self.versionFile
1324 self.basicHeaderObj.version = self.versionFile
1325 self.basicHeaderObj.dataBlock = self.nTotalBlocks
1325 self.basicHeaderObj.dataBlock = self.nTotalBlocks
1326 utc = numpy.floor(self.dataOut.utctime)
1326 utc = numpy.floor(self.dataOut.utctime)
1327 milisecond = (self.dataOut.utctime - utc) * 1000.0
1327 milisecond = (self.dataOut.utctime - utc) * 1000.0
1328 self.basicHeaderObj.utc = utc
1328 self.basicHeaderObj.utc = utc
1329 self.basicHeaderObj.miliSecond = milisecond
1329 self.basicHeaderObj.miliSecond = milisecond
1330 self.basicHeaderObj.timeZone = self.dataOut.timeZone
1330 self.basicHeaderObj.timeZone = self.dataOut.timeZone
1331 self.basicHeaderObj.dstFlag = self.dataOut.dstFlag
1331 self.basicHeaderObj.dstFlag = self.dataOut.dstFlag
1332 self.basicHeaderObj.errorCount = self.dataOut.errorCount
1332 self.basicHeaderObj.errorCount = self.dataOut.errorCount
1333
1333
1334 def setFirstHeader(self):
1334 def setFirstHeader(self):
1335 """
1335 """
1336 Obtiene una copia del First Header
1336 Obtiene una copia del First Header
1337
1337
1338 Affected:
1338 Affected:
1339
1339
1340 self.basicHeaderObj
1340 self.basicHeaderObj
1341 self.systemHeaderObj
1341 self.systemHeaderObj
1342 self.radarControllerHeaderObj
1342 self.radarControllerHeaderObj
1343 self.processingHeaderObj self.
1343 self.processingHeaderObj self.
1344
1344
1345 Return:
1345 Return:
1346 None
1346 None
1347 """
1347 """
1348
1348
1349 raise NotImplementedError
1349 raise NotImplementedError
1350
1350
1351 def __writeFirstHeader(self):
1351 def __writeFirstHeader(self):
1352 """
1352 """
1353 Escribe el primer header del file es decir el Basic header y el Long header (SystemHeader, RadarControllerHeader, ProcessingHeader)
1353 Escribe el primer header del file es decir el Basic header y el Long header (SystemHeader, RadarControllerHeader, ProcessingHeader)
1354
1354
1355 Affected:
1355 Affected:
1356 __dataType
1356 __dataType
1357
1357
1358 Return:
1358 Return:
1359 None
1359 None
1360 """
1360 """
1361
1361
1362 # CALCULAR PARAMETROS
1362 # CALCULAR PARAMETROS
1363
1363
1364 sizeLongHeader = self.systemHeaderObj.size + \
1364 sizeLongHeader = self.systemHeaderObj.size + \
1365 self.radarControllerHeaderObj.size + self.processingHeaderObj.size
1365 self.radarControllerHeaderObj.size + self.processingHeaderObj.size
1366 self.basicHeaderObj.size = self.basicHeaderSize + sizeLongHeader
1366 self.basicHeaderObj.size = self.basicHeaderSize + sizeLongHeader
1367
1367
1368 self.basicHeaderObj.write(self.fp)
1368 self.basicHeaderObj.write(self.fp)
1369 self.systemHeaderObj.write(self.fp)
1369 self.systemHeaderObj.write(self.fp)
1370 self.radarControllerHeaderObj.write(self.fp)
1370 self.radarControllerHeaderObj.write(self.fp)
1371 self.processingHeaderObj.write(self.fp)
1371 self.processingHeaderObj.write(self.fp)
1372
1372
1373 def __setNewBlock(self):
1373 def __setNewBlock(self):
1374 """
1374 """
1375 Si es un nuevo file escribe el First Header caso contrario escribe solo el Basic Header
1375 Si es un nuevo file escribe el First Header caso contrario escribe solo el Basic Header
1376
1376
1377 Return:
1377 Return:
1378 0 : si no pudo escribir nada
1378 0 : si no pudo escribir nada
1379 1 : Si escribio el Basic el First Header
1379 1 : Si escribio el Basic el First Header
1380 """
1380 """
1381 if self.fp == None:
1381 if self.fp == None:
1382 self.setNextFile()
1382 self.setNextFile()
1383
1383
1384 if self.flagIsNewFile:
1384 if self.flagIsNewFile:
1385 return 1
1385 return 1
1386
1386
1387 if self.blockIndex < self.processingHeaderObj.dataBlocksPerFile:
1387 if self.blockIndex < self.processingHeaderObj.dataBlocksPerFile:
1388 self.basicHeaderObj.write(self.fp)
1388 self.basicHeaderObj.write(self.fp)
1389 return 1
1389 return 1
1390
1390
1391 if not(self.setNextFile()):
1391 if not(self.setNextFile()):
1392 return 0
1392 return 0
1393
1393
1394 return 1
1394 return 1
1395
1395
1396 def writeNextBlock(self):
1396 def writeNextBlock(self):
1397 """
1397 """
1398 Selecciona el bloque siguiente de datos y los escribe en un file
1398 Selecciona el bloque siguiente de datos y los escribe en un file
1399
1399
1400 Return:
1400 Return:
1401 0 : Si no hizo pudo escribir el bloque de datos
1401 0 : Si no hizo pudo escribir el bloque de datos
1402 1 : Si no pudo escribir el bloque de datos
1402 1 : Si no pudo escribir el bloque de datos
1403 """
1403 """
1404 if not(self.__setNewBlock()):
1404 if not(self.__setNewBlock()):
1405 return 0
1405 return 0
1406
1406
1407 self.writeBlock()
1407 self.writeBlock()
1408
1408
1409 print("[Writing] Block No. %d/%d" % (self.blockIndex,
1409 print("[Writing] Block No. %d/%d" % (self.blockIndex,
1410 self.processingHeaderObj.dataBlocksPerFile))
1410 self.processingHeaderObj.dataBlocksPerFile))
1411
1411
1412 return 1
1412 return 1
1413
1413
1414 def setNextFile(self):
1414 def setNextFile(self):
1415 """Determina el siguiente file que sera escrito
1415 """Determina el siguiente file que sera escrito
1416
1416
1417 Affected:
1417 Affected:
1418 self.filename
1418 self.filename
1419 self.subfolder
1419 self.subfolder
1420 self.fp
1420 self.fp
1421 self.setFile
1421 self.setFile
1422 self.flagIsNewFile
1422 self.flagIsNewFile
1423
1423
1424 Return:
1424 Return:
1425 0 : Si el archivo no puede ser escrito
1425 0 : Si el archivo no puede ser escrito
1426 1 : Si el archivo esta listo para ser escrito
1426 1 : Si el archivo esta listo para ser escrito
1427 """
1427 """
1428 ext = self.ext
1428 ext = self.ext
1429 path = self.path
1429 path = self.path
1430
1430
1431 if self.fp != None:
1431 if self.fp != None:
1432 self.fp.close()
1432 self.fp.close()
1433
1433
1434 if not os.path.exists(path):
1434 if not os.path.exists(path):
1435 os.mkdir(path)
1435 os.mkdir(path)
1436
1436
1437 timeTuple = time.localtime(self.dataOut.utctime)
1437 timeTuple = time.localtime(self.dataOut.utctime)
1438 subfolder = 'd%4.4d%3.3d' % (timeTuple.tm_year, timeTuple.tm_yday)
1438 subfolder = 'd%4.4d%3.3d' % (timeTuple.tm_year, timeTuple.tm_yday)
1439
1439
1440 fullpath = os.path.join(path, subfolder)
1440 fullpath = os.path.join(path, subfolder)
1441 setFile = self.setFile
1441 setFile = self.setFile
1442
1442
1443 if not(os.path.exists(fullpath)):
1443 if not(os.path.exists(fullpath)):
1444 os.mkdir(fullpath)
1444 os.mkdir(fullpath)
1445 setFile = -1 # inicializo mi contador de seteo
1445 setFile = -1 # inicializo mi contador de seteo
1446 else:
1446 else:
1447 filesList = os.listdir(fullpath)
1447 filesList = os.listdir(fullpath)
1448 if len(filesList) > 0:
1448 if len(filesList) > 0:
1449 filesList = sorted(filesList, key=str.lower)
1449 filesList = sorted(filesList, key=str.lower)
1450 filen = filesList[-1]
1450 filen = filesList[-1]
1451 # el filename debera tener el siguiente formato
1451 # el filename debera tener el siguiente formato
1452 # 0 1234 567 89A BCDE (hex)
1452 # 0 1234 567 89A BCDE (hex)
1453 # x YYYY DDD SSS .ext
1453 # x YYYY DDD SSS .ext
1454 if isNumber(filen[8:11]):
1454 if isNumber(filen[8:11]):
1455 # inicializo mi contador de seteo al seteo del ultimo file
1455 # inicializo mi contador de seteo al seteo del ultimo file
1456 setFile = int(filen[8:11])
1456 setFile = int(filen[8:11])
1457 else:
1457 else:
1458 setFile = -1
1458 setFile = -1
1459 else:
1459 else:
1460 setFile = -1 # inicializo mi contador de seteo
1460 setFile = -1 # inicializo mi contador de seteo
1461
1461
1462 setFile += 1
1462 setFile += 1
1463
1463
1464 # If this is a new day it resets some values
1464 # If this is a new day it resets some values
1465 if self.dataOut.datatime.date() > self.fileDate:
1465 if self.dataOut.datatime.date() > self.fileDate:
1466 setFile = 0
1466 setFile = 0
1467 self.nTotalBlocks = 0
1467 self.nTotalBlocks = 0
1468
1468
1469 filen = '{}{:04d}{:03d}{:03d}{}'.format(
1469 filen = '{}{:04d}{:03d}{:03d}{}'.format(
1470 self.optchar, timeTuple.tm_year, timeTuple.tm_yday, setFile, ext)
1470 self.optchar, timeTuple.tm_year, timeTuple.tm_yday, setFile, ext)
1471
1471
1472 filename = os.path.join(path, subfolder, filen)
1472 filename = os.path.join(path, subfolder, filen)
1473
1473
1474 fp = open(filename, 'wb')
1474 fp = open(filename, 'wb')
1475
1475
1476 self.blockIndex = 0
1476 self.blockIndex = 0
1477 self.filename = filename
1477 self.filename = filename
1478 self.subfolder = subfolder
1478 self.subfolder = subfolder
1479 self.fp = fp
1479 self.fp = fp
1480 self.setFile = setFile
1480 self.setFile = setFile
1481 self.flagIsNewFile = 1
1481 self.flagIsNewFile = 1
1482 self.fileDate = self.dataOut.datatime.date()
1482 self.fileDate = self.dataOut.datatime.date()
1483 self.setFirstHeader()
1483 self.setFirstHeader()
1484
1484
1485 print('[Writing] Opening file: %s' % self.filename)
1485 print('[Writing] Opening file: %s' % self.filename)
1486
1486
1487 self.__writeFirstHeader()
1487 self.__writeFirstHeader()
1488
1488
1489 return 1
1489 return 1
1490
1490
1491 def setup(self, dataOut, path, blocksPerFile, profilesPerBlock=64, set=None, ext=None, datatype=4):
1491 def setup(self, dataOut, path, blocksPerFile, profilesPerBlock=64, set=None, ext=None, datatype=4):
1492 """
1492 """
1493 Setea el tipo de formato en la cual sera guardada la data y escribe el First Header
1493 Setea el tipo de formato en la cual sera guardada la data y escribe el First Header
1494
1494
1495 Inputs:
1495 Inputs:
1496 path : directory where data will be saved
1496 path : directory where data will be saved
1497 profilesPerBlock : number of profiles per block
1497 profilesPerBlock : number of profiles per block
1498 set : initial file set
1498 set : initial file set
1499 datatype : An integer number that defines data type:
1499 datatype : An integer number that defines data type:
1500 0 : int8 (1 byte)
1500 0 : int8 (1 byte)
1501 1 : int16 (2 bytes)
1501 1 : int16 (2 bytes)
1502 2 : int32 (4 bytes)
1502 2 : int32 (4 bytes)
1503 3 : int64 (8 bytes)
1503 3 : int64 (8 bytes)
1504 4 : float32 (4 bytes)
1504 4 : float32 (4 bytes)
1505 5 : double64 (8 bytes)
1505 5 : double64 (8 bytes)
1506
1506
1507 Return:
1507 Return:
1508 0 : Si no realizo un buen seteo
1508 0 : Si no realizo un buen seteo
1509 1 : Si realizo un buen seteo
1509 1 : Si realizo un buen seteo
1510 """
1510 """
1511
1511
1512 if ext == None:
1512 if ext == None:
1513 ext = self.ext
1513 ext = self.ext
1514
1514
1515 self.ext = ext.lower()
1515 self.ext = ext.lower()
1516
1516
1517 self.path = path
1517 self.path = path
1518
1518
1519 if set is None:
1519 if set is None:
1520 self.setFile = -1
1520 self.setFile = -1
1521 else:
1521 else:
1522 self.setFile = set - 1
1522 self.setFile = set - 1
1523
1523
1524 self.blocksPerFile = blocksPerFile
1524 self.blocksPerFile = blocksPerFile
1525 self.profilesPerBlock = profilesPerBlock
1525 self.profilesPerBlock = profilesPerBlock
1526 self.dataOut = dataOut
1526 self.dataOut = dataOut
1527 self.fileDate = self.dataOut.datatime.date()
1527 self.fileDate = self.dataOut.datatime.date()
1528 self.dtype = self.dataOut.dtype
1528 self.dtype = self.dataOut.dtype
1529
1529
1530 if datatype is not None:
1530 if datatype is not None:
1531 self.dtype = get_numpy_dtype(datatype)
1531 self.dtype = get_numpy_dtype(datatype)
1532
1532
1533 if not(self.setNextFile()):
1533 if not(self.setNextFile()):
1534 print("[Writing] There isn't a next file")
1534 print("[Writing] There isn't a next file")
1535 return 0
1535 return 0
1536
1536
1537 self.setBlockDimension()
1537 self.setBlockDimension()
1538
1538
1539 return 1
1539 return 1
1540
1540
1541 def run(self, dataOut, path, blocksPerFile=100, profilesPerBlock=64, set=None, ext=None, datatype=4, **kwargs):
1541 def run(self, dataOut, path, blocksPerFile=100, profilesPerBlock=64, set=None, ext=None, datatype=4, **kwargs):
1542
1542
1543 if not(self.isConfig):
1543 if not(self.isConfig):
1544
1544
1545 self.setup(dataOut, path, blocksPerFile, profilesPerBlock=profilesPerBlock,
1545 self.setup(dataOut, path, blocksPerFile, profilesPerBlock=profilesPerBlock,
1546 set=set, ext=ext, datatype=datatype, **kwargs)
1546 set=set, ext=ext, datatype=datatype, **kwargs)
1547 self.isConfig = True
1547 self.isConfig = True
1548
1548
1549 self.dataOut = dataOut
1549 self.dataOut = dataOut
1550 self.putData()
1550 self.putData()
1551 return self.dataOut
1551 return self.dataOut
1552
1552
1553 @MPDecorator
1553 @MPDecorator
1554 class printInfo(Operation):
1554 class printInfo(Operation):
1555
1555
1556 def __init__(self):
1556 def __init__(self):
1557
1557
1558 Operation.__init__(self)
1558 Operation.__init__(self)
1559 self.__printInfo = True
1559 self.__printInfo = True
1560
1560
1561 def run(self, dataOut, headers = ['systemHeaderObj', 'radarControllerHeaderObj', 'processingHeaderObj']):
1561 def run(self, dataOut, headers = ['systemHeaderObj', 'radarControllerHeaderObj', 'processingHeaderObj']):
1562 if self.__printInfo == False:
1562 if self.__printInfo == False:
1563 return
1563 return
1564
1564
1565 for header in headers:
1565 for header in headers:
1566 if hasattr(dataOut, header):
1566 if hasattr(dataOut, header):
1567 obj = getattr(dataOut, header)
1567 obj = getattr(dataOut, header)
1568 if hasattr(obj, 'printInfo'):
1568 if hasattr(obj, 'printInfo'):
1569 obj.printInfo()
1569 obj.printInfo()
1570 else:
1570 else:
1571 print(obj)
1571 print(obj)
1572 else:
1572 else:
1573 log.warning('Header {} Not found in object'.format(header))
1573 log.warning('Header {} Not found in object'.format(header))
1574
1574
1575 self.__printInfo = False
1575 self.__printInfo = False
@@ -1,663 +1,661
1 '''
1 '''
2 Created on Set 9, 2015
2 Created on Set 9, 2015
3
3
4 @author: roj-idl71 Karim Kuyeng
4 @author: roj-idl71 Karim Kuyeng
5
5
6 @update: 2021, Joab Apaza
6 @update: 2021, Joab Apaza
7 '''
7 '''
8
8
9 import os
9 import os
10 import sys
10 import sys
11 import glob
11 import glob
12 import fnmatch
12 import fnmatch
13 import datetime
13 import datetime
14 import time
14 import time
15 import re
15 import re
16 import h5py
16 import h5py
17 import numpy
17 import numpy
18
18
19 try:
19 try:
20 from gevent import sleep
20 from gevent import sleep
21 except:
21 except:
22 from time import sleep
22 from time import sleep
23
23
24 from schainpy.model.data.jroheaderIO import RadarControllerHeader, SystemHeader
24 from schainpy.model.data.jroheaderIO import RadarControllerHeader, SystemHeader
25 from schainpy.model.data.jrodata import Voltage
25 from schainpy.model.data.jrodata import Voltage
26 from schainpy.model.proc.jroproc_base import ProcessingUnit, Operation, MPDecorator
26 from schainpy.model.proc.jroproc_base import ProcessingUnit, Operation, MPDecorator
27 from numpy import imag
27 from numpy import imag
28
28
29
29
30 class AMISRReader(ProcessingUnit):
30 class AMISRReader(ProcessingUnit):
31 '''
31 '''
32 classdocs
32 classdocs
33 '''
33 '''
34
34
35 def __init__(self):
35 def __init__(self):
36 '''
36 '''
37 Constructor
37 Constructor
38 '''
38 '''
39
39
40 ProcessingUnit.__init__(self)
40 ProcessingUnit.__init__(self)
41
41
42 self.set = None
42 self.set = None
43 self.subset = None
43 self.subset = None
44 self.extension_file = '.h5'
44 self.extension_file = '.h5'
45 self.dtc_str = 'dtc'
45 self.dtc_str = 'dtc'
46 self.dtc_id = 0
46 self.dtc_id = 0
47 self.status = True
47 self.status = True
48 self.isConfig = False
48 self.isConfig = False
49 self.dirnameList = []
49 self.dirnameList = []
50 self.filenameList = []
50 self.filenameList = []
51 self.fileIndex = None
51 self.fileIndex = None
52 self.flagNoMoreFiles = False
52 self.flagNoMoreFiles = False
53 self.flagIsNewFile = 0
53 self.flagIsNewFile = 0
54 self.filename = ''
54 self.filename = ''
55 self.amisrFilePointer = None
55 self.amisrFilePointer = None
56 self.realBeamCode = []
56 self.realBeamCode = []
57 self.beamCodeMap = None
57 self.beamCodeMap = None
58 self.azimuthList = []
58 self.azimuthList = []
59 self.elevationList = []
59 self.elevationList = []
60 self.dataShape = None
60 self.dataShape = None
61
61
62
62
63
63
64 self.profileIndex = 0
64 self.profileIndex = 0
65
65
66
66
67 self.beamCodeByFrame = None
67 self.beamCodeByFrame = None
68 self.radacTimeByFrame = None
68 self.radacTimeByFrame = None
69
69
70 self.dataset = None
70 self.dataset = None
71
71
72 self.__firstFile = True
72 self.__firstFile = True
73
73
74 self.buffer = None
74 self.buffer = None
75
75
76 self.timezone = 'ut'
76 self.timezone = 'ut'
77
77
78 self.__waitForNewFile = 20
78 self.__waitForNewFile = 20
79 self.__filename_online = None
79 self.__filename_online = None
80 #Is really necessary create the output object in the initializer
80 #Is really necessary create the output object in the initializer
81 self.dataOut = Voltage()
81 self.dataOut = Voltage()
82 self.dataOut.error=False
82 self.dataOut.error=False
83
83
84
84
85 def setup(self,path=None,
85 def setup(self,path=None,
86 startDate=None,
86 startDate=None,
87 endDate=None,
87 endDate=None,
88 startTime=None,
88 startTime=None,
89 endTime=None,
89 endTime=None,
90 walk=True,
90 walk=True,
91 timezone='ut',
91 timezone='ut',
92 all=0,
92 all=0,
93 code = None,
93 code = None,
94 nCode = 0,
94 nCode = 0,
95 nBaud = 0,
95 nBaud = 0,
96 online=False):
96 online=False):
97
97
98
98
99
99
100 self.timezone = timezone
100 self.timezone = timezone
101 self.all = all
101 self.all = all
102 self.online = online
102 self.online = online
103
103
104 self.code = code
104 self.code = code
105 self.nCode = int(nCode)
105 self.nCode = int(nCode)
106 self.nBaud = int(nBaud)
106 self.nBaud = int(nBaud)
107
107
108
108
109
109
110 #self.findFiles()
110 #self.findFiles()
111 if not(online):
111 if not(online):
112 #Busqueda de archivos offline
112 #Busqueda de archivos offline
113 self.searchFilesOffLine(path, startDate, endDate, startTime, endTime, walk)
113 self.searchFilesOffLine(path, startDate, endDate, startTime, endTime, walk)
114 else:
114 else:
115 self.searchFilesOnLine(path, startDate, endDate, startTime,endTime,walk)
115 self.searchFilesOnLine(path, startDate, endDate, startTime,endTime,walk)
116
116
117 if not(self.filenameList):
117 if not(self.filenameList):
118 print("There is no files into the folder: %s"%(path))
118 print("There is no files into the folder: %s"%(path))
119 sys.exit()
119 sys.exit()
120
120
121 self.fileIndex = 0
121 self.fileIndex = 0
122
122
123 self.readNextFile(online)
123 self.readNextFile(online)
124
124
125 '''
125 '''
126 Add code
126 Add code
127 '''
127 '''
128 self.isConfig = True
128 self.isConfig = True
129 # print("Setup Done")
129 # print("Setup Done")
130 pass
130 pass
131
131
132
132
133 def readAMISRHeader(self,fp):
133 def readAMISRHeader(self,fp):
134
134
135 if self.isConfig and (not self.flagNoMoreFiles):
135 if self.isConfig and (not self.flagNoMoreFiles):
136 newShape = fp.get('Raw11/Data/Samples/Data').shape[1:]
136 newShape = fp.get('Raw11/Data/Samples/Data').shape[1:]
137 if self.dataShape != newShape and newShape != None:
137 if self.dataShape != newShape and newShape != None:
138 print("\nNEW FILE HAS A DIFFERENT SHAPE")
138 print("\nNEW FILE HAS A DIFFERENT SHAPE")
139 print(self.dataShape,newShape,"\n")
139 print(self.dataShape,newShape,"\n")
140 return 0
140 return 0
141 else:
141 else:
142 self.dataShape = fp.get('Raw11/Data/Samples/Data').shape[1:]
142 self.dataShape = fp.get('Raw11/Data/Samples/Data').shape[1:]
143
143
144
144
145 header = 'Raw11/Data/RadacHeader'
145 header = 'Raw11/Data/RadacHeader'
146 self.beamCodeByPulse = fp.get(header+'/BeamCode') # LIST OF BEAMS PER PROFILE, TO BE USED ON REARRANGE
146 self.beamCodeByPulse = fp.get(header+'/BeamCode') # LIST OF BEAMS PER PROFILE, TO BE USED ON REARRANGE
147 if (self.startDate> datetime.date(2021, 7, 15)): #Se cambió la forma de extracción de Apuntes el 17
147 if (self.startDate> datetime.date(2021, 7, 15)): #Se cambió la forma de extracción de Apuntes el 17
148 self.beamcodeFile = fp['Setup/Beamcodefile'][()].decode()
148 self.beamcodeFile = fp['Setup/Beamcodefile'][()].decode()
149 self.trueBeams = self.beamcodeFile.split("\n")
149 self.trueBeams = self.beamcodeFile.split("\n")
150 self.trueBeams.pop()#remove last
150 self.trueBeams.pop()#remove last
151 [self.realBeamCode.append(x) for x in self.trueBeams if x not in self.realBeamCode]
151 [self.realBeamCode.append(x) for x in self.trueBeams if x not in self.realBeamCode]
152 self.beamCode = [int(x, 16) for x in self.realBeamCode]
152 self.beamCode = [int(x, 16) for x in self.realBeamCode]
153 else:
153 else:
154 _beamCode= fp.get('Raw11/Data/Beamcodes') #se usa la manera previa al cambio de apuntes
154 _beamCode= fp.get('Raw11/Data/Beamcodes') #se usa la manera previa al cambio de apuntes
155 self.beamCode = _beamCode[0,:]
155 self.beamCode = _beamCode[0,:]
156
156
157 if self.beamCodeMap == None:
157 if self.beamCodeMap == None:
158 self.beamCodeMap = fp['Setup/BeamcodeMap']
158 self.beamCodeMap = fp['Setup/BeamcodeMap']
159 for beam in self.beamCode:
159 for beam in self.beamCode:
160 beamAziElev = numpy.where(self.beamCodeMap[:,0]==beam)
160 beamAziElev = numpy.where(self.beamCodeMap[:,0]==beam)
161 beamAziElev = beamAziElev[0].squeeze()
161 beamAziElev = beamAziElev[0].squeeze()
162 self.azimuthList.append(self.beamCodeMap[beamAziElev,1])
162 self.azimuthList.append(self.beamCodeMap[beamAziElev,1])
163 self.elevationList.append(self.beamCodeMap[beamAziElev,2])
163 self.elevationList.append(self.beamCodeMap[beamAziElev,2])
164 #print("Beamssss: ",self.beamCodeMap[beamAziElev,1],self.beamCodeMap[beamAziElev,2])
164 #print("Beamssss: ",self.beamCodeMap[beamAziElev,1],self.beamCodeMap[beamAziElev,2])
165 #print(self.beamCode)
165 #print(self.beamCode)
166 #self.code = fp.get(header+'/Code') # NOT USE FOR THIS
166 #self.code = fp.get(header+'/Code') # NOT USE FOR THIS
167 self.frameCount = fp.get(header+'/FrameCount')# NOT USE FOR THIS
167 self.frameCount = fp.get(header+'/FrameCount')# NOT USE FOR THIS
168 self.modeGroup = fp.get(header+'/ModeGroup')# NOT USE FOR THIS
168 self.modeGroup = fp.get(header+'/ModeGroup')# NOT USE FOR THIS
169 self.nsamplesPulse = fp.get(header+'/NSamplesPulse')# TO GET NSA OR USING DATA FOR THAT
169 self.nsamplesPulse = fp.get(header+'/NSamplesPulse')# TO GET NSA OR USING DATA FOR THAT
170 self.pulseCount = fp.get(header+'/PulseCount')# NOT USE FOR THIS
170 self.pulseCount = fp.get(header+'/PulseCount')# NOT USE FOR THIS
171 self.radacTime = fp.get(header+'/RadacTime')# 1st TIME ON FILE ANDE CALCULATE THE REST WITH IPP*nindexprofile
171 self.radacTime = fp.get(header+'/RadacTime')# 1st TIME ON FILE ANDE CALCULATE THE REST WITH IPP*nindexprofile
172 self.timeCount = fp.get(header+'/TimeCount')# NOT USE FOR THIS
172 self.timeCount = fp.get(header+'/TimeCount')# NOT USE FOR THIS
173 self.timeStatus = fp.get(header+'/TimeStatus')# NOT USE FOR THIS
173 self.timeStatus = fp.get(header+'/TimeStatus')# NOT USE FOR THIS
174 self.rangeFromFile = fp.get('Raw11/Data/Samples/Range')
174 self.rangeFromFile = fp.get('Raw11/Data/Samples/Range')
175 self.frequency = fp.get('Rx/Frequency')
175 self.frequency = fp.get('Rx/Frequency')
176 txAus = fp.get('Raw11/Data/Pulsewidth')
176 txAus = fp.get('Raw11/Data/Pulsewidth')
177
177
178
178
179 self.nblocks = self.pulseCount.shape[0] #nblocks
179 self.nblocks = self.pulseCount.shape[0] #nblocks
180
180
181 self.nprofiles = self.pulseCount.shape[1] #nprofile
181 self.nprofiles = self.pulseCount.shape[1] #nprofile
182 self.nsa = self.nsamplesPulse[0,0] #ngates
182 self.nsa = self.nsamplesPulse[0,0] #ngates
183 self.nchannels = len(self.beamCode)
183 self.nchannels = len(self.beamCode)
184 self.ippSeconds = (self.radacTime[0][1] -self.radacTime[0][0]) #Ipp in seconds
184 self.ippSeconds = (self.radacTime[0][1] -self.radacTime[0][0]) #Ipp in seconds
185 #self.__waitForNewFile = self.nblocks # wait depending on the number of blocks since each block is 1 sec
185 #self.__waitForNewFile = self.nblocks # wait depending on the number of blocks since each block is 1 sec
186 self.__waitForNewFile = self.nblocks * self.nprofiles * self.ippSeconds # wait until new file is created
186 self.__waitForNewFile = self.nblocks * self.nprofiles * self.ippSeconds # wait until new file is created
187
187
188 #filling radar controller header parameters
188 #filling radar controller header parameters
189 self.__ippKm = self.ippSeconds *.15*1e6 # in km
189 self.__ippKm = self.ippSeconds *.15*1e6 # in km
190 self.__txA = (txAus.value)*.15 #(ipp[us]*.15km/1us) in km
190 self.__txA = (txAus.value)*.15 #(ipp[us]*.15km/1us) in km
191 self.__txB = 0
191 self.__txB = 0
192 nWindows=1
192 nWindows=1
193 self.__nSamples = self.nsa
193 self.__nSamples = self.nsa
194 self.__firstHeight = self.rangeFromFile[0][0]/1000 #in km
194 self.__firstHeight = self.rangeFromFile[0][0]/1000 #in km
195 self.__deltaHeight = (self.rangeFromFile[0][1] - self.rangeFromFile[0][0])/1000
195 self.__deltaHeight = (self.rangeFromFile[0][1] - self.rangeFromFile[0][0])/1000
196
196
197 #for now until understand why the code saved is different (code included even though code not in tuf file)
197 #for now until understand why the code saved is different (code included even though code not in tuf file)
198 #self.__codeType = 0
198 #self.__codeType = 0
199 # self.__nCode = None
199 # self.__nCode = None
200 # self.__nBaud = None
200 # self.__nBaud = None
201 self.__code = self.code
201 self.__code = self.code
202 self.__codeType = 0
202 self.__codeType = 0
203 if self.code != None:
203 if self.code != None:
204 self.__codeType = 1
204 self.__codeType = 1
205 self.__nCode = self.nCode
205 self.__nCode = self.nCode
206 self.__nBaud = self.nBaud
206 self.__nBaud = self.nBaud
207 #self.__code = 0
207 #self.__code = 0
208
208
209 #filling system header parameters
209 #filling system header parameters
210 self.__nSamples = self.nsa
210 self.__nSamples = self.nsa
211 self.newProfiles = self.nprofiles/self.nchannels
211 self.newProfiles = self.nprofiles/self.nchannels
212 self.__channelList = list(range(self.nchannels))
212 self.__channelList = list(range(self.nchannels))
213
213
214 self.__frequency = self.frequency[0][0]
214 self.__frequency = self.frequency[0][0]
215
215
216
216
217 return 1
217 return 1
218
218
219
219
220 def createBuffers(self):
220 def createBuffers(self):
221
221
222 pass
222 pass
223
223
224 def __setParameters(self,path='', startDate='',endDate='',startTime='', endTime='', walk=''):
224 def __setParameters(self,path='', startDate='',endDate='',startTime='', endTime='', walk=''):
225 self.path = path
225 self.path = path
226 self.startDate = startDate
226 self.startDate = startDate
227 self.endDate = endDate
227 self.endDate = endDate
228 self.startTime = startTime
228 self.startTime = startTime
229 self.endTime = endTime
229 self.endTime = endTime
230 self.walk = walk
230 self.walk = walk
231
231
232 def __checkPath(self):
232 def __checkPath(self):
233 if os.path.exists(self.path):
233 if os.path.exists(self.path):
234 self.status = 1
234 self.status = 1
235 else:
235 else:
236 self.status = 0
236 self.status = 0
237 print('Path:%s does not exists'%self.path)
237 print('Path:%s does not exists'%self.path)
238
238
239 return
239 return
240
240
241
241
242 def __selDates(self, amisr_dirname_format):
242 def __selDates(self, amisr_dirname_format):
243 try:
243 try:
244 year = int(amisr_dirname_format[0:4])
244 year = int(amisr_dirname_format[0:4])
245 month = int(amisr_dirname_format[4:6])
245 month = int(amisr_dirname_format[4:6])
246 dom = int(amisr_dirname_format[6:8])
246 dom = int(amisr_dirname_format[6:8])
247 thisDate = datetime.date(year,month,dom)
247 thisDate = datetime.date(year,month,dom)
248
248
249 if (thisDate>=self.startDate and thisDate <= self.endDate):
249 if (thisDate>=self.startDate and thisDate <= self.endDate):
250 return amisr_dirname_format
250 return amisr_dirname_format
251 except:
251 except:
252 return None
252 return None
253
253
254
254
255 def __findDataForDates(self,online=False):
255 def __findDataForDates(self,online=False):
256
256
257 if not(self.status):
257 if not(self.status):
258 return None
258 return None
259
259
260 pat = '\d+.\d+'
260 pat = '\d+.\d+'
261 dirnameList = [re.search(pat,x) for x in os.listdir(self.path)]
261 dirnameList = [re.search(pat,x) for x in os.listdir(self.path)]
262 dirnameList = [x for x in dirnameList if x!=None]
262 dirnameList = [x for x in dirnameList if x!=None]
263 dirnameList = [x.string for x in dirnameList]
263 dirnameList = [x.string for x in dirnameList]
264 if not(online):
264 if not(online):
265 dirnameList = [self.__selDates(x) for x in dirnameList]
265 dirnameList = [self.__selDates(x) for x in dirnameList]
266 dirnameList = [x for x in dirnameList if x!=None]
266 dirnameList = [x for x in dirnameList if x!=None]
267 if len(dirnameList)>0:
267 if len(dirnameList)>0:
268 self.status = 1
268 self.status = 1
269 self.dirnameList = dirnameList
269 self.dirnameList = dirnameList
270 self.dirnameList.sort()
270 self.dirnameList.sort()
271 else:
271 else:
272 self.status = 0
272 self.status = 0
273 return None
273 return None
274
274
275 def __getTimeFromData(self):
275 def __getTimeFromData(self):
276 startDateTime_Reader = datetime.datetime.combine(self.startDate,self.startTime)
276 startDateTime_Reader = datetime.datetime.combine(self.startDate,self.startTime)
277 endDateTime_Reader = datetime.datetime.combine(self.endDate,self.endTime)
277 endDateTime_Reader = datetime.datetime.combine(self.endDate,self.endTime)
278
278
279 print('Filtering Files from %s to %s'%(startDateTime_Reader, endDateTime_Reader))
279 print('Filtering Files from %s to %s'%(startDateTime_Reader, endDateTime_Reader))
280 print('........................................')
280 print('........................................')
281 filter_filenameList = []
281 filter_filenameList = []
282 self.filenameList.sort()
282 self.filenameList.sort()
283 #for i in range(len(self.filenameList)-1):
283 #for i in range(len(self.filenameList)-1):
284 for i in range(len(self.filenameList)):
284 for i in range(len(self.filenameList)):
285 filename = self.filenameList[i]
285 filename = self.filenameList[i]
286 fp = h5py.File(filename,'r')
286 fp = h5py.File(filename,'r')
287 time_str = fp.get('Time/RadacTimeString')
287 time_str = fp.get('Time/RadacTimeString')
288
288
289 startDateTimeStr_File = time_str[0][0].decode('UTF-8').split('.')[0]
289 startDateTimeStr_File = time_str[0][0].decode('UTF-8').split('.')[0]
290 #startDateTimeStr_File = "2019-12-16 09:21:11"
290 #startDateTimeStr_File = "2019-12-16 09:21:11"
291 junk = time.strptime(startDateTimeStr_File, '%Y-%m-%d %H:%M:%S')
291 junk = time.strptime(startDateTimeStr_File, '%Y-%m-%d %H:%M:%S')
292 startDateTime_File = datetime.datetime(junk.tm_year,junk.tm_mon,junk.tm_mday,junk.tm_hour, junk.tm_min, junk.tm_sec)
292 startDateTime_File = datetime.datetime(junk.tm_year,junk.tm_mon,junk.tm_mday,junk.tm_hour, junk.tm_min, junk.tm_sec)
293
293
294 #endDateTimeStr_File = "2019-12-16 11:10:11"
294 #endDateTimeStr_File = "2019-12-16 11:10:11"
295 endDateTimeStr_File = time_str[-1][-1].decode('UTF-8').split('.')[0]
295 endDateTimeStr_File = time_str[-1][-1].decode('UTF-8').split('.')[0]
296 junk = time.strptime(endDateTimeStr_File, '%Y-%m-%d %H:%M:%S')
296 junk = time.strptime(endDateTimeStr_File, '%Y-%m-%d %H:%M:%S')
297 endDateTime_File = datetime.datetime(junk.tm_year,junk.tm_mon,junk.tm_mday,junk.tm_hour, junk.tm_min, junk.tm_sec)
297 endDateTime_File = datetime.datetime(junk.tm_year,junk.tm_mon,junk.tm_mday,junk.tm_hour, junk.tm_min, junk.tm_sec)
298
298
299 fp.close()
299 fp.close()
300
300
301 #print("check time", startDateTime_File)
301 #print("check time", startDateTime_File)
302 if self.timezone == 'lt':
302 if self.timezone == 'lt':
303 startDateTime_File = startDateTime_File - datetime.timedelta(minutes = 300)
303 startDateTime_File = startDateTime_File - datetime.timedelta(minutes = 300)
304 endDateTime_File = endDateTime_File - datetime.timedelta(minutes = 300)
304 endDateTime_File = endDateTime_File - datetime.timedelta(minutes = 300)
305 if (endDateTime_File>=startDateTime_Reader and endDateTime_File<=endDateTime_Reader):
305 if (endDateTime_File>=startDateTime_Reader and endDateTime_File<=endDateTime_Reader):
306 filter_filenameList.append(filename)
306 filter_filenameList.append(filename)
307
307
308 if (endDateTime_File>endDateTime_Reader):
308 if (endDateTime_File>endDateTime_Reader):
309 break
309 break
310
310
311
311
312 filter_filenameList.sort()
312 filter_filenameList.sort()
313 self.filenameList = filter_filenameList
313 self.filenameList = filter_filenameList
314 return 1
314 return 1
315
315
316 def __filterByGlob1(self, dirName):
316 def __filterByGlob1(self, dirName):
317 filter_files = glob.glob1(dirName, '*.*%s'%self.extension_file)
317 filter_files = glob.glob1(dirName, '*.*%s'%self.extension_file)
318 filter_files.sort()
318 filter_files.sort()
319 filterDict = {}
319 filterDict = {}
320 filterDict.setdefault(dirName)
320 filterDict.setdefault(dirName)
321 filterDict[dirName] = filter_files
321 filterDict[dirName] = filter_files
322 return filterDict
322 return filterDict
323
323
324 def __getFilenameList(self, fileListInKeys, dirList):
324 def __getFilenameList(self, fileListInKeys, dirList):
325 for value in fileListInKeys:
325 for value in fileListInKeys:
326 dirName = list(value.keys())[0]
326 dirName = list(value.keys())[0]
327 for file in value[dirName]:
327 for file in value[dirName]:
328 filename = os.path.join(dirName, file)
328 filename = os.path.join(dirName, file)
329 self.filenameList.append(filename)
329 self.filenameList.append(filename)
330
330
331
331
332 def __selectDataForTimes(self, online=False):
332 def __selectDataForTimes(self, online=False):
333 #aun no esta implementado el filtro for tiempo
333 #aun no esta implementado el filtro for tiempo
334 if not(self.status):
334 if not(self.status):
335 return None
335 return None
336
336
337 dirList = [os.path.join(self.path,x) for x in self.dirnameList]
337 dirList = [os.path.join(self.path,x) for x in self.dirnameList]
338
338
339 fileListInKeys = [self.__filterByGlob1(x) for x in dirList]
339 fileListInKeys = [self.__filterByGlob1(x) for x in dirList]
340
340
341 self.__getFilenameList(fileListInKeys, dirList)
341 self.__getFilenameList(fileListInKeys, dirList)
342 if not(online):
342 if not(online):
343 #filtro por tiempo
343 #filtro por tiempo
344 if not(self.all):
344 if not(self.all):
345 self.__getTimeFromData()
345 self.__getTimeFromData()
346
346
347 if len(self.filenameList)>0:
347 if len(self.filenameList)>0:
348 self.status = 1
348 self.status = 1
349 self.filenameList.sort()
349 self.filenameList.sort()
350 else:
350 else:
351 self.status = 0
351 self.status = 0
352 return None
352 return None
353
353
354 else:
354 else:
355 #get the last file - 1
355 #get the last file - 1
356 self.filenameList = [self.filenameList[-2]]
356 self.filenameList = [self.filenameList[-2]]
357 new_dirnameList = []
357 new_dirnameList = []
358 for dirname in self.dirnameList:
358 for dirname in self.dirnameList:
359 junk = numpy.array([dirname in x for x in self.filenameList])
359 junk = numpy.array([dirname in x for x in self.filenameList])
360 junk_sum = junk.sum()
360 junk_sum = junk.sum()
361 if junk_sum > 0:
361 if junk_sum > 0:
362 new_dirnameList.append(dirname)
362 new_dirnameList.append(dirname)
363 self.dirnameList = new_dirnameList
363 self.dirnameList = new_dirnameList
364 return 1
364 return 1
365
365
366 def searchFilesOnLine(self, path, startDate, endDate, startTime=datetime.time(0,0,0),
366 def searchFilesOnLine(self, path, startDate, endDate, startTime=datetime.time(0,0,0),
367 endTime=datetime.time(23,59,59),walk=True):
367 endTime=datetime.time(23,59,59),walk=True):
368
368
369 if endDate ==None:
369 if endDate ==None:
370 startDate = datetime.datetime.utcnow().date()
370 startDate = datetime.datetime.utcnow().date()
371 endDate = datetime.datetime.utcnow().date()
371 endDate = datetime.datetime.utcnow().date()
372
372
373 self.__setParameters(path=path, startDate=startDate, endDate=endDate,startTime = startTime,endTime=endTime, walk=walk)
373 self.__setParameters(path=path, startDate=startDate, endDate=endDate,startTime = startTime,endTime=endTime, walk=walk)
374
374
375 self.__checkPath()
375 self.__checkPath()
376
376
377 self.__findDataForDates(online=True)
377 self.__findDataForDates(online=True)
378
378
379 self.dirnameList = [self.dirnameList[-1]]
379 self.dirnameList = [self.dirnameList[-1]]
380
380
381 self.__selectDataForTimes(online=True)
381 self.__selectDataForTimes(online=True)
382
382
383 return
383 return
384
384
385
385
386 def searchFilesOffLine(self,
386 def searchFilesOffLine(self,
387 path,
387 path,
388 startDate,
388 startDate,
389 endDate,
389 endDate,
390 startTime=datetime.time(0,0,0),
390 startTime=datetime.time(0,0,0),
391 endTime=datetime.time(23,59,59),
391 endTime=datetime.time(23,59,59),
392 walk=True):
392 walk=True):
393
393
394 self.__setParameters(path, startDate, endDate, startTime, endTime, walk)
394 self.__setParameters(path, startDate, endDate, startTime, endTime, walk)
395
395
396 self.__checkPath()
396 self.__checkPath()
397
397
398 self.__findDataForDates()
398 self.__findDataForDates()
399
399
400 self.__selectDataForTimes()
400 self.__selectDataForTimes()
401
401
402 for i in range(len(self.filenameList)):
402 for i in range(len(self.filenameList)):
403 print("%s" %(self.filenameList[i]))
403 print("%s" %(self.filenameList[i]))
404
404
405 return
405 return
406
406
407 def __setNextFileOffline(self):
407 def __setNextFileOffline(self):
408
408
409 try:
409 try:
410 self.filename = self.filenameList[self.fileIndex]
410 self.filename = self.filenameList[self.fileIndex]
411 self.amisrFilePointer = h5py.File(self.filename,'r')
411 self.amisrFilePointer = h5py.File(self.filename,'r')
412 self.fileIndex += 1
412 self.fileIndex += 1
413 except:
413 except:
414 self.flagNoMoreFiles = 1
414 self.flagNoMoreFiles = 1
415 print("No more Files")
415 print("No more Files")
416 return 0
416 return 0
417
417
418 self.flagIsNewFile = 1
418 self.flagIsNewFile = 1
419 print("Setting the file: %s"%self.filename)
419 print("Setting the file: %s"%self.filename)
420
420
421 return 1
421 return 1
422
422
423
423
424 def __setNextFileOnline(self):
424 def __setNextFileOnline(self):
425 filename = self.filenameList[0]
425 filename = self.filenameList[0]
426 if self.__filename_online != None:
426 if self.__filename_online != None:
427 self.__selectDataForTimes(online=True)
427 self.__selectDataForTimes(online=True)
428 filename = self.filenameList[0]
428 filename = self.filenameList[0]
429 wait = 0
429 wait = 0
430 self.__waitForNewFile=300 ## DEBUG:
430 self.__waitForNewFile=300 ## DEBUG:
431 while self.__filename_online == filename:
431 while self.__filename_online == filename:
432 print('waiting %d seconds to get a new file...'%(self.__waitForNewFile))
432 print('waiting %d seconds to get a new file...'%(self.__waitForNewFile))
433 if wait == 5:
433 if wait == 5:
434 self.flagNoMoreFiles = 1
434 self.flagNoMoreFiles = 1
435 return 0
435 return 0
436 sleep(self.__waitForNewFile)
436 sleep(self.__waitForNewFile)
437 self.__selectDataForTimes(online=True)
437 self.__selectDataForTimes(online=True)
438 filename = self.filenameList[0]
438 filename = self.filenameList[0]
439 wait += 1
439 wait += 1
440
440
441 self.__filename_online = filename
441 self.__filename_online = filename
442
442
443 self.amisrFilePointer = h5py.File(filename,'r')
443 self.amisrFilePointer = h5py.File(filename,'r')
444 self.flagIsNewFile = 1
444 self.flagIsNewFile = 1
445 self.filename = filename
445 self.filename = filename
446 print("Setting the file: %s"%self.filename)
446 print("Setting the file: %s"%self.filename)
447 return 1
447 return 1
448
448
449
449
450 def readData(self):
450 def readData(self):
451 buffer = self.amisrFilePointer.get('Raw11/Data/Samples/Data')
451 buffer = self.amisrFilePointer.get('Raw11/Data/Samples/Data')
452 re = buffer[:,:,:,0]
452 re = buffer[:,:,:,0]
453 im = buffer[:,:,:,1]
453 im = buffer[:,:,:,1]
454 dataset = re + im*1j
454 dataset = re + im*1j
455
455
456 self.radacTime = self.amisrFilePointer.get('Raw11/Data/RadacHeader/RadacTime')
456 self.radacTime = self.amisrFilePointer.get('Raw11/Data/RadacHeader/RadacTime')
457 timeset = self.radacTime[:,0]
457 timeset = self.radacTime[:,0]
458
458
459 return dataset,timeset
459 return dataset,timeset
460
460
461 def reshapeData(self):
461 def reshapeData(self):
462 #self.beamCodeByPulse, self.beamCode, self.nblocks, self.nprofiles, self.nsa,
462 #self.beamCodeByPulse, self.beamCode, self.nblocks, self.nprofiles, self.nsa,
463 channels = self.beamCodeByPulse[0,:]
463 channels = self.beamCodeByPulse[0,:]
464 nchan = self.nchannels
464 nchan = self.nchannels
465 #self.newProfiles = self.nprofiles/nchan #must be defined on filljroheader
465 #self.newProfiles = self.nprofiles/nchan #must be defined on filljroheader
466 nblocks = self.nblocks
466 nblocks = self.nblocks
467 nsamples = self.nsa
467 nsamples = self.nsa
468
468
469 #Dimensions : nChannels, nProfiles, nSamples
469 #Dimensions : nChannels, nProfiles, nSamples
470 new_block = numpy.empty((nblocks, nchan, numpy.int_(self.newProfiles), nsamples), dtype="complex64")
470 new_block = numpy.empty((nblocks, nchan, numpy.int_(self.newProfiles), nsamples), dtype="complex64")
471 ############################################
471 ############################################
472
472
473 for thisChannel in range(nchan):
473 for thisChannel in range(nchan):
474 new_block[:,thisChannel,:,:] = self.dataset[:,numpy.where(channels==self.beamCode[thisChannel])[0],:]
474 new_block[:,thisChannel,:,:] = self.dataset[:,numpy.where(channels==self.beamCode[thisChannel])[0],:]
475
475
476
476
477 new_block = numpy.transpose(new_block, (1,0,2,3))
477 new_block = numpy.transpose(new_block, (1,0,2,3))
478 new_block = numpy.reshape(new_block, (nchan,-1, nsamples))
478 new_block = numpy.reshape(new_block, (nchan,-1, nsamples))
479
479
480 return new_block
480 return new_block
481
481
482 def updateIndexes(self):
482 def updateIndexes(self):
483
483
484 pass
484 pass
485
485
486 def fillJROHeader(self):
486 def fillJROHeader(self):
487
487
488 #fill radar controller header
488 #fill radar controller header
489 self.dataOut.radarControllerHeaderObj = RadarControllerHeader(ipp=self.__ippKm,
489 self.dataOut.radarControllerHeaderObj = RadarControllerHeader(ipp=self.__ippKm,
490 txA=self.__txA,
490 txA=self.__txA,
491 txB=0,
491 txB=0,
492 nWindows=1,
492 nWindows=1,
493 nHeights=self.__nSamples,
493 nHeights=self.__nSamples,
494 firstHeight=self.__firstHeight,
494 firstHeight=self.__firstHeight,
495 deltaHeight=self.__deltaHeight,
495 deltaHeight=self.__deltaHeight,
496 codeType=self.__codeType,
496 codeType=self.__codeType,
497 nCode=self.__nCode, nBaud=self.__nBaud,
497 nCode=self.__nCode, nBaud=self.__nBaud,
498 code = self.__code,
498 code = self.__code,
499 fClock=1)
499 fClock=1)
500
500
501 #fill system header
501 #fill system header
502 self.dataOut.systemHeaderObj = SystemHeader(nSamples=self.__nSamples,
502 self.dataOut.systemHeaderObj = SystemHeader(nSamples=self.__nSamples,
503 nProfiles=self.newProfiles,
503 nProfiles=self.newProfiles,
504 nChannels=len(self.__channelList),
504 nChannels=len(self.__channelList),
505 adcResolution=14,
505 adcResolution=14,
506 pciDioBusWidth=32)
506 pciDioBusWidth=32)
507
507
508 self.dataOut.type = "Voltage"
508 self.dataOut.type = "Voltage"
509 self.dataOut.data = None
509 self.dataOut.data = None
510 self.dataOut.dtype = numpy.dtype([('real','<i8'),('imag','<i8')])
510 self.dataOut.dtype = numpy.dtype([('real','<i8'),('imag','<i8')])
511 # self.dataOut.nChannels = 0
511 # self.dataOut.nChannels = 0
512
512
513 # self.dataOut.nHeights = 0
513 # self.dataOut.nHeights = 0
514
514
515 self.dataOut.nProfiles = self.newProfiles*self.nblocks
515 self.dataOut.nProfiles = self.newProfiles*self.nblocks
516 #self.dataOut.heightList = self.__firstHeigth + numpy.arange(self.__nSamples, dtype = numpy.float)*self.__deltaHeigth
516 #self.dataOut.heightList = self.__firstHeigth + numpy.arange(self.__nSamples, dtype = numpy.float)*self.__deltaHeigth
517 ranges = numpy.reshape(self.rangeFromFile.value,(-1))
517 ranges = numpy.reshape(self.rangeFromFile.value,(-1))
518 self.dataOut.heightList = ranges/1000.0 #km
518 self.dataOut.heightList = ranges/1000.0 #km
519 self.dataOut.channelList = self.__channelList
519 self.dataOut.channelList = self.__channelList
520 self.dataOut.blocksize = self.dataOut.nChannels * self.dataOut.nHeights
520 self.dataOut.blocksize = self.dataOut.nChannels * self.dataOut.nHeights
521
521
522 # self.dataOut.channelIndexList = None
522 # self.dataOut.channelIndexList = None
523
523
524
524
525 self.dataOut.azimuthList = numpy.array(self.azimuthList)
525 self.dataOut.azimuthList = numpy.array(self.azimuthList)
526 self.dataOut.elevationList = numpy.array(self.elevationList)
526 self.dataOut.elevationList = numpy.array(self.elevationList)
527 self.dataOut.codeList = numpy.array(self.beamCode)
527 self.dataOut.codeList = numpy.array(self.beamCode)
528 #print(self.dataOut.elevationList)
528 #print(self.dataOut.elevationList)
529 self.dataOut.flagNoData = True
529 self.dataOut.flagNoData = True
530
530
531 #Set to TRUE if the data is discontinuous
531 #Set to TRUE if the data is discontinuous
532 self.dataOut.flagDiscontinuousBlock = False
532 self.dataOut.flagDiscontinuousBlock = False
533
533
534 self.dataOut.utctime = None
534 self.dataOut.utctime = None
535
535
536 #self.dataOut.timeZone = -5 #self.__timezone/60 #timezone like jroheader, difference in minutes between UTC and localtime
536 #self.dataOut.timeZone = -5 #self.__timezone/60 #timezone like jroheader, difference in minutes between UTC and localtime
537 if self.timezone == 'lt':
537 if self.timezone == 'lt':
538 self.dataOut.timeZone = time.timezone / 60. #get the timezone in minutes
538 self.dataOut.timeZone = time.timezone / 60. #get the timezone in minutes
539 else:
539 else:
540 self.dataOut.timeZone = 0 #by default time is UTC
540 self.dataOut.timeZone = 0 #by default time is UTC
541
541
542 self.dataOut.dstFlag = 0
542 self.dataOut.dstFlag = 0
543 self.dataOut.errorCount = 0
543 self.dataOut.errorCount = 0
544 self.dataOut.nCohInt = 1
544 self.dataOut.nCohInt = 1
545 self.dataOut.flagDecodeData = False #asumo que la data esta decodificada
545 self.dataOut.flagDecodeData = False #asumo que la data esta decodificada
546 self.dataOut.flagDeflipData = False #asumo que la data esta sin flip
546 self.dataOut.flagDeflipData = False #asumo que la data esta sin flip
547 self.dataOut.flagShiftFFT = False
547 self.dataOut.flagShiftFFT = False
548 self.dataOut.ippSeconds = self.ippSeconds
548 self.dataOut.ippSeconds = self.ippSeconds
549
549
550 #Time interval between profiles
550 #Time interval between profiles
551 #self.dataOut.timeInterval = self.dataOut.ippSeconds * self.dataOut.nCohInt
551 #self.dataOut.timeInterval = self.dataOut.ippSeconds * self.dataOut.nCohInt
552
552
553 self.dataOut.frequency = self.__frequency
553 self.dataOut.frequency = self.__frequency
554 self.dataOut.realtime = self.online
554 self.dataOut.realtime = self.online
555 pass
555 pass
556
556
557 def readNextFile(self,online=False):
557 def readNextFile(self,online=False):
558
558
559 if not(online):
559 if not(online):
560 newFile = self.__setNextFileOffline()
560 newFile = self.__setNextFileOffline()
561 else:
561 else:
562 newFile = self.__setNextFileOnline()
562 newFile = self.__setNextFileOnline()
563
563
564 if not(newFile):
564 if not(newFile):
565 self.dataOut.error = True
565 self.dataOut.error = True
566 return 0
566 return 0
567
567
568 if not self.readAMISRHeader(self.amisrFilePointer):
568 if not self.readAMISRHeader(self.amisrFilePointer):
569 self.dataOut.error = True
569 self.dataOut.error = True
570 return 0
570 return 0
571
571
572 self.createBuffers()
572 self.createBuffers()
573 self.fillJROHeader()
573 self.fillJROHeader()
574
574
575 #self.__firstFile = False
575 #self.__firstFile = False
576
576
577
577
578
578
579 self.dataset,self.timeset = self.readData()
579 self.dataset,self.timeset = self.readData()
580
580
581 if self.endDate!=None:
581 if self.endDate!=None:
582 endDateTime_Reader = datetime.datetime.combine(self.endDate,self.endTime)
582 endDateTime_Reader = datetime.datetime.combine(self.endDate,self.endTime)
583 time_str = self.amisrFilePointer.get('Time/RadacTimeString')
583 time_str = self.amisrFilePointer.get('Time/RadacTimeString')
584 startDateTimeStr_File = time_str[0][0].decode('UTF-8').split('.')[0]
584 startDateTimeStr_File = time_str[0][0].decode('UTF-8').split('.')[0]
585 junk = time.strptime(startDateTimeStr_File, '%Y-%m-%d %H:%M:%S')
585 junk = time.strptime(startDateTimeStr_File, '%Y-%m-%d %H:%M:%S')
586 startDateTime_File = datetime.datetime(junk.tm_year,junk.tm_mon,junk.tm_mday,junk.tm_hour, junk.tm_min, junk.tm_sec)
586 startDateTime_File = datetime.datetime(junk.tm_year,junk.tm_mon,junk.tm_mday,junk.tm_hour, junk.tm_min, junk.tm_sec)
587 if self.timezone == 'lt':
587 if self.timezone == 'lt':
588 startDateTime_File = startDateTime_File - datetime.timedelta(minutes = 300)
588 startDateTime_File = startDateTime_File - datetime.timedelta(minutes = 300)
589 if (startDateTime_File>endDateTime_Reader):
589 if (startDateTime_File>endDateTime_Reader):
590 return 0
590 return 0
591
591
592 self.jrodataset = self.reshapeData()
592 self.jrodataset = self.reshapeData()
593 #----self.updateIndexes()
593 #----self.updateIndexes()
594 self.profileIndex = 0
594 self.profileIndex = 0
595
595
596 return 1
596 return 1
597
597
598
598
599 def __hasNotDataInBuffer(self):
599 def __hasNotDataInBuffer(self):
600 if self.profileIndex >= (self.newProfiles*self.nblocks):
600 if self.profileIndex >= (self.newProfiles*self.nblocks):
601 return 1
601 return 1
602 return 0
602 return 0
603
603
604
604
605 def getData(self):
605 def getData(self):
606
606
607 if self.flagNoMoreFiles:
607 if self.flagNoMoreFiles:
608 self.dataOut.flagNoData = True
608 self.dataOut.flagNoData = True
609 return 0
609 return 0
610
610
611 if self.__hasNotDataInBuffer():
611 if self.__hasNotDataInBuffer():
612 if not (self.readNextFile(self.online)):
612 if not (self.readNextFile(self.online)):
613 return 0
613 return 0
614
614
615
615
616 if self.dataset is None: # setear esta condicion cuando no hayan datos por leer
616 if self.dataset is None: # setear esta condicion cuando no hayan datos por leer
617 self.dataOut.flagNoData = True
617 self.dataOut.flagNoData = True
618 return 0
618 return 0
619
619
620 #self.dataOut.data = numpy.reshape(self.jrodataset[self.profileIndex,:],(1,-1))
620 #self.dataOut.data = numpy.reshape(self.jrodataset[self.profileIndex,:],(1,-1))
621
621
622 self.dataOut.data = self.jrodataset[:,self.profileIndex,:]
622 self.dataOut.data = self.jrodataset[:,self.profileIndex,:]
623
623
624 #print("R_t",self.timeset)
624 #print("R_t",self.timeset)
625
625
626 #self.dataOut.utctime = self.jrotimeset[self.profileIndex]
626 #self.dataOut.utctime = self.jrotimeset[self.profileIndex]
627 #verificar basic header de jro data y ver si es compatible con este valor
627 #verificar basic header de jro data y ver si es compatible con este valor
628 #self.dataOut.utctime = self.timeset + (self.profileIndex * self.ippSeconds * self.nchannels)
628 #self.dataOut.utctime = self.timeset + (self.profileIndex * self.ippSeconds * self.nchannels)
629 indexprof = numpy.mod(self.profileIndex, self.newProfiles)
629 indexprof = numpy.mod(self.profileIndex, self.newProfiles)
630 indexblock = self.profileIndex/self.newProfiles
630 indexblock = self.profileIndex/self.newProfiles
631 #print (indexblock, indexprof)
631 #print (indexblock, indexprof)
632 diffUTC = 1.8e4 #UTC diference from peru in seconds --Joab
632 diffUTC = 1.8e4 #UTC diference from peru in seconds --Joab
633 diffUTC = 0
633 diffUTC = 0
634 t_comp = (indexprof * self.ippSeconds * self.nchannels) + diffUTC #
634 t_comp = (indexprof * self.ippSeconds * self.nchannels) + diffUTC #
635
635
636 #print("utc :",indexblock," __ ",t_comp)
636 #print("utc :",indexblock," __ ",t_comp)
637 #print(numpy.shape(self.timeset))
637 #print(numpy.shape(self.timeset))
638 self.dataOut.utctime = self.timeset[numpy.int_(indexblock)] + t_comp
638 self.dataOut.utctime = self.timeset[numpy.int_(indexblock)] + t_comp
639 #self.dataOut.utctime = self.timeset[self.profileIndex] + t_comp
639 #self.dataOut.utctime = self.timeset[self.profileIndex] + t_comp
640 #print(self.dataOut.utctime)
640 #print(self.dataOut.utctime)
641 self.dataOut.profileIndex = self.profileIndex
641 self.dataOut.profileIndex = self.profileIndex
642 #print("N profile:",self.profileIndex,self.newProfiles,self.nblocks,self.dataOut.utctime)
642 #print("N profile:",self.profileIndex,self.newProfiles,self.nblocks,self.dataOut.utctime)
643 self.dataOut.flagNoData = False
643 self.dataOut.flagNoData = False
644 # if indexprof == 0:
644 # if indexprof == 0:
645 # print self.dataOut.utctime
645 # print self.dataOut.utctime
646
646
647 self.profileIndex += 1
647 self.profileIndex += 1
648
648
649 #return self.dataOut.data
649 return self.dataOut.data
650
650
651
651
652 def run(self, **kwargs):
652 def run(self, **kwargs):
653 '''
653 '''
654 This method will be called many times so here you should put all your code
654 This method will be called many times so here you should put all your code
655 '''
655 '''
656 #print("running kamisr")
656 #print("running kamisr")
657 if not self.isConfig:
657 if not self.isConfig:
658 self.setup(**kwargs)
658 self.setup(**kwargs)
659 self.isConfig = True
659 self.isConfig = True
660
660
661 self.getData()
661 self.getData()
662 #return(self.dataOut.data)
663 return(self.dataOut)
@@ -1,626 +1,651
1 import os
1 import os
2 import time
2 import time
3 import datetime
3 import datetime
4
4
5 import numpy
5 import numpy
6 import h5py
6 import h5py
7
7
8 import schainpy.admin
8 import schainpy.admin
9 from schainpy.model.data.jrodata import *
9 from schainpy.model.data.jrodata import *
10 from schainpy.model.proc.jroproc_base import ProcessingUnit, Operation, MPDecorator
10 from schainpy.model.proc.jroproc_base import ProcessingUnit, Operation, MPDecorator
11 from schainpy.model.io.jroIO_base import *
11 from schainpy.model.io.jroIO_base import *
12 from schainpy.utils import log
12 from schainpy.utils import log
13
13
14
14
15 class HDFReader(Reader, ProcessingUnit):
15 class HDFReader(Reader, ProcessingUnit):
16 """Processing unit to read HDF5 format files
16 """Processing unit to read HDF5 format files
17
17
18 This unit reads HDF5 files created with `HDFWriter` operation contains
18 This unit reads HDF5 files created with `HDFWriter` operation contains
19 by default two groups Data and Metadata all variables would be saved as `dataOut`
19 by default two groups Data and Metadata all variables would be saved as `dataOut`
20 attributes.
20 attributes.
21 It is possible to read any HDF5 file by given the structure in the `description`
21 It is possible to read any HDF5 file by given the structure in the `description`
22 parameter, also you can add extra values to metadata with the parameter `extras`.
22 parameter, also you can add extra values to metadata with the parameter `extras`.
23
23
24 Parameters:
24 Parameters:
25 -----------
25 -----------
26 path : str
26 path : str
27 Path where files are located.
27 Path where files are located.
28 startDate : date
28 startDate : date
29 Start date of the files
29 Start date of the files
30 endDate : list
30 endDate : list
31 End date of the files
31 End date of the files
32 startTime : time
32 startTime : time
33 Start time of the files
33 Start time of the files
34 endTime : time
34 endTime : time
35 End time of the files
35 End time of the files
36 description : dict, optional
36 description : dict, optional
37 Dictionary with the description of the HDF5 file
37 Dictionary with the description of the HDF5 file
38 extras : dict, optional
38 extras : dict, optional
39 Dictionary with extra metadata to be be added to `dataOut`
39 Dictionary with extra metadata to be be added to `dataOut`
40
40
41 Examples
41 Examples
42 --------
42 --------
43
43
44 desc = {
44 desc = {
45 'Data': {
45 'Data': {
46 'data_output': ['u', 'v', 'w'],
46 'data_output': ['u', 'v', 'w'],
47 'utctime': 'timestamps',
47 'utctime': 'timestamps',
48 } ,
48 } ,
49 'Metadata': {
49 'Metadata': {
50 'heightList': 'heights'
50 'heightList': 'heights'
51 }
51 }
52 }
52 }
53
53
54 desc = {
54 desc = {
55 'Data': {
55 'Data': {
56 'data_output': 'winds',
56 'data_output': 'winds',
57 'utctime': 'timestamps'
57 'utctime': 'timestamps'
58 },
58 },
59 'Metadata': {
59 'Metadata': {
60 'heightList': 'heights'
60 'heightList': 'heights'
61 }
61 }
62 }
62 }
63
63
64 extras = {
64 extras = {
65 'timeZone': 300
65 'timeZone': 300
66 }
66 }
67
67
68 reader = project.addReadUnit(
68 reader = project.addReadUnit(
69 name='HDFReader',
69 name='HDFReader',
70 path='/path/to/files',
70 path='/path/to/files',
71 startDate='2019/01/01',
71 startDate='2019/01/01',
72 endDate='2019/01/31',
72 endDate='2019/01/31',
73 startTime='00:00:00',
73 startTime='00:00:00',
74 endTime='23:59:59',
74 endTime='23:59:59',
75 # description=json.dumps(desc),
75 # description=json.dumps(desc),
76 # extras=json.dumps(extras),
76 # extras=json.dumps(extras),
77 )
77 )
78
78
79 """
79 """
80
80
81 __attrs__ = ['path', 'startDate', 'endDate', 'startTime', 'endTime', 'description', 'extras']
81 __attrs__ = ['path', 'startDate', 'endDate', 'startTime', 'endTime', 'description', 'extras']
82
82
83 def __init__(self):
83 def __init__(self):
84 ProcessingUnit.__init__(self)
84 ProcessingUnit.__init__(self)
85 self.dataOut = Parameters()
85 self.dataOut = Parameters()
86 self.ext = ".hdf5"
86 self.ext = ".hdf5"
87 self.optchar = "D"
87 self.optchar = "D"
88 self.meta = {}
88 self.meta = {}
89 self.data = {}
89 self.data = {}
90 self.open_file = h5py.File
90 self.open_file = h5py.File
91 self.open_mode = 'r'
91 self.open_mode = 'r'
92 self.description = {}
92 self.description = {}
93 self.extras = {}
93 self.extras = {}
94 self.filefmt = "*%Y%j***"
94 self.filefmt = "*%Y%j***"
95 self.folderfmt = "*%Y%j"
95 self.folderfmt = "*%Y%j"
96 self.utcoffset = 0
96 self.utcoffset = 0
97
97
98 def setup(self, **kwargs):
98 def setup(self, **kwargs):
99
99
100 self.set_kwargs(**kwargs)
100 self.set_kwargs(**kwargs)
101 if not self.ext.startswith('.'):
101 if not self.ext.startswith('.'):
102 self.ext = '.{}'.format(self.ext)
102 self.ext = '.{}'.format(self.ext)
103
103
104 if self.online:
104 if self.online:
105 log.log("Searching files in online mode...", self.name)
105 log.log("Searching files in online mode...", self.name)
106
106
107 for nTries in range(self.nTries):
107 for nTries in range(self.nTries):
108 fullpath = self.searchFilesOnLine(self.path, self.startDate,
108 fullpath = self.searchFilesOnLine(self.path, self.startDate,
109 self.endDate, self.expLabel, self.ext, self.walk,
109 self.endDate, self.expLabel, self.ext, self.walk,
110 self.filefmt, self.folderfmt)
110 self.filefmt, self.folderfmt)
111 pathname, filename = os.path.split(fullpath)
112 print(pathname,filename)
111 try:
113 try:
112 fullpath = next(fullpath)
114 fullpath = next(fullpath)
115
113 except:
116 except:
114 fullpath = None
117 fullpath = None
115
118
116 if fullpath:
119 if fullpath:
117 break
120 break
118
121
119 log.warning(
122 log.warning(
120 'Waiting {} sec for a valid file in {}: try {} ...'.format(
123 'Waiting {} sec for a valid file in {}: try {} ...'.format(
121 self.delay, self.path, nTries + 1),
124 self.delay, self.path, nTries + 1),
122 self.name)
125 self.name)
123 time.sleep(self.delay)
126 time.sleep(self.delay)
124
127
125 if not(fullpath):
128 if not(fullpath):
126 raise schainpy.admin.SchainError(
129 raise schainpy.admin.SchainError(
127 'There isn\'t any valid file in {}'.format(self.path))
130 'There isn\'t any valid file in {}'.format(self.path))
128
131
129 pathname, filename = os.path.split(fullpath)
132 pathname, filename = os.path.split(fullpath)
130 self.year = int(filename[1:5])
133 self.year = int(filename[1:5])
131 self.doy = int(filename[5:8])
134 self.doy = int(filename[5:8])
132 self.set = int(filename[8:11]) - 1
135 self.set = int(filename[8:11]) - 1
133 else:
136 else:
134 log.log("Searching files in {}".format(self.path), self.name)
137 log.log("Searching files in {}".format(self.path), self.name)
135 self.filenameList = self.searchFilesOffLine(self.path, self.startDate,
138 self.filenameList = self.searchFilesOffLine(self.path, self.startDate,
136 self.endDate, self.expLabel, self.ext, self.walk, self.filefmt, self.folderfmt)
139 self.endDate, self.expLabel, self.ext, self.walk, self.filefmt, self.folderfmt)
137
140
138 self.setNextFile()
141 self.setNextFile()
139
142
140 return
143 return
141
144
145
142 def readFirstHeader(self):
146 def readFirstHeader(self):
143 '''Read metadata and data'''
147 '''Read metadata and data'''
144
148
145 self.__readMetadata()
149 self.__readMetadata()
146 self.__readData()
150 self.__readData()
147 self.__setBlockList()
151 self.__setBlockList()
148
152
149 if 'type' in self.meta:
153 if 'type' in self.meta:
150 self.dataOut = eval(self.meta['type'])()
154 self.dataOut = eval(self.meta['type'])()
151
155
152 for attr in self.meta:
156 for attr in self.meta:
157 print("attr: ", attr)
153 setattr(self.dataOut, attr, self.meta[attr])
158 setattr(self.dataOut, attr, self.meta[attr])
154
159
160
155 self.blockIndex = 0
161 self.blockIndex = 0
156
162
157 return
163 return
158
164
159 def __setBlockList(self):
165 def __setBlockList(self):
160 '''
166 '''
161 Selects the data within the times defined
167 Selects the data within the times defined
162
168
163 self.fp
169 self.fp
164 self.startTime
170 self.startTime
165 self.endTime
171 self.endTime
166 self.blockList
172 self.blockList
167 self.blocksPerFile
173 self.blocksPerFile
168
174
169 '''
175 '''
170
176
171 startTime = self.startTime
177 startTime = self.startTime
172 endTime = self.endTime
178 endTime = self.endTime
173 thisUtcTime = self.data['utctime'] + self.utcoffset
179 thisUtcTime = self.data['utctime'] + self.utcoffset
174 self.interval = numpy.min(thisUtcTime[1:] - thisUtcTime[:-1])
180 self.interval = numpy.min(thisUtcTime[1:] - thisUtcTime[:-1])
175 thisDatetime = datetime.datetime.utcfromtimestamp(thisUtcTime[0])
181 thisDatetime = datetime.datetime.utcfromtimestamp(thisUtcTime[0])
176
182 self.startFileDatetime = thisDatetime
183 print("datee ",self.startFileDatetime)
177 thisDate = thisDatetime.date()
184 thisDate = thisDatetime.date()
178 thisTime = thisDatetime.time()
185 thisTime = thisDatetime.time()
179
186
180 startUtcTime = (datetime.datetime.combine(thisDate, startTime) - datetime.datetime(1970, 1, 1)).total_seconds()
187 startUtcTime = (datetime.datetime.combine(thisDate, startTime) - datetime.datetime(1970, 1, 1)).total_seconds()
181 endUtcTime = (datetime.datetime.combine(thisDate, endTime) - datetime.datetime(1970, 1, 1)).total_seconds()
188 endUtcTime = (datetime.datetime.combine(thisDate, endTime) - datetime.datetime(1970, 1, 1)).total_seconds()
182
189
183 ind = numpy.where(numpy.logical_and(thisUtcTime >= startUtcTime, thisUtcTime < endUtcTime))[0]
190 ind = numpy.where(numpy.logical_and(thisUtcTime >= startUtcTime, thisUtcTime < endUtcTime))[0]
184
191
185 self.blockList = ind
192 self.blockList = ind
186 self.blocksPerFile = len(ind)
193 self.blocksPerFile = len(ind)
194 self.blocksPerFile = len(thisUtcTime)
187 return
195 return
188
196
189 def __readMetadata(self):
197 def __readMetadata(self):
190 '''
198 '''
191 Reads Metadata
199 Reads Metadata
192 '''
200 '''
193
201
194 meta = {}
202 meta = {}
195
203
196 if self.description:
204 if self.description:
197 for key, value in self.description['Metadata'].items():
205 for key, value in self.description['Metadata'].items():
198 meta[key] = self.fp[value][()]
206 meta[key] = self.fp[value][()]
199 else:
207 else:
200 grp = self.fp['Metadata']
208 grp = self.fp['Metadata']
201 for name in grp:
209 for name in grp:
202 meta[name] = grp[name][()]
210 meta[name] = grp[name][()]
203
211
204 if self.extras:
212 if self.extras:
205 for key, value in self.extras.items():
213 for key, value in self.extras.items():
206 meta[key] = value
214 meta[key] = value
207 self.meta = meta
215 self.meta = meta
208
216
209 return
217 return
210
218
219
220
221 def checkForRealPath(self, nextFile, nextDay):
222
223 # print("check FRP")
224 # dt = self.startFileDatetime + datetime.timedelta(1)
225 # filename = '{}.{}{}'.format(self.path, dt.strftime('%Y%m%d'), self.ext)
226 # fullfilename = os.path.join(self.path, filename)
227 # print("check Path ",fullfilename,filename)
228 # if os.path.exists(fullfilename):
229 # return fullfilename, filename
230 # return None, filename
231 return None,None
232
211 def __readData(self):
233 def __readData(self):
212
234
213 data = {}
235 data = {}
214
236
215 if self.description:
237 if self.description:
216 for key, value in self.description['Data'].items():
238 for key, value in self.description['Data'].items():
217 if isinstance(value, str):
239 if isinstance(value, str):
218 if isinstance(self.fp[value], h5py.Dataset):
240 if isinstance(self.fp[value], h5py.Dataset):
219 data[key] = self.fp[value][()]
241 data[key] = self.fp[value][()]
220 elif isinstance(self.fp[value], h5py.Group):
242 elif isinstance(self.fp[value], h5py.Group):
221 array = []
243 array = []
222 for ch in self.fp[value]:
244 for ch in self.fp[value]:
223 array.append(self.fp[value][ch][()])
245 array.append(self.fp[value][ch][()])
224 data[key] = numpy.array(array)
246 data[key] = numpy.array(array)
225 elif isinstance(value, list):
247 elif isinstance(value, list):
226 array = []
248 array = []
227 for ch in value:
249 for ch in value:
228 array.append(self.fp[ch][()])
250 array.append(self.fp[ch][()])
229 data[key] = numpy.array(array)
251 data[key] = numpy.array(array)
230 else:
252 else:
231 grp = self.fp['Data']
253 grp = self.fp['Data']
232 for name in grp:
254 for name in grp:
233 if isinstance(grp[name], h5py.Dataset):
255 if isinstance(grp[name], h5py.Dataset):
234 array = grp[name][()]
256 array = grp[name][()]
235 elif isinstance(grp[name], h5py.Group):
257 elif isinstance(grp[name], h5py.Group):
236 array = []
258 array = []
237 for ch in grp[name]:
259 for ch in grp[name]:
238 array.append(grp[name][ch][()])
260 array.append(grp[name][ch][()])
239 array = numpy.array(array)
261 array = numpy.array(array)
240 else:
262 else:
241 log.warning('Unknown type: {}'.format(name))
263 log.warning('Unknown type: {}'.format(name))
242
264
243 if name in self.description:
265 if name in self.description:
244 key = self.description[name]
266 key = self.description[name]
245 else:
267 else:
246 key = name
268 key = name
247 data[key] = array
269 data[key] = array
248
270
249 self.data = data
271 self.data = data
250 return
272 return
251
273
252 def getData(self):
274 def getData(self):
253
275 if not self.isDateTimeInRange(self.startFileDatetime, self.startDate, self.endDate, self.startTime, self.endTime):
276 self.dataOut.flagNoData = True
277 self.dataOut.error = True
278 return
254 for attr in self.data:
279 for attr in self.data:
255 if self.data[attr].ndim == 1:
280 if self.data[attr].ndim == 1:
256 setattr(self.dataOut, attr, self.data[attr][self.blockIndex])
281 setattr(self.dataOut, attr, self.data[attr][self.blockIndex])
257 else:
282 else:
258 setattr(self.dataOut, attr, self.data[attr][:, self.blockIndex])
283 setattr(self.dataOut, attr, self.data[attr][:, self.blockIndex])
259
284
260 self.dataOut.flagNoData = False
285 self.dataOut.flagNoData = False
261 self.blockIndex += 1
286 self.blockIndex += 1
262
287
263 log.log("Block No. {}/{} -> {}".format(
288 log.log("Block No. {}/{} -> {}".format(
264 self.blockIndex,
289 self.blockIndex,
265 self.blocksPerFile,
290 self.blocksPerFile,
266 self.dataOut.datatime.ctime()), self.name)
291 self.dataOut.datatime.ctime()), self.name)
267
292
268 return
293 return
269
294
270 def run(self, **kwargs):
295 def run(self, **kwargs):
271
296
272 if not(self.isConfig):
297 if not(self.isConfig):
273 self.setup(**kwargs)
298 self.setup(**kwargs)
274 self.isConfig = True
299 self.isConfig = True
275
300
276 if self.blockIndex == self.blocksPerFile:
301 if self.blockIndex == self.blocksPerFile:
277 self.setNextFile()
302 self.setNextFile()
278
303
279 self.getData()
304 self.getData()
280
305
281 return
306 return
282
307
283 @MPDecorator
308 @MPDecorator
284 class HDFWriter(Operation):
309 class HDFWriter(Operation):
285 """Operation to write HDF5 files.
310 """Operation to write HDF5 files.
286
311
287 The HDF5 file contains by default two groups Data and Metadata where
312 The HDF5 file contains by default two groups Data and Metadata where
288 you can save any `dataOut` attribute specified by `dataList` and `metadataList`
313 you can save any `dataOut` attribute specified by `dataList` and `metadataList`
289 parameters, data attributes are normaly time dependent where the metadata
314 parameters, data attributes are normaly time dependent where the metadata
290 are not.
315 are not.
291 It is possible to customize the structure of the HDF5 file with the
316 It is possible to customize the structure of the HDF5 file with the
292 optional description parameter see the examples.
317 optional description parameter see the examples.
293
318
294 Parameters:
319 Parameters:
295 -----------
320 -----------
296 path : str
321 path : str
297 Path where files will be saved.
322 Path where files will be saved.
298 blocksPerFile : int
323 blocksPerFile : int
299 Number of blocks per file
324 Number of blocks per file
300 metadataList : list
325 metadataList : list
301 List of the dataOut attributes that will be saved as metadata
326 List of the dataOut attributes that will be saved as metadata
302 dataList : int
327 dataList : int
303 List of the dataOut attributes that will be saved as data
328 List of the dataOut attributes that will be saved as data
304 setType : bool
329 setType : bool
305 If True the name of the files corresponds to the timestamp of the data
330 If True the name of the files corresponds to the timestamp of the data
306 description : dict, optional
331 description : dict, optional
307 Dictionary with the desired description of the HDF5 file
332 Dictionary with the desired description of the HDF5 file
308
333
309 Examples
334 Examples
310 --------
335 --------
311
336
312 desc = {
337 desc = {
313 'data_output': {'winds': ['z', 'w', 'v']},
338 'data_output': {'winds': ['z', 'w', 'v']},
314 'utctime': 'timestamps',
339 'utctime': 'timestamps',
315 'heightList': 'heights'
340 'heightList': 'heights'
316 }
341 }
317 desc = {
342 desc = {
318 'data_output': ['z', 'w', 'v'],
343 'data_output': ['z', 'w', 'v'],
319 'utctime': 'timestamps',
344 'utctime': 'timestamps',
320 'heightList': 'heights'
345 'heightList': 'heights'
321 }
346 }
322 desc = {
347 desc = {
323 'Data': {
348 'Data': {
324 'data_output': 'winds',
349 'data_output': 'winds',
325 'utctime': 'timestamps'
350 'utctime': 'timestamps'
326 },
351 },
327 'Metadata': {
352 'Metadata': {
328 'heightList': 'heights'
353 'heightList': 'heights'
329 }
354 }
330 }
355 }
331
356
332 writer = proc_unit.addOperation(name='HDFWriter')
357 writer = proc_unit.addOperation(name='HDFWriter')
333 writer.addParameter(name='path', value='/path/to/file')
358 writer.addParameter(name='path', value='/path/to/file')
334 writer.addParameter(name='blocksPerFile', value='32')
359 writer.addParameter(name='blocksPerFile', value='32')
335 writer.addParameter(name='metadataList', value='heightList,timeZone')
360 writer.addParameter(name='metadataList', value='heightList,timeZone')
336 writer.addParameter(name='dataList',value='data_output,utctime')
361 writer.addParameter(name='dataList',value='data_output,utctime')
337 # writer.addParameter(name='description',value=json.dumps(desc))
362 # writer.addParameter(name='description',value=json.dumps(desc))
338
363
339 """
364 """
340
365
341 ext = ".hdf5"
366 ext = ".hdf5"
342 optchar = "D"
367 optchar = "D"
343 filename = None
368 filename = None
344 path = None
369 path = None
345 setFile = None
370 setFile = None
346 fp = None
371 fp = None
347 firsttime = True
372 firsttime = True
348 #Configurations
373 #Configurations
349 blocksPerFile = None
374 blocksPerFile = None
350 blockIndex = None
375 blockIndex = None
351 dataOut = None
376 dataOut = None
352 #Data Arrays
377 #Data Arrays
353 dataList = None
378 dataList = None
354 metadataList = None
379 metadataList = None
355 currentDay = None
380 currentDay = None
356 lastTime = None
381 lastTime = None
357
382
358 def __init__(self):
383 def __init__(self):
359
384
360 Operation.__init__(self)
385 Operation.__init__(self)
361 return
386 return
362
387
363 def setup(self, path=None, blocksPerFile=10, metadataList=None, dataList=None, setType=None, description=None):
388 def setup(self, path=None, blocksPerFile=10, metadataList=None, dataList=None, setType=None, description=None):
364 self.path = path
389 self.path = path
365 self.blocksPerFile = blocksPerFile
390 self.blocksPerFile = blocksPerFile
366 self.metadataList = metadataList
391 self.metadataList = metadataList
367 self.dataList = [s.strip() for s in dataList]
392 self.dataList = [s.strip() for s in dataList]
368 self.setType = setType
393 self.setType = setType
369 self.description = description
394 self.description = description
370
395
371 if self.metadataList is None:
396 if self.metadataList is None:
372 self.metadataList = self.dataOut.metadata_list
397 self.metadataList = self.dataOut.metadata_list
373
398
374 tableList = []
399 tableList = []
375 dsList = []
400 dsList = []
376
401
377 for i in range(len(self.dataList)):
402 for i in range(len(self.dataList)):
378 dsDict = {}
403 dsDict = {}
379 if hasattr(self.dataOut, self.dataList[i]):
404 if hasattr(self.dataOut, self.dataList[i]):
380 dataAux = getattr(self.dataOut, self.dataList[i])
405 dataAux = getattr(self.dataOut, self.dataList[i])
381 dsDict['variable'] = self.dataList[i]
406 dsDict['variable'] = self.dataList[i]
382 else:
407 else:
383 log.warning('Attribute {} not found in dataOut', self.name)
408 log.warning('Attribute {} not found in dataOut', self.name)
384 continue
409 continue
385
410
386 if dataAux is None:
411 if dataAux is None:
387 continue
412 continue
388 elif isinstance(dataAux, (int, float, numpy.integer, numpy.float)):
413 elif isinstance(dataAux, (int, float, numpy.integer, numpy.float)):
389 dsDict['nDim'] = 0
414 dsDict['nDim'] = 0
390 else:
415 else:
391 dsDict['nDim'] = len(dataAux.shape)
416 dsDict['nDim'] = len(dataAux.shape)
392 dsDict['shape'] = dataAux.shape
417 dsDict['shape'] = dataAux.shape
393 dsDict['dsNumber'] = dataAux.shape[0]
418 dsDict['dsNumber'] = dataAux.shape[0]
394 dsDict['dtype'] = dataAux.dtype
419 dsDict['dtype'] = dataAux.dtype
395
420
396 dsList.append(dsDict)
421 dsList.append(dsDict)
397
422
398 self.dsList = dsList
423 self.dsList = dsList
399 self.currentDay = self.dataOut.datatime.date()
424 self.currentDay = self.dataOut.datatime.date()
400
425
401 def timeFlag(self):
426 def timeFlag(self):
402 currentTime = self.dataOut.utctime
427 currentTime = self.dataOut.utctime
403 timeTuple = time.localtime(currentTime)
428 timeTuple = time.localtime(currentTime)
404 dataDay = timeTuple.tm_yday
429 dataDay = timeTuple.tm_yday
405
430
406 if self.lastTime is None:
431 if self.lastTime is None:
407 self.lastTime = currentTime
432 self.lastTime = currentTime
408 self.currentDay = dataDay
433 self.currentDay = dataDay
409 return False
434 return False
410
435
411 timeDiff = currentTime - self.lastTime
436 timeDiff = currentTime - self.lastTime
412
437
413 #Si el dia es diferente o si la diferencia entre un dato y otro supera la hora
438 #Si el dia es diferente o si la diferencia entre un dato y otro supera la hora
414 if dataDay != self.currentDay:
439 if dataDay != self.currentDay:
415 self.currentDay = dataDay
440 self.currentDay = dataDay
416 return True
441 return True
417 elif timeDiff > 3*60*60:
442 elif timeDiff > 3*60*60:
418 self.lastTime = currentTime
443 self.lastTime = currentTime
419 return True
444 return True
420 else:
445 else:
421 self.lastTime = currentTime
446 self.lastTime = currentTime
422 return False
447 return False
423
448
424 def run(self, dataOut, path, blocksPerFile=10, metadataList=None,
449 def run(self, dataOut, path, blocksPerFile=10, metadataList=None,
425 dataList=[], setType=None, description={}):
450 dataList=[], setType=None, description={}):
426
451
427 self.dataOut = dataOut
452 self.dataOut = dataOut
428 if not(self.isConfig):
453 if not(self.isConfig):
429 self.setup(path=path, blocksPerFile=blocksPerFile,
454 self.setup(path=path, blocksPerFile=blocksPerFile,
430 metadataList=metadataList, dataList=dataList,
455 metadataList=metadataList, dataList=dataList,
431 setType=setType, description=description)
456 setType=setType, description=description)
432
457
433 self.isConfig = True
458 self.isConfig = True
434 self.setNextFile()
459 self.setNextFile()
435
460
436 self.putData()
461 self.putData()
437 return
462 return
438
463
439 def setNextFile(self):
464 def setNextFile(self):
440
465
441 ext = self.ext
466 ext = self.ext
442 path = self.path
467 path = self.path
443 setFile = self.setFile
468 setFile = self.setFile
444
469
445 timeTuple = time.localtime(self.dataOut.utctime)
470 timeTuple = time.localtime(self.dataOut.utctime)
446 subfolder = 'd%4.4d%3.3d' % (timeTuple.tm_year,timeTuple.tm_yday)
471 subfolder = 'd%4.4d%3.3d' % (timeTuple.tm_year,timeTuple.tm_yday)
447 fullpath = os.path.join(path, subfolder)
472 fullpath = os.path.join(path, subfolder)
448
473
449 if os.path.exists(fullpath):
474 if os.path.exists(fullpath):
450 filesList = os.listdir(fullpath)
475 filesList = os.listdir(fullpath)
451 filesList = [k for k in filesList if k.startswith(self.optchar)]
476 filesList = [k for k in filesList if k.startswith(self.optchar)]
452 if len( filesList ) > 0:
477 if len( filesList ) > 0:
453 filesList = sorted(filesList, key=str.lower)
478 filesList = sorted(filesList, key=str.lower)
454 filen = filesList[-1]
479 filen = filesList[-1]
455 # el filename debera tener el siguiente formato
480 # el filename debera tener el siguiente formato
456 # 0 1234 567 89A BCDE (hex)
481 # 0 1234 567 89A BCDE (hex)
457 # x YYYY DDD SSS .ext
482 # x YYYY DDD SSS .ext
458 if isNumber(filen[8:11]):
483 if isNumber(filen[8:11]):
459 setFile = int(filen[8:11]) #inicializo mi contador de seteo al seteo del ultimo file
484 setFile = int(filen[8:11]) #inicializo mi contador de seteo al seteo del ultimo file
460 else:
485 else:
461 setFile = -1
486 setFile = -1
462 else:
487 else:
463 setFile = -1 #inicializo mi contador de seteo
488 setFile = -1 #inicializo mi contador de seteo
464 else:
489 else:
465 os.makedirs(fullpath)
490 os.makedirs(fullpath)
466 setFile = -1 #inicializo mi contador de seteo
491 setFile = -1 #inicializo mi contador de seteo
467
492
468 if self.setType is None:
493 if self.setType is None:
469 setFile += 1
494 setFile += 1
470 file = '%s%4.4d%3.3d%03d%s' % (self.optchar,
495 file = '%s%4.4d%3.3d%03d%s' % (self.optchar,
471 timeTuple.tm_year,
496 timeTuple.tm_year,
472 timeTuple.tm_yday,
497 timeTuple.tm_yday,
473 setFile,
498 setFile,
474 ext )
499 ext )
475 else:
500 else:
476 setFile = timeTuple.tm_hour*60+timeTuple.tm_min
501 setFile = timeTuple.tm_hour*60+timeTuple.tm_min
477 file = '%s%4.4d%3.3d%04d%s' % (self.optchar,
502 file = '%s%4.4d%3.3d%04d%s' % (self.optchar,
478 timeTuple.tm_year,
503 timeTuple.tm_year,
479 timeTuple.tm_yday,
504 timeTuple.tm_yday,
480 setFile,
505 setFile,
481 ext )
506 ext )
482
507
483 self.filename = os.path.join( path, subfolder, file )
508 self.filename = os.path.join( path, subfolder, file )
484
509
485 #Setting HDF5 File
510 #Setting HDF5 File
486 self.fp = h5py.File(self.filename, 'w')
511 self.fp = h5py.File(self.filename, 'w')
487 #write metadata
512 #write metadata
488 self.writeMetadata(self.fp)
513 self.writeMetadata(self.fp)
489 #Write data
514 #Write data
490 self.writeData(self.fp)
515 self.writeData(self.fp)
491
516
492 def getLabel(self, name, x=None):
517 def getLabel(self, name, x=None):
493
518
494 if x is None:
519 if x is None:
495 if 'Data' in self.description:
520 if 'Data' in self.description:
496 data = self.description['Data']
521 data = self.description['Data']
497 if 'Metadata' in self.description:
522 if 'Metadata' in self.description:
498 data.update(self.description['Metadata'])
523 data.update(self.description['Metadata'])
499 else:
524 else:
500 data = self.description
525 data = self.description
501 if name in data:
526 if name in data:
502 if isinstance(data[name], str):
527 if isinstance(data[name], str):
503 return data[name]
528 return data[name]
504 elif isinstance(data[name], list):
529 elif isinstance(data[name], list):
505 return None
530 return None
506 elif isinstance(data[name], dict):
531 elif isinstance(data[name], dict):
507 for key, value in data[name].items():
532 for key, value in data[name].items():
508 return key
533 return key
509 return name
534 return name
510 else:
535 else:
511 if 'Metadata' in self.description:
536 if 'Metadata' in self.description:
512 meta = self.description['Metadata']
537 meta = self.description['Metadata']
513 else:
538 else:
514 meta = self.description
539 meta = self.description
515 if name in meta:
540 if name in meta:
516 if isinstance(meta[name], list):
541 if isinstance(meta[name], list):
517 return meta[name][x]
542 return meta[name][x]
518 elif isinstance(meta[name], dict):
543 elif isinstance(meta[name], dict):
519 for key, value in meta[name].items():
544 for key, value in meta[name].items():
520 return value[x]
545 return value[x]
521 if 'cspc' in name:
546 if 'cspc' in name:
522 return 'pair{:02d}'.format(x)
547 return 'pair{:02d}'.format(x)
523 else:
548 else:
524 return 'channel{:02d}'.format(x)
549 return 'channel{:02d}'.format(x)
525
550
526 def writeMetadata(self, fp):
551 def writeMetadata(self, fp):
527
552
528 if self.description:
553 if self.description:
529 if 'Metadata' in self.description:
554 if 'Metadata' in self.description:
530 grp = fp.create_group('Metadata')
555 grp = fp.create_group('Metadata')
531 else:
556 else:
532 grp = fp
557 grp = fp
533 else:
558 else:
534 grp = fp.create_group('Metadata')
559 grp = fp.create_group('Metadata')
535
560
536 for i in range(len(self.metadataList)):
561 for i in range(len(self.metadataList)):
537 if not hasattr(self.dataOut, self.metadataList[i]):
562 if not hasattr(self.dataOut, self.metadataList[i]):
538 log.warning('Metadata: `{}` not found'.format(self.metadataList[i]), self.name)
563 log.warning('Metadata: `{}` not found'.format(self.metadataList[i]), self.name)
539 continue
564 continue
540 value = getattr(self.dataOut, self.metadataList[i])
565 value = getattr(self.dataOut, self.metadataList[i])
541 if isinstance(value, bool):
566 if isinstance(value, bool):
542 if value is True:
567 if value is True:
543 value = 1
568 value = 1
544 else:
569 else:
545 value = 0
570 value = 0
546 grp.create_dataset(self.getLabel(self.metadataList[i]), data=value)
571 grp.create_dataset(self.getLabel(self.metadataList[i]), data=value)
547 return
572 return
548
573
549 def writeData(self, fp):
574 def writeData(self, fp):
550
575
551 if self.description:
576 if self.description:
552 if 'Data' in self.description:
577 if 'Data' in self.description:
553 grp = fp.create_group('Data')
578 grp = fp.create_group('Data')
554 else:
579 else:
555 grp = fp
580 grp = fp
556 else:
581 else:
557 grp = fp.create_group('Data')
582 grp = fp.create_group('Data')
558
583
559 dtsets = []
584 dtsets = []
560 data = []
585 data = []
561
586
562 for dsInfo in self.dsList:
587 for dsInfo in self.dsList:
563 if dsInfo['nDim'] == 0:
588 if dsInfo['nDim'] == 0:
564 ds = grp.create_dataset(
589 ds = grp.create_dataset(
565 self.getLabel(dsInfo['variable']),
590 self.getLabel(dsInfo['variable']),
566 (self.blocksPerFile, ),
591 (self.blocksPerFile, ),
567 chunks=True,
592 chunks=True,
568 dtype=numpy.float64)
593 dtype=numpy.float64)
569 dtsets.append(ds)
594 dtsets.append(ds)
570 data.append((dsInfo['variable'], -1))
595 data.append((dsInfo['variable'], -1))
571 else:
596 else:
572 label = self.getLabel(dsInfo['variable'])
597 label = self.getLabel(dsInfo['variable'])
573 if label is not None:
598 if label is not None:
574 sgrp = grp.create_group(label)
599 sgrp = grp.create_group(label)
575 else:
600 else:
576 sgrp = grp
601 sgrp = grp
577 for i in range(dsInfo['dsNumber']):
602 for i in range(dsInfo['dsNumber']):
578 ds = sgrp.create_dataset(
603 ds = sgrp.create_dataset(
579 self.getLabel(dsInfo['variable'], i),
604 self.getLabel(dsInfo['variable'], i),
580 (self.blocksPerFile, ) + dsInfo['shape'][1:],
605 (self.blocksPerFile, ) + dsInfo['shape'][1:],
581 chunks=True,
606 chunks=True,
582 dtype=dsInfo['dtype'])
607 dtype=dsInfo['dtype'])
583 dtsets.append(ds)
608 dtsets.append(ds)
584 data.append((dsInfo['variable'], i))
609 data.append((dsInfo['variable'], i))
585 fp.flush()
610 fp.flush()
586
611
587 log.log('Creating file: {}'.format(fp.filename), self.name)
612 log.log('Creating file: {}'.format(fp.filename), self.name)
588
613
589 self.ds = dtsets
614 self.ds = dtsets
590 self.data = data
615 self.data = data
591 self.firsttime = True
616 self.firsttime = True
592 self.blockIndex = 0
617 self.blockIndex = 0
593 return
618 return
594
619
595 def putData(self):
620 def putData(self):
596
621
597 if (self.blockIndex == self.blocksPerFile) or self.timeFlag():
622 if (self.blockIndex == self.blocksPerFile) or self.timeFlag():
598 self.closeFile()
623 self.closeFile()
599 self.setNextFile()
624 self.setNextFile()
600
625
601 for i, ds in enumerate(self.ds):
626 for i, ds in enumerate(self.ds):
602 attr, ch = self.data[i]
627 attr, ch = self.data[i]
603 if ch == -1:
628 if ch == -1:
604 ds[self.blockIndex] = getattr(self.dataOut, attr)
629 ds[self.blockIndex] = getattr(self.dataOut, attr)
605 else:
630 else:
606 ds[self.blockIndex] = getattr(self.dataOut, attr)[ch]
631 ds[self.blockIndex] = getattr(self.dataOut, attr)[ch]
607
632
608 self.fp.flush()
633 self.fp.flush()
609 self.blockIndex += 1
634 self.blockIndex += 1
610 log.log('Block No. {}/{}'.format(self.blockIndex, self.blocksPerFile), self.name)
635 log.log('Block No. {}/{}'.format(self.blockIndex, self.blocksPerFile), self.name)
611
636
612 return
637 return
613
638
614 def closeFile(self):
639 def closeFile(self):
615
640
616 if self.blockIndex != self.blocksPerFile:
641 if self.blockIndex != self.blocksPerFile:
617 for ds in self.ds:
642 for ds in self.ds:
618 ds.resize(self.blockIndex, axis=0)
643 ds.resize(self.blockIndex, axis=0)
619
644
620 if self.fp:
645 if self.fp:
621 self.fp.flush()
646 self.fp.flush()
622 self.fp.close()
647 self.fp.close()
623
648
624 def close(self):
649 def close(self):
625
650
626 self.closeFile()
651 self.closeFile()
@@ -1,3890 +1,3889
1 import numpy
1 import numpy
2 import math
2 import math
3 from scipy import optimize, interpolate, signal, stats, ndimage
3 from scipy import optimize, interpolate, signal, stats, ndimage
4 import scipy
4 import scipy
5 import re
5 import re
6 import datetime
6 import datetime
7 import copy
7 import copy
8 import sys
8 import sys
9 import importlib
9 import importlib
10 import itertools
10 import itertools
11 from multiprocessing import Pool, TimeoutError
11 from multiprocessing import Pool, TimeoutError
12 from multiprocessing.pool import ThreadPool
12 from multiprocessing.pool import ThreadPool
13 import time
13 import time
14
14
15 from scipy.optimize import fmin_l_bfgs_b #optimize with bounds on state papameters
15 from scipy.optimize import fmin_l_bfgs_b #optimize with bounds on state papameters
16 from .jroproc_base import ProcessingUnit, Operation, MPDecorator
16 from .jroproc_base import ProcessingUnit, Operation, MPDecorator
17 from schainpy.model.data.jrodata import Parameters, hildebrand_sekhon
17 from schainpy.model.data.jrodata import Parameters, hildebrand_sekhon
18 from scipy import asarray as ar,exp
18 from scipy import asarray as ar,exp
19 from scipy.optimize import curve_fit
19 from scipy.optimize import curve_fit
20 from schainpy.utils import log
20 from schainpy.utils import log
21 import warnings
21 import warnings
22 from numpy import NaN
22 from numpy import NaN
23 from scipy.optimize.optimize import OptimizeWarning
23 from scipy.optimize.optimize import OptimizeWarning
24 warnings.filterwarnings('ignore')
24 warnings.filterwarnings('ignore')
25
25
26 import matplotlib.pyplot as plt
26 import matplotlib.pyplot as plt
27
27
28 SPEED_OF_LIGHT = 299792458
28 SPEED_OF_LIGHT = 299792458
29
29
30 '''solving pickling issue'''
30 '''solving pickling issue'''
31
31
32 def _pickle_method(method):
32 def _pickle_method(method):
33 func_name = method.__func__.__name__
33 func_name = method.__func__.__name__
34 obj = method.__self__
34 obj = method.__self__
35 cls = method.__self__.__class__
35 cls = method.__self__.__class__
36 return _unpickle_method, (func_name, obj, cls)
36 return _unpickle_method, (func_name, obj, cls)
37
37
38 def _unpickle_method(func_name, obj, cls):
38 def _unpickle_method(func_name, obj, cls):
39 for cls in cls.mro():
39 for cls in cls.mro():
40 try:
40 try:
41 func = cls.__dict__[func_name]
41 func = cls.__dict__[func_name]
42 except KeyError:
42 except KeyError:
43 pass
43 pass
44 else:
44 else:
45 break
45 break
46 return func.__get__(obj, cls)
46 return func.__get__(obj, cls)
47
47
48
48
49 class ParametersProc(ProcessingUnit):
49 class ParametersProc(ProcessingUnit):
50
50
51 METHODS = {}
51 METHODS = {}
52 nSeconds = None
52 nSeconds = None
53
53
54 def __init__(self):
54 def __init__(self):
55 ProcessingUnit.__init__(self)
55 ProcessingUnit.__init__(self)
56
56
57 # self.objectDict = {}
57 # self.objectDict = {}
58 self.buffer = None
58 self.buffer = None
59 self.firstdatatime = None
59 self.firstdatatime = None
60 self.profIndex = 0
60 self.profIndex = 0
61 self.dataOut = Parameters()
61 self.dataOut = Parameters()
62 self.setupReq = False #Agregar a todas las unidades de proc
62 self.setupReq = False #Agregar a todas las unidades de proc
63
63 print("INIT PROC")
64 def __updateObjFromInput(self):
64 def __updateObjFromInput(self):
65
65
66 self.dataOut.inputUnit = self.dataIn.type
66 self.dataOut.inputUnit = self.dataIn.type
67
67
68 self.dataOut.timeZone = self.dataIn.timeZone
68 self.dataOut.timeZone = self.dataIn.timeZone
69 self.dataOut.dstFlag = self.dataIn.dstFlag
69 self.dataOut.dstFlag = self.dataIn.dstFlag
70 self.dataOut.errorCount = self.dataIn.errorCount
70 self.dataOut.errorCount = self.dataIn.errorCount
71 self.dataOut.useLocalTime = self.dataIn.useLocalTime
71 self.dataOut.useLocalTime = self.dataIn.useLocalTime
72
72
73 self.dataOut.radarControllerHeaderObj = self.dataIn.radarControllerHeaderObj.copy()
73 self.dataOut.radarControllerHeaderObj = self.dataIn.radarControllerHeaderObj.copy()
74 self.dataOut.systemHeaderObj = self.dataIn.systemHeaderObj.copy()
74 self.dataOut.systemHeaderObj = self.dataIn.systemHeaderObj.copy()
75 self.dataOut.channelList = self.dataIn.channelList
75 self.dataOut.channelList = self.dataIn.channelList
76 self.dataOut.heightList = self.dataIn.heightList
76 self.dataOut.heightList = self.dataIn.heightList
77 self.dataOut.dtype = numpy.dtype([('real','<f4'),('imag','<f4')])
77 self.dataOut.dtype = numpy.dtype([('real','<f4'),('imag','<f4')])
78 # self.dataOut.nHeights = self.dataIn.nHeights
78 # self.dataOut.nHeights = self.dataIn.nHeights
79 # self.dataOut.nChannels = self.dataIn.nChannels
79 # self.dataOut.nChannels = self.dataIn.nChannels
80 # self.dataOut.nBaud = self.dataIn.nBaud
80 # self.dataOut.nBaud = self.dataIn.nBaud
81 # self.dataOut.nCode = self.dataIn.nCode
81 # self.dataOut.nCode = self.dataIn.nCode
82 # self.dataOut.code = self.dataIn.code
82 # self.dataOut.code = self.dataIn.code
83 # self.dataOut.nProfiles = self.dataOut.nFFTPoints
83 # self.dataOut.nProfiles = self.dataOut.nFFTPoints
84 self.dataOut.flagDiscontinuousBlock = self.dataIn.flagDiscontinuousBlock
84 self.dataOut.flagDiscontinuousBlock = self.dataIn.flagDiscontinuousBlock
85 # self.dataOut.utctime = self.firstdatatime
85 # self.dataOut.utctime = self.firstdatatime
86 self.dataOut.utctime = self.dataIn.utctime
86 self.dataOut.utctime = self.dataIn.utctime
87 self.dataOut.flagDecodeData = self.dataIn.flagDecodeData #asumo q la data esta decodificada
87 self.dataOut.flagDecodeData = self.dataIn.flagDecodeData #asumo q la data esta decodificada
88 self.dataOut.flagDeflipData = self.dataIn.flagDeflipData #asumo q la data esta sin flip
88 self.dataOut.flagDeflipData = self.dataIn.flagDeflipData #asumo q la data esta sin flip
89 self.dataOut.nCohInt = self.dataIn.nCohInt
89 self.dataOut.nCohInt = self.dataIn.nCohInt
90 # self.dataOut.nIncohInt = 1
90 # self.dataOut.nIncohInt = 1
91 # self.dataOut.ippSeconds = self.dataIn.ippSeconds
91 # self.dataOut.ippSeconds = self.dataIn.ippSeconds
92 # self.dataOut.windowOfFilter = self.dataIn.windowOfFilter
92 # self.dataOut.windowOfFilter = self.dataIn.windowOfFilter
93 self.dataOut.timeInterval1 = self.dataIn.timeInterval
93 self.dataOut.timeInterval1 = self.dataIn.timeInterval
94 self.dataOut.heightList = self.dataIn.heightList
94 self.dataOut.heightList = self.dataIn.heightList
95 self.dataOut.frequency = self.dataIn.frequency
95 self.dataOut.frequency = self.dataIn.frequency
96 # self.dataOut.noise = self.dataIn.noise
96 # self.dataOut.noise = self.dataIn.noise
97 self.dataOut.codeList = self.dataIn.codeList
97 self.dataOut.codeList = self.dataIn.codeList
98 self.dataOut.azimuthList = self.dataIn.azimuthList
98 self.dataOut.azimuthList = self.dataIn.azimuthList
99 self.dataOut.elevationList = self.dataIn.elevationList
99 self.dataOut.elevationList = self.dataIn.elevationList
100
100
101 def run(self):
101 def run(self):
102
102 print("run proc param")
103
104
103
105 #---------------------- Voltage Data ---------------------------
104 #---------------------- Voltage Data ---------------------------
106
105
107 if self.dataIn.type == "Voltage":
106 if self.dataIn.type == "Voltage":
108
107
109 self.__updateObjFromInput()
108 self.__updateObjFromInput()
110 self.dataOut.data_pre = self.dataIn.data.copy()
109 self.dataOut.data_pre = self.dataIn.data.copy()
111 self.dataOut.flagNoData = False
110 self.dataOut.flagNoData = False
112 self.dataOut.utctimeInit = self.dataIn.utctime
111 self.dataOut.utctimeInit = self.dataIn.utctime
113 self.dataOut.paramInterval = self.dataIn.nProfiles*self.dataIn.nCohInt*self.dataIn.ippSeconds
112 self.dataOut.paramInterval = self.dataIn.nProfiles*self.dataIn.nCohInt*self.dataIn.ippSeconds
114 if hasattr(self.dataIn, 'dataPP_POW'):
113 if hasattr(self.dataIn, 'dataPP_POW'):
115 self.dataOut.dataPP_POW = self.dataIn.dataPP_POW
114 self.dataOut.dataPP_POW = self.dataIn.dataPP_POW
116
115
117 if hasattr(self.dataIn, 'dataPP_POWER'):
116 if hasattr(self.dataIn, 'dataPP_POWER'):
118 self.dataOut.dataPP_POWER = self.dataIn.dataPP_POWER
117 self.dataOut.dataPP_POWER = self.dataIn.dataPP_POWER
119
118
120 if hasattr(self.dataIn, 'dataPP_DOP'):
119 if hasattr(self.dataIn, 'dataPP_DOP'):
121 self.dataOut.dataPP_DOP = self.dataIn.dataPP_DOP
120 self.dataOut.dataPP_DOP = self.dataIn.dataPP_DOP
122
121
123 if hasattr(self.dataIn, 'dataPP_SNR'):
122 if hasattr(self.dataIn, 'dataPP_SNR'):
124 self.dataOut.dataPP_SNR = self.dataIn.dataPP_SNR
123 self.dataOut.dataPP_SNR = self.dataIn.dataPP_SNR
125
124
126 if hasattr(self.dataIn, 'dataPP_WIDTH'):
125 if hasattr(self.dataIn, 'dataPP_WIDTH'):
127 self.dataOut.dataPP_WIDTH = self.dataIn.dataPP_WIDTH
126 self.dataOut.dataPP_WIDTH = self.dataIn.dataPP_WIDTH
128 return
127 return
129
128
130 #---------------------- Spectra Data ---------------------------
129 #---------------------- Spectra Data ---------------------------
131
130
132 if self.dataIn.type == "Spectra":
131 if self.dataIn.type == "Spectra":
133
132
134 self.dataOut.data_pre = [self.dataIn.data_spc, self.dataIn.data_cspc]
133 self.dataOut.data_pre = [self.dataIn.data_spc, self.dataIn.data_cspc]
135 self.dataOut.data_spc = self.dataIn.data_spc
134 self.dataOut.data_spc = self.dataIn.data_spc
136 self.dataOut.data_cspc = self.dataIn.data_cspc
135 self.dataOut.data_cspc = self.dataIn.data_cspc
137 self.dataOut.nProfiles = self.dataIn.nProfiles
136 self.dataOut.nProfiles = self.dataIn.nProfiles
138 self.dataOut.nIncohInt = self.dataIn.nIncohInt
137 self.dataOut.nIncohInt = self.dataIn.nIncohInt
139 self.dataOut.nFFTPoints = self.dataIn.nFFTPoints
138 self.dataOut.nFFTPoints = self.dataIn.nFFTPoints
140 self.dataOut.ippFactor = self.dataIn.ippFactor
139 self.dataOut.ippFactor = self.dataIn.ippFactor
141 self.dataOut.abscissaList = self.dataIn.getVelRange(1)
140 self.dataOut.abscissaList = self.dataIn.getVelRange(1)
142 self.dataOut.spc_noise = self.dataIn.getNoise()
141 self.dataOut.spc_noise = self.dataIn.getNoise()
143 self.dataOut.spc_range = (self.dataIn.getFreqRange(1) , self.dataIn.getAcfRange(1) , self.dataIn.getVelRange(1))
142 self.dataOut.spc_range = (self.dataIn.getFreqRange(1) , self.dataIn.getAcfRange(1) , self.dataIn.getVelRange(1))
144 # self.dataOut.normFactor = self.dataIn.normFactor
143 # self.dataOut.normFactor = self.dataIn.normFactor
145 self.dataOut.pairsList = self.dataIn.pairsList
144 self.dataOut.pairsList = self.dataIn.pairsList
146 self.dataOut.groupList = self.dataIn.pairsList
145 self.dataOut.groupList = self.dataIn.pairsList
147 self.dataOut.flagNoData = False
146 self.dataOut.flagNoData = False
148
147
149 if hasattr(self.dataIn, 'ChanDist'): #Distances of receiver channels
148 if hasattr(self.dataIn, 'ChanDist'): #Distances of receiver channels
150 self.dataOut.ChanDist = self.dataIn.ChanDist
149 self.dataOut.ChanDist = self.dataIn.ChanDist
151 else: self.dataOut.ChanDist = None
150 else: self.dataOut.ChanDist = None
152
151
153 #if hasattr(self.dataIn, 'VelRange'): #Velocities range
152 #if hasattr(self.dataIn, 'VelRange'): #Velocities range
154 # self.dataOut.VelRange = self.dataIn.VelRange
153 # self.dataOut.VelRange = self.dataIn.VelRange
155 #else: self.dataOut.VelRange = None
154 #else: self.dataOut.VelRange = None
156
155
157 if hasattr(self.dataIn, 'RadarConst'): #Radar Constant
156 if hasattr(self.dataIn, 'RadarConst'): #Radar Constant
158 self.dataOut.RadarConst = self.dataIn.RadarConst
157 self.dataOut.RadarConst = self.dataIn.RadarConst
159
158
160 if hasattr(self.dataIn, 'NPW'): #NPW
159 if hasattr(self.dataIn, 'NPW'): #NPW
161 self.dataOut.NPW = self.dataIn.NPW
160 self.dataOut.NPW = self.dataIn.NPW
162
161
163 if hasattr(self.dataIn, 'COFA'): #COFA
162 if hasattr(self.dataIn, 'COFA'): #COFA
164 self.dataOut.COFA = self.dataIn.COFA
163 self.dataOut.COFA = self.dataIn.COFA
165
164
166
165
167
166
168 #---------------------- Correlation Data ---------------------------
167 #---------------------- Correlation Data ---------------------------
169
168
170 if self.dataIn.type == "Correlation":
169 if self.dataIn.type == "Correlation":
171 acf_ind, ccf_ind, acf_pairs, ccf_pairs, data_acf, data_ccf = self.dataIn.splitFunctions()
170 acf_ind, ccf_ind, acf_pairs, ccf_pairs, data_acf, data_ccf = self.dataIn.splitFunctions()
172
171
173 self.dataOut.data_pre = (self.dataIn.data_cf[acf_ind,:], self.dataIn.data_cf[ccf_ind,:,:])
172 self.dataOut.data_pre = (self.dataIn.data_cf[acf_ind,:], self.dataIn.data_cf[ccf_ind,:,:])
174 self.dataOut.normFactor = (self.dataIn.normFactor[acf_ind,:], self.dataIn.normFactor[ccf_ind,:])
173 self.dataOut.normFactor = (self.dataIn.normFactor[acf_ind,:], self.dataIn.normFactor[ccf_ind,:])
175 self.dataOut.groupList = (acf_pairs, ccf_pairs)
174 self.dataOut.groupList = (acf_pairs, ccf_pairs)
176
175
177 self.dataOut.abscissaList = self.dataIn.lagRange
176 self.dataOut.abscissaList = self.dataIn.lagRange
178 self.dataOut.noise = self.dataIn.noise
177 self.dataOut.noise = self.dataIn.noise
179 self.dataOut.data_snr = self.dataIn.SNR
178 self.dataOut.data_snr = self.dataIn.SNR
180 self.dataOut.flagNoData = False
179 self.dataOut.flagNoData = False
181 self.dataOut.nAvg = self.dataIn.nAvg
180 self.dataOut.nAvg = self.dataIn.nAvg
182
181
183 #---------------------- Parameters Data ---------------------------
182 #---------------------- Parameters Data ---------------------------
184
183
185 if self.dataIn.type == "Parameters":
184 if self.dataIn.type == "Parameters":
186 self.dataOut.copy(self.dataIn)
185 self.dataOut.copy(self.dataIn)
187 self.dataOut.flagNoData = False
186 self.dataOut.flagNoData = False
188
187 self.prin("DAta In")
189 return True
188 return True
190
189
191 self.__updateObjFromInput()
190 self.__updateObjFromInput()
192 self.dataOut.utctimeInit = self.dataIn.utctime
191 self.dataOut.utctimeInit = self.dataIn.utctime
193 self.dataOut.paramInterval = self.dataIn.timeInterval
192 self.dataOut.paramInterval = self.dataIn.timeInterval
194
193
195 return
194 return
196
195
197
196
198 def target(tups):
197 def target(tups):
199
198
200 obj, args = tups
199 obj, args = tups
201
200
202 return obj.FitGau(args)
201 return obj.FitGau(args)
203
202
204 class RemoveWideGC(Operation):
203 class RemoveWideGC(Operation):
205 ''' This class remove the wide clutter and replace it with a simple interpolation points
204 ''' This class remove the wide clutter and replace it with a simple interpolation points
206 This mainly applies to CLAIRE radar
205 This mainly applies to CLAIRE radar
207
206
208 ClutterWidth : Width to look for the clutter peak
207 ClutterWidth : Width to look for the clutter peak
209
208
210 Input:
209 Input:
211
210
212 self.dataOut.data_pre : SPC and CSPC
211 self.dataOut.data_pre : SPC and CSPC
213 self.dataOut.spc_range : To select wind and rainfall velocities
212 self.dataOut.spc_range : To select wind and rainfall velocities
214
213
215 Affected:
214 Affected:
216
215
217 self.dataOut.data_pre : It is used for the new SPC and CSPC ranges of wind
216 self.dataOut.data_pre : It is used for the new SPC and CSPC ranges of wind
218
217
219 Written by D. Scipión 25.02.2021
218 Written by D. Scipión 25.02.2021
220 '''
219 '''
221 def __init__(self):
220 def __init__(self):
222 Operation.__init__(self)
221 Operation.__init__(self)
223 self.i = 0
222 self.i = 0
224 self.ich = 0
223 self.ich = 0
225 self.ir = 0
224 self.ir = 0
226
225
227 def run(self, dataOut, ClutterWidth=2.5):
226 def run(self, dataOut, ClutterWidth=2.5):
228 # print ('Entering RemoveWideGC ... ')
227 # print ('Entering RemoveWideGC ... ')
229
228
230 self.spc = dataOut.data_pre[0].copy()
229 self.spc = dataOut.data_pre[0].copy()
231 self.spc_out = dataOut.data_pre[0].copy()
230 self.spc_out = dataOut.data_pre[0].copy()
232 self.Num_Chn = self.spc.shape[0]
231 self.Num_Chn = self.spc.shape[0]
233 self.Num_Hei = self.spc.shape[2]
232 self.Num_Hei = self.spc.shape[2]
234 VelRange = dataOut.spc_range[2][:-1]
233 VelRange = dataOut.spc_range[2][:-1]
235 dv = VelRange[1]-VelRange[0]
234 dv = VelRange[1]-VelRange[0]
236
235
237 # Find the velocities that corresponds to zero
236 # Find the velocities that corresponds to zero
238 gc_values = numpy.squeeze(numpy.where(numpy.abs(VelRange) <= ClutterWidth))
237 gc_values = numpy.squeeze(numpy.where(numpy.abs(VelRange) <= ClutterWidth))
239
238
240 # Removing novalid data from the spectra
239 # Removing novalid data from the spectra
241 for ich in range(self.Num_Chn) :
240 for ich in range(self.Num_Chn) :
242 for ir in range(self.Num_Hei) :
241 for ir in range(self.Num_Hei) :
243 # Estimate the noise at each range
242 # Estimate the noise at each range
244 HSn = hildebrand_sekhon(self.spc[ich,:,ir],dataOut.nIncohInt)
243 HSn = hildebrand_sekhon(self.spc[ich,:,ir],dataOut.nIncohInt)
245
244
246 # Removing the noise floor at each range
245 # Removing the noise floor at each range
247 novalid = numpy.where(self.spc[ich,:,ir] < HSn)
246 novalid = numpy.where(self.spc[ich,:,ir] < HSn)
248 self.spc[ich,novalid,ir] = HSn
247 self.spc[ich,novalid,ir] = HSn
249
248
250 junk = numpy.append(numpy.insert(numpy.squeeze(self.spc[ich,gc_values,ir]),0,HSn),HSn)
249 junk = numpy.append(numpy.insert(numpy.squeeze(self.spc[ich,gc_values,ir]),0,HSn),HSn)
251 j1index = numpy.squeeze(numpy.where(numpy.diff(junk)>0))
250 j1index = numpy.squeeze(numpy.where(numpy.diff(junk)>0))
252 j2index = numpy.squeeze(numpy.where(numpy.diff(junk)<0))
251 j2index = numpy.squeeze(numpy.where(numpy.diff(junk)<0))
253 if ((numpy.size(j1index)<=1) | (numpy.size(j2index)<=1)) :
252 if ((numpy.size(j1index)<=1) | (numpy.size(j2index)<=1)) :
254 continue
253 continue
255 junk3 = numpy.squeeze(numpy.diff(j1index))
254 junk3 = numpy.squeeze(numpy.diff(j1index))
256 junk4 = numpy.squeeze(numpy.diff(j2index))
255 junk4 = numpy.squeeze(numpy.diff(j2index))
257
256
258 valleyindex = j2index[numpy.where(junk4>1)]
257 valleyindex = j2index[numpy.where(junk4>1)]
259 peakindex = j1index[numpy.where(junk3>1)]
258 peakindex = j1index[numpy.where(junk3>1)]
260
259
261 isvalid = numpy.squeeze(numpy.where(numpy.abs(VelRange[gc_values[peakindex]]) <= 2.5*dv))
260 isvalid = numpy.squeeze(numpy.where(numpy.abs(VelRange[gc_values[peakindex]]) <= 2.5*dv))
262 if numpy.size(isvalid) == 0 :
261 if numpy.size(isvalid) == 0 :
263 continue
262 continue
264 if numpy.size(isvalid) >1 :
263 if numpy.size(isvalid) >1 :
265 vindex = numpy.argmax(self.spc[ich,gc_values[peakindex[isvalid]],ir])
264 vindex = numpy.argmax(self.spc[ich,gc_values[peakindex[isvalid]],ir])
266 isvalid = isvalid[vindex]
265 isvalid = isvalid[vindex]
267
266
268 # clutter peak
267 # clutter peak
269 gcpeak = peakindex[isvalid]
268 gcpeak = peakindex[isvalid]
270 vl = numpy.where(valleyindex < gcpeak)
269 vl = numpy.where(valleyindex < gcpeak)
271 if numpy.size(vl) == 0:
270 if numpy.size(vl) == 0:
272 continue
271 continue
273 gcvl = valleyindex[vl[0][-1]]
272 gcvl = valleyindex[vl[0][-1]]
274 vr = numpy.where(valleyindex > gcpeak)
273 vr = numpy.where(valleyindex > gcpeak)
275 if numpy.size(vr) == 0:
274 if numpy.size(vr) == 0:
276 continue
275 continue
277 gcvr = valleyindex[vr[0][0]]
276 gcvr = valleyindex[vr[0][0]]
278
277
279 # Removing the clutter
278 # Removing the clutter
280 interpindex = numpy.array([gc_values[gcvl], gc_values[gcvr]])
279 interpindex = numpy.array([gc_values[gcvl], gc_values[gcvr]])
281 gcindex = gc_values[gcvl+1:gcvr-1]
280 gcindex = gc_values[gcvl+1:gcvr-1]
282 self.spc_out[ich,gcindex,ir] = numpy.interp(VelRange[gcindex],VelRange[interpindex],self.spc[ich,interpindex,ir])
281 self.spc_out[ich,gcindex,ir] = numpy.interp(VelRange[gcindex],VelRange[interpindex],self.spc[ich,interpindex,ir])
283
282
284 dataOut.data_pre[0] = self.spc_out
283 dataOut.data_pre[0] = self.spc_out
285 #print ('Leaving RemoveWideGC ... ')
284 #print ('Leaving RemoveWideGC ... ')
286 return dataOut
285 return dataOut
287
286
288 class SpectralFilters(Operation):
287 class SpectralFilters(Operation):
289 ''' This class allows to replace the novalid values with noise for each channel
288 ''' This class allows to replace the novalid values with noise for each channel
290 This applies to CLAIRE RADAR
289 This applies to CLAIRE RADAR
291
290
292 PositiveLimit : RightLimit of novalid data
291 PositiveLimit : RightLimit of novalid data
293 NegativeLimit : LeftLimit of novalid data
292 NegativeLimit : LeftLimit of novalid data
294
293
295 Input:
294 Input:
296
295
297 self.dataOut.data_pre : SPC and CSPC
296 self.dataOut.data_pre : SPC and CSPC
298 self.dataOut.spc_range : To select wind and rainfall velocities
297 self.dataOut.spc_range : To select wind and rainfall velocities
299
298
300 Affected:
299 Affected:
301
300
302 self.dataOut.data_pre : It is used for the new SPC and CSPC ranges of wind
301 self.dataOut.data_pre : It is used for the new SPC and CSPC ranges of wind
303
302
304 Written by D. Scipión 29.01.2021
303 Written by D. Scipión 29.01.2021
305 '''
304 '''
306 def __init__(self):
305 def __init__(self):
307 Operation.__init__(self)
306 Operation.__init__(self)
308 self.i = 0
307 self.i = 0
309
308
310 def run(self, dataOut, ):
309 def run(self, dataOut, ):
311
310
312 self.spc = dataOut.data_pre[0].copy()
311 self.spc = dataOut.data_pre[0].copy()
313 self.Num_Chn = self.spc.shape[0]
312 self.Num_Chn = self.spc.shape[0]
314 VelRange = dataOut.spc_range[2]
313 VelRange = dataOut.spc_range[2]
315
314
316 # novalid corresponds to data within the Negative and PositiveLimit
315 # novalid corresponds to data within the Negative and PositiveLimit
317
316
318
317
319 # Removing novalid data from the spectra
318 # Removing novalid data from the spectra
320 for i in range(self.Num_Chn):
319 for i in range(self.Num_Chn):
321 self.spc[i,novalid,:] = dataOut.noise[i]
320 self.spc[i,novalid,:] = dataOut.noise[i]
322 dataOut.data_pre[0] = self.spc
321 dataOut.data_pre[0] = self.spc
323 return dataOut
322 return dataOut
324
323
325 class GaussianFit(Operation):
324 class GaussianFit(Operation):
326
325
327 '''
326 '''
328 Function that fit of one and two generalized gaussians (gg) based
327 Function that fit of one and two generalized gaussians (gg) based
329 on the PSD shape across an "power band" identified from a cumsum of
328 on the PSD shape across an "power band" identified from a cumsum of
330 the measured spectrum - noise.
329 the measured spectrum - noise.
331
330
332 Input:
331 Input:
333 self.dataOut.data_pre : SelfSpectra
332 self.dataOut.data_pre : SelfSpectra
334
333
335 Output:
334 Output:
336 self.dataOut.SPCparam : SPC_ch1, SPC_ch2
335 self.dataOut.SPCparam : SPC_ch1, SPC_ch2
337
336
338 '''
337 '''
339 def __init__(self):
338 def __init__(self):
340 Operation.__init__(self)
339 Operation.__init__(self)
341 self.i=0
340 self.i=0
342
341
343
342
344 # 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
343 # 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
345 def run(self, dataOut, SNRdBlimit=-9, method='generalized'):
344 def run(self, dataOut, SNRdBlimit=-9, method='generalized'):
346 """This routine will find a couple of generalized Gaussians to a power spectrum
345 """This routine will find a couple of generalized Gaussians to a power spectrum
347 methods: generalized, squared
346 methods: generalized, squared
348 input: spc
347 input: spc
349 output:
348 output:
350 noise, amplitude0,shift0,width0,p0,Amplitude1,shift1,width1,p1
349 noise, amplitude0,shift0,width0,p0,Amplitude1,shift1,width1,p1
351 """
350 """
352 print ('Entering ',method,' double Gaussian fit')
351 print ('Entering ',method,' double Gaussian fit')
353 self.spc = dataOut.data_pre[0].copy()
352 self.spc = dataOut.data_pre[0].copy()
354 self.Num_Hei = self.spc.shape[2]
353 self.Num_Hei = self.spc.shape[2]
355 self.Num_Bin = self.spc.shape[1]
354 self.Num_Bin = self.spc.shape[1]
356 self.Num_Chn = self.spc.shape[0]
355 self.Num_Chn = self.spc.shape[0]
357
356
358 start_time = time.time()
357 start_time = time.time()
359
358
360 pool = Pool(processes=self.Num_Chn)
359 pool = Pool(processes=self.Num_Chn)
361 args = [(dataOut.spc_range[2], ich, dataOut.spc_noise[ich], dataOut.nIncohInt, SNRdBlimit) for ich in range(self.Num_Chn)]
360 args = [(dataOut.spc_range[2], ich, dataOut.spc_noise[ich], dataOut.nIncohInt, SNRdBlimit) for ich in range(self.Num_Chn)]
362 objs = [self for __ in range(self.Num_Chn)]
361 objs = [self for __ in range(self.Num_Chn)]
363 attrs = list(zip(objs, args))
362 attrs = list(zip(objs, args))
364 DGauFitParam = pool.map(target, attrs)
363 DGauFitParam = pool.map(target, attrs)
365 # Parameters:
364 # Parameters:
366 # 0. Noise, 1. Amplitude, 2. Shift, 3. Width 4. Power
365 # 0. Noise, 1. Amplitude, 2. Shift, 3. Width 4. Power
367 dataOut.DGauFitParams = numpy.asarray(DGauFitParam)
366 dataOut.DGauFitParams = numpy.asarray(DGauFitParam)
368
367
369 # Double Gaussian Curves
368 # Double Gaussian Curves
370 gau0 = numpy.zeros([self.Num_Chn,self.Num_Bin,self.Num_Hei])
369 gau0 = numpy.zeros([self.Num_Chn,self.Num_Bin,self.Num_Hei])
371 gau0[:] = numpy.NaN
370 gau0[:] = numpy.NaN
372 gau1 = numpy.zeros([self.Num_Chn,self.Num_Bin,self.Num_Hei])
371 gau1 = numpy.zeros([self.Num_Chn,self.Num_Bin,self.Num_Hei])
373 gau1[:] = numpy.NaN
372 gau1[:] = numpy.NaN
374 x_mtr = numpy.transpose(numpy.tile(dataOut.getVelRange(1)[:-1], (self.Num_Hei,1)))
373 x_mtr = numpy.transpose(numpy.tile(dataOut.getVelRange(1)[:-1], (self.Num_Hei,1)))
375 for iCh in range(self.Num_Chn):
374 for iCh in range(self.Num_Chn):
376 N0 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][0,:,0]] * self.Num_Bin))
375 N0 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][0,:,0]] * self.Num_Bin))
377 N1 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][0,:,1]] * self.Num_Bin))
376 N1 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][0,:,1]] * self.Num_Bin))
378 A0 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][1,:,0]] * self.Num_Bin))
377 A0 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][1,:,0]] * self.Num_Bin))
379 A1 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][1,:,1]] * self.Num_Bin))
378 A1 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][1,:,1]] * self.Num_Bin))
380 v0 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][2,:,0]] * self.Num_Bin))
379 v0 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][2,:,0]] * self.Num_Bin))
381 v1 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][2,:,1]] * self.Num_Bin))
380 v1 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][2,:,1]] * self.Num_Bin))
382 s0 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][3,:,0]] * self.Num_Bin))
381 s0 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][3,:,0]] * self.Num_Bin))
383 s1 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][3,:,1]] * self.Num_Bin))
382 s1 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][3,:,1]] * self.Num_Bin))
384 if method == 'genealized':
383 if method == 'genealized':
385 p0 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][4,:,0]] * self.Num_Bin))
384 p0 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][4,:,0]] * self.Num_Bin))
386 p1 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][4,:,1]] * self.Num_Bin))
385 p1 = numpy.transpose(numpy.transpose([dataOut.DGauFitParams[iCh][4,:,1]] * self.Num_Bin))
387 elif method == 'squared':
386 elif method == 'squared':
388 p0 = 2.
387 p0 = 2.
389 p1 = 2.
388 p1 = 2.
390 gau0[iCh] = A0*numpy.exp(-0.5*numpy.abs((x_mtr-v0)/s0)**p0)+N0
389 gau0[iCh] = A0*numpy.exp(-0.5*numpy.abs((x_mtr-v0)/s0)**p0)+N0
391 gau1[iCh] = A1*numpy.exp(-0.5*numpy.abs((x_mtr-v1)/s1)**p1)+N1
390 gau1[iCh] = A1*numpy.exp(-0.5*numpy.abs((x_mtr-v1)/s1)**p1)+N1
392 dataOut.GaussFit0 = gau0
391 dataOut.GaussFit0 = gau0
393 dataOut.GaussFit1 = gau1
392 dataOut.GaussFit1 = gau1
394
393
395 print('Leaving ',method ,' double Gaussian fit')
394 print('Leaving ',method ,' double Gaussian fit')
396 return dataOut
395 return dataOut
397
396
398 def FitGau(self, X):
397 def FitGau(self, X):
399 # print('Entering FitGau')
398 # print('Entering FitGau')
400 # Assigning the variables
399 # Assigning the variables
401 Vrange, ch, wnoise, num_intg, SNRlimit = X
400 Vrange, ch, wnoise, num_intg, SNRlimit = X
402 # Noise Limits
401 # Noise Limits
403 noisebl = wnoise * 0.9
402 noisebl = wnoise * 0.9
404 noisebh = wnoise * 1.1
403 noisebh = wnoise * 1.1
405 # Radar Velocity
404 # Radar Velocity
406 Va = max(Vrange)
405 Va = max(Vrange)
407 deltav = Vrange[1] - Vrange[0]
406 deltav = Vrange[1] - Vrange[0]
408 x = numpy.arange(self.Num_Bin)
407 x = numpy.arange(self.Num_Bin)
409
408
410 # print ('stop 0')
409 # print ('stop 0')
411
410
412 # 5 parameters, 2 Gaussians
411 # 5 parameters, 2 Gaussians
413 DGauFitParam = numpy.zeros([5, self.Num_Hei,2])
412 DGauFitParam = numpy.zeros([5, self.Num_Hei,2])
414 DGauFitParam[:] = numpy.NaN
413 DGauFitParam[:] = numpy.NaN
415
414
416 # SPCparam = []
415 # SPCparam = []
417 # SPC_ch1 = numpy.zeros([self.Num_Bin,self.Num_Hei])
416 # SPC_ch1 = numpy.zeros([self.Num_Bin,self.Num_Hei])
418 # SPC_ch2 = numpy.zeros([self.Num_Bin,self.Num_Hei])
417 # SPC_ch2 = numpy.zeros([self.Num_Bin,self.Num_Hei])
419 # SPC_ch1[:] = 0 #numpy.NaN
418 # SPC_ch1[:] = 0 #numpy.NaN
420 # SPC_ch2[:] = 0 #numpy.NaN
419 # SPC_ch2[:] = 0 #numpy.NaN
421 # print ('stop 1')
420 # print ('stop 1')
422 for ht in range(self.Num_Hei):
421 for ht in range(self.Num_Hei):
423 # print (ht)
422 # print (ht)
424 # print ('stop 2')
423 # print ('stop 2')
425 # Spectra at each range
424 # Spectra at each range
426 spc = numpy.asarray(self.spc)[ch,:,ht]
425 spc = numpy.asarray(self.spc)[ch,:,ht]
427 snr = ( spc.mean() - wnoise ) / wnoise
426 snr = ( spc.mean() - wnoise ) / wnoise
428 snrdB = 10.*numpy.log10(snr)
427 snrdB = 10.*numpy.log10(snr)
429
428
430 #print ('stop 3')
429 #print ('stop 3')
431 if snrdB < SNRlimit :
430 if snrdB < SNRlimit :
432 # snr = numpy.NaN
431 # snr = numpy.NaN
433 # SPC_ch1[:,ht] = 0#numpy.NaN
432 # SPC_ch1[:,ht] = 0#numpy.NaN
434 # SPC_ch1[:,ht] = 0#numpy.NaN
433 # SPC_ch1[:,ht] = 0#numpy.NaN
435 # SPCparam = (SPC_ch1,SPC_ch2)
434 # SPCparam = (SPC_ch1,SPC_ch2)
436 # print ('SNR less than SNRth')
435 # print ('SNR less than SNRth')
437 continue
436 continue
438 # wnoise = hildebrand_sekhon(spc,num_intg)
437 # wnoise = hildebrand_sekhon(spc,num_intg)
439 # print ('stop 2.01')
438 # print ('stop 2.01')
440 #############################################
439 #############################################
441 # normalizing spc and noise
440 # normalizing spc and noise
442 # This part differs from gg1
441 # This part differs from gg1
443 # spc_norm_max = max(spc) #commented by D. Scipión 19.03.2021
442 # spc_norm_max = max(spc) #commented by D. Scipión 19.03.2021
444 #spc = spc / spc_norm_max
443 #spc = spc / spc_norm_max
445 # pnoise = pnoise #/ spc_norm_max #commented by D. Scipión 19.03.2021
444 # pnoise = pnoise #/ spc_norm_max #commented by D. Scipión 19.03.2021
446 #############################################
445 #############################################
447
446
448 # print ('stop 2.1')
447 # print ('stop 2.1')
449 fatspectra=1.0
448 fatspectra=1.0
450 # noise per channel.... we might want to use the noise at each range
449 # noise per channel.... we might want to use the noise at each range
451
450
452 # wnoise = noise_ #/ spc_norm_max #commented by D. Scipión 19.03.2021
451 # wnoise = noise_ #/ spc_norm_max #commented by D. Scipión 19.03.2021
453 #wnoise,stdv,i_max,index =enoise(spc,num_intg) #noise estimate using Hildebrand Sekhon, only wnoise is used
452 #wnoise,stdv,i_max,index =enoise(spc,num_intg) #noise estimate using Hildebrand Sekhon, only wnoise is used
454 #if wnoise>1.1*pnoise: # to be tested later
453 #if wnoise>1.1*pnoise: # to be tested later
455 # wnoise=pnoise
454 # wnoise=pnoise
456 # noisebl = wnoise*0.9
455 # noisebl = wnoise*0.9
457 # noisebh = wnoise*1.1
456 # noisebh = wnoise*1.1
458 spc = spc - wnoise # signal
457 spc = spc - wnoise # signal
459
458
460 # print ('stop 2.2')
459 # print ('stop 2.2')
461 minx = numpy.argmin(spc)
460 minx = numpy.argmin(spc)
462 #spcs=spc.copy()
461 #spcs=spc.copy()
463 spcs = numpy.roll(spc,-minx)
462 spcs = numpy.roll(spc,-minx)
464 cum = numpy.cumsum(spcs)
463 cum = numpy.cumsum(spcs)
465 # tot_noise = wnoise * self.Num_Bin #64;
464 # tot_noise = wnoise * self.Num_Bin #64;
466
465
467 # print ('stop 2.3')
466 # print ('stop 2.3')
468 # snr = sum(spcs) / tot_noise
467 # snr = sum(spcs) / tot_noise
469 # snrdB = 10.*numpy.log10(snr)
468 # snrdB = 10.*numpy.log10(snr)
470 #print ('stop 3')
469 #print ('stop 3')
471 # if snrdB < SNRlimit :
470 # if snrdB < SNRlimit :
472 # snr = numpy.NaN
471 # snr = numpy.NaN
473 # SPC_ch1[:,ht] = 0#numpy.NaN
472 # SPC_ch1[:,ht] = 0#numpy.NaN
474 # SPC_ch1[:,ht] = 0#numpy.NaN
473 # SPC_ch1[:,ht] = 0#numpy.NaN
475 # SPCparam = (SPC_ch1,SPC_ch2)
474 # SPCparam = (SPC_ch1,SPC_ch2)
476 # print ('SNR less than SNRth')
475 # print ('SNR less than SNRth')
477 # continue
476 # continue
478
477
479
478
480 #if snrdB<-18 or numpy.isnan(snrdB) or num_intg<4:
479 #if snrdB<-18 or numpy.isnan(snrdB) or num_intg<4:
481 # return [None,]*4,[None,]*4,None,snrdB,None,None,[None,]*5,[None,]*9,None
480 # return [None,]*4,[None,]*4,None,snrdB,None,None,[None,]*5,[None,]*9,None
482 # print ('stop 4')
481 # print ('stop 4')
483 cummax = max(cum)
482 cummax = max(cum)
484 epsi = 0.08 * fatspectra # cumsum to narrow down the energy region
483 epsi = 0.08 * fatspectra # cumsum to narrow down the energy region
485 cumlo = cummax * epsi
484 cumlo = cummax * epsi
486 cumhi = cummax * (1-epsi)
485 cumhi = cummax * (1-epsi)
487 powerindex = numpy.array(numpy.where(numpy.logical_and(cum>cumlo, cum<cumhi))[0])
486 powerindex = numpy.array(numpy.where(numpy.logical_and(cum>cumlo, cum<cumhi))[0])
488
487
489 # print ('stop 5')
488 # print ('stop 5')
490 if len(powerindex) < 1:# case for powerindex 0
489 if len(powerindex) < 1:# case for powerindex 0
491 # print ('powerindex < 1')
490 # print ('powerindex < 1')
492 continue
491 continue
493 powerlo = powerindex[0]
492 powerlo = powerindex[0]
494 powerhi = powerindex[-1]
493 powerhi = powerindex[-1]
495 powerwidth = powerhi-powerlo
494 powerwidth = powerhi-powerlo
496 if powerwidth <= 1:
495 if powerwidth <= 1:
497 # print('powerwidth <= 1')
496 # print('powerwidth <= 1')
498 continue
497 continue
499
498
500 # print ('stop 6')
499 # print ('stop 6')
501 firstpeak = powerlo + powerwidth/10.# first gaussian energy location
500 firstpeak = powerlo + powerwidth/10.# first gaussian energy location
502 secondpeak = powerhi - powerwidth/10. #second gaussian energy location
501 secondpeak = powerhi - powerwidth/10. #second gaussian energy location
503 midpeak = (firstpeak + secondpeak)/2.
502 midpeak = (firstpeak + secondpeak)/2.
504 firstamp = spcs[int(firstpeak)]
503 firstamp = spcs[int(firstpeak)]
505 secondamp = spcs[int(secondpeak)]
504 secondamp = spcs[int(secondpeak)]
506 midamp = spcs[int(midpeak)]
505 midamp = spcs[int(midpeak)]
507
506
508 y_data = spc + wnoise
507 y_data = spc + wnoise
509
508
510 ''' single Gaussian '''
509 ''' single Gaussian '''
511 shift0 = numpy.mod(midpeak+minx, self.Num_Bin )
510 shift0 = numpy.mod(midpeak+minx, self.Num_Bin )
512 width0 = powerwidth/4.#Initialization entire power of spectrum divided by 4
511 width0 = powerwidth/4.#Initialization entire power of spectrum divided by 4
513 power0 = 2.
512 power0 = 2.
514 amplitude0 = midamp
513 amplitude0 = midamp
515 state0 = [shift0,width0,amplitude0,power0,wnoise]
514 state0 = [shift0,width0,amplitude0,power0,wnoise]
516 bnds = ((0,self.Num_Bin-1),(1,powerwidth),(0,None),(0.5,3.),(noisebl,noisebh))
515 bnds = ((0,self.Num_Bin-1),(1,powerwidth),(0,None),(0.5,3.),(noisebl,noisebh))
517 lsq1 = fmin_l_bfgs_b(self.misfit1, state0, args=(y_data,x,num_intg), bounds=bnds, approx_grad=True)
516 lsq1 = fmin_l_bfgs_b(self.misfit1, state0, args=(y_data,x,num_intg), bounds=bnds, approx_grad=True)
518 # print ('stop 7.1')
517 # print ('stop 7.1')
519 # print (bnds)
518 # print (bnds)
520
519
521 chiSq1=lsq1[1]
520 chiSq1=lsq1[1]
522
521
523 # print ('stop 8')
522 # print ('stop 8')
524 if fatspectra<1.0 and powerwidth<4:
523 if fatspectra<1.0 and powerwidth<4:
525 choice=0
524 choice=0
526 Amplitude0=lsq1[0][2]
525 Amplitude0=lsq1[0][2]
527 shift0=lsq1[0][0]
526 shift0=lsq1[0][0]
528 width0=lsq1[0][1]
527 width0=lsq1[0][1]
529 p0=lsq1[0][3]
528 p0=lsq1[0][3]
530 Amplitude1=0.
529 Amplitude1=0.
531 shift1=0.
530 shift1=0.
532 width1=0.
531 width1=0.
533 p1=0.
532 p1=0.
534 noise=lsq1[0][4]
533 noise=lsq1[0][4]
535 #return (numpy.array([shift0,width0,Amplitude0,p0]),
534 #return (numpy.array([shift0,width0,Amplitude0,p0]),
536 # numpy.array([shift1,width1,Amplitude1,p1]),noise,snrdB,chiSq1,6.,sigmas1,[None,]*9,choice)
535 # numpy.array([shift1,width1,Amplitude1,p1]),noise,snrdB,chiSq1,6.,sigmas1,[None,]*9,choice)
537
536
538 # print ('stop 9')
537 # print ('stop 9')
539 ''' two Gaussians '''
538 ''' two Gaussians '''
540 #shift0=numpy.mod(firstpeak+minx,64); shift1=numpy.mod(secondpeak+minx,64)
539 #shift0=numpy.mod(firstpeak+minx,64); shift1=numpy.mod(secondpeak+minx,64)
541 shift0 = numpy.mod(firstpeak+minx, self.Num_Bin )
540 shift0 = numpy.mod(firstpeak+minx, self.Num_Bin )
542 shift1 = numpy.mod(secondpeak+minx, self.Num_Bin )
541 shift1 = numpy.mod(secondpeak+minx, self.Num_Bin )
543 width0 = powerwidth/6.
542 width0 = powerwidth/6.
544 width1 = width0
543 width1 = width0
545 power0 = 2.
544 power0 = 2.
546 power1 = power0
545 power1 = power0
547 amplitude0 = firstamp
546 amplitude0 = firstamp
548 amplitude1 = secondamp
547 amplitude1 = secondamp
549 state0 = [shift0,width0,amplitude0,power0,shift1,width1,amplitude1,power1,wnoise]
548 state0 = [shift0,width0,amplitude0,power0,shift1,width1,amplitude1,power1,wnoise]
550 #bnds=((0,63),(1,powerwidth/2.),(0,None),(0.5,3.),(0,63),(1,powerwidth/2.),(0,None),(0.5,3.),(noisebl,noisebh))
549 #bnds=((0,63),(1,powerwidth/2.),(0,None),(0.5,3.),(0,63),(1,powerwidth/2.),(0,None),(0.5,3.),(noisebl,noisebh))
551 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))
550 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))
552 #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))
551 #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))
553
552
554 # print ('stop 10')
553 # print ('stop 10')
555 lsq2 = fmin_l_bfgs_b( self.misfit2 , state0 , args=(y_data,x,num_intg) , bounds=bnds , approx_grad=True )
554 lsq2 = fmin_l_bfgs_b( self.misfit2 , state0 , args=(y_data,x,num_intg) , bounds=bnds , approx_grad=True )
556
555
557 # print ('stop 11')
556 # print ('stop 11')
558 chiSq2 = lsq2[1]
557 chiSq2 = lsq2[1]
559
558
560 # print ('stop 12')
559 # print ('stop 12')
561
560
562 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)
561 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)
563
562
564 # print ('stop 13')
563 # print ('stop 13')
565 if snrdB>-12: # when SNR is strong pick the peak with least shift (LOS velocity) error
564 if snrdB>-12: # when SNR is strong pick the peak with least shift (LOS velocity) error
566 if oneG:
565 if oneG:
567 choice = 0
566 choice = 0
568 else:
567 else:
569 w1 = lsq2[0][1]; w2 = lsq2[0][5]
568 w1 = lsq2[0][1]; w2 = lsq2[0][5]
570 a1 = lsq2[0][2]; a2 = lsq2[0][6]
569 a1 = lsq2[0][2]; a2 = lsq2[0][6]
571 p1 = lsq2[0][3]; p2 = lsq2[0][7]
570 p1 = lsq2[0][3]; p2 = lsq2[0][7]
572 s1 = (2**(1+1./p1))*scipy.special.gamma(1./p1)/p1
571 s1 = (2**(1+1./p1))*scipy.special.gamma(1./p1)/p1
573 s2 = (2**(1+1./p2))*scipy.special.gamma(1./p2)/p2
572 s2 = (2**(1+1./p2))*scipy.special.gamma(1./p2)/p2
574 gp1 = a1*w1*s1; gp2 = a2*w2*s2 # power content of each ggaussian with proper p scaling
573 gp1 = a1*w1*s1; gp2 = a2*w2*s2 # power content of each ggaussian with proper p scaling
575
574
576 if gp1>gp2:
575 if gp1>gp2:
577 if a1>0.7*a2:
576 if a1>0.7*a2:
578 choice = 1
577 choice = 1
579 else:
578 else:
580 choice = 2
579 choice = 2
581 elif gp2>gp1:
580 elif gp2>gp1:
582 if a2>0.7*a1:
581 if a2>0.7*a1:
583 choice = 2
582 choice = 2
584 else:
583 else:
585 choice = 1
584 choice = 1
586 else:
585 else:
587 choice = numpy.argmax([a1,a2])+1
586 choice = numpy.argmax([a1,a2])+1
588 #else:
587 #else:
589 #choice=argmin([std2a,std2b])+1
588 #choice=argmin([std2a,std2b])+1
590
589
591 else: # with low SNR go to the most energetic peak
590 else: # with low SNR go to the most energetic peak
592 choice = numpy.argmax([lsq1[0][2]*lsq1[0][1],lsq2[0][2]*lsq2[0][1],lsq2[0][6]*lsq2[0][5]])
591 choice = numpy.argmax([lsq1[0][2]*lsq1[0][1],lsq2[0][2]*lsq2[0][1],lsq2[0][6]*lsq2[0][5]])
593
592
594 # print ('stop 14')
593 # print ('stop 14')
595 shift0 = lsq2[0][0]
594 shift0 = lsq2[0][0]
596 vel0 = Vrange[0] + shift0 * deltav
595 vel0 = Vrange[0] + shift0 * deltav
597 shift1 = lsq2[0][4]
596 shift1 = lsq2[0][4]
598 # vel1=Vrange[0] + shift1 * deltav
597 # vel1=Vrange[0] + shift1 * deltav
599
598
600 # max_vel = 1.0
599 # max_vel = 1.0
601 # Va = max(Vrange)
600 # Va = max(Vrange)
602 # deltav = Vrange[1]-Vrange[0]
601 # deltav = Vrange[1]-Vrange[0]
603 # print ('stop 15')
602 # print ('stop 15')
604 #first peak will be 0, second peak will be 1
603 #first peak will be 0, second peak will be 1
605 # if vel0 > -1.0 and vel0 < max_vel : #first peak is in the correct range # Commented by D.Scipión 19.03.2021
604 # if vel0 > -1.0 and vel0 < max_vel : #first peak is in the correct range # Commented by D.Scipión 19.03.2021
606 if vel0 > -Va and vel0 < Va : #first peak is in the correct range
605 if vel0 > -Va and vel0 < Va : #first peak is in the correct range
607 shift0 = lsq2[0][0]
606 shift0 = lsq2[0][0]
608 width0 = lsq2[0][1]
607 width0 = lsq2[0][1]
609 Amplitude0 = lsq2[0][2]
608 Amplitude0 = lsq2[0][2]
610 p0 = lsq2[0][3]
609 p0 = lsq2[0][3]
611
610
612 shift1 = lsq2[0][4]
611 shift1 = lsq2[0][4]
613 width1 = lsq2[0][5]
612 width1 = lsq2[0][5]
614 Amplitude1 = lsq2[0][6]
613 Amplitude1 = lsq2[0][6]
615 p1 = lsq2[0][7]
614 p1 = lsq2[0][7]
616 noise = lsq2[0][8]
615 noise = lsq2[0][8]
617 else:
616 else:
618 shift1 = lsq2[0][0]
617 shift1 = lsq2[0][0]
619 width1 = lsq2[0][1]
618 width1 = lsq2[0][1]
620 Amplitude1 = lsq2[0][2]
619 Amplitude1 = lsq2[0][2]
621 p1 = lsq2[0][3]
620 p1 = lsq2[0][3]
622
621
623 shift0 = lsq2[0][4]
622 shift0 = lsq2[0][4]
624 width0 = lsq2[0][5]
623 width0 = lsq2[0][5]
625 Amplitude0 = lsq2[0][6]
624 Amplitude0 = lsq2[0][6]
626 p0 = lsq2[0][7]
625 p0 = lsq2[0][7]
627 noise = lsq2[0][8]
626 noise = lsq2[0][8]
628
627
629 if Amplitude0<0.05: # in case the peak is noise
628 if Amplitude0<0.05: # in case the peak is noise
630 shift0,width0,Amplitude0,p0 = 4*[numpy.NaN]
629 shift0,width0,Amplitude0,p0 = 4*[numpy.NaN]
631 if Amplitude1<0.05:
630 if Amplitude1<0.05:
632 shift1,width1,Amplitude1,p1 = 4*[numpy.NaN]
631 shift1,width1,Amplitude1,p1 = 4*[numpy.NaN]
633
632
634 # print ('stop 16 ')
633 # print ('stop 16 ')
635 # SPC_ch1[:,ht] = noise + Amplitude0*numpy.exp(-0.5*(abs(x-shift0)/width0)**p0)
634 # SPC_ch1[:,ht] = noise + Amplitude0*numpy.exp(-0.5*(abs(x-shift0)/width0)**p0)
636 # SPC_ch2[:,ht] = noise + Amplitude1*numpy.exp(-0.5*(abs(x-shift1)/width1)**p1)
635 # SPC_ch2[:,ht] = noise + Amplitude1*numpy.exp(-0.5*(abs(x-shift1)/width1)**p1)
637 # SPCparam = (SPC_ch1,SPC_ch2)
636 # SPCparam = (SPC_ch1,SPC_ch2)
638
637
639 DGauFitParam[0,ht,0] = noise
638 DGauFitParam[0,ht,0] = noise
640 DGauFitParam[0,ht,1] = noise
639 DGauFitParam[0,ht,1] = noise
641 DGauFitParam[1,ht,0] = Amplitude0
640 DGauFitParam[1,ht,0] = Amplitude0
642 DGauFitParam[1,ht,1] = Amplitude1
641 DGauFitParam[1,ht,1] = Amplitude1
643 DGauFitParam[2,ht,0] = Vrange[0] + shift0 * deltav
642 DGauFitParam[2,ht,0] = Vrange[0] + shift0 * deltav
644 DGauFitParam[2,ht,1] = Vrange[0] + shift1 * deltav
643 DGauFitParam[2,ht,1] = Vrange[0] + shift1 * deltav
645 DGauFitParam[3,ht,0] = width0 * deltav
644 DGauFitParam[3,ht,0] = width0 * deltav
646 DGauFitParam[3,ht,1] = width1 * deltav
645 DGauFitParam[3,ht,1] = width1 * deltav
647 DGauFitParam[4,ht,0] = p0
646 DGauFitParam[4,ht,0] = p0
648 DGauFitParam[4,ht,1] = p1
647 DGauFitParam[4,ht,1] = p1
649
648
650 # print (DGauFitParam.shape)
649 # print (DGauFitParam.shape)
651 # print ('Leaving FitGau')
650 # print ('Leaving FitGau')
652 return DGauFitParam
651 return DGauFitParam
653 # return SPCparam
652 # return SPCparam
654 # return GauSPC
653 # return GauSPC
655
654
656 def y_model1(self,x,state):
655 def y_model1(self,x,state):
657 shift0, width0, amplitude0, power0, noise = state
656 shift0, width0, amplitude0, power0, noise = state
658 model0 = amplitude0*numpy.exp(-0.5*abs((x - shift0)/width0)**power0)
657 model0 = amplitude0*numpy.exp(-0.5*abs((x - shift0)/width0)**power0)
659 model0u = amplitude0*numpy.exp(-0.5*abs((x - shift0 - self.Num_Bin)/width0)**power0)
658 model0u = amplitude0*numpy.exp(-0.5*abs((x - shift0 - self.Num_Bin)/width0)**power0)
660 model0d = amplitude0*numpy.exp(-0.5*abs((x - shift0 + self.Num_Bin)/width0)**power0)
659 model0d = amplitude0*numpy.exp(-0.5*abs((x - shift0 + self.Num_Bin)/width0)**power0)
661 return model0 + model0u + model0d + noise
660 return model0 + model0u + model0d + noise
662
661
663 def y_model2(self,x,state): #Equation for two generalized Gaussians with Nyquist
662 def y_model2(self,x,state): #Equation for two generalized Gaussians with Nyquist
664 shift0, width0, amplitude0, power0, shift1, width1, amplitude1, power1, noise = state
663 shift0, width0, amplitude0, power0, shift1, width1, amplitude1, power1, noise = state
665 model0 = amplitude0*numpy.exp(-0.5*abs((x-shift0)/width0)**power0)
664 model0 = amplitude0*numpy.exp(-0.5*abs((x-shift0)/width0)**power0)
666 model0u = amplitude0*numpy.exp(-0.5*abs((x - shift0 - self.Num_Bin)/width0)**power0)
665 model0u = amplitude0*numpy.exp(-0.5*abs((x - shift0 - self.Num_Bin)/width0)**power0)
667 model0d = amplitude0*numpy.exp(-0.5*abs((x - shift0 + self.Num_Bin)/width0)**power0)
666 model0d = amplitude0*numpy.exp(-0.5*abs((x - shift0 + self.Num_Bin)/width0)**power0)
668
667
669 model1 = amplitude1*numpy.exp(-0.5*abs((x - shift1)/width1)**power1)
668 model1 = amplitude1*numpy.exp(-0.5*abs((x - shift1)/width1)**power1)
670 model1u = amplitude1*numpy.exp(-0.5*abs((x - shift1 - self.Num_Bin)/width1)**power1)
669 model1u = amplitude1*numpy.exp(-0.5*abs((x - shift1 - self.Num_Bin)/width1)**power1)
671 model1d = amplitude1*numpy.exp(-0.5*abs((x - shift1 + self.Num_Bin)/width1)**power1)
670 model1d = amplitude1*numpy.exp(-0.5*abs((x - shift1 + self.Num_Bin)/width1)**power1)
672 return model0 + model0u + model0d + model1 + model1u + model1d + noise
671 return model0 + model0u + model0d + model1 + model1u + model1d + noise
673
672
674 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.
673 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.
675
674
676 return num_intg*sum((numpy.log(y_data)-numpy.log(self.y_model1(x,state)))**2)#/(64-5.) # /(64-5.) can be commented
675 return num_intg*sum((numpy.log(y_data)-numpy.log(self.y_model1(x,state)))**2)#/(64-5.) # /(64-5.) can be commented
677
676
678 def misfit2(self,state,y_data,x,num_intg):
677 def misfit2(self,state,y_data,x,num_intg):
679 return num_intg*sum((numpy.log(y_data)-numpy.log(self.y_model2(x,state)))**2)#/(64-9.)
678 return num_intg*sum((numpy.log(y_data)-numpy.log(self.y_model2(x,state)))**2)#/(64-9.)
680
679
681
680
682
681
683 class PrecipitationProc(Operation):
682 class PrecipitationProc(Operation):
684
683
685 '''
684 '''
686 Operator that estimates Reflectivity factor (Z), and estimates rainfall Rate (R)
685 Operator that estimates Reflectivity factor (Z), and estimates rainfall Rate (R)
687
686
688 Input:
687 Input:
689 self.dataOut.data_pre : SelfSpectra
688 self.dataOut.data_pre : SelfSpectra
690
689
691 Output:
690 Output:
692
691
693 self.dataOut.data_output : Reflectivity factor, rainfall Rate
692 self.dataOut.data_output : Reflectivity factor, rainfall Rate
694
693
695
694
696 Parameters affected:
695 Parameters affected:
697 '''
696 '''
698
697
699 def __init__(self):
698 def __init__(self):
700 Operation.__init__(self)
699 Operation.__init__(self)
701 self.i=0
700 self.i=0
702
701
703 def run(self, dataOut, radar=None, Pt=5000, Gt=295.1209, Gr=70.7945, Lambda=0.6741, aL=2.5118,
702 def run(self, dataOut, radar=None, Pt=5000, Gt=295.1209, Gr=70.7945, Lambda=0.6741, aL=2.5118,
704 tauW=4e-06, ThetaT=0.1656317, ThetaR=0.36774087, Km2 = 0.93, Altitude=3350,SNRdBlimit=-30):
703 tauW=4e-06, ThetaT=0.1656317, ThetaR=0.36774087, Km2 = 0.93, Altitude=3350,SNRdBlimit=-30):
705
704
706 # print ('Entering PrecepitationProc ... ')
705 # print ('Entering PrecepitationProc ... ')
707
706
708 if radar == "MIRA35C" :
707 if radar == "MIRA35C" :
709
708
710 self.spc = dataOut.data_pre[0].copy()
709 self.spc = dataOut.data_pre[0].copy()
711 self.Num_Hei = self.spc.shape[2]
710 self.Num_Hei = self.spc.shape[2]
712 self.Num_Bin = self.spc.shape[1]
711 self.Num_Bin = self.spc.shape[1]
713 self.Num_Chn = self.spc.shape[0]
712 self.Num_Chn = self.spc.shape[0]
714 Ze = self.dBZeMODE2(dataOut)
713 Ze = self.dBZeMODE2(dataOut)
715
714
716 else:
715 else:
717
716
718 self.spc = dataOut.data_pre[0].copy()
717 self.spc = dataOut.data_pre[0].copy()
719
718
720 #NOTA SE DEBE REMOVER EL RANGO DEL PULSO TX
719 #NOTA SE DEBE REMOVER EL RANGO DEL PULSO TX
721 self.spc[:,:,0:7]= numpy.NaN
720 self.spc[:,:,0:7]= numpy.NaN
722
721
723 self.Num_Hei = self.spc.shape[2]
722 self.Num_Hei = self.spc.shape[2]
724 self.Num_Bin = self.spc.shape[1]
723 self.Num_Bin = self.spc.shape[1]
725 self.Num_Chn = self.spc.shape[0]
724 self.Num_Chn = self.spc.shape[0]
726
725
727 VelRange = dataOut.spc_range[2]
726 VelRange = dataOut.spc_range[2]
728
727
729 ''' Se obtiene la constante del RADAR '''
728 ''' Se obtiene la constante del RADAR '''
730
729
731 self.Pt = Pt
730 self.Pt = Pt
732 self.Gt = Gt
731 self.Gt = Gt
733 self.Gr = Gr
732 self.Gr = Gr
734 self.Lambda = Lambda
733 self.Lambda = Lambda
735 self.aL = aL
734 self.aL = aL
736 self.tauW = tauW
735 self.tauW = tauW
737 self.ThetaT = ThetaT
736 self.ThetaT = ThetaT
738 self.ThetaR = ThetaR
737 self.ThetaR = ThetaR
739 self.GSys = 10**(36.63/10) # Ganancia de los LNA 36.63 dB
738 self.GSys = 10**(36.63/10) # Ganancia de los LNA 36.63 dB
740 self.lt = 10**(1.67/10) # Perdida en cables Tx 1.67 dB
739 self.lt = 10**(1.67/10) # Perdida en cables Tx 1.67 dB
741 self.lr = 10**(5.73/10) # Perdida en cables Rx 5.73 dB
740 self.lr = 10**(5.73/10) # Perdida en cables Rx 5.73 dB
742
741
743 Numerator = ( (4*numpy.pi)**3 * aL**2 * 16 * numpy.log(2) )
742 Numerator = ( (4*numpy.pi)**3 * aL**2 * 16 * numpy.log(2) )
744 Denominator = ( Pt * Gt * Gr * Lambda**2 * SPEED_OF_LIGHT * tauW * numpy.pi * ThetaT * ThetaR)
743 Denominator = ( Pt * Gt * Gr * Lambda**2 * SPEED_OF_LIGHT * tauW * numpy.pi * ThetaT * ThetaR)
745 RadarConstant = 10e-26 * Numerator / Denominator #
744 RadarConstant = 10e-26 * Numerator / Denominator #
746 ExpConstant = 10**(40/10) #Constante Experimental
745 ExpConstant = 10**(40/10) #Constante Experimental
747
746
748 SignalPower = numpy.zeros([self.Num_Chn,self.Num_Bin,self.Num_Hei])
747 SignalPower = numpy.zeros([self.Num_Chn,self.Num_Bin,self.Num_Hei])
749 for i in range(self.Num_Chn):
748 for i in range(self.Num_Chn):
750 SignalPower[i,:,:] = self.spc[i,:,:] - dataOut.noise[i]
749 SignalPower[i,:,:] = self.spc[i,:,:] - dataOut.noise[i]
751 SignalPower[numpy.where(SignalPower < 0)] = 1e-20
750 SignalPower[numpy.where(SignalPower < 0)] = 1e-20
752
751
753 SPCmean = numpy.mean(SignalPower, 0)
752 SPCmean = numpy.mean(SignalPower, 0)
754 Pr = SPCmean[:,:]/dataOut.normFactor
753 Pr = SPCmean[:,:]/dataOut.normFactor
755
754
756 # Declaring auxiliary variables
755 # Declaring auxiliary variables
757 Range = dataOut.heightList*1000. #Range in m
756 Range = dataOut.heightList*1000. #Range in m
758 # replicate the heightlist to obtain a matrix [Num_Bin,Num_Hei]
757 # replicate the heightlist to obtain a matrix [Num_Bin,Num_Hei]
759 rMtrx = numpy.transpose(numpy.transpose([dataOut.heightList*1000.] * self.Num_Bin))
758 rMtrx = numpy.transpose(numpy.transpose([dataOut.heightList*1000.] * self.Num_Bin))
760 zMtrx = rMtrx+Altitude
759 zMtrx = rMtrx+Altitude
761 # replicate the VelRange to obtain a matrix [Num_Bin,Num_Hei]
760 # replicate the VelRange to obtain a matrix [Num_Bin,Num_Hei]
762 VelMtrx = numpy.transpose(numpy.tile(VelRange[:-1], (self.Num_Hei,1)))
761 VelMtrx = numpy.transpose(numpy.tile(VelRange[:-1], (self.Num_Hei,1)))
763
762
764 # height dependence to air density Foote and Du Toit (1969)
763 # height dependence to air density Foote and Du Toit (1969)
765 delv_z = 1 + 3.68e-5 * zMtrx + 1.71e-9 * zMtrx**2
764 delv_z = 1 + 3.68e-5 * zMtrx + 1.71e-9 * zMtrx**2
766 VMtrx = VelMtrx / delv_z #Normalized velocity
765 VMtrx = VelMtrx / delv_z #Normalized velocity
767 VMtrx[numpy.where(VMtrx> 9.6)] = numpy.NaN
766 VMtrx[numpy.where(VMtrx> 9.6)] = numpy.NaN
768 # Diameter is related to the fall speed of falling drops
767 # Diameter is related to the fall speed of falling drops
769 D_Vz = -1.667 * numpy.log( 0.9369 - 0.097087 * VMtrx ) # D in [mm]
768 D_Vz = -1.667 * numpy.log( 0.9369 - 0.097087 * VMtrx ) # D in [mm]
770 # Only valid for D>= 0.16 mm
769 # Only valid for D>= 0.16 mm
771 D_Vz[numpy.where(D_Vz < 0.16)] = numpy.NaN
770 D_Vz[numpy.where(D_Vz < 0.16)] = numpy.NaN
772
771
773 #Calculate Radar Reflectivity ETAn
772 #Calculate Radar Reflectivity ETAn
774 ETAn = (RadarConstant *ExpConstant) * Pr * rMtrx**2 #Reflectivity (ETA)
773 ETAn = (RadarConstant *ExpConstant) * Pr * rMtrx**2 #Reflectivity (ETA)
775 ETAd = ETAn * 6.18 * exp( -0.6 * D_Vz ) * delv_z
774 ETAd = ETAn * 6.18 * exp( -0.6 * D_Vz ) * delv_z
776 # Radar Cross Section
775 # Radar Cross Section
777 sigmaD = Km2 * (D_Vz * 1e-3 )**6 * numpy.pi**5 / Lambda**4
776 sigmaD = Km2 * (D_Vz * 1e-3 )**6 * numpy.pi**5 / Lambda**4
778 # Drop Size Distribution
777 # Drop Size Distribution
779 DSD = ETAn / sigmaD
778 DSD = ETAn / sigmaD
780 # Equivalente Reflectivy
779 # Equivalente Reflectivy
781 Ze_eqn = numpy.nansum( DSD * D_Vz**6 ,axis=0)
780 Ze_eqn = numpy.nansum( DSD * D_Vz**6 ,axis=0)
782 Ze_org = numpy.nansum(ETAn * Lambda**4, axis=0) / (1e-18*numpy.pi**5 * Km2) # [mm^6 /m^3]
781 Ze_org = numpy.nansum(ETAn * Lambda**4, axis=0) / (1e-18*numpy.pi**5 * Km2) # [mm^6 /m^3]
783 # RainFall Rate
782 # RainFall Rate
784 RR = 0.0006*numpy.pi * numpy.nansum( D_Vz**3 * DSD * VelMtrx ,0) #mm/hr
783 RR = 0.0006*numpy.pi * numpy.nansum( D_Vz**3 * DSD * VelMtrx ,0) #mm/hr
785
784
786 # Censoring the data
785 # Censoring the data
787 # Removing data with SNRth < 0dB se debe considerar el SNR por canal
786 # Removing data with SNRth < 0dB se debe considerar el SNR por canal
788 SNRth = 10**(SNRdBlimit/10) #-30dB
787 SNRth = 10**(SNRdBlimit/10) #-30dB
789 novalid = numpy.where((dataOut.data_snr[0,:] <SNRth) | (dataOut.data_snr[1,:] <SNRth) | (dataOut.data_snr[2,:] <SNRth)) # AND condition. Maybe OR condition better
788 novalid = numpy.where((dataOut.data_snr[0,:] <SNRth) | (dataOut.data_snr[1,:] <SNRth) | (dataOut.data_snr[2,:] <SNRth)) # AND condition. Maybe OR condition better
790 W = numpy.nanmean(dataOut.data_dop,0)
789 W = numpy.nanmean(dataOut.data_dop,0)
791 W[novalid] = numpy.NaN
790 W[novalid] = numpy.NaN
792 Ze_org[novalid] = numpy.NaN
791 Ze_org[novalid] = numpy.NaN
793 RR[novalid] = numpy.NaN
792 RR[novalid] = numpy.NaN
794
793
795 dataOut.data_output = RR[8]
794 dataOut.data_output = RR[8]
796 dataOut.data_param = numpy.ones([3,self.Num_Hei])
795 dataOut.data_param = numpy.ones([3,self.Num_Hei])
797 dataOut.channelList = [0,1,2]
796 dataOut.channelList = [0,1,2]
798
797
799 dataOut.data_param[0]=10*numpy.log10(Ze_org)
798 dataOut.data_param[0]=10*numpy.log10(Ze_org)
800 dataOut.data_param[1]=-W
799 dataOut.data_param[1]=-W
801 dataOut.data_param[2]=RR
800 dataOut.data_param[2]=RR
802
801
803 # print ('Leaving PrecepitationProc ... ')
802 # print ('Leaving PrecepitationProc ... ')
804 return dataOut
803 return dataOut
805
804
806 def dBZeMODE2(self, dataOut): # Processing for MIRA35C
805 def dBZeMODE2(self, dataOut): # Processing for MIRA35C
807
806
808 NPW = dataOut.NPW
807 NPW = dataOut.NPW
809 COFA = dataOut.COFA
808 COFA = dataOut.COFA
810
809
811 SNR = numpy.array([self.spc[0,:,:] / NPW[0]]) #, self.spc[1,:,:] / NPW[1]])
810 SNR = numpy.array([self.spc[0,:,:] / NPW[0]]) #, self.spc[1,:,:] / NPW[1]])
812 RadarConst = dataOut.RadarConst
811 RadarConst = dataOut.RadarConst
813 #frequency = 34.85*10**9
812 #frequency = 34.85*10**9
814
813
815 ETA = numpy.zeros(([self.Num_Chn ,self.Num_Hei]))
814 ETA = numpy.zeros(([self.Num_Chn ,self.Num_Hei]))
816 data_output = numpy.ones([self.Num_Chn , self.Num_Hei])*numpy.NaN
815 data_output = numpy.ones([self.Num_Chn , self.Num_Hei])*numpy.NaN
817
816
818 ETA = numpy.sum(SNR,1)
817 ETA = numpy.sum(SNR,1)
819
818
820 ETA = numpy.where(ETA != 0. , ETA, numpy.NaN)
819 ETA = numpy.where(ETA != 0. , ETA, numpy.NaN)
821
820
822 Ze = numpy.ones([self.Num_Chn, self.Num_Hei] )
821 Ze = numpy.ones([self.Num_Chn, self.Num_Hei] )
823
822
824 for r in range(self.Num_Hei):
823 for r in range(self.Num_Hei):
825
824
826 Ze[0,r] = ( ETA[0,r] ) * COFA[0,r][0] * RadarConst * ((r/5000.)**2)
825 Ze[0,r] = ( ETA[0,r] ) * COFA[0,r][0] * RadarConst * ((r/5000.)**2)
827 #Ze[1,r] = ( ETA[1,r] ) * COFA[1,r][0] * RadarConst * ((r/5000.)**2)
826 #Ze[1,r] = ( ETA[1,r] ) * COFA[1,r][0] * RadarConst * ((r/5000.)**2)
828
827
829 return Ze
828 return Ze
830
829
831 # def GetRadarConstant(self):
830 # def GetRadarConstant(self):
832 #
831 #
833 # """
832 # """
834 # Constants:
833 # Constants:
835 #
834 #
836 # Pt: Transmission Power dB 5kW 5000
835 # Pt: Transmission Power dB 5kW 5000
837 # Gt: Transmission Gain dB 24.7 dB 295.1209
836 # Gt: Transmission Gain dB 24.7 dB 295.1209
838 # Gr: Reception Gain dB 18.5 dB 70.7945
837 # Gr: Reception Gain dB 18.5 dB 70.7945
839 # Lambda: Wavelenght m 0.6741 m 0.6741
838 # Lambda: Wavelenght m 0.6741 m 0.6741
840 # aL: Attenuation loses dB 4dB 2.5118
839 # aL: Attenuation loses dB 4dB 2.5118
841 # tauW: Width of transmission pulse s 4us 4e-6
840 # tauW: Width of transmission pulse s 4us 4e-6
842 # ThetaT: Transmission antenna bean angle rad 0.1656317 rad 0.1656317
841 # ThetaT: Transmission antenna bean angle rad 0.1656317 rad 0.1656317
843 # ThetaR: Reception antenna beam angle rad 0.36774087 rad 0.36774087
842 # ThetaR: Reception antenna beam angle rad 0.36774087 rad 0.36774087
844 #
843 #
845 # """
844 # """
846 #
845 #
847 # Numerator = ( (4*numpy.pi)**3 * aL**2 * 16 * numpy.log(2) )
846 # Numerator = ( (4*numpy.pi)**3 * aL**2 * 16 * numpy.log(2) )
848 # Denominator = ( Pt * Gt * Gr * Lambda**2 * SPEED_OF_LIGHT * TauW * numpy.pi * ThetaT * TheraR)
847 # Denominator = ( Pt * Gt * Gr * Lambda**2 * SPEED_OF_LIGHT * TauW * numpy.pi * ThetaT * TheraR)
849 # RadarConstant = Numerator / Denominator
848 # RadarConstant = Numerator / Denominator
850 #
849 #
851 # return RadarConstant
850 # return RadarConstant
852
851
853
852
854
853
855 class FullSpectralAnalysis(Operation):
854 class FullSpectralAnalysis(Operation):
856
855
857 """
856 """
858 Function that implements Full Spectral Analysis technique.
857 Function that implements Full Spectral Analysis technique.
859
858
860 Input:
859 Input:
861 self.dataOut.data_pre : SelfSpectra and CrossSpectra data
860 self.dataOut.data_pre : SelfSpectra and CrossSpectra data
862 self.dataOut.groupList : Pairlist of channels
861 self.dataOut.groupList : Pairlist of channels
863 self.dataOut.ChanDist : Physical distance between receivers
862 self.dataOut.ChanDist : Physical distance between receivers
864
863
865
864
866 Output:
865 Output:
867
866
868 self.dataOut.data_output : Zonal wind, Meridional wind, and Vertical wind
867 self.dataOut.data_output : Zonal wind, Meridional wind, and Vertical wind
869
868
870
869
871 Parameters affected: Winds, height range, SNR
870 Parameters affected: Winds, height range, SNR
872
871
873 """
872 """
874 def run(self, dataOut, Xi01=None, Xi02=None, Xi12=None, Eta01=None, Eta02=None, Eta12=None, SNRdBlimit=-30,
873 def run(self, dataOut, Xi01=None, Xi02=None, Xi12=None, Eta01=None, Eta02=None, Eta12=None, SNRdBlimit=-30,
875 minheight=None, maxheight=None, NegativeLimit=None, PositiveLimit=None):
874 minheight=None, maxheight=None, NegativeLimit=None, PositiveLimit=None):
876
875
877 spc = dataOut.data_pre[0].copy()
876 spc = dataOut.data_pre[0].copy()
878 cspc = dataOut.data_pre[1]
877 cspc = dataOut.data_pre[1]
879 nHeights = spc.shape[2]
878 nHeights = spc.shape[2]
880
879
881 # first_height = 0.75 #km (ref: data header 20170822)
880 # first_height = 0.75 #km (ref: data header 20170822)
882 # resolution_height = 0.075 #km
881 # resolution_height = 0.075 #km
883 '''
882 '''
884 finding height range. check this when radar parameters are changed!
883 finding height range. check this when radar parameters are changed!
885 '''
884 '''
886 if maxheight is not None:
885 if maxheight is not None:
887 # range_max = math.ceil((maxheight - first_height) / resolution_height) # theoretical
886 # range_max = math.ceil((maxheight - first_height) / resolution_height) # theoretical
888 range_max = math.ceil(13.26 * maxheight - 3) # empirical, works better
887 range_max = math.ceil(13.26 * maxheight - 3) # empirical, works better
889 else:
888 else:
890 range_max = nHeights
889 range_max = nHeights
891 if minheight is not None:
890 if minheight is not None:
892 # range_min = int((minheight - first_height) / resolution_height) # theoretical
891 # range_min = int((minheight - first_height) / resolution_height) # theoretical
893 range_min = int(13.26 * minheight - 5) # empirical, works better
892 range_min = int(13.26 * minheight - 5) # empirical, works better
894 if range_min < 0:
893 if range_min < 0:
895 range_min = 0
894 range_min = 0
896 else:
895 else:
897 range_min = 0
896 range_min = 0
898
897
899 pairsList = dataOut.groupList
898 pairsList = dataOut.groupList
900 if dataOut.ChanDist is not None :
899 if dataOut.ChanDist is not None :
901 ChanDist = dataOut.ChanDist
900 ChanDist = dataOut.ChanDist
902 else:
901 else:
903 ChanDist = numpy.array([[Xi01, Eta01],[Xi02,Eta02],[Xi12,Eta12]])
902 ChanDist = numpy.array([[Xi01, Eta01],[Xi02,Eta02],[Xi12,Eta12]])
904
903
905 # 4 variables: zonal, meridional, vertical, and average SNR
904 # 4 variables: zonal, meridional, vertical, and average SNR
906 data_param = numpy.zeros([4,nHeights]) * numpy.NaN
905 data_param = numpy.zeros([4,nHeights]) * numpy.NaN
907 velocityX = numpy.zeros([nHeights]) * numpy.NaN
906 velocityX = numpy.zeros([nHeights]) * numpy.NaN
908 velocityY = numpy.zeros([nHeights]) * numpy.NaN
907 velocityY = numpy.zeros([nHeights]) * numpy.NaN
909 velocityZ = numpy.zeros([nHeights]) * numpy.NaN
908 velocityZ = numpy.zeros([nHeights]) * numpy.NaN
910
909
911 dbSNR = 10*numpy.log10(numpy.average(dataOut.data_snr,0))
910 dbSNR = 10*numpy.log10(numpy.average(dataOut.data_snr,0))
912
911
913 '''***********************************************WIND ESTIMATION**************************************'''
912 '''***********************************************WIND ESTIMATION**************************************'''
914 for Height in range(nHeights):
913 for Height in range(nHeights):
915
914
916 if Height >= range_min and Height < range_max:
915 if Height >= range_min and Height < range_max:
917 # error_code will be useful in future analysis
916 # error_code will be useful in future analysis
918 [Vzon,Vmer,Vver, error_code] = self.WindEstimation(spc[:,:,Height], cspc[:,:,Height], pairsList,
917 [Vzon,Vmer,Vver, error_code] = self.WindEstimation(spc[:,:,Height], cspc[:,:,Height], pairsList,
919 ChanDist, Height, dataOut.noise, dataOut.spc_range, dbSNR[Height], SNRdBlimit, NegativeLimit, PositiveLimit,dataOut.frequency)
918 ChanDist, Height, dataOut.noise, dataOut.spc_range, dbSNR[Height], SNRdBlimit, NegativeLimit, PositiveLimit,dataOut.frequency)
920
919
921 if abs(Vzon) < 100. and abs(Vmer) < 100.:
920 if abs(Vzon) < 100. and abs(Vmer) < 100.:
922 velocityX[Height] = Vzon
921 velocityX[Height] = Vzon
923 velocityY[Height] = -Vmer
922 velocityY[Height] = -Vmer
924 velocityZ[Height] = Vver
923 velocityZ[Height] = Vver
925
924
926 # Censoring data with SNR threshold
925 # Censoring data with SNR threshold
927 dbSNR [dbSNR < SNRdBlimit] = numpy.NaN
926 dbSNR [dbSNR < SNRdBlimit] = numpy.NaN
928
927
929 data_param[0] = velocityX
928 data_param[0] = velocityX
930 data_param[1] = velocityY
929 data_param[1] = velocityY
931 data_param[2] = velocityZ
930 data_param[2] = velocityZ
932 data_param[3] = dbSNR
931 data_param[3] = dbSNR
933 dataOut.data_param = data_param
932 dataOut.data_param = data_param
934 return dataOut
933 return dataOut
935
934
936 def moving_average(self,x, N=2):
935 def moving_average(self,x, N=2):
937 """ convolution for smoothenig data. note that last N-1 values are convolution with zeroes """
936 """ convolution for smoothenig data. note that last N-1 values are convolution with zeroes """
938 return numpy.convolve(x, numpy.ones((N,))/N)[(N-1):]
937 return numpy.convolve(x, numpy.ones((N,))/N)[(N-1):]
939
938
940 def gaus(self,xSamples,Amp,Mu,Sigma):
939 def gaus(self,xSamples,Amp,Mu,Sigma):
941 return Amp * numpy.exp(-0.5*((xSamples - Mu)/Sigma)**2)
940 return Amp * numpy.exp(-0.5*((xSamples - Mu)/Sigma)**2)
942
941
943 def Moments(self, ySamples, xSamples):
942 def Moments(self, ySamples, xSamples):
944 Power = numpy.nanmean(ySamples) # Power, 0th Moment
943 Power = numpy.nanmean(ySamples) # Power, 0th Moment
945 yNorm = ySamples / numpy.nansum(ySamples)
944 yNorm = ySamples / numpy.nansum(ySamples)
946 RadVel = numpy.nansum(xSamples * yNorm) # Radial Velocity, 1st Moment
945 RadVel = numpy.nansum(xSamples * yNorm) # Radial Velocity, 1st Moment
947 Sigma2 = numpy.nansum(yNorm * (xSamples - RadVel)**2) # Spectral Width, 2nd Moment
946 Sigma2 = numpy.nansum(yNorm * (xSamples - RadVel)**2) # Spectral Width, 2nd Moment
948 StdDev = numpy.sqrt(numpy.abs(Sigma2)) # Desv. Estandar, Ancho espectral
947 StdDev = numpy.sqrt(numpy.abs(Sigma2)) # Desv. Estandar, Ancho espectral
949 return numpy.array([Power,RadVel,StdDev])
948 return numpy.array([Power,RadVel,StdDev])
950
949
951 def StopWindEstimation(self, error_code):
950 def StopWindEstimation(self, error_code):
952 Vzon = numpy.NaN
951 Vzon = numpy.NaN
953 Vmer = numpy.NaN
952 Vmer = numpy.NaN
954 Vver = numpy.NaN
953 Vver = numpy.NaN
955 return Vzon, Vmer, Vver, error_code
954 return Vzon, Vmer, Vver, error_code
956
955
957 def AntiAliasing(self, interval, maxstep):
956 def AntiAliasing(self, interval, maxstep):
958 """
957 """
959 function to prevent errors from aliased values when computing phaseslope
958 function to prevent errors from aliased values when computing phaseslope
960 """
959 """
961 antialiased = numpy.zeros(len(interval))
960 antialiased = numpy.zeros(len(interval))
962 copyinterval = interval.copy()
961 copyinterval = interval.copy()
963
962
964 antialiased[0] = copyinterval[0]
963 antialiased[0] = copyinterval[0]
965
964
966 for i in range(1,len(antialiased)):
965 for i in range(1,len(antialiased)):
967 step = interval[i] - interval[i-1]
966 step = interval[i] - interval[i-1]
968 if step > maxstep:
967 if step > maxstep:
969 copyinterval -= 2*numpy.pi
968 copyinterval -= 2*numpy.pi
970 antialiased[i] = copyinterval[i]
969 antialiased[i] = copyinterval[i]
971 elif step < maxstep*(-1):
970 elif step < maxstep*(-1):
972 copyinterval += 2*numpy.pi
971 copyinterval += 2*numpy.pi
973 antialiased[i] = copyinterval[i]
972 antialiased[i] = copyinterval[i]
974 else:
973 else:
975 antialiased[i] = copyinterval[i].copy()
974 antialiased[i] = copyinterval[i].copy()
976
975
977 return antialiased
976 return antialiased
978
977
979 def WindEstimation(self, spc, cspc, pairsList, ChanDist, Height, noise, AbbsisaRange, dbSNR, SNRlimit, NegativeLimit, PositiveLimit, radfreq):
978 def WindEstimation(self, spc, cspc, pairsList, ChanDist, Height, noise, AbbsisaRange, dbSNR, SNRlimit, NegativeLimit, PositiveLimit, radfreq):
980 """
979 """
981 Function that Calculates Zonal, Meridional and Vertical wind velocities.
980 Function that Calculates Zonal, Meridional and Vertical wind velocities.
982 Initial Version by E. Bocanegra updated by J. Zibell until Nov. 2019.
981 Initial Version by E. Bocanegra updated by J. Zibell until Nov. 2019.
983
982
984 Input:
983 Input:
985 spc, cspc : self spectra and cross spectra data. In Briggs notation something like S_i*(S_i)_conj, (S_j)_conj respectively.
984 spc, cspc : self spectra and cross spectra data. In Briggs notation something like S_i*(S_i)_conj, (S_j)_conj respectively.
986 pairsList : Pairlist of channels
985 pairsList : Pairlist of channels
987 ChanDist : array of xi_ij and eta_ij
986 ChanDist : array of xi_ij and eta_ij
988 Height : height at which data is processed
987 Height : height at which data is processed
989 noise : noise in [channels] format for specific height
988 noise : noise in [channels] format for specific height
990 Abbsisarange : range of the frequencies or velocities
989 Abbsisarange : range of the frequencies or velocities
991 dbSNR, SNRlimit : signal to noise ratio in db, lower limit
990 dbSNR, SNRlimit : signal to noise ratio in db, lower limit
992
991
993 Output:
992 Output:
994 Vzon, Vmer, Vver : wind velocities
993 Vzon, Vmer, Vver : wind velocities
995 error_code : int that states where code is terminated
994 error_code : int that states where code is terminated
996
995
997 0 : no error detected
996 0 : no error detected
998 1 : Gaussian of mean spc exceeds widthlimit
997 1 : Gaussian of mean spc exceeds widthlimit
999 2 : no Gaussian of mean spc found
998 2 : no Gaussian of mean spc found
1000 3 : SNR to low or velocity to high -> prec. e.g.
999 3 : SNR to low or velocity to high -> prec. e.g.
1001 4 : at least one Gaussian of cspc exceeds widthlimit
1000 4 : at least one Gaussian of cspc exceeds widthlimit
1002 5 : zero out of three cspc Gaussian fits converged
1001 5 : zero out of three cspc Gaussian fits converged
1003 6 : phase slope fit could not be found
1002 6 : phase slope fit could not be found
1004 7 : arrays used to fit phase have different length
1003 7 : arrays used to fit phase have different length
1005 8 : frequency range is either too short (len <= 5) or very long (> 30% of cspc)
1004 8 : frequency range is either too short (len <= 5) or very long (> 30% of cspc)
1006
1005
1007 """
1006 """
1008
1007
1009 error_code = 0
1008 error_code = 0
1010
1009
1011 nChan = spc.shape[0]
1010 nChan = spc.shape[0]
1012 nProf = spc.shape[1]
1011 nProf = spc.shape[1]
1013 nPair = cspc.shape[0]
1012 nPair = cspc.shape[0]
1014
1013
1015 SPC_Samples = numpy.zeros([nChan, nProf]) # for normalized spc values for one height
1014 SPC_Samples = numpy.zeros([nChan, nProf]) # for normalized spc values for one height
1016 CSPC_Samples = numpy.zeros([nPair, nProf], dtype=numpy.complex_) # for normalized cspc values
1015 CSPC_Samples = numpy.zeros([nPair, nProf], dtype=numpy.complex_) # for normalized cspc values
1017 phase = numpy.zeros([nPair, nProf]) # phase between channels
1016 phase = numpy.zeros([nPair, nProf]) # phase between channels
1018 PhaseSlope = numpy.zeros(nPair) # slope of the phases, channelwise
1017 PhaseSlope = numpy.zeros(nPair) # slope of the phases, channelwise
1019 PhaseInter = numpy.zeros(nPair) # intercept to the slope of the phases, channelwise
1018 PhaseInter = numpy.zeros(nPair) # intercept to the slope of the phases, channelwise
1020 xFrec = AbbsisaRange[0][:-1] # frequency range
1019 xFrec = AbbsisaRange[0][:-1] # frequency range
1021 xVel = AbbsisaRange[2][:-1] # velocity range
1020 xVel = AbbsisaRange[2][:-1] # velocity range
1022 xSamples = xFrec # the frequency range is taken
1021 xSamples = xFrec # the frequency range is taken
1023 delta_x = xSamples[1] - xSamples[0] # delta_f or delta_x
1022 delta_x = xSamples[1] - xSamples[0] # delta_f or delta_x
1024
1023
1025 # only consider velocities with in NegativeLimit and PositiveLimit
1024 # only consider velocities with in NegativeLimit and PositiveLimit
1026 if (NegativeLimit is None):
1025 if (NegativeLimit is None):
1027 NegativeLimit = numpy.min(xVel)
1026 NegativeLimit = numpy.min(xVel)
1028 if (PositiveLimit is None):
1027 if (PositiveLimit is None):
1029 PositiveLimit = numpy.max(xVel)
1028 PositiveLimit = numpy.max(xVel)
1030 xvalid = numpy.where((xVel > NegativeLimit) & (xVel < PositiveLimit))
1029 xvalid = numpy.where((xVel > NegativeLimit) & (xVel < PositiveLimit))
1031 xSamples_zoom = xSamples[xvalid]
1030 xSamples_zoom = xSamples[xvalid]
1032
1031
1033 '''Getting Eij and Nij'''
1032 '''Getting Eij and Nij'''
1034 Xi01, Xi02, Xi12 = ChanDist[:,0]
1033 Xi01, Xi02, Xi12 = ChanDist[:,0]
1035 Eta01, Eta02, Eta12 = ChanDist[:,1]
1034 Eta01, Eta02, Eta12 = ChanDist[:,1]
1036
1035
1037 # spwd limit - updated by D. Scipión 30.03.2021
1036 # spwd limit - updated by D. Scipión 30.03.2021
1038 widthlimit = 10
1037 widthlimit = 10
1039 '''************************* SPC is normalized ********************************'''
1038 '''************************* SPC is normalized ********************************'''
1040 spc_norm = spc.copy()
1039 spc_norm = spc.copy()
1041 # For each channel
1040 # For each channel
1042 for i in range(nChan):
1041 for i in range(nChan):
1043 spc_sub = spc_norm[i,:] - noise[i] # only the signal power
1042 spc_sub = spc_norm[i,:] - noise[i] # only the signal power
1044 SPC_Samples[i] = spc_sub / (numpy.nansum(spc_sub) * delta_x)
1043 SPC_Samples[i] = spc_sub / (numpy.nansum(spc_sub) * delta_x)
1045
1044
1046 '''********************** FITTING MEAN SPC GAUSSIAN **********************'''
1045 '''********************** FITTING MEAN SPC GAUSSIAN **********************'''
1047
1046
1048 """ the gaussian of the mean: first subtract noise, then normalize. this is legal because
1047 """ the gaussian of the mean: first subtract noise, then normalize. this is legal because
1049 you only fit the curve and don't need the absolute value of height for calculation,
1048 you only fit the curve and don't need the absolute value of height for calculation,
1050 only for estimation of width. for normalization of cross spectra, you need initial,
1049 only for estimation of width. for normalization of cross spectra, you need initial,
1051 unnormalized self-spectra With noise.
1050 unnormalized self-spectra With noise.
1052
1051
1053 Technically, you don't even need to normalize the self-spectra, as you only need the
1052 Technically, you don't even need to normalize the self-spectra, as you only need the
1054 width of the peak. However, it was left this way. Note that the normalization has a flaw:
1053 width of the peak. However, it was left this way. Note that the normalization has a flaw:
1055 due to subtraction of the noise, some values are below zero. Raw "spc" values should be
1054 due to subtraction of the noise, some values are below zero. Raw "spc" values should be
1056 >= 0, as it is the modulus squared of the signals (complex * it's conjugate)
1055 >= 0, as it is the modulus squared of the signals (complex * it's conjugate)
1057 """
1056 """
1058 # initial conditions
1057 # initial conditions
1059 popt = [1e-10,0,1e-10]
1058 popt = [1e-10,0,1e-10]
1060 # Spectra average
1059 # Spectra average
1061 SPCMean = numpy.average(SPC_Samples,0)
1060 SPCMean = numpy.average(SPC_Samples,0)
1062 # Moments in frequency
1061 # Moments in frequency
1063 SPCMoments = self.Moments(SPCMean[xvalid], xSamples_zoom)
1062 SPCMoments = self.Moments(SPCMean[xvalid], xSamples_zoom)
1064
1063
1065 # Gauss Fit SPC in frequency domain
1064 # Gauss Fit SPC in frequency domain
1066 if dbSNR > SNRlimit: # only if SNR > SNRth
1065 if dbSNR > SNRlimit: # only if SNR > SNRth
1067 try:
1066 try:
1068 popt,pcov = curve_fit(self.gaus,xSamples_zoom,SPCMean[xvalid],p0=SPCMoments)
1067 popt,pcov = curve_fit(self.gaus,xSamples_zoom,SPCMean[xvalid],p0=SPCMoments)
1069 if popt[2] <= 0 or popt[2] > widthlimit: # CONDITION
1068 if popt[2] <= 0 or popt[2] > widthlimit: # CONDITION
1070 return self.StopWindEstimation(error_code = 1)
1069 return self.StopWindEstimation(error_code = 1)
1071 FitGauss = self.gaus(xSamples_zoom,*popt)
1070 FitGauss = self.gaus(xSamples_zoom,*popt)
1072 except :#RuntimeError:
1071 except :#RuntimeError:
1073 return self.StopWindEstimation(error_code = 2)
1072 return self.StopWindEstimation(error_code = 2)
1074 else:
1073 else:
1075 return self.StopWindEstimation(error_code = 3)
1074 return self.StopWindEstimation(error_code = 3)
1076
1075
1077 '''***************************** CSPC Normalization *************************
1076 '''***************************** CSPC Normalization *************************
1078 The Spc spectra are used to normalize the crossspectra. Peaks from precipitation
1077 The Spc spectra are used to normalize the crossspectra. Peaks from precipitation
1079 influence the norm which is not desired. First, a range is identified where the
1078 influence the norm which is not desired. First, a range is identified where the
1080 wind peak is estimated -> sum_wind is sum of those frequencies. Next, the area
1079 wind peak is estimated -> sum_wind is sum of those frequencies. Next, the area
1081 around it gets cut off and values replaced by mean determined by the boundary
1080 around it gets cut off and values replaced by mean determined by the boundary
1082 data -> sum_noise (spc is not normalized here, thats why the noise is important)
1081 data -> sum_noise (spc is not normalized here, thats why the noise is important)
1083
1082
1084 The sums are then added and multiplied by range/datapoints, because you need
1083 The sums are then added and multiplied by range/datapoints, because you need
1085 an integral and not a sum for normalization.
1084 an integral and not a sum for normalization.
1086
1085
1087 A norm is found according to Briggs 92.
1086 A norm is found according to Briggs 92.
1088 '''
1087 '''
1089 # for each pair
1088 # for each pair
1090 for i in range(nPair):
1089 for i in range(nPair):
1091 cspc_norm = cspc[i,:].copy()
1090 cspc_norm = cspc[i,:].copy()
1092 chan_index0 = pairsList[i][0]
1091 chan_index0 = pairsList[i][0]
1093 chan_index1 = pairsList[i][1]
1092 chan_index1 = pairsList[i][1]
1094 CSPC_Samples[i] = cspc_norm / (numpy.sqrt(numpy.nansum(spc_norm[chan_index0])*numpy.nansum(spc_norm[chan_index1])) * delta_x)
1093 CSPC_Samples[i] = cspc_norm / (numpy.sqrt(numpy.nansum(spc_norm[chan_index0])*numpy.nansum(spc_norm[chan_index1])) * delta_x)
1095 phase[i] = numpy.arctan2(CSPC_Samples[i].imag, CSPC_Samples[i].real)
1094 phase[i] = numpy.arctan2(CSPC_Samples[i].imag, CSPC_Samples[i].real)
1096
1095
1097 CSPCmoments = numpy.vstack([self.Moments(numpy.abs(CSPC_Samples[0,xvalid]), xSamples_zoom),
1096 CSPCmoments = numpy.vstack([self.Moments(numpy.abs(CSPC_Samples[0,xvalid]), xSamples_zoom),
1098 self.Moments(numpy.abs(CSPC_Samples[1,xvalid]), xSamples_zoom),
1097 self.Moments(numpy.abs(CSPC_Samples[1,xvalid]), xSamples_zoom),
1099 self.Moments(numpy.abs(CSPC_Samples[2,xvalid]), xSamples_zoom)])
1098 self.Moments(numpy.abs(CSPC_Samples[2,xvalid]), xSamples_zoom)])
1100
1099
1101 popt01, popt02, popt12 = [1e-10,0,1e-10], [1e-10,0,1e-10] ,[1e-10,0,1e-10]
1100 popt01, popt02, popt12 = [1e-10,0,1e-10], [1e-10,0,1e-10] ,[1e-10,0,1e-10]
1102 FitGauss01, FitGauss02, FitGauss12 = numpy.zeros(len(xSamples)), numpy.zeros(len(xSamples)), numpy.zeros(len(xSamples))
1101 FitGauss01, FitGauss02, FitGauss12 = numpy.zeros(len(xSamples)), numpy.zeros(len(xSamples)), numpy.zeros(len(xSamples))
1103
1102
1104 '''*******************************FIT GAUSS CSPC************************************'''
1103 '''*******************************FIT GAUSS CSPC************************************'''
1105 try:
1104 try:
1106 popt01,pcov = curve_fit(self.gaus,xSamples_zoom,numpy.abs(CSPC_Samples[0][xvalid]),p0=CSPCmoments[0])
1105 popt01,pcov = curve_fit(self.gaus,xSamples_zoom,numpy.abs(CSPC_Samples[0][xvalid]),p0=CSPCmoments[0])
1107 if popt01[2] > widthlimit: # CONDITION
1106 if popt01[2] > widthlimit: # CONDITION
1108 return self.StopWindEstimation(error_code = 4)
1107 return self.StopWindEstimation(error_code = 4)
1109 popt02,pcov = curve_fit(self.gaus,xSamples_zoom,numpy.abs(CSPC_Samples[1][xvalid]),p0=CSPCmoments[1])
1108 popt02,pcov = curve_fit(self.gaus,xSamples_zoom,numpy.abs(CSPC_Samples[1][xvalid]),p0=CSPCmoments[1])
1110 if popt02[2] > widthlimit: # CONDITION
1109 if popt02[2] > widthlimit: # CONDITION
1111 return self.StopWindEstimation(error_code = 4)
1110 return self.StopWindEstimation(error_code = 4)
1112 popt12,pcov = curve_fit(self.gaus,xSamples_zoom,numpy.abs(CSPC_Samples[2][xvalid]),p0=CSPCmoments[2])
1111 popt12,pcov = curve_fit(self.gaus,xSamples_zoom,numpy.abs(CSPC_Samples[2][xvalid]),p0=CSPCmoments[2])
1113 if popt12[2] > widthlimit: # CONDITION
1112 if popt12[2] > widthlimit: # CONDITION
1114 return self.StopWindEstimation(error_code = 4)
1113 return self.StopWindEstimation(error_code = 4)
1115
1114
1116 FitGauss01 = self.gaus(xSamples_zoom, *popt01)
1115 FitGauss01 = self.gaus(xSamples_zoom, *popt01)
1117 FitGauss02 = self.gaus(xSamples_zoom, *popt02)
1116 FitGauss02 = self.gaus(xSamples_zoom, *popt02)
1118 FitGauss12 = self.gaus(xSamples_zoom, *popt12)
1117 FitGauss12 = self.gaus(xSamples_zoom, *popt12)
1119 except:
1118 except:
1120 return self.StopWindEstimation(error_code = 5)
1119 return self.StopWindEstimation(error_code = 5)
1121
1120
1122
1121
1123 '''************* Getting Fij ***************'''
1122 '''************* Getting Fij ***************'''
1124 # x-axis point of the gaussian where the center is located from GaussFit of spectra
1123 # x-axis point of the gaussian where the center is located from GaussFit of spectra
1125 GaussCenter = popt[1]
1124 GaussCenter = popt[1]
1126 ClosestCenter = xSamples_zoom[numpy.abs(xSamples_zoom-GaussCenter).argmin()]
1125 ClosestCenter = xSamples_zoom[numpy.abs(xSamples_zoom-GaussCenter).argmin()]
1127 PointGauCenter = numpy.where(xSamples_zoom==ClosestCenter)[0][0]
1126 PointGauCenter = numpy.where(xSamples_zoom==ClosestCenter)[0][0]
1128
1127
1129 # Point where e^-1 is located in the gaussian
1128 # Point where e^-1 is located in the gaussian
1130 PeMinus1 = numpy.max(FitGauss) * numpy.exp(-1)
1129 PeMinus1 = numpy.max(FitGauss) * numpy.exp(-1)
1131 FijClosest = FitGauss[numpy.abs(FitGauss-PeMinus1).argmin()] # The closest point to"Peminus1" in "FitGauss"
1130 FijClosest = FitGauss[numpy.abs(FitGauss-PeMinus1).argmin()] # The closest point to"Peminus1" in "FitGauss"
1132 PointFij = numpy.where(FitGauss==FijClosest)[0][0]
1131 PointFij = numpy.where(FitGauss==FijClosest)[0][0]
1133 Fij = numpy.abs(xSamples_zoom[PointFij] - xSamples_zoom[PointGauCenter])
1132 Fij = numpy.abs(xSamples_zoom[PointFij] - xSamples_zoom[PointGauCenter])
1134
1133
1135 '''********** Taking frequency ranges from mean SPCs **********'''
1134 '''********** Taking frequency ranges from mean SPCs **********'''
1136 GauWidth = popt[2] * 3/2 # Bandwidth of Gau01
1135 GauWidth = popt[2] * 3/2 # Bandwidth of Gau01
1137 Range = numpy.empty(2)
1136 Range = numpy.empty(2)
1138 Range[0] = GaussCenter - GauWidth
1137 Range[0] = GaussCenter - GauWidth
1139 Range[1] = GaussCenter + GauWidth
1138 Range[1] = GaussCenter + GauWidth
1140 # Point in x-axis where the bandwidth is located (min:max)
1139 # Point in x-axis where the bandwidth is located (min:max)
1141 ClosRangeMin = xSamples_zoom[numpy.abs(xSamples_zoom-Range[0]).argmin()]
1140 ClosRangeMin = xSamples_zoom[numpy.abs(xSamples_zoom-Range[0]).argmin()]
1142 ClosRangeMax = xSamples_zoom[numpy.abs(xSamples_zoom-Range[1]).argmin()]
1141 ClosRangeMax = xSamples_zoom[numpy.abs(xSamples_zoom-Range[1]).argmin()]
1143 PointRangeMin = numpy.where(xSamples_zoom==ClosRangeMin)[0][0]
1142 PointRangeMin = numpy.where(xSamples_zoom==ClosRangeMin)[0][0]
1144 PointRangeMax = numpy.where(xSamples_zoom==ClosRangeMax)[0][0]
1143 PointRangeMax = numpy.where(xSamples_zoom==ClosRangeMax)[0][0]
1145 Range = numpy.array([ PointRangeMin, PointRangeMax ])
1144 Range = numpy.array([ PointRangeMin, PointRangeMax ])
1146 FrecRange = xSamples_zoom[ Range[0] : Range[1] ]
1145 FrecRange = xSamples_zoom[ Range[0] : Range[1] ]
1147
1146
1148 '''************************** Getting Phase Slope ***************************'''
1147 '''************************** Getting Phase Slope ***************************'''
1149 for i in range(nPair):
1148 for i in range(nPair):
1150 if len(FrecRange) > 5:
1149 if len(FrecRange) > 5:
1151 PhaseRange = phase[i, xvalid[0][Range[0]:Range[1]]].copy()
1150 PhaseRange = phase[i, xvalid[0][Range[0]:Range[1]]].copy()
1152 mask = ~numpy.isnan(FrecRange) & ~numpy.isnan(PhaseRange)
1151 mask = ~numpy.isnan(FrecRange) & ~numpy.isnan(PhaseRange)
1153 if len(FrecRange) == len(PhaseRange):
1152 if len(FrecRange) == len(PhaseRange):
1154 try:
1153 try:
1155 slope, intercept, _, _, _ = stats.linregress(FrecRange[mask], self.AntiAliasing(PhaseRange[mask], 4.5))
1154 slope, intercept, _, _, _ = stats.linregress(FrecRange[mask], self.AntiAliasing(PhaseRange[mask], 4.5))
1156 PhaseSlope[i] = slope
1155 PhaseSlope[i] = slope
1157 PhaseInter[i] = intercept
1156 PhaseInter[i] = intercept
1158 except:
1157 except:
1159 return self.StopWindEstimation(error_code = 6)
1158 return self.StopWindEstimation(error_code = 6)
1160 else:
1159 else:
1161 return self.StopWindEstimation(error_code = 7)
1160 return self.StopWindEstimation(error_code = 7)
1162 else:
1161 else:
1163 return self.StopWindEstimation(error_code = 8)
1162 return self.StopWindEstimation(error_code = 8)
1164
1163
1165 '''*** Constants A-H correspond to the convention as in Briggs and Vincent 1992 ***'''
1164 '''*** Constants A-H correspond to the convention as in Briggs and Vincent 1992 ***'''
1166
1165
1167 '''Getting constant C'''
1166 '''Getting constant C'''
1168 cC=(Fij*numpy.pi)**2
1167 cC=(Fij*numpy.pi)**2
1169
1168
1170 '''****** Getting constants F and G ******'''
1169 '''****** Getting constants F and G ******'''
1171 MijEijNij = numpy.array([[Xi02,Eta02], [Xi12,Eta12]])
1170 MijEijNij = numpy.array([[Xi02,Eta02], [Xi12,Eta12]])
1172 # MijEijNij = numpy.array([[Xi01,Eta01], [Xi02,Eta02], [Xi12,Eta12]])
1171 # MijEijNij = numpy.array([[Xi01,Eta01], [Xi02,Eta02], [Xi12,Eta12]])
1173 # MijResult0 = (-PhaseSlope[0] * cC) / (2*numpy.pi)
1172 # MijResult0 = (-PhaseSlope[0] * cC) / (2*numpy.pi)
1174 MijResult1 = (-PhaseSlope[1] * cC) / (2*numpy.pi)
1173 MijResult1 = (-PhaseSlope[1] * cC) / (2*numpy.pi)
1175 MijResult2 = (-PhaseSlope[2] * cC) / (2*numpy.pi)
1174 MijResult2 = (-PhaseSlope[2] * cC) / (2*numpy.pi)
1176 # MijResults = numpy.array([MijResult0, MijResult1, MijResult2])
1175 # MijResults = numpy.array([MijResult0, MijResult1, MijResult2])
1177 MijResults = numpy.array([MijResult1, MijResult2])
1176 MijResults = numpy.array([MijResult1, MijResult2])
1178 (cF,cG) = numpy.linalg.solve(MijEijNij, MijResults)
1177 (cF,cG) = numpy.linalg.solve(MijEijNij, MijResults)
1179
1178
1180 '''****** Getting constants A, B and H ******'''
1179 '''****** Getting constants A, B and H ******'''
1181 W01 = numpy.nanmax( FitGauss01 )
1180 W01 = numpy.nanmax( FitGauss01 )
1182 W02 = numpy.nanmax( FitGauss02 )
1181 W02 = numpy.nanmax( FitGauss02 )
1183 W12 = numpy.nanmax( FitGauss12 )
1182 W12 = numpy.nanmax( FitGauss12 )
1184
1183
1185 WijResult01 = ((cF * Xi01 + cG * Eta01)**2)/cC - numpy.log(W01 / numpy.sqrt(numpy.pi / cC))
1184 WijResult01 = ((cF * Xi01 + cG * Eta01)**2)/cC - numpy.log(W01 / numpy.sqrt(numpy.pi / cC))
1186 WijResult02 = ((cF * Xi02 + cG * Eta02)**2)/cC - numpy.log(W02 / numpy.sqrt(numpy.pi / cC))
1185 WijResult02 = ((cF * Xi02 + cG * Eta02)**2)/cC - numpy.log(W02 / numpy.sqrt(numpy.pi / cC))
1187 WijResult12 = ((cF * Xi12 + cG * Eta12)**2)/cC - numpy.log(W12 / numpy.sqrt(numpy.pi / cC))
1186 WijResult12 = ((cF * Xi12 + cG * Eta12)**2)/cC - numpy.log(W12 / numpy.sqrt(numpy.pi / cC))
1188 WijResults = numpy.array([WijResult01, WijResult02, WijResult12])
1187 WijResults = numpy.array([WijResult01, WijResult02, WijResult12])
1189
1188
1190 WijEijNij = numpy.array([ [Xi01**2, Eta01**2, 2*Xi01*Eta01] , [Xi02**2, Eta02**2, 2*Xi02*Eta02] , [Xi12**2, Eta12**2, 2*Xi12*Eta12] ])
1189 WijEijNij = numpy.array([ [Xi01**2, Eta01**2, 2*Xi01*Eta01] , [Xi02**2, Eta02**2, 2*Xi02*Eta02] , [Xi12**2, Eta12**2, 2*Xi12*Eta12] ])
1191 (cA,cB,cH) = numpy.linalg.solve(WijEijNij, WijResults)
1190 (cA,cB,cH) = numpy.linalg.solve(WijEijNij, WijResults)
1192
1191
1193 VxVy = numpy.array([[cA,cH],[cH,cB]])
1192 VxVy = numpy.array([[cA,cH],[cH,cB]])
1194 VxVyResults = numpy.array([-cF,-cG])
1193 VxVyResults = numpy.array([-cF,-cG])
1195 (Vmer,Vzon) = numpy.linalg.solve(VxVy, VxVyResults)
1194 (Vmer,Vzon) = numpy.linalg.solve(VxVy, VxVyResults)
1196 Vver = -SPCMoments[1]*SPEED_OF_LIGHT/(2*radfreq)
1195 Vver = -SPCMoments[1]*SPEED_OF_LIGHT/(2*radfreq)
1197 error_code = 0
1196 error_code = 0
1198
1197
1199 return Vzon, Vmer, Vver, error_code
1198 return Vzon, Vmer, Vver, error_code
1200
1199
1201 class SpectralMoments(Operation):
1200 class SpectralMoments(Operation):
1202
1201
1203 '''
1202 '''
1204 Function SpectralMoments()
1203 Function SpectralMoments()
1205
1204
1206 Calculates moments (power, mean, standard deviation) and SNR of the signal
1205 Calculates moments (power, mean, standard deviation) and SNR of the signal
1207
1206
1208 Type of dataIn: Spectra
1207 Type of dataIn: Spectra
1209
1208
1210 Configuration Parameters:
1209 Configuration Parameters:
1211
1210
1212 dirCosx : Cosine director in X axis
1211 dirCosx : Cosine director in X axis
1213 dirCosy : Cosine director in Y axis
1212 dirCosy : Cosine director in Y axis
1214
1213
1215 elevation :
1214 elevation :
1216 azimuth :
1215 azimuth :
1217
1216
1218 Input:
1217 Input:
1219 channelList : simple channel list to select e.g. [2,3,7]
1218 channelList : simple channel list to select e.g. [2,3,7]
1220 self.dataOut.data_pre : Spectral data
1219 self.dataOut.data_pre : Spectral data
1221 self.dataOut.abscissaList : List of frequencies
1220 self.dataOut.abscissaList : List of frequencies
1222 self.dataOut.noise : Noise level per channel
1221 self.dataOut.noise : Noise level per channel
1223
1222
1224 Affected:
1223 Affected:
1225 self.dataOut.moments : Parameters per channel
1224 self.dataOut.moments : Parameters per channel
1226 self.dataOut.data_snr : SNR per channel
1225 self.dataOut.data_snr : SNR per channel
1227
1226
1228 '''
1227 '''
1229
1228
1230 def run(self, dataOut):
1229 def run(self, dataOut):
1231
1230
1232 data = dataOut.data_pre[0]
1231 data = dataOut.data_pre[0]
1233 absc = dataOut.abscissaList[:-1]
1232 absc = dataOut.abscissaList[:-1]
1234 noise = dataOut.noise
1233 noise = dataOut.noise
1235 nChannel = data.shape[0]
1234 nChannel = data.shape[0]
1236 data_param = numpy.zeros((nChannel, 4, data.shape[2]))
1235 data_param = numpy.zeros((nChannel, 4, data.shape[2]))
1237
1236
1238 for ind in range(nChannel):
1237 for ind in range(nChannel):
1239 data_param[ind,:,:] = self.__calculateMoments( data[ind,:,:] , absc , noise[ind] )
1238 data_param[ind,:,:] = self.__calculateMoments( data[ind,:,:] , absc , noise[ind] )
1240
1239
1241 dataOut.moments = data_param[:,1:,:]
1240 dataOut.moments = data_param[:,1:,:]
1242 dataOut.data_snr = data_param[:,0]
1241 dataOut.data_snr = data_param[:,0]
1243 dataOut.data_pow = data_param[:,1]
1242 dataOut.data_pow = data_param[:,1]
1244 dataOut.data_dop = data_param[:,2]
1243 dataOut.data_dop = data_param[:,2]
1245 dataOut.data_width = data_param[:,3]
1244 dataOut.data_width = data_param[:,3]
1246
1245
1247 return dataOut
1246 return dataOut
1248
1247
1249 def __calculateMoments(self, oldspec, oldfreq, n0,
1248 def __calculateMoments(self, oldspec, oldfreq, n0,
1250 nicoh = None, graph = None, smooth = None, type1 = None, fwindow = None, snrth = None, dc = None, aliasing = None, oldfd = None, wwauto = None):
1249 nicoh = None, graph = None, smooth = None, type1 = None, fwindow = None, snrth = None, dc = None, aliasing = None, oldfd = None, wwauto = None):
1251
1250
1252 if (nicoh is None): nicoh = 1
1251 if (nicoh is None): nicoh = 1
1253 if (graph is None): graph = 0
1252 if (graph is None): graph = 0
1254 if (smooth is None): smooth = 0
1253 if (smooth is None): smooth = 0
1255 elif (self.smooth < 3): smooth = 0
1254 elif (self.smooth < 3): smooth = 0
1256
1255
1257 if (type1 is None): type1 = 0
1256 if (type1 is None): type1 = 0
1258 if (fwindow is None): fwindow = numpy.zeros(oldfreq.size) + 1
1257 if (fwindow is None): fwindow = numpy.zeros(oldfreq.size) + 1
1259 if (snrth is None): snrth = -3
1258 if (snrth is None): snrth = -3
1260 if (dc is None): dc = 0
1259 if (dc is None): dc = 0
1261 if (aliasing is None): aliasing = 0
1260 if (aliasing is None): aliasing = 0
1262 if (oldfd is None): oldfd = 0
1261 if (oldfd is None): oldfd = 0
1263 if (wwauto is None): wwauto = 0
1262 if (wwauto is None): wwauto = 0
1264
1263
1265 if (n0 < 1.e-20): n0 = 1.e-20
1264 if (n0 < 1.e-20): n0 = 1.e-20
1266
1265
1267 freq = oldfreq
1266 freq = oldfreq
1268 vec_power = numpy.zeros(oldspec.shape[1])
1267 vec_power = numpy.zeros(oldspec.shape[1])
1269 vec_fd = numpy.zeros(oldspec.shape[1])
1268 vec_fd = numpy.zeros(oldspec.shape[1])
1270 vec_w = numpy.zeros(oldspec.shape[1])
1269 vec_w = numpy.zeros(oldspec.shape[1])
1271 vec_snr = numpy.zeros(oldspec.shape[1])
1270 vec_snr = numpy.zeros(oldspec.shape[1])
1272
1271
1273 # oldspec = numpy.ma.masked_invalid(oldspec)
1272 # oldspec = numpy.ma.masked_invalid(oldspec)
1274
1273
1275 for ind in range(oldspec.shape[1]):
1274 for ind in range(oldspec.shape[1]):
1276
1275
1277 spec = oldspec[:,ind]
1276 spec = oldspec[:,ind]
1278 aux = spec*fwindow
1277 aux = spec*fwindow
1279 max_spec = aux.max()
1278 max_spec = aux.max()
1280 m = aux.tolist().index(max_spec)
1279 m = aux.tolist().index(max_spec)
1281
1280
1282 # Smooth
1281 # Smooth
1283 if (smooth == 0):
1282 if (smooth == 0):
1284 spec2 = spec
1283 spec2 = spec
1285 else:
1284 else:
1286 spec2 = scipy.ndimage.filters.uniform_filter1d(spec,size=smooth)
1285 spec2 = scipy.ndimage.filters.uniform_filter1d(spec,size=smooth)
1287
1286
1288 # Moments Estimation
1287 # Moments Estimation
1289 bb = spec2[numpy.arange(m,spec2.size)]
1288 bb = spec2[numpy.arange(m,spec2.size)]
1290 bb = (bb<n0).nonzero()
1289 bb = (bb<n0).nonzero()
1291 bb = bb[0]
1290 bb = bb[0]
1292
1291
1293 ss = spec2[numpy.arange(0,m + 1)]
1292 ss = spec2[numpy.arange(0,m + 1)]
1294 ss = (ss<n0).nonzero()
1293 ss = (ss<n0).nonzero()
1295 ss = ss[0]
1294 ss = ss[0]
1296
1295
1297 if (bb.size == 0):
1296 if (bb.size == 0):
1298 bb0 = spec.size - 1 - m
1297 bb0 = spec.size - 1 - m
1299 else:
1298 else:
1300 bb0 = bb[0] - 1
1299 bb0 = bb[0] - 1
1301 if (bb0 < 0):
1300 if (bb0 < 0):
1302 bb0 = 0
1301 bb0 = 0
1303
1302
1304 if (ss.size == 0):
1303 if (ss.size == 0):
1305 ss1 = 1
1304 ss1 = 1
1306 else:
1305 else:
1307 ss1 = max(ss) + 1
1306 ss1 = max(ss) + 1
1308
1307
1309 if (ss1 > m):
1308 if (ss1 > m):
1310 ss1 = m
1309 ss1 = m
1311
1310
1312 valid = numpy.arange(int(m + bb0 - ss1 + 1)) + ss1
1311 valid = numpy.arange(int(m + bb0 - ss1 + 1)) + ss1
1313
1312
1314 signal_power = ((spec2[valid] - n0) * fwindow[valid]).mean() # D. Scipión added with correct definition
1313 signal_power = ((spec2[valid] - n0) * fwindow[valid]).mean() # D. Scipión added with correct definition
1315 total_power = (spec2[valid] * fwindow[valid]).mean() # D. Scipión added with correct definition
1314 total_power = (spec2[valid] * fwindow[valid]).mean() # D. Scipión added with correct definition
1316 power = ((spec2[valid] - n0) * fwindow[valid]).sum()
1315 power = ((spec2[valid] - n0) * fwindow[valid]).sum()
1317 fd = ((spec2[valid]- n0)*freq[valid] * fwindow[valid]).sum() / power
1316 fd = ((spec2[valid]- n0)*freq[valid] * fwindow[valid]).sum() / power
1318 w = numpy.sqrt(((spec2[valid] - n0)*fwindow[valid]*(freq[valid]- fd)**2).sum() / power)
1317 w = numpy.sqrt(((spec2[valid] - n0)*fwindow[valid]*(freq[valid]- fd)**2).sum() / power)
1319 snr = (spec2.mean()-n0)/n0
1318 snr = (spec2.mean()-n0)/n0
1320 if (snr < 1.e-20) :
1319 if (snr < 1.e-20) :
1321 snr = 1.e-20
1320 snr = 1.e-20
1322
1321
1323 # vec_power[ind] = power #D. Scipión replaced with the line below
1322 # vec_power[ind] = power #D. Scipión replaced with the line below
1324 vec_power[ind] = total_power
1323 vec_power[ind] = total_power
1325 vec_fd[ind] = fd
1324 vec_fd[ind] = fd
1326 vec_w[ind] = w
1325 vec_w[ind] = w
1327 vec_snr[ind] = snr
1326 vec_snr[ind] = snr
1328
1327
1329 return numpy.vstack((vec_snr, vec_power, vec_fd, vec_w))
1328 return numpy.vstack((vec_snr, vec_power, vec_fd, vec_w))
1330
1329
1331 #------------------ Get SA Parameters --------------------------
1330 #------------------ Get SA Parameters --------------------------
1332
1331
1333 def GetSAParameters(self):
1332 def GetSAParameters(self):
1334 #SA en frecuencia
1333 #SA en frecuencia
1335 pairslist = self.dataOut.groupList
1334 pairslist = self.dataOut.groupList
1336 num_pairs = len(pairslist)
1335 num_pairs = len(pairslist)
1337
1336
1338 vel = self.dataOut.abscissaList
1337 vel = self.dataOut.abscissaList
1339 spectra = self.dataOut.data_pre
1338 spectra = self.dataOut.data_pre
1340 cspectra = self.dataIn.data_cspc
1339 cspectra = self.dataIn.data_cspc
1341 delta_v = vel[1] - vel[0]
1340 delta_v = vel[1] - vel[0]
1342
1341
1343 #Calculating the power spectrum
1342 #Calculating the power spectrum
1344 spc_pow = numpy.sum(spectra, 3)*delta_v
1343 spc_pow = numpy.sum(spectra, 3)*delta_v
1345 #Normalizing Spectra
1344 #Normalizing Spectra
1346 norm_spectra = spectra/spc_pow
1345 norm_spectra = spectra/spc_pow
1347 #Calculating the norm_spectra at peak
1346 #Calculating the norm_spectra at peak
1348 max_spectra = numpy.max(norm_spectra, 3)
1347 max_spectra = numpy.max(norm_spectra, 3)
1349
1348
1350 #Normalizing Cross Spectra
1349 #Normalizing Cross Spectra
1351 norm_cspectra = numpy.zeros(cspectra.shape)
1350 norm_cspectra = numpy.zeros(cspectra.shape)
1352
1351
1353 for i in range(num_chan):
1352 for i in range(num_chan):
1354 norm_cspectra[i,:,:] = cspectra[i,:,:]/numpy.sqrt(spc_pow[pairslist[i][0],:]*spc_pow[pairslist[i][1],:])
1353 norm_cspectra[i,:,:] = cspectra[i,:,:]/numpy.sqrt(spc_pow[pairslist[i][0],:]*spc_pow[pairslist[i][1],:])
1355
1354
1356 max_cspectra = numpy.max(norm_cspectra,2)
1355 max_cspectra = numpy.max(norm_cspectra,2)
1357 max_cspectra_index = numpy.argmax(norm_cspectra, 2)
1356 max_cspectra_index = numpy.argmax(norm_cspectra, 2)
1358
1357
1359 for i in range(num_pairs):
1358 for i in range(num_pairs):
1360 cspc_par[i,:,:] = __calculateMoments(norm_cspectra)
1359 cspc_par[i,:,:] = __calculateMoments(norm_cspectra)
1361 #------------------- Get Lags ----------------------------------
1360 #------------------- Get Lags ----------------------------------
1362
1361
1363 class SALags(Operation):
1362 class SALags(Operation):
1364 '''
1363 '''
1365 Function GetMoments()
1364 Function GetMoments()
1366
1365
1367 Input:
1366 Input:
1368 self.dataOut.data_pre
1367 self.dataOut.data_pre
1369 self.dataOut.abscissaList
1368 self.dataOut.abscissaList
1370 self.dataOut.noise
1369 self.dataOut.noise
1371 self.dataOut.normFactor
1370 self.dataOut.normFactor
1372 self.dataOut.data_snr
1371 self.dataOut.data_snr
1373 self.dataOut.groupList
1372 self.dataOut.groupList
1374 self.dataOut.nChannels
1373 self.dataOut.nChannels
1375
1374
1376 Affected:
1375 Affected:
1377 self.dataOut.data_param
1376 self.dataOut.data_param
1378
1377
1379 '''
1378 '''
1380 def run(self, dataOut):
1379 def run(self, dataOut):
1381 data_acf = dataOut.data_pre[0]
1380 data_acf = dataOut.data_pre[0]
1382 data_ccf = dataOut.data_pre[1]
1381 data_ccf = dataOut.data_pre[1]
1383 normFactor_acf = dataOut.normFactor[0]
1382 normFactor_acf = dataOut.normFactor[0]
1384 normFactor_ccf = dataOut.normFactor[1]
1383 normFactor_ccf = dataOut.normFactor[1]
1385 pairs_acf = dataOut.groupList[0]
1384 pairs_acf = dataOut.groupList[0]
1386 pairs_ccf = dataOut.groupList[1]
1385 pairs_ccf = dataOut.groupList[1]
1387
1386
1388 nHeights = dataOut.nHeights
1387 nHeights = dataOut.nHeights
1389 absc = dataOut.abscissaList
1388 absc = dataOut.abscissaList
1390 noise = dataOut.noise
1389 noise = dataOut.noise
1391 SNR = dataOut.data_snr
1390 SNR = dataOut.data_snr
1392 nChannels = dataOut.nChannels
1391 nChannels = dataOut.nChannels
1393 # pairsList = dataOut.groupList
1392 # pairsList = dataOut.groupList
1394 # pairsAutoCorr, pairsCrossCorr = self.__getPairsAutoCorr(pairsList, nChannels)
1393 # pairsAutoCorr, pairsCrossCorr = self.__getPairsAutoCorr(pairsList, nChannels)
1395
1394
1396 for l in range(len(pairs_acf)):
1395 for l in range(len(pairs_acf)):
1397 data_acf[l,:,:] = data_acf[l,:,:]/normFactor_acf[l,:]
1396 data_acf[l,:,:] = data_acf[l,:,:]/normFactor_acf[l,:]
1398
1397
1399 for l in range(len(pairs_ccf)):
1398 for l in range(len(pairs_ccf)):
1400 data_ccf[l,:,:] = data_ccf[l,:,:]/normFactor_ccf[l,:]
1399 data_ccf[l,:,:] = data_ccf[l,:,:]/normFactor_ccf[l,:]
1401
1400
1402 dataOut.data_param = numpy.zeros((len(pairs_ccf)*2 + 1, nHeights))
1401 dataOut.data_param = numpy.zeros((len(pairs_ccf)*2 + 1, nHeights))
1403 dataOut.data_param[:-1,:] = self.__calculateTaus(data_acf, data_ccf, absc)
1402 dataOut.data_param[:-1,:] = self.__calculateTaus(data_acf, data_ccf, absc)
1404 dataOut.data_param[-1,:] = self.__calculateLag1Phase(data_acf, absc)
1403 dataOut.data_param[-1,:] = self.__calculateLag1Phase(data_acf, absc)
1405 return
1404 return
1406
1405
1407 # def __getPairsAutoCorr(self, pairsList, nChannels):
1406 # def __getPairsAutoCorr(self, pairsList, nChannels):
1408 #
1407 #
1409 # pairsAutoCorr = numpy.zeros(nChannels, dtype = 'int')*numpy.nan
1408 # pairsAutoCorr = numpy.zeros(nChannels, dtype = 'int')*numpy.nan
1410 #
1409 #
1411 # for l in range(len(pairsList)):
1410 # for l in range(len(pairsList)):
1412 # firstChannel = pairsList[l][0]
1411 # firstChannel = pairsList[l][0]
1413 # secondChannel = pairsList[l][1]
1412 # secondChannel = pairsList[l][1]
1414 #
1413 #
1415 # #Obteniendo pares de Autocorrelacion
1414 # #Obteniendo pares de Autocorrelacion
1416 # if firstChannel == secondChannel:
1415 # if firstChannel == secondChannel:
1417 # pairsAutoCorr[firstChannel] = int(l)
1416 # pairsAutoCorr[firstChannel] = int(l)
1418 #
1417 #
1419 # pairsAutoCorr = pairsAutoCorr.astype(int)
1418 # pairsAutoCorr = pairsAutoCorr.astype(int)
1420 #
1419 #
1421 # pairsCrossCorr = range(len(pairsList))
1420 # pairsCrossCorr = range(len(pairsList))
1422 # pairsCrossCorr = numpy.delete(pairsCrossCorr,pairsAutoCorr)
1421 # pairsCrossCorr = numpy.delete(pairsCrossCorr,pairsAutoCorr)
1423 #
1422 #
1424 # return pairsAutoCorr, pairsCrossCorr
1423 # return pairsAutoCorr, pairsCrossCorr
1425
1424
1426 def __calculateTaus(self, data_acf, data_ccf, lagRange):
1425 def __calculateTaus(self, data_acf, data_ccf, lagRange):
1427
1426
1428 lag0 = data_acf.shape[1]/2
1427 lag0 = data_acf.shape[1]/2
1429 #Funcion de Autocorrelacion
1428 #Funcion de Autocorrelacion
1430 mean_acf = stats.nanmean(data_acf, axis = 0)
1429 mean_acf = stats.nanmean(data_acf, axis = 0)
1431
1430
1432 #Obtencion Indice de TauCross
1431 #Obtencion Indice de TauCross
1433 ind_ccf = data_ccf.argmax(axis = 1)
1432 ind_ccf = data_ccf.argmax(axis = 1)
1434 #Obtencion Indice de TauAuto
1433 #Obtencion Indice de TauAuto
1435 ind_acf = numpy.zeros(ind_ccf.shape,dtype = 'int')
1434 ind_acf = numpy.zeros(ind_ccf.shape,dtype = 'int')
1436 ccf_lag0 = data_ccf[:,lag0,:]
1435 ccf_lag0 = data_ccf[:,lag0,:]
1437
1436
1438 for i in range(ccf_lag0.shape[0]):
1437 for i in range(ccf_lag0.shape[0]):
1439 ind_acf[i,:] = numpy.abs(mean_acf - ccf_lag0[i,:]).argmin(axis = 0)
1438 ind_acf[i,:] = numpy.abs(mean_acf - ccf_lag0[i,:]).argmin(axis = 0)
1440
1439
1441 #Obtencion de TauCross y TauAuto
1440 #Obtencion de TauCross y TauAuto
1442 tau_ccf = lagRange[ind_ccf]
1441 tau_ccf = lagRange[ind_ccf]
1443 tau_acf = lagRange[ind_acf]
1442 tau_acf = lagRange[ind_acf]
1444
1443
1445 Nan1, Nan2 = numpy.where(tau_ccf == lagRange[0])
1444 Nan1, Nan2 = numpy.where(tau_ccf == lagRange[0])
1446
1445
1447 tau_ccf[Nan1,Nan2] = numpy.nan
1446 tau_ccf[Nan1,Nan2] = numpy.nan
1448 tau_acf[Nan1,Nan2] = numpy.nan
1447 tau_acf[Nan1,Nan2] = numpy.nan
1449 tau = numpy.vstack((tau_ccf,tau_acf))
1448 tau = numpy.vstack((tau_ccf,tau_acf))
1450
1449
1451 return tau
1450 return tau
1452
1451
1453 def __calculateLag1Phase(self, data, lagTRange):
1452 def __calculateLag1Phase(self, data, lagTRange):
1454 data1 = stats.nanmean(data, axis = 0)
1453 data1 = stats.nanmean(data, axis = 0)
1455 lag1 = numpy.where(lagTRange == 0)[0][0] + 1
1454 lag1 = numpy.where(lagTRange == 0)[0][0] + 1
1456
1455
1457 phase = numpy.angle(data1[lag1,:])
1456 phase = numpy.angle(data1[lag1,:])
1458
1457
1459 return phase
1458 return phase
1460
1459
1461 class SpectralFitting(Operation):
1460 class SpectralFitting(Operation):
1462 '''
1461 '''
1463 Function GetMoments()
1462 Function GetMoments()
1464
1463
1465 Input:
1464 Input:
1466 Output:
1465 Output:
1467 Variables modified:
1466 Variables modified:
1468 '''
1467 '''
1469
1468
1470 def run(self, dataOut, getSNR = True, path=None, file=None, groupList=None):
1469 def run(self, dataOut, getSNR = True, path=None, file=None, groupList=None):
1471
1470
1472
1471
1473 if path != None:
1472 if path != None:
1474 sys.path.append(path)
1473 sys.path.append(path)
1475 self.dataOut.library = importlib.import_module(file)
1474 self.dataOut.library = importlib.import_module(file)
1476
1475
1477 #To be inserted as a parameter
1476 #To be inserted as a parameter
1478 groupArray = numpy.array(groupList)
1477 groupArray = numpy.array(groupList)
1479 # groupArray = numpy.array([[0,1],[2,3]])
1478 # groupArray = numpy.array([[0,1],[2,3]])
1480 self.dataOut.groupList = groupArray
1479 self.dataOut.groupList = groupArray
1481
1480
1482 nGroups = groupArray.shape[0]
1481 nGroups = groupArray.shape[0]
1483 nChannels = self.dataIn.nChannels
1482 nChannels = self.dataIn.nChannels
1484 nHeights=self.dataIn.heightList.size
1483 nHeights=self.dataIn.heightList.size
1485
1484
1486 #Parameters Array
1485 #Parameters Array
1487 self.dataOut.data_param = None
1486 self.dataOut.data_param = None
1488
1487
1489 #Set constants
1488 #Set constants
1490 constants = self.dataOut.library.setConstants(self.dataIn)
1489 constants = self.dataOut.library.setConstants(self.dataIn)
1491 self.dataOut.constants = constants
1490 self.dataOut.constants = constants
1492 M = self.dataIn.normFactor
1491 M = self.dataIn.normFactor
1493 N = self.dataIn.nFFTPoints
1492 N = self.dataIn.nFFTPoints
1494 ippSeconds = self.dataIn.ippSeconds
1493 ippSeconds = self.dataIn.ippSeconds
1495 K = self.dataIn.nIncohInt
1494 K = self.dataIn.nIncohInt
1496 pairsArray = numpy.array(self.dataIn.pairsList)
1495 pairsArray = numpy.array(self.dataIn.pairsList)
1497
1496
1498 #List of possible combinations
1497 #List of possible combinations
1499 listComb = itertools.combinations(numpy.arange(groupArray.shape[1]),2)
1498 listComb = itertools.combinations(numpy.arange(groupArray.shape[1]),2)
1500 indCross = numpy.zeros(len(list(listComb)), dtype = 'int')
1499 indCross = numpy.zeros(len(list(listComb)), dtype = 'int')
1501
1500
1502 if getSNR:
1501 if getSNR:
1503 listChannels = groupArray.reshape((groupArray.size))
1502 listChannels = groupArray.reshape((groupArray.size))
1504 listChannels.sort()
1503 listChannels.sort()
1505 noise = self.dataIn.getNoise()
1504 noise = self.dataIn.getNoise()
1506 self.dataOut.data_snr = self.__getSNR(self.dataIn.data_spc[listChannels,:,:], noise[listChannels])
1505 self.dataOut.data_snr = self.__getSNR(self.dataIn.data_spc[listChannels,:,:], noise[listChannels])
1507
1506
1508 for i in range(nGroups):
1507 for i in range(nGroups):
1509 coord = groupArray[i,:]
1508 coord = groupArray[i,:]
1510
1509
1511 #Input data array
1510 #Input data array
1512 data = self.dataIn.data_spc[coord,:,:]/(M*N)
1511 data = self.dataIn.data_spc[coord,:,:]/(M*N)
1513 data = data.reshape((data.shape[0]*data.shape[1],data.shape[2]))
1512 data = data.reshape((data.shape[0]*data.shape[1],data.shape[2]))
1514
1513
1515 #Cross Spectra data array for Covariance Matrixes
1514 #Cross Spectra data array for Covariance Matrixes
1516 ind = 0
1515 ind = 0
1517 for pairs in listComb:
1516 for pairs in listComb:
1518 pairsSel = numpy.array([coord[x],coord[y]])
1517 pairsSel = numpy.array([coord[x],coord[y]])
1519 indCross[ind] = int(numpy.where(numpy.all(pairsArray == pairsSel, axis = 1))[0][0])
1518 indCross[ind] = int(numpy.where(numpy.all(pairsArray == pairsSel, axis = 1))[0][0])
1520 ind += 1
1519 ind += 1
1521 dataCross = self.dataIn.data_cspc[indCross,:,:]/(M*N)
1520 dataCross = self.dataIn.data_cspc[indCross,:,:]/(M*N)
1522 dataCross = dataCross**2/K
1521 dataCross = dataCross**2/K
1523
1522
1524 for h in range(nHeights):
1523 for h in range(nHeights):
1525
1524
1526 #Input
1525 #Input
1527 d = data[:,h]
1526 d = data[:,h]
1528
1527
1529 #Covariance Matrix
1528 #Covariance Matrix
1530 D = numpy.diag(d**2/K)
1529 D = numpy.diag(d**2/K)
1531 ind = 0
1530 ind = 0
1532 for pairs in listComb:
1531 for pairs in listComb:
1533 #Coordinates in Covariance Matrix
1532 #Coordinates in Covariance Matrix
1534 x = pairs[0]
1533 x = pairs[0]
1535 y = pairs[1]
1534 y = pairs[1]
1536 #Channel Index
1535 #Channel Index
1537 S12 = dataCross[ind,:,h]
1536 S12 = dataCross[ind,:,h]
1538 D12 = numpy.diag(S12)
1537 D12 = numpy.diag(S12)
1539 #Completing Covariance Matrix with Cross Spectras
1538 #Completing Covariance Matrix with Cross Spectras
1540 D[x*N:(x+1)*N,y*N:(y+1)*N] = D12
1539 D[x*N:(x+1)*N,y*N:(y+1)*N] = D12
1541 D[y*N:(y+1)*N,x*N:(x+1)*N] = D12
1540 D[y*N:(y+1)*N,x*N:(x+1)*N] = D12
1542 ind += 1
1541 ind += 1
1543 Dinv=numpy.linalg.inv(D)
1542 Dinv=numpy.linalg.inv(D)
1544 L=numpy.linalg.cholesky(Dinv)
1543 L=numpy.linalg.cholesky(Dinv)
1545 LT=L.T
1544 LT=L.T
1546
1545
1547 dp = numpy.dot(LT,d)
1546 dp = numpy.dot(LT,d)
1548
1547
1549 #Initial values
1548 #Initial values
1550 data_spc = self.dataIn.data_spc[coord,:,h]
1549 data_spc = self.dataIn.data_spc[coord,:,h]
1551
1550
1552 if (h>0)and(error1[3]<5):
1551 if (h>0)and(error1[3]<5):
1553 p0 = self.dataOut.data_param[i,:,h-1]
1552 p0 = self.dataOut.data_param[i,:,h-1]
1554 else:
1553 else:
1555 p0 = numpy.array(self.dataOut.library.initialValuesFunction(data_spc, constants, i))
1554 p0 = numpy.array(self.dataOut.library.initialValuesFunction(data_spc, constants, i))
1556
1555
1557 try:
1556 try:
1558 #Least Squares
1557 #Least Squares
1559 minp,covp,infodict,mesg,ier = optimize.leastsq(self.__residFunction,p0,args=(dp,LT,constants),full_output=True)
1558 minp,covp,infodict,mesg,ier = optimize.leastsq(self.__residFunction,p0,args=(dp,LT,constants),full_output=True)
1560 # minp,covp = optimize.leastsq(self.__residFunction,p0,args=(dp,LT,constants))
1559 # minp,covp = optimize.leastsq(self.__residFunction,p0,args=(dp,LT,constants))
1561 #Chi square error
1560 #Chi square error
1562 error0 = numpy.sum(infodict['fvec']**2)/(2*N)
1561 error0 = numpy.sum(infodict['fvec']**2)/(2*N)
1563 #Error with Jacobian
1562 #Error with Jacobian
1564 error1 = self.dataOut.library.errorFunction(minp,constants,LT)
1563 error1 = self.dataOut.library.errorFunction(minp,constants,LT)
1565 except:
1564 except:
1566 minp = p0*numpy.nan
1565 minp = p0*numpy.nan
1567 error0 = numpy.nan
1566 error0 = numpy.nan
1568 error1 = p0*numpy.nan
1567 error1 = p0*numpy.nan
1569
1568
1570 #Save
1569 #Save
1571 if self.dataOut.data_param is None:
1570 if self.dataOut.data_param is None:
1572 self.dataOut.data_param = numpy.zeros((nGroups, p0.size, nHeights))*numpy.nan
1571 self.dataOut.data_param = numpy.zeros((nGroups, p0.size, nHeights))*numpy.nan
1573 self.dataOut.data_error = numpy.zeros((nGroups, p0.size + 1, nHeights))*numpy.nan
1572 self.dataOut.data_error = numpy.zeros((nGroups, p0.size + 1, nHeights))*numpy.nan
1574
1573
1575 self.dataOut.data_error[i,:,h] = numpy.hstack((error0,error1))
1574 self.dataOut.data_error[i,:,h] = numpy.hstack((error0,error1))
1576 self.dataOut.data_param[i,:,h] = minp
1575 self.dataOut.data_param[i,:,h] = minp
1577 return
1576 return
1578
1577
1579 def __residFunction(self, p, dp, LT, constants):
1578 def __residFunction(self, p, dp, LT, constants):
1580
1579
1581 fm = self.dataOut.library.modelFunction(p, constants)
1580 fm = self.dataOut.library.modelFunction(p, constants)
1582 fmp=numpy.dot(LT,fm)
1581 fmp=numpy.dot(LT,fm)
1583
1582
1584 return dp-fmp
1583 return dp-fmp
1585
1584
1586 def __getSNR(self, z, noise):
1585 def __getSNR(self, z, noise):
1587
1586
1588 avg = numpy.average(z, axis=1)
1587 avg = numpy.average(z, axis=1)
1589 SNR = (avg.T-noise)/noise
1588 SNR = (avg.T-noise)/noise
1590 SNR = SNR.T
1589 SNR = SNR.T
1591 return SNR
1590 return SNR
1592
1591
1593 def __chisq(p,chindex,hindex):
1592 def __chisq(p,chindex,hindex):
1594 #similar to Resid but calculates CHI**2
1593 #similar to Resid but calculates CHI**2
1595 [LT,d,fm]=setupLTdfm(p,chindex,hindex)
1594 [LT,d,fm]=setupLTdfm(p,chindex,hindex)
1596 dp=numpy.dot(LT,d)
1595 dp=numpy.dot(LT,d)
1597 fmp=numpy.dot(LT,fm)
1596 fmp=numpy.dot(LT,fm)
1598 chisq=numpy.dot((dp-fmp).T,(dp-fmp))
1597 chisq=numpy.dot((dp-fmp).T,(dp-fmp))
1599 return chisq
1598 return chisq
1600
1599
1601 class WindProfiler(Operation):
1600 class WindProfiler(Operation):
1602
1601
1603 __isConfig = False
1602 __isConfig = False
1604
1603
1605 __initime = None
1604 __initime = None
1606 __lastdatatime = None
1605 __lastdatatime = None
1607 __integrationtime = None
1606 __integrationtime = None
1608
1607
1609 __buffer = None
1608 __buffer = None
1610
1609
1611 __dataReady = False
1610 __dataReady = False
1612
1611
1613 __firstdata = None
1612 __firstdata = None
1614
1613
1615 n = None
1614 n = None
1616
1615
1617 def __init__(self):
1616 def __init__(self):
1618 Operation.__init__(self)
1617 Operation.__init__(self)
1619
1618
1620 def __calculateCosDir(self, elev, azim):
1619 def __calculateCosDir(self, elev, azim):
1621 zen = (90 - elev)*numpy.pi/180
1620 zen = (90 - elev)*numpy.pi/180
1622 azim = azim*numpy.pi/180
1621 azim = azim*numpy.pi/180
1623 cosDirX = numpy.sqrt((1-numpy.cos(zen)**2)/((1+numpy.tan(azim)**2)))
1622 cosDirX = numpy.sqrt((1-numpy.cos(zen)**2)/((1+numpy.tan(azim)**2)))
1624 cosDirY = numpy.sqrt(1-numpy.cos(zen)**2-cosDirX**2)
1623 cosDirY = numpy.sqrt(1-numpy.cos(zen)**2-cosDirX**2)
1625
1624
1626 signX = numpy.sign(numpy.cos(azim))
1625 signX = numpy.sign(numpy.cos(azim))
1627 signY = numpy.sign(numpy.sin(azim))
1626 signY = numpy.sign(numpy.sin(azim))
1628
1627
1629 cosDirX = numpy.copysign(cosDirX, signX)
1628 cosDirX = numpy.copysign(cosDirX, signX)
1630 cosDirY = numpy.copysign(cosDirY, signY)
1629 cosDirY = numpy.copysign(cosDirY, signY)
1631 return cosDirX, cosDirY
1630 return cosDirX, cosDirY
1632
1631
1633 def __calculateAngles(self, theta_x, theta_y, azimuth):
1632 def __calculateAngles(self, theta_x, theta_y, azimuth):
1634
1633
1635 dir_cosw = numpy.sqrt(1-theta_x**2-theta_y**2)
1634 dir_cosw = numpy.sqrt(1-theta_x**2-theta_y**2)
1636 zenith_arr = numpy.arccos(dir_cosw)
1635 zenith_arr = numpy.arccos(dir_cosw)
1637 azimuth_arr = numpy.arctan2(theta_x,theta_y) + azimuth*math.pi/180
1636 azimuth_arr = numpy.arctan2(theta_x,theta_y) + azimuth*math.pi/180
1638
1637
1639 dir_cosu = numpy.sin(azimuth_arr)*numpy.sin(zenith_arr)
1638 dir_cosu = numpy.sin(azimuth_arr)*numpy.sin(zenith_arr)
1640 dir_cosv = numpy.cos(azimuth_arr)*numpy.sin(zenith_arr)
1639 dir_cosv = numpy.cos(azimuth_arr)*numpy.sin(zenith_arr)
1641
1640
1642 return azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw
1641 return azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw
1643
1642
1644 def __calculateMatA(self, dir_cosu, dir_cosv, dir_cosw, horOnly):
1643 def __calculateMatA(self, dir_cosu, dir_cosv, dir_cosw, horOnly):
1645
1644
1646 #
1645 #
1647 if horOnly:
1646 if horOnly:
1648 A = numpy.c_[dir_cosu,dir_cosv]
1647 A = numpy.c_[dir_cosu,dir_cosv]
1649 else:
1648 else:
1650 A = numpy.c_[dir_cosu,dir_cosv,dir_cosw]
1649 A = numpy.c_[dir_cosu,dir_cosv,dir_cosw]
1651 A = numpy.asmatrix(A)
1650 A = numpy.asmatrix(A)
1652 A1 = numpy.linalg.inv(A.transpose()*A)*A.transpose()
1651 A1 = numpy.linalg.inv(A.transpose()*A)*A.transpose()
1653
1652
1654 return A1
1653 return A1
1655
1654
1656 def __correctValues(self, heiRang, phi, velRadial, SNR):
1655 def __correctValues(self, heiRang, phi, velRadial, SNR):
1657 listPhi = phi.tolist()
1656 listPhi = phi.tolist()
1658 maxid = listPhi.index(max(listPhi))
1657 maxid = listPhi.index(max(listPhi))
1659 minid = listPhi.index(min(listPhi))
1658 minid = listPhi.index(min(listPhi))
1660
1659
1661 rango = list(range(len(phi)))
1660 rango = list(range(len(phi)))
1662 # rango = numpy.delete(rango,maxid)
1661 # rango = numpy.delete(rango,maxid)
1663
1662
1664 heiRang1 = heiRang*math.cos(phi[maxid])
1663 heiRang1 = heiRang*math.cos(phi[maxid])
1665 heiRangAux = heiRang*math.cos(phi[minid])
1664 heiRangAux = heiRang*math.cos(phi[minid])
1666 indOut = (heiRang1 < heiRangAux[0]).nonzero()
1665 indOut = (heiRang1 < heiRangAux[0]).nonzero()
1667 heiRang1 = numpy.delete(heiRang1,indOut)
1666 heiRang1 = numpy.delete(heiRang1,indOut)
1668
1667
1669 velRadial1 = numpy.zeros([len(phi),len(heiRang1)])
1668 velRadial1 = numpy.zeros([len(phi),len(heiRang1)])
1670 SNR1 = numpy.zeros([len(phi),len(heiRang1)])
1669 SNR1 = numpy.zeros([len(phi),len(heiRang1)])
1671
1670
1672 for i in rango:
1671 for i in rango:
1673 x = heiRang*math.cos(phi[i])
1672 x = heiRang*math.cos(phi[i])
1674 y1 = velRadial[i,:]
1673 y1 = velRadial[i,:]
1675 f1 = interpolate.interp1d(x,y1,kind = 'cubic')
1674 f1 = interpolate.interp1d(x,y1,kind = 'cubic')
1676
1675
1677 x1 = heiRang1
1676 x1 = heiRang1
1678 y11 = f1(x1)
1677 y11 = f1(x1)
1679
1678
1680 y2 = SNR[i,:]
1679 y2 = SNR[i,:]
1681 f2 = interpolate.interp1d(x,y2,kind = 'cubic')
1680 f2 = interpolate.interp1d(x,y2,kind = 'cubic')
1682 y21 = f2(x1)
1681 y21 = f2(x1)
1683
1682
1684 velRadial1[i,:] = y11
1683 velRadial1[i,:] = y11
1685 SNR1[i,:] = y21
1684 SNR1[i,:] = y21
1686
1685
1687 return heiRang1, velRadial1, SNR1
1686 return heiRang1, velRadial1, SNR1
1688
1687
1689 def __calculateVelUVW(self, A, velRadial):
1688 def __calculateVelUVW(self, A, velRadial):
1690
1689
1691 #Operacion Matricial
1690 #Operacion Matricial
1692 # velUVW = numpy.zeros((velRadial.shape[1],3))
1691 # velUVW = numpy.zeros((velRadial.shape[1],3))
1693 # for ind in range(velRadial.shape[1]):
1692 # for ind in range(velRadial.shape[1]):
1694 # velUVW[ind,:] = numpy.dot(A,velRadial[:,ind])
1693 # velUVW[ind,:] = numpy.dot(A,velRadial[:,ind])
1695 # velUVW = velUVW.transpose()
1694 # velUVW = velUVW.transpose()
1696 velUVW = numpy.zeros((A.shape[0],velRadial.shape[1]))
1695 velUVW = numpy.zeros((A.shape[0],velRadial.shape[1]))
1697 velUVW[:,:] = numpy.dot(A,velRadial)
1696 velUVW[:,:] = numpy.dot(A,velRadial)
1698
1697
1699
1698
1700 return velUVW
1699 return velUVW
1701
1700
1702 # def techniqueDBS(self, velRadial0, dirCosx, disrCosy, azimuth, correct, horizontalOnly, heiRang, SNR0):
1701 # def techniqueDBS(self, velRadial0, dirCosx, disrCosy, azimuth, correct, horizontalOnly, heiRang, SNR0):
1703
1702
1704 def techniqueDBS(self, kwargs):
1703 def techniqueDBS(self, kwargs):
1705 """
1704 """
1706 Function that implements Doppler Beam Swinging (DBS) technique.
1705 Function that implements Doppler Beam Swinging (DBS) technique.
1707
1706
1708 Input: Radial velocities, Direction cosines (x and y) of the Beam, Antenna azimuth,
1707 Input: Radial velocities, Direction cosines (x and y) of the Beam, Antenna azimuth,
1709 Direction correction (if necessary), Ranges and SNR
1708 Direction correction (if necessary), Ranges and SNR
1710
1709
1711 Output: Winds estimation (Zonal, Meridional and Vertical)
1710 Output: Winds estimation (Zonal, Meridional and Vertical)
1712
1711
1713 Parameters affected: Winds, height range, SNR
1712 Parameters affected: Winds, height range, SNR
1714 """
1713 """
1715 velRadial0 = kwargs['velRadial']
1714 velRadial0 = kwargs['velRadial']
1716 heiRang = kwargs['heightList']
1715 heiRang = kwargs['heightList']
1717 SNR0 = kwargs['SNR']
1716 SNR0 = kwargs['SNR']
1718
1717
1719 if 'dirCosx' in kwargs and 'dirCosy' in kwargs:
1718 if 'dirCosx' in kwargs and 'dirCosy' in kwargs:
1720 theta_x = numpy.array(kwargs['dirCosx'])
1719 theta_x = numpy.array(kwargs['dirCosx'])
1721 theta_y = numpy.array(kwargs['dirCosy'])
1720 theta_y = numpy.array(kwargs['dirCosy'])
1722 else:
1721 else:
1723 elev = numpy.array(kwargs['elevation'])
1722 elev = numpy.array(kwargs['elevation'])
1724 azim = numpy.array(kwargs['azimuth'])
1723 azim = numpy.array(kwargs['azimuth'])
1725 theta_x, theta_y = self.__calculateCosDir(elev, azim)
1724 theta_x, theta_y = self.__calculateCosDir(elev, azim)
1726 azimuth = kwargs['correctAzimuth']
1725 azimuth = kwargs['correctAzimuth']
1727 if 'horizontalOnly' in kwargs:
1726 if 'horizontalOnly' in kwargs:
1728 horizontalOnly = kwargs['horizontalOnly']
1727 horizontalOnly = kwargs['horizontalOnly']
1729 else: horizontalOnly = False
1728 else: horizontalOnly = False
1730 if 'correctFactor' in kwargs:
1729 if 'correctFactor' in kwargs:
1731 correctFactor = kwargs['correctFactor']
1730 correctFactor = kwargs['correctFactor']
1732 else: correctFactor = 1
1731 else: correctFactor = 1
1733 if 'channelList' in kwargs:
1732 if 'channelList' in kwargs:
1734 channelList = kwargs['channelList']
1733 channelList = kwargs['channelList']
1735 if len(channelList) == 2:
1734 if len(channelList) == 2:
1736 horizontalOnly = True
1735 horizontalOnly = True
1737 arrayChannel = numpy.array(channelList)
1736 arrayChannel = numpy.array(channelList)
1738 param = param[arrayChannel,:,:]
1737 param = param[arrayChannel,:,:]
1739 theta_x = theta_x[arrayChannel]
1738 theta_x = theta_x[arrayChannel]
1740 theta_y = theta_y[arrayChannel]
1739 theta_y = theta_y[arrayChannel]
1741
1740
1742 azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw = self.__calculateAngles(theta_x, theta_y, azimuth)
1741 azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw = self.__calculateAngles(theta_x, theta_y, azimuth)
1743 heiRang1, velRadial1, SNR1 = self.__correctValues(heiRang, zenith_arr, correctFactor*velRadial0, SNR0)
1742 heiRang1, velRadial1, SNR1 = self.__correctValues(heiRang, zenith_arr, correctFactor*velRadial0, SNR0)
1744 A = self.__calculateMatA(dir_cosu, dir_cosv, dir_cosw, horizontalOnly)
1743 A = self.__calculateMatA(dir_cosu, dir_cosv, dir_cosw, horizontalOnly)
1745
1744
1746 #Calculo de Componentes de la velocidad con DBS
1745 #Calculo de Componentes de la velocidad con DBS
1747 winds = self.__calculateVelUVW(A,velRadial1)
1746 winds = self.__calculateVelUVW(A,velRadial1)
1748
1747
1749 return winds, heiRang1, SNR1
1748 return winds, heiRang1, SNR1
1750
1749
1751 def __calculateDistance(self, posx, posy, pairs_ccf, azimuth = None):
1750 def __calculateDistance(self, posx, posy, pairs_ccf, azimuth = None):
1752
1751
1753 nPairs = len(pairs_ccf)
1752 nPairs = len(pairs_ccf)
1754 posx = numpy.asarray(posx)
1753 posx = numpy.asarray(posx)
1755 posy = numpy.asarray(posy)
1754 posy = numpy.asarray(posy)
1756
1755
1757 #Rotacion Inversa para alinear con el azimuth
1756 #Rotacion Inversa para alinear con el azimuth
1758 if azimuth!= None:
1757 if azimuth!= None:
1759 azimuth = azimuth*math.pi/180
1758 azimuth = azimuth*math.pi/180
1760 posx1 = posx*math.cos(azimuth) + posy*math.sin(azimuth)
1759 posx1 = posx*math.cos(azimuth) + posy*math.sin(azimuth)
1761 posy1 = -posx*math.sin(azimuth) + posy*math.cos(azimuth)
1760 posy1 = -posx*math.sin(azimuth) + posy*math.cos(azimuth)
1762 else:
1761 else:
1763 posx1 = posx
1762 posx1 = posx
1764 posy1 = posy
1763 posy1 = posy
1765
1764
1766 #Calculo de Distancias
1765 #Calculo de Distancias
1767 distx = numpy.zeros(nPairs)
1766 distx = numpy.zeros(nPairs)
1768 disty = numpy.zeros(nPairs)
1767 disty = numpy.zeros(nPairs)
1769 dist = numpy.zeros(nPairs)
1768 dist = numpy.zeros(nPairs)
1770 ang = numpy.zeros(nPairs)
1769 ang = numpy.zeros(nPairs)
1771
1770
1772 for i in range(nPairs):
1771 for i in range(nPairs):
1773 distx[i] = posx1[pairs_ccf[i][1]] - posx1[pairs_ccf[i][0]]
1772 distx[i] = posx1[pairs_ccf[i][1]] - posx1[pairs_ccf[i][0]]
1774 disty[i] = posy1[pairs_ccf[i][1]] - posy1[pairs_ccf[i][0]]
1773 disty[i] = posy1[pairs_ccf[i][1]] - posy1[pairs_ccf[i][0]]
1775 dist[i] = numpy.sqrt(distx[i]**2 + disty[i]**2)
1774 dist[i] = numpy.sqrt(distx[i]**2 + disty[i]**2)
1776 ang[i] = numpy.arctan2(disty[i],distx[i])
1775 ang[i] = numpy.arctan2(disty[i],distx[i])
1777
1776
1778 return distx, disty, dist, ang
1777 return distx, disty, dist, ang
1779 #Calculo de Matrices
1778 #Calculo de Matrices
1780 # nPairs = len(pairs)
1779 # nPairs = len(pairs)
1781 # ang1 = numpy.zeros((nPairs, 2, 1))
1780 # ang1 = numpy.zeros((nPairs, 2, 1))
1782 # dist1 = numpy.zeros((nPairs, 2, 1))
1781 # dist1 = numpy.zeros((nPairs, 2, 1))
1783 #
1782 #
1784 # for j in range(nPairs):
1783 # for j in range(nPairs):
1785 # dist1[j,0,0] = dist[pairs[j][0]]
1784 # dist1[j,0,0] = dist[pairs[j][0]]
1786 # dist1[j,1,0] = dist[pairs[j][1]]
1785 # dist1[j,1,0] = dist[pairs[j][1]]
1787 # ang1[j,0,0] = ang[pairs[j][0]]
1786 # ang1[j,0,0] = ang[pairs[j][0]]
1788 # ang1[j,1,0] = ang[pairs[j][1]]
1787 # ang1[j,1,0] = ang[pairs[j][1]]
1789 #
1788 #
1790 # return distx,disty, dist1,ang1
1789 # return distx,disty, dist1,ang1
1791
1790
1792
1791
1793 def __calculateVelVer(self, phase, lagTRange, _lambda):
1792 def __calculateVelVer(self, phase, lagTRange, _lambda):
1794
1793
1795 Ts = lagTRange[1] - lagTRange[0]
1794 Ts = lagTRange[1] - lagTRange[0]
1796 velW = -_lambda*phase/(4*math.pi*Ts)
1795 velW = -_lambda*phase/(4*math.pi*Ts)
1797
1796
1798 return velW
1797 return velW
1799
1798
1800 def __calculateVelHorDir(self, dist, tau1, tau2, ang):
1799 def __calculateVelHorDir(self, dist, tau1, tau2, ang):
1801 nPairs = tau1.shape[0]
1800 nPairs = tau1.shape[0]
1802 nHeights = tau1.shape[1]
1801 nHeights = tau1.shape[1]
1803 vel = numpy.zeros((nPairs,3,nHeights))
1802 vel = numpy.zeros((nPairs,3,nHeights))
1804 dist1 = numpy.reshape(dist, (dist.size,1))
1803 dist1 = numpy.reshape(dist, (dist.size,1))
1805
1804
1806 angCos = numpy.cos(ang)
1805 angCos = numpy.cos(ang)
1807 angSin = numpy.sin(ang)
1806 angSin = numpy.sin(ang)
1808
1807
1809 vel0 = dist1*tau1/(2*tau2**2)
1808 vel0 = dist1*tau1/(2*tau2**2)
1810 vel[:,0,:] = (vel0*angCos).sum(axis = 1)
1809 vel[:,0,:] = (vel0*angCos).sum(axis = 1)
1811 vel[:,1,:] = (vel0*angSin).sum(axis = 1)
1810 vel[:,1,:] = (vel0*angSin).sum(axis = 1)
1812
1811
1813 ind = numpy.where(numpy.isinf(vel))
1812 ind = numpy.where(numpy.isinf(vel))
1814 vel[ind] = numpy.nan
1813 vel[ind] = numpy.nan
1815
1814
1816 return vel
1815 return vel
1817
1816
1818 # def __getPairsAutoCorr(self, pairsList, nChannels):
1817 # def __getPairsAutoCorr(self, pairsList, nChannels):
1819 #
1818 #
1820 # pairsAutoCorr = numpy.zeros(nChannels, dtype = 'int')*numpy.nan
1819 # pairsAutoCorr = numpy.zeros(nChannels, dtype = 'int')*numpy.nan
1821 #
1820 #
1822 # for l in range(len(pairsList)):
1821 # for l in range(len(pairsList)):
1823 # firstChannel = pairsList[l][0]
1822 # firstChannel = pairsList[l][0]
1824 # secondChannel = pairsList[l][1]
1823 # secondChannel = pairsList[l][1]
1825 #
1824 #
1826 # #Obteniendo pares de Autocorrelacion
1825 # #Obteniendo pares de Autocorrelacion
1827 # if firstChannel == secondChannel:
1826 # if firstChannel == secondChannel:
1828 # pairsAutoCorr[firstChannel] = int(l)
1827 # pairsAutoCorr[firstChannel] = int(l)
1829 #
1828 #
1830 # pairsAutoCorr = pairsAutoCorr.astype(int)
1829 # pairsAutoCorr = pairsAutoCorr.astype(int)
1831 #
1830 #
1832 # pairsCrossCorr = range(len(pairsList))
1831 # pairsCrossCorr = range(len(pairsList))
1833 # pairsCrossCorr = numpy.delete(pairsCrossCorr,pairsAutoCorr)
1832 # pairsCrossCorr = numpy.delete(pairsCrossCorr,pairsAutoCorr)
1834 #
1833 #
1835 # return pairsAutoCorr, pairsCrossCorr
1834 # return pairsAutoCorr, pairsCrossCorr
1836
1835
1837 # def techniqueSA(self, pairsSelected, pairsList, nChannels, tau, azimuth, _lambda, position_x, position_y, lagTRange, correctFactor):
1836 # def techniqueSA(self, pairsSelected, pairsList, nChannels, tau, azimuth, _lambda, position_x, position_y, lagTRange, correctFactor):
1838 def techniqueSA(self, kwargs):
1837 def techniqueSA(self, kwargs):
1839
1838
1840 """
1839 """
1841 Function that implements Spaced Antenna (SA) technique.
1840 Function that implements Spaced Antenna (SA) technique.
1842
1841
1843 Input: Radial velocities, Direction cosines (x and y) of the Beam, Antenna azimuth,
1842 Input: Radial velocities, Direction cosines (x and y) of the Beam, Antenna azimuth,
1844 Direction correction (if necessary), Ranges and SNR
1843 Direction correction (if necessary), Ranges and SNR
1845
1844
1846 Output: Winds estimation (Zonal, Meridional and Vertical)
1845 Output: Winds estimation (Zonal, Meridional and Vertical)
1847
1846
1848 Parameters affected: Winds
1847 Parameters affected: Winds
1849 """
1848 """
1850 position_x = kwargs['positionX']
1849 position_x = kwargs['positionX']
1851 position_y = kwargs['positionY']
1850 position_y = kwargs['positionY']
1852 azimuth = kwargs['azimuth']
1851 azimuth = kwargs['azimuth']
1853
1852
1854 if 'correctFactor' in kwargs:
1853 if 'correctFactor' in kwargs:
1855 correctFactor = kwargs['correctFactor']
1854 correctFactor = kwargs['correctFactor']
1856 else:
1855 else:
1857 correctFactor = 1
1856 correctFactor = 1
1858
1857
1859 groupList = kwargs['groupList']
1858 groupList = kwargs['groupList']
1860 pairs_ccf = groupList[1]
1859 pairs_ccf = groupList[1]
1861 tau = kwargs['tau']
1860 tau = kwargs['tau']
1862 _lambda = kwargs['_lambda']
1861 _lambda = kwargs['_lambda']
1863
1862
1864 #Cross Correlation pairs obtained
1863 #Cross Correlation pairs obtained
1865 # pairsAutoCorr, pairsCrossCorr = self.__getPairsAutoCorr(pairssList, nChannels)
1864 # pairsAutoCorr, pairsCrossCorr = self.__getPairsAutoCorr(pairssList, nChannels)
1866 # pairsArray = numpy.array(pairsList)[pairsCrossCorr]
1865 # pairsArray = numpy.array(pairsList)[pairsCrossCorr]
1867 # pairsSelArray = numpy.array(pairsSelected)
1866 # pairsSelArray = numpy.array(pairsSelected)
1868 # pairs = []
1867 # pairs = []
1869 #
1868 #
1870 # #Wind estimation pairs obtained
1869 # #Wind estimation pairs obtained
1871 # for i in range(pairsSelArray.shape[0]/2):
1870 # for i in range(pairsSelArray.shape[0]/2):
1872 # ind1 = numpy.where(numpy.all(pairsArray == pairsSelArray[2*i], axis = 1))[0][0]
1871 # ind1 = numpy.where(numpy.all(pairsArray == pairsSelArray[2*i], axis = 1))[0][0]
1873 # ind2 = numpy.where(numpy.all(pairsArray == pairsSelArray[2*i + 1], axis = 1))[0][0]
1872 # ind2 = numpy.where(numpy.all(pairsArray == pairsSelArray[2*i + 1], axis = 1))[0][0]
1874 # pairs.append((ind1,ind2))
1873 # pairs.append((ind1,ind2))
1875
1874
1876 indtau = tau.shape[0]/2
1875 indtau = tau.shape[0]/2
1877 tau1 = tau[:indtau,:]
1876 tau1 = tau[:indtau,:]
1878 tau2 = tau[indtau:-1,:]
1877 tau2 = tau[indtau:-1,:]
1879 # tau1 = tau1[pairs,:]
1878 # tau1 = tau1[pairs,:]
1880 # tau2 = tau2[pairs,:]
1879 # tau2 = tau2[pairs,:]
1881 phase1 = tau[-1,:]
1880 phase1 = tau[-1,:]
1882
1881
1883 #---------------------------------------------------------------------
1882 #---------------------------------------------------------------------
1884 #Metodo Directo
1883 #Metodo Directo
1885 distx, disty, dist, ang = self.__calculateDistance(position_x, position_y, pairs_ccf,azimuth)
1884 distx, disty, dist, ang = self.__calculateDistance(position_x, position_y, pairs_ccf,azimuth)
1886 winds = self.__calculateVelHorDir(dist, tau1, tau2, ang)
1885 winds = self.__calculateVelHorDir(dist, tau1, tau2, ang)
1887 winds = stats.nanmean(winds, axis=0)
1886 winds = stats.nanmean(winds, axis=0)
1888 #---------------------------------------------------------------------
1887 #---------------------------------------------------------------------
1889 #Metodo General
1888 #Metodo General
1890 # distx, disty, dist = self.calculateDistance(position_x,position_y,pairsCrossCorr, pairsList, azimuth)
1889 # distx, disty, dist = self.calculateDistance(position_x,position_y,pairsCrossCorr, pairsList, azimuth)
1891 # #Calculo Coeficientes de Funcion de Correlacion
1890 # #Calculo Coeficientes de Funcion de Correlacion
1892 # F,G,A,B,H = self.calculateCoef(tau1,tau2,distx,disty,n)
1891 # F,G,A,B,H = self.calculateCoef(tau1,tau2,distx,disty,n)
1893 # #Calculo de Velocidades
1892 # #Calculo de Velocidades
1894 # winds = self.calculateVelUV(F,G,A,B,H)
1893 # winds = self.calculateVelUV(F,G,A,B,H)
1895
1894
1896 #---------------------------------------------------------------------
1895 #---------------------------------------------------------------------
1897 winds[2,:] = self.__calculateVelVer(phase1, lagTRange, _lambda)
1896 winds[2,:] = self.__calculateVelVer(phase1, lagTRange, _lambda)
1898 winds = correctFactor*winds
1897 winds = correctFactor*winds
1899 return winds
1898 return winds
1900
1899
1901 def __checkTime(self, currentTime, paramInterval, outputInterval):
1900 def __checkTime(self, currentTime, paramInterval, outputInterval):
1902
1901
1903 dataTime = currentTime + paramInterval
1902 dataTime = currentTime + paramInterval
1904 deltaTime = dataTime - self.__initime
1903 deltaTime = dataTime - self.__initime
1905
1904
1906 if deltaTime >= outputInterval or deltaTime < 0:
1905 if deltaTime >= outputInterval or deltaTime < 0:
1907 self.__dataReady = True
1906 self.__dataReady = True
1908 return
1907 return
1909
1908
1910 def techniqueMeteors(self, arrayMeteor, meteorThresh, heightMin, heightMax):
1909 def techniqueMeteors(self, arrayMeteor, meteorThresh, heightMin, heightMax):
1911 '''
1910 '''
1912 Function that implements winds estimation technique with detected meteors.
1911 Function that implements winds estimation technique with detected meteors.
1913
1912
1914 Input: Detected meteors, Minimum meteor quantity to wind estimation
1913 Input: Detected meteors, Minimum meteor quantity to wind estimation
1915
1914
1916 Output: Winds estimation (Zonal and Meridional)
1915 Output: Winds estimation (Zonal and Meridional)
1917
1916
1918 Parameters affected: Winds
1917 Parameters affected: Winds
1919 '''
1918 '''
1920 #Settings
1919 #Settings
1921 nInt = (heightMax - heightMin)/2
1920 nInt = (heightMax - heightMin)/2
1922 nInt = int(nInt)
1921 nInt = int(nInt)
1923 winds = numpy.zeros((2,nInt))*numpy.nan
1922 winds = numpy.zeros((2,nInt))*numpy.nan
1924
1923
1925 #Filter errors
1924 #Filter errors
1926 error = numpy.where(arrayMeteor[:,-1] == 0)[0]
1925 error = numpy.where(arrayMeteor[:,-1] == 0)[0]
1927 finalMeteor = arrayMeteor[error,:]
1926 finalMeteor = arrayMeteor[error,:]
1928
1927
1929 #Meteor Histogram
1928 #Meteor Histogram
1930 finalHeights = finalMeteor[:,2]
1929 finalHeights = finalMeteor[:,2]
1931 hist = numpy.histogram(finalHeights, bins = nInt, range = (heightMin,heightMax))
1930 hist = numpy.histogram(finalHeights, bins = nInt, range = (heightMin,heightMax))
1932 nMeteorsPerI = hist[0]
1931 nMeteorsPerI = hist[0]
1933 heightPerI = hist[1]
1932 heightPerI = hist[1]
1934
1933
1935 #Sort of meteors
1934 #Sort of meteors
1936 indSort = finalHeights.argsort()
1935 indSort = finalHeights.argsort()
1937 finalMeteor2 = finalMeteor[indSort,:]
1936 finalMeteor2 = finalMeteor[indSort,:]
1938
1937
1939 # Calculating winds
1938 # Calculating winds
1940 ind1 = 0
1939 ind1 = 0
1941 ind2 = 0
1940 ind2 = 0
1942
1941
1943 for i in range(nInt):
1942 for i in range(nInt):
1944 nMet = nMeteorsPerI[i]
1943 nMet = nMeteorsPerI[i]
1945 ind1 = ind2
1944 ind1 = ind2
1946 ind2 = ind1 + nMet
1945 ind2 = ind1 + nMet
1947
1946
1948 meteorAux = finalMeteor2[ind1:ind2,:]
1947 meteorAux = finalMeteor2[ind1:ind2,:]
1949
1948
1950 if meteorAux.shape[0] >= meteorThresh:
1949 if meteorAux.shape[0] >= meteorThresh:
1951 vel = meteorAux[:, 6]
1950 vel = meteorAux[:, 6]
1952 zen = meteorAux[:, 4]*numpy.pi/180
1951 zen = meteorAux[:, 4]*numpy.pi/180
1953 azim = meteorAux[:, 3]*numpy.pi/180
1952 azim = meteorAux[:, 3]*numpy.pi/180
1954
1953
1955 n = numpy.cos(zen)
1954 n = numpy.cos(zen)
1956 # m = (1 - n**2)/(1 - numpy.tan(azim)**2)
1955 # m = (1 - n**2)/(1 - numpy.tan(azim)**2)
1957 # l = m*numpy.tan(azim)
1956 # l = m*numpy.tan(azim)
1958 l = numpy.sin(zen)*numpy.sin(azim)
1957 l = numpy.sin(zen)*numpy.sin(azim)
1959 m = numpy.sin(zen)*numpy.cos(azim)
1958 m = numpy.sin(zen)*numpy.cos(azim)
1960
1959
1961 A = numpy.vstack((l, m)).transpose()
1960 A = numpy.vstack((l, m)).transpose()
1962 A1 = numpy.dot(numpy.linalg.inv( numpy.dot(A.transpose(),A) ),A.transpose())
1961 A1 = numpy.dot(numpy.linalg.inv( numpy.dot(A.transpose(),A) ),A.transpose())
1963 windsAux = numpy.dot(A1, vel)
1962 windsAux = numpy.dot(A1, vel)
1964
1963
1965 winds[0,i] = windsAux[0]
1964 winds[0,i] = windsAux[0]
1966 winds[1,i] = windsAux[1]
1965 winds[1,i] = windsAux[1]
1967
1966
1968 return winds, heightPerI[:-1]
1967 return winds, heightPerI[:-1]
1969
1968
1970 def techniqueNSM_SA(self, **kwargs):
1969 def techniqueNSM_SA(self, **kwargs):
1971 metArray = kwargs['metArray']
1970 metArray = kwargs['metArray']
1972 heightList = kwargs['heightList']
1971 heightList = kwargs['heightList']
1973 timeList = kwargs['timeList']
1972 timeList = kwargs['timeList']
1974
1973
1975 rx_location = kwargs['rx_location']
1974 rx_location = kwargs['rx_location']
1976 groupList = kwargs['groupList']
1975 groupList = kwargs['groupList']
1977 azimuth = kwargs['azimuth']
1976 azimuth = kwargs['azimuth']
1978 dfactor = kwargs['dfactor']
1977 dfactor = kwargs['dfactor']
1979 k = kwargs['k']
1978 k = kwargs['k']
1980
1979
1981 azimuth1, dist = self.__calculateAzimuth1(rx_location, groupList, azimuth)
1980 azimuth1, dist = self.__calculateAzimuth1(rx_location, groupList, azimuth)
1982 d = dist*dfactor
1981 d = dist*dfactor
1983 #Phase calculation
1982 #Phase calculation
1984 metArray1 = self.__getPhaseSlope(metArray, heightList, timeList)
1983 metArray1 = self.__getPhaseSlope(metArray, heightList, timeList)
1985
1984
1986 metArray1[:,-2] = metArray1[:,-2]*metArray1[:,2]*1000/(k*d[metArray1[:,1].astype(int)]) #angles into velocities
1985 metArray1[:,-2] = metArray1[:,-2]*metArray1[:,2]*1000/(k*d[metArray1[:,1].astype(int)]) #angles into velocities
1987
1986
1988 velEst = numpy.zeros((heightList.size,2))*numpy.nan
1987 velEst = numpy.zeros((heightList.size,2))*numpy.nan
1989 azimuth1 = azimuth1*numpy.pi/180
1988 azimuth1 = azimuth1*numpy.pi/180
1990
1989
1991 for i in range(heightList.size):
1990 for i in range(heightList.size):
1992 h = heightList[i]
1991 h = heightList[i]
1993 indH = numpy.where((metArray1[:,2] == h)&(numpy.abs(metArray1[:,-2]) < 100))[0]
1992 indH = numpy.where((metArray1[:,2] == h)&(numpy.abs(metArray1[:,-2]) < 100))[0]
1994 metHeight = metArray1[indH,:]
1993 metHeight = metArray1[indH,:]
1995 if metHeight.shape[0] >= 2:
1994 if metHeight.shape[0] >= 2:
1996 velAux = numpy.asmatrix(metHeight[:,-2]).T #Radial Velocities
1995 velAux = numpy.asmatrix(metHeight[:,-2]).T #Radial Velocities
1997 iazim = metHeight[:,1].astype(int)
1996 iazim = metHeight[:,1].astype(int)
1998 azimAux = numpy.asmatrix(azimuth1[iazim]).T #Azimuths
1997 azimAux = numpy.asmatrix(azimuth1[iazim]).T #Azimuths
1999 A = numpy.hstack((numpy.cos(azimAux),numpy.sin(azimAux)))
1998 A = numpy.hstack((numpy.cos(azimAux),numpy.sin(azimAux)))
2000 A = numpy.asmatrix(A)
1999 A = numpy.asmatrix(A)
2001 A1 = numpy.linalg.pinv(A.transpose()*A)*A.transpose()
2000 A1 = numpy.linalg.pinv(A.transpose()*A)*A.transpose()
2002 velHor = numpy.dot(A1,velAux)
2001 velHor = numpy.dot(A1,velAux)
2003
2002
2004 velEst[i,:] = numpy.squeeze(velHor)
2003 velEst[i,:] = numpy.squeeze(velHor)
2005 return velEst
2004 return velEst
2006
2005
2007 def __getPhaseSlope(self, metArray, heightList, timeList):
2006 def __getPhaseSlope(self, metArray, heightList, timeList):
2008 meteorList = []
2007 meteorList = []
2009 #utctime sec1 height SNR velRad ph0 ph1 ph2 coh0 coh1 coh2
2008 #utctime sec1 height SNR velRad ph0 ph1 ph2 coh0 coh1 coh2
2010 #Putting back together the meteor matrix
2009 #Putting back together the meteor matrix
2011 utctime = metArray[:,0]
2010 utctime = metArray[:,0]
2012 uniqueTime = numpy.unique(utctime)
2011 uniqueTime = numpy.unique(utctime)
2013
2012
2014 phaseDerThresh = 0.5
2013 phaseDerThresh = 0.5
2015 ippSeconds = timeList[1] - timeList[0]
2014 ippSeconds = timeList[1] - timeList[0]
2016 sec = numpy.where(timeList>1)[0][0]
2015 sec = numpy.where(timeList>1)[0][0]
2017 nPairs = metArray.shape[1] - 6
2016 nPairs = metArray.shape[1] - 6
2018 nHeights = len(heightList)
2017 nHeights = len(heightList)
2019
2018
2020 for t in uniqueTime:
2019 for t in uniqueTime:
2021 metArray1 = metArray[utctime==t,:]
2020 metArray1 = metArray[utctime==t,:]
2022 # phaseDerThresh = numpy.pi/4 #reducir Phase thresh
2021 # phaseDerThresh = numpy.pi/4 #reducir Phase thresh
2023 tmet = metArray1[:,1].astype(int)
2022 tmet = metArray1[:,1].astype(int)
2024 hmet = metArray1[:,2].astype(int)
2023 hmet = metArray1[:,2].astype(int)
2025
2024
2026 metPhase = numpy.zeros((nPairs, heightList.size, timeList.size - 1))
2025 metPhase = numpy.zeros((nPairs, heightList.size, timeList.size - 1))
2027 metPhase[:,:] = numpy.nan
2026 metPhase[:,:] = numpy.nan
2028 metPhase[:,hmet,tmet] = metArray1[:,6:].T
2027 metPhase[:,hmet,tmet] = metArray1[:,6:].T
2029
2028
2030 #Delete short trails
2029 #Delete short trails
2031 metBool = ~numpy.isnan(metPhase[0,:,:])
2030 metBool = ~numpy.isnan(metPhase[0,:,:])
2032 heightVect = numpy.sum(metBool, axis = 1)
2031 heightVect = numpy.sum(metBool, axis = 1)
2033 metBool[heightVect<sec,:] = False
2032 metBool[heightVect<sec,:] = False
2034 metPhase[:,heightVect<sec,:] = numpy.nan
2033 metPhase[:,heightVect<sec,:] = numpy.nan
2035
2034
2036 #Derivative
2035 #Derivative
2037 metDer = numpy.abs(metPhase[:,:,1:] - metPhase[:,:,:-1])
2036 metDer = numpy.abs(metPhase[:,:,1:] - metPhase[:,:,:-1])
2038 phDerAux = numpy.dstack((numpy.full((nPairs,nHeights,1), False, dtype=bool),metDer > phaseDerThresh))
2037 phDerAux = numpy.dstack((numpy.full((nPairs,nHeights,1), False, dtype=bool),metDer > phaseDerThresh))
2039 metPhase[phDerAux] = numpy.nan
2038 metPhase[phDerAux] = numpy.nan
2040
2039
2041 #--------------------------METEOR DETECTION -----------------------------------------
2040 #--------------------------METEOR DETECTION -----------------------------------------
2042 indMet = numpy.where(numpy.any(metBool,axis=1))[0]
2041 indMet = numpy.where(numpy.any(metBool,axis=1))[0]
2043
2042
2044 for p in numpy.arange(nPairs):
2043 for p in numpy.arange(nPairs):
2045 phase = metPhase[p,:,:]
2044 phase = metPhase[p,:,:]
2046 phDer = metDer[p,:,:]
2045 phDer = metDer[p,:,:]
2047
2046
2048 for h in indMet:
2047 for h in indMet:
2049 height = heightList[h]
2048 height = heightList[h]
2050 phase1 = phase[h,:] #82
2049 phase1 = phase[h,:] #82
2051 phDer1 = phDer[h,:]
2050 phDer1 = phDer[h,:]
2052
2051
2053 phase1[~numpy.isnan(phase1)] = numpy.unwrap(phase1[~numpy.isnan(phase1)]) #Unwrap
2052 phase1[~numpy.isnan(phase1)] = numpy.unwrap(phase1[~numpy.isnan(phase1)]) #Unwrap
2054
2053
2055 indValid = numpy.where(~numpy.isnan(phase1))[0]
2054 indValid = numpy.where(~numpy.isnan(phase1))[0]
2056 initMet = indValid[0]
2055 initMet = indValid[0]
2057 endMet = 0
2056 endMet = 0
2058
2057
2059 for i in range(len(indValid)-1):
2058 for i in range(len(indValid)-1):
2060
2059
2061 #Time difference
2060 #Time difference
2062 inow = indValid[i]
2061 inow = indValid[i]
2063 inext = indValid[i+1]
2062 inext = indValid[i+1]
2064 idiff = inext - inow
2063 idiff = inext - inow
2065 #Phase difference
2064 #Phase difference
2066 phDiff = numpy.abs(phase1[inext] - phase1[inow])
2065 phDiff = numpy.abs(phase1[inext] - phase1[inow])
2067
2066
2068 if idiff>sec or phDiff>numpy.pi/4 or inext==indValid[-1]: #End of Meteor
2067 if idiff>sec or phDiff>numpy.pi/4 or inext==indValid[-1]: #End of Meteor
2069 sizeTrail = inow - initMet + 1
2068 sizeTrail = inow - initMet + 1
2070 if sizeTrail>3*sec: #Too short meteors
2069 if sizeTrail>3*sec: #Too short meteors
2071 x = numpy.arange(initMet,inow+1)*ippSeconds
2070 x = numpy.arange(initMet,inow+1)*ippSeconds
2072 y = phase1[initMet:inow+1]
2071 y = phase1[initMet:inow+1]
2073 ynnan = ~numpy.isnan(y)
2072 ynnan = ~numpy.isnan(y)
2074 x = x[ynnan]
2073 x = x[ynnan]
2075 y = y[ynnan]
2074 y = y[ynnan]
2076 slope, intercept, r_value, p_value, std_err = stats.linregress(x,y)
2075 slope, intercept, r_value, p_value, std_err = stats.linregress(x,y)
2077 ylin = x*slope + intercept
2076 ylin = x*slope + intercept
2078 rsq = r_value**2
2077 rsq = r_value**2
2079 if rsq > 0.5:
2078 if rsq > 0.5:
2080 vel = slope#*height*1000/(k*d)
2079 vel = slope#*height*1000/(k*d)
2081 estAux = numpy.array([utctime,p,height, vel, rsq])
2080 estAux = numpy.array([utctime,p,height, vel, rsq])
2082 meteorList.append(estAux)
2081 meteorList.append(estAux)
2083 initMet = inext
2082 initMet = inext
2084 metArray2 = numpy.array(meteorList)
2083 metArray2 = numpy.array(meteorList)
2085
2084
2086 return metArray2
2085 return metArray2
2087
2086
2088 def __calculateAzimuth1(self, rx_location, pairslist, azimuth0):
2087 def __calculateAzimuth1(self, rx_location, pairslist, azimuth0):
2089
2088
2090 azimuth1 = numpy.zeros(len(pairslist))
2089 azimuth1 = numpy.zeros(len(pairslist))
2091 dist = numpy.zeros(len(pairslist))
2090 dist = numpy.zeros(len(pairslist))
2092
2091
2093 for i in range(len(rx_location)):
2092 for i in range(len(rx_location)):
2094 ch0 = pairslist[i][0]
2093 ch0 = pairslist[i][0]
2095 ch1 = pairslist[i][1]
2094 ch1 = pairslist[i][1]
2096
2095
2097 diffX = rx_location[ch0][0] - rx_location[ch1][0]
2096 diffX = rx_location[ch0][0] - rx_location[ch1][0]
2098 diffY = rx_location[ch0][1] - rx_location[ch1][1]
2097 diffY = rx_location[ch0][1] - rx_location[ch1][1]
2099 azimuth1[i] = numpy.arctan2(diffY,diffX)*180/numpy.pi
2098 azimuth1[i] = numpy.arctan2(diffY,diffX)*180/numpy.pi
2100 dist[i] = numpy.sqrt(diffX**2 + diffY**2)
2099 dist[i] = numpy.sqrt(diffX**2 + diffY**2)
2101
2100
2102 azimuth1 -= azimuth0
2101 azimuth1 -= azimuth0
2103 return azimuth1, dist
2102 return azimuth1, dist
2104
2103
2105 def techniqueNSM_DBS(self, **kwargs):
2104 def techniqueNSM_DBS(self, **kwargs):
2106 metArray = kwargs['metArray']
2105 metArray = kwargs['metArray']
2107 heightList = kwargs['heightList']
2106 heightList = kwargs['heightList']
2108 timeList = kwargs['timeList']
2107 timeList = kwargs['timeList']
2109 azimuth = kwargs['azimuth']
2108 azimuth = kwargs['azimuth']
2110 theta_x = numpy.array(kwargs['theta_x'])
2109 theta_x = numpy.array(kwargs['theta_x'])
2111 theta_y = numpy.array(kwargs['theta_y'])
2110 theta_y = numpy.array(kwargs['theta_y'])
2112
2111
2113 utctime = metArray[:,0]
2112 utctime = metArray[:,0]
2114 cmet = metArray[:,1].astype(int)
2113 cmet = metArray[:,1].astype(int)
2115 hmet = metArray[:,3].astype(int)
2114 hmet = metArray[:,3].astype(int)
2116 SNRmet = metArray[:,4]
2115 SNRmet = metArray[:,4]
2117 vmet = metArray[:,5]
2116 vmet = metArray[:,5]
2118 spcmet = metArray[:,6]
2117 spcmet = metArray[:,6]
2119
2118
2120 nChan = numpy.max(cmet) + 1
2119 nChan = numpy.max(cmet) + 1
2121 nHeights = len(heightList)
2120 nHeights = len(heightList)
2122
2121
2123 azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw = self.__calculateAngles(theta_x, theta_y, azimuth)
2122 azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw = self.__calculateAngles(theta_x, theta_y, azimuth)
2124 hmet = heightList[hmet]
2123 hmet = heightList[hmet]
2125 h1met = hmet*numpy.cos(zenith_arr[cmet]) #Corrected heights
2124 h1met = hmet*numpy.cos(zenith_arr[cmet]) #Corrected heights
2126
2125
2127 velEst = numpy.zeros((heightList.size,2))*numpy.nan
2126 velEst = numpy.zeros((heightList.size,2))*numpy.nan
2128
2127
2129 for i in range(nHeights - 1):
2128 for i in range(nHeights - 1):
2130 hmin = heightList[i]
2129 hmin = heightList[i]
2131 hmax = heightList[i + 1]
2130 hmax = heightList[i + 1]
2132
2131
2133 thisH = (h1met>=hmin) & (h1met<hmax) & (cmet!=2) & (SNRmet>8) & (vmet<50) & (spcmet<10)
2132 thisH = (h1met>=hmin) & (h1met<hmax) & (cmet!=2) & (SNRmet>8) & (vmet<50) & (spcmet<10)
2134 indthisH = numpy.where(thisH)
2133 indthisH = numpy.where(thisH)
2135
2134
2136 if numpy.size(indthisH) > 3:
2135 if numpy.size(indthisH) > 3:
2137
2136
2138 vel_aux = vmet[thisH]
2137 vel_aux = vmet[thisH]
2139 chan_aux = cmet[thisH]
2138 chan_aux = cmet[thisH]
2140 cosu_aux = dir_cosu[chan_aux]
2139 cosu_aux = dir_cosu[chan_aux]
2141 cosv_aux = dir_cosv[chan_aux]
2140 cosv_aux = dir_cosv[chan_aux]
2142 cosw_aux = dir_cosw[chan_aux]
2141 cosw_aux = dir_cosw[chan_aux]
2143
2142
2144 nch = numpy.size(numpy.unique(chan_aux))
2143 nch = numpy.size(numpy.unique(chan_aux))
2145 if nch > 1:
2144 if nch > 1:
2146 A = self.__calculateMatA(cosu_aux, cosv_aux, cosw_aux, True)
2145 A = self.__calculateMatA(cosu_aux, cosv_aux, cosw_aux, True)
2147 velEst[i,:] = numpy.dot(A,vel_aux)
2146 velEst[i,:] = numpy.dot(A,vel_aux)
2148
2147
2149 return velEst
2148 return velEst
2150
2149
2151 def run(self, dataOut, technique, nHours=1, hmin=70, hmax=110, **kwargs):
2150 def run(self, dataOut, technique, nHours=1, hmin=70, hmax=110, **kwargs):
2152
2151
2153 param = dataOut.data_param
2152 param = dataOut.data_param
2154 if dataOut.abscissaList.any():
2153 if dataOut.abscissaList.any():
2155 #if dataOut.abscissaList != None:
2154 #if dataOut.abscissaList != None:
2156 absc = dataOut.abscissaList[:-1]
2155 absc = dataOut.abscissaList[:-1]
2157 # noise = dataOut.noise
2156 # noise = dataOut.noise
2158 heightList = dataOut.heightList
2157 heightList = dataOut.heightList
2159 SNR = dataOut.data_snr
2158 SNR = dataOut.data_snr
2160
2159
2161 if technique == 'DBS':
2160 if technique == 'DBS':
2162
2161
2163 kwargs['velRadial'] = param[:,1,:] #Radial velocity
2162 kwargs['velRadial'] = param[:,1,:] #Radial velocity
2164 kwargs['heightList'] = heightList
2163 kwargs['heightList'] = heightList
2165 kwargs['SNR'] = SNR
2164 kwargs['SNR'] = SNR
2166
2165
2167 dataOut.data_output, dataOut.heightList, dataOut.data_snr = self.techniqueDBS(kwargs) #DBS Function
2166 dataOut.data_output, dataOut.heightList, dataOut.data_snr = self.techniqueDBS(kwargs) #DBS Function
2168 dataOut.utctimeInit = dataOut.utctime
2167 dataOut.utctimeInit = dataOut.utctime
2169 dataOut.outputInterval = dataOut.paramInterval
2168 dataOut.outputInterval = dataOut.paramInterval
2170
2169
2171 elif technique == 'SA':
2170 elif technique == 'SA':
2172
2171
2173 #Parameters
2172 #Parameters
2174 # position_x = kwargs['positionX']
2173 # position_x = kwargs['positionX']
2175 # position_y = kwargs['positionY']
2174 # position_y = kwargs['positionY']
2176 # azimuth = kwargs['azimuth']
2175 # azimuth = kwargs['azimuth']
2177 #
2176 #
2178 # if kwargs.has_key('crosspairsList'):
2177 # if kwargs.has_key('crosspairsList'):
2179 # pairs = kwargs['crosspairsList']
2178 # pairs = kwargs['crosspairsList']
2180 # else:
2179 # else:
2181 # pairs = None
2180 # pairs = None
2182 #
2181 #
2183 # if kwargs.has_key('correctFactor'):
2182 # if kwargs.has_key('correctFactor'):
2184 # correctFactor = kwargs['correctFactor']
2183 # correctFactor = kwargs['correctFactor']
2185 # else:
2184 # else:
2186 # correctFactor = 1
2185 # correctFactor = 1
2187
2186
2188 # tau = dataOut.data_param
2187 # tau = dataOut.data_param
2189 # _lambda = dataOut.C/dataOut.frequency
2188 # _lambda = dataOut.C/dataOut.frequency
2190 # pairsList = dataOut.groupList
2189 # pairsList = dataOut.groupList
2191 # nChannels = dataOut.nChannels
2190 # nChannels = dataOut.nChannels
2192
2191
2193 kwargs['groupList'] = dataOut.groupList
2192 kwargs['groupList'] = dataOut.groupList
2194 kwargs['tau'] = dataOut.data_param
2193 kwargs['tau'] = dataOut.data_param
2195 kwargs['_lambda'] = dataOut.C/dataOut.frequency
2194 kwargs['_lambda'] = dataOut.C/dataOut.frequency
2196 # dataOut.data_output = self.techniqueSA(pairs, pairsList, nChannels, tau, azimuth, _lambda, position_x, position_y, absc, correctFactor)
2195 # dataOut.data_output = self.techniqueSA(pairs, pairsList, nChannels, tau, azimuth, _lambda, position_x, position_y, absc, correctFactor)
2197 dataOut.data_output = self.techniqueSA(kwargs)
2196 dataOut.data_output = self.techniqueSA(kwargs)
2198 dataOut.utctimeInit = dataOut.utctime
2197 dataOut.utctimeInit = dataOut.utctime
2199 dataOut.outputInterval = dataOut.timeInterval
2198 dataOut.outputInterval = dataOut.timeInterval
2200
2199
2201 elif technique == 'Meteors':
2200 elif technique == 'Meteors':
2202 dataOut.flagNoData = True
2201 dataOut.flagNoData = True
2203 self.__dataReady = False
2202 self.__dataReady = False
2204
2203
2205 if 'nHours' in kwargs:
2204 if 'nHours' in kwargs:
2206 nHours = kwargs['nHours']
2205 nHours = kwargs['nHours']
2207 else:
2206 else:
2208 nHours = 1
2207 nHours = 1
2209
2208
2210 if 'meteorsPerBin' in kwargs:
2209 if 'meteorsPerBin' in kwargs:
2211 meteorThresh = kwargs['meteorsPerBin']
2210 meteorThresh = kwargs['meteorsPerBin']
2212 else:
2211 else:
2213 meteorThresh = 6
2212 meteorThresh = 6
2214
2213
2215 if 'hmin' in kwargs:
2214 if 'hmin' in kwargs:
2216 hmin = kwargs['hmin']
2215 hmin = kwargs['hmin']
2217 else: hmin = 70
2216 else: hmin = 70
2218 if 'hmax' in kwargs:
2217 if 'hmax' in kwargs:
2219 hmax = kwargs['hmax']
2218 hmax = kwargs['hmax']
2220 else: hmax = 110
2219 else: hmax = 110
2221
2220
2222 dataOut.outputInterval = nHours*3600
2221 dataOut.outputInterval = nHours*3600
2223
2222
2224 if self.__isConfig == False:
2223 if self.__isConfig == False:
2225 # self.__initime = dataOut.datatime.replace(minute = 0, second = 0, microsecond = 03)
2224 # self.__initime = dataOut.datatime.replace(minute = 0, second = 0, microsecond = 03)
2226 #Get Initial LTC time
2225 #Get Initial LTC time
2227 self.__initime = datetime.datetime.utcfromtimestamp(dataOut.utctime)
2226 self.__initime = datetime.datetime.utcfromtimestamp(dataOut.utctime)
2228 self.__initime = (self.__initime.replace(minute = 0, second = 0, microsecond = 0) - datetime.datetime(1970, 1, 1)).total_seconds()
2227 self.__initime = (self.__initime.replace(minute = 0, second = 0, microsecond = 0) - datetime.datetime(1970, 1, 1)).total_seconds()
2229
2228
2230 self.__isConfig = True
2229 self.__isConfig = True
2231
2230
2232 if self.__buffer is None:
2231 if self.__buffer is None:
2233 self.__buffer = dataOut.data_param
2232 self.__buffer = dataOut.data_param
2234 self.__firstdata = copy.copy(dataOut)
2233 self.__firstdata = copy.copy(dataOut)
2235
2234
2236 else:
2235 else:
2237 self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param))
2236 self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param))
2238
2237
2239 self.__checkTime(dataOut.utctime, dataOut.paramInterval, dataOut.outputInterval) #Check if the buffer is ready
2238 self.__checkTime(dataOut.utctime, dataOut.paramInterval, dataOut.outputInterval) #Check if the buffer is ready
2240
2239
2241 if self.__dataReady:
2240 if self.__dataReady:
2242 dataOut.utctimeInit = self.__initime
2241 dataOut.utctimeInit = self.__initime
2243
2242
2244 self.__initime += dataOut.outputInterval #to erase time offset
2243 self.__initime += dataOut.outputInterval #to erase time offset
2245
2244
2246 dataOut.data_output, dataOut.heightList = self.techniqueMeteors(self.__buffer, meteorThresh, hmin, hmax)
2245 dataOut.data_output, dataOut.heightList = self.techniqueMeteors(self.__buffer, meteorThresh, hmin, hmax)
2247 dataOut.flagNoData = False
2246 dataOut.flagNoData = False
2248 self.__buffer = None
2247 self.__buffer = None
2249
2248
2250 elif technique == 'Meteors1':
2249 elif technique == 'Meteors1':
2251 dataOut.flagNoData = True
2250 dataOut.flagNoData = True
2252 self.__dataReady = False
2251 self.__dataReady = False
2253
2252
2254 if 'nMins' in kwargs:
2253 if 'nMins' in kwargs:
2255 nMins = kwargs['nMins']
2254 nMins = kwargs['nMins']
2256 else: nMins = 20
2255 else: nMins = 20
2257 if 'rx_location' in kwargs:
2256 if 'rx_location' in kwargs:
2258 rx_location = kwargs['rx_location']
2257 rx_location = kwargs['rx_location']
2259 else: rx_location = [(0,1),(1,1),(1,0)]
2258 else: rx_location = [(0,1),(1,1),(1,0)]
2260 if 'azimuth' in kwargs:
2259 if 'azimuth' in kwargs:
2261 azimuth = kwargs['azimuth']
2260 azimuth = kwargs['azimuth']
2262 else: azimuth = 51.06
2261 else: azimuth = 51.06
2263 if 'dfactor' in kwargs:
2262 if 'dfactor' in kwargs:
2264 dfactor = kwargs['dfactor']
2263 dfactor = kwargs['dfactor']
2265 if 'mode' in kwargs:
2264 if 'mode' in kwargs:
2266 mode = kwargs['mode']
2265 mode = kwargs['mode']
2267 if 'theta_x' in kwargs:
2266 if 'theta_x' in kwargs:
2268 theta_x = kwargs['theta_x']
2267 theta_x = kwargs['theta_x']
2269 if 'theta_y' in kwargs:
2268 if 'theta_y' in kwargs:
2270 theta_y = kwargs['theta_y']
2269 theta_y = kwargs['theta_y']
2271 else: mode = 'SA'
2270 else: mode = 'SA'
2272
2271
2273 #Borrar luego esto
2272 #Borrar luego esto
2274 if dataOut.groupList is None:
2273 if dataOut.groupList is None:
2275 dataOut.groupList = [(0,1),(0,2),(1,2)]
2274 dataOut.groupList = [(0,1),(0,2),(1,2)]
2276 groupList = dataOut.groupList
2275 groupList = dataOut.groupList
2277 C = 3e8
2276 C = 3e8
2278 freq = 50e6
2277 freq = 50e6
2279 lamb = C/freq
2278 lamb = C/freq
2280 k = 2*numpy.pi/lamb
2279 k = 2*numpy.pi/lamb
2281
2280
2282 timeList = dataOut.abscissaList
2281 timeList = dataOut.abscissaList
2283 heightList = dataOut.heightList
2282 heightList = dataOut.heightList
2284
2283
2285 if self.__isConfig == False:
2284 if self.__isConfig == False:
2286 dataOut.outputInterval = nMins*60
2285 dataOut.outputInterval = nMins*60
2287 # self.__initime = dataOut.datatime.replace(minute = 0, second = 0, microsecond = 03)
2286 # self.__initime = dataOut.datatime.replace(minute = 0, second = 0, microsecond = 03)
2288 #Get Initial LTC time
2287 #Get Initial LTC time
2289 initime = datetime.datetime.utcfromtimestamp(dataOut.utctime)
2288 initime = datetime.datetime.utcfromtimestamp(dataOut.utctime)
2290 minuteAux = initime.minute
2289 minuteAux = initime.minute
2291 minuteNew = int(numpy.floor(minuteAux/nMins)*nMins)
2290 minuteNew = int(numpy.floor(minuteAux/nMins)*nMins)
2292 self.__initime = (initime.replace(minute = minuteNew, second = 0, microsecond = 0) - datetime.datetime(1970, 1, 1)).total_seconds()
2291 self.__initime = (initime.replace(minute = minuteNew, second = 0, microsecond = 0) - datetime.datetime(1970, 1, 1)).total_seconds()
2293
2292
2294 self.__isConfig = True
2293 self.__isConfig = True
2295
2294
2296 if self.__buffer is None:
2295 if self.__buffer is None:
2297 self.__buffer = dataOut.data_param
2296 self.__buffer = dataOut.data_param
2298 self.__firstdata = copy.copy(dataOut)
2297 self.__firstdata = copy.copy(dataOut)
2299
2298
2300 else:
2299 else:
2301 self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param))
2300 self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param))
2302
2301
2303 self.__checkTime(dataOut.utctime, dataOut.paramInterval, dataOut.outputInterval) #Check if the buffer is ready
2302 self.__checkTime(dataOut.utctime, dataOut.paramInterval, dataOut.outputInterval) #Check if the buffer is ready
2304
2303
2305 if self.__dataReady:
2304 if self.__dataReady:
2306 dataOut.utctimeInit = self.__initime
2305 dataOut.utctimeInit = self.__initime
2307 self.__initime += dataOut.outputInterval #to erase time offset
2306 self.__initime += dataOut.outputInterval #to erase time offset
2308
2307
2309 metArray = self.__buffer
2308 metArray = self.__buffer
2310 if mode == 'SA':
2309 if mode == 'SA':
2311 dataOut.data_output = self.techniqueNSM_SA(rx_location=rx_location, groupList=groupList, azimuth=azimuth, dfactor=dfactor, k=k,metArray=metArray, heightList=heightList,timeList=timeList)
2310 dataOut.data_output = self.techniqueNSM_SA(rx_location=rx_location, groupList=groupList, azimuth=azimuth, dfactor=dfactor, k=k,metArray=metArray, heightList=heightList,timeList=timeList)
2312 elif mode == 'DBS':
2311 elif mode == 'DBS':
2313 dataOut.data_output = self.techniqueNSM_DBS(metArray=metArray,heightList=heightList,timeList=timeList, azimuth=azimuth, theta_x=theta_x, theta_y=theta_y)
2312 dataOut.data_output = self.techniqueNSM_DBS(metArray=metArray,heightList=heightList,timeList=timeList, azimuth=azimuth, theta_x=theta_x, theta_y=theta_y)
2314 dataOut.data_output = dataOut.data_output.T
2313 dataOut.data_output = dataOut.data_output.T
2315 dataOut.flagNoData = False
2314 dataOut.flagNoData = False
2316 self.__buffer = None
2315 self.__buffer = None
2317
2316
2318 return
2317 return
2319
2318
2320 class EWDriftsEstimation(Operation):
2319 class EWDriftsEstimation(Operation):
2321
2320
2322 def __init__(self):
2321 def __init__(self):
2323 Operation.__init__(self)
2322 Operation.__init__(self)
2324
2323
2325 def __correctValues(self, heiRang, phi, velRadial, SNR):
2324 def __correctValues(self, heiRang, phi, velRadial, SNR):
2326 listPhi = phi.tolist()
2325 listPhi = phi.tolist()
2327 maxid = listPhi.index(max(listPhi))
2326 maxid = listPhi.index(max(listPhi))
2328 minid = listPhi.index(min(listPhi))
2327 minid = listPhi.index(min(listPhi))
2329
2328
2330 rango = list(range(len(phi)))
2329 rango = list(range(len(phi)))
2331 # rango = numpy.delete(rango,maxid)
2330 # rango = numpy.delete(rango,maxid)
2332
2331
2333 heiRang1 = heiRang*math.cos(phi[maxid])
2332 heiRang1 = heiRang*math.cos(phi[maxid])
2334 heiRangAux = heiRang*math.cos(phi[minid])
2333 heiRangAux = heiRang*math.cos(phi[minid])
2335 indOut = (heiRang1 < heiRangAux[0]).nonzero()
2334 indOut = (heiRang1 < heiRangAux[0]).nonzero()
2336 heiRang1 = numpy.delete(heiRang1,indOut)
2335 heiRang1 = numpy.delete(heiRang1,indOut)
2337
2336
2338 velRadial1 = numpy.zeros([len(phi),len(heiRang1)])
2337 velRadial1 = numpy.zeros([len(phi),len(heiRang1)])
2339 SNR1 = numpy.zeros([len(phi),len(heiRang1)])
2338 SNR1 = numpy.zeros([len(phi),len(heiRang1)])
2340
2339
2341 for i in rango:
2340 for i in rango:
2342 x = heiRang*math.cos(phi[i])
2341 x = heiRang*math.cos(phi[i])
2343 y1 = velRadial[i,:]
2342 y1 = velRadial[i,:]
2344 f1 = interpolate.interp1d(x,y1,kind = 'cubic')
2343 f1 = interpolate.interp1d(x,y1,kind = 'cubic')
2345
2344
2346 x1 = heiRang1
2345 x1 = heiRang1
2347 y11 = f1(x1)
2346 y11 = f1(x1)
2348
2347
2349 y2 = SNR[i,:]
2348 y2 = SNR[i,:]
2350 f2 = interpolate.interp1d(x,y2,kind = 'cubic')
2349 f2 = interpolate.interp1d(x,y2,kind = 'cubic')
2351 y21 = f2(x1)
2350 y21 = f2(x1)
2352
2351
2353 velRadial1[i,:] = y11
2352 velRadial1[i,:] = y11
2354 SNR1[i,:] = y21
2353 SNR1[i,:] = y21
2355
2354
2356 return heiRang1, velRadial1, SNR1
2355 return heiRang1, velRadial1, SNR1
2357
2356
2358 def run(self, dataOut, zenith, zenithCorrection):
2357 def run(self, dataOut, zenith, zenithCorrection):
2359 heiRang = dataOut.heightList
2358 heiRang = dataOut.heightList
2360 velRadial = dataOut.data_param[:,3,:]
2359 velRadial = dataOut.data_param[:,3,:]
2361 SNR = dataOut.data_snr
2360 SNR = dataOut.data_snr
2362
2361
2363 zenith = numpy.array(zenith)
2362 zenith = numpy.array(zenith)
2364 zenith -= zenithCorrection
2363 zenith -= zenithCorrection
2365 zenith *= numpy.pi/180
2364 zenith *= numpy.pi/180
2366
2365
2367 heiRang1, velRadial1, SNR1 = self.__correctValues(heiRang, numpy.abs(zenith), velRadial, SNR)
2366 heiRang1, velRadial1, SNR1 = self.__correctValues(heiRang, numpy.abs(zenith), velRadial, SNR)
2368
2367
2369 alp = zenith[0]
2368 alp = zenith[0]
2370 bet = zenith[1]
2369 bet = zenith[1]
2371
2370
2372 w_w = velRadial1[0,:]
2371 w_w = velRadial1[0,:]
2373 w_e = velRadial1[1,:]
2372 w_e = velRadial1[1,:]
2374
2373
2375 w = (w_w*numpy.sin(bet) - w_e*numpy.sin(alp))/(numpy.cos(alp)*numpy.sin(bet) - numpy.cos(bet)*numpy.sin(alp))
2374 w = (w_w*numpy.sin(bet) - w_e*numpy.sin(alp))/(numpy.cos(alp)*numpy.sin(bet) - numpy.cos(bet)*numpy.sin(alp))
2376 u = (w_w*numpy.cos(bet) - w_e*numpy.cos(alp))/(numpy.sin(alp)*numpy.cos(bet) - numpy.sin(bet)*numpy.cos(alp))
2375 u = (w_w*numpy.cos(bet) - w_e*numpy.cos(alp))/(numpy.sin(alp)*numpy.cos(bet) - numpy.sin(bet)*numpy.cos(alp))
2377
2376
2378 winds = numpy.vstack((u,w))
2377 winds = numpy.vstack((u,w))
2379
2378
2380 dataOut.heightList = heiRang1
2379 dataOut.heightList = heiRang1
2381 dataOut.data_output = winds
2380 dataOut.data_output = winds
2382 dataOut.data_snr = SNR1
2381 dataOut.data_snr = SNR1
2383
2382
2384 dataOut.utctimeInit = dataOut.utctime
2383 dataOut.utctimeInit = dataOut.utctime
2385 dataOut.outputInterval = dataOut.timeInterval
2384 dataOut.outputInterval = dataOut.timeInterval
2386 return
2385 return
2387
2386
2388 #--------------- Non Specular Meteor ----------------
2387 #--------------- Non Specular Meteor ----------------
2389
2388
2390 class NonSpecularMeteorDetection(Operation):
2389 class NonSpecularMeteorDetection(Operation):
2391
2390
2392 def run(self, dataOut, mode, SNRthresh=8, phaseDerThresh=0.5, cohThresh=0.8, allData = False):
2391 def run(self, dataOut, mode, SNRthresh=8, phaseDerThresh=0.5, cohThresh=0.8, allData = False):
2393 data_acf = dataOut.data_pre[0]
2392 data_acf = dataOut.data_pre[0]
2394 data_ccf = dataOut.data_pre[1]
2393 data_ccf = dataOut.data_pre[1]
2395 pairsList = dataOut.groupList[1]
2394 pairsList = dataOut.groupList[1]
2396
2395
2397 lamb = dataOut.C/dataOut.frequency
2396 lamb = dataOut.C/dataOut.frequency
2398 tSamp = dataOut.ippSeconds*dataOut.nCohInt
2397 tSamp = dataOut.ippSeconds*dataOut.nCohInt
2399 paramInterval = dataOut.paramInterval
2398 paramInterval = dataOut.paramInterval
2400
2399
2401 nChannels = data_acf.shape[0]
2400 nChannels = data_acf.shape[0]
2402 nLags = data_acf.shape[1]
2401 nLags = data_acf.shape[1]
2403 nProfiles = data_acf.shape[2]
2402 nProfiles = data_acf.shape[2]
2404 nHeights = dataOut.nHeights
2403 nHeights = dataOut.nHeights
2405 nCohInt = dataOut.nCohInt
2404 nCohInt = dataOut.nCohInt
2406 sec = numpy.round(nProfiles/dataOut.paramInterval)
2405 sec = numpy.round(nProfiles/dataOut.paramInterval)
2407 heightList = dataOut.heightList
2406 heightList = dataOut.heightList
2408 ippSeconds = dataOut.ippSeconds*dataOut.nCohInt*dataOut.nAvg
2407 ippSeconds = dataOut.ippSeconds*dataOut.nCohInt*dataOut.nAvg
2409 utctime = dataOut.utctime
2408 utctime = dataOut.utctime
2410
2409
2411 dataOut.abscissaList = numpy.arange(0,paramInterval+ippSeconds,ippSeconds)
2410 dataOut.abscissaList = numpy.arange(0,paramInterval+ippSeconds,ippSeconds)
2412
2411
2413 #------------------------ SNR --------------------------------------
2412 #------------------------ SNR --------------------------------------
2414 power = data_acf[:,0,:,:].real
2413 power = data_acf[:,0,:,:].real
2415 noise = numpy.zeros(nChannels)
2414 noise = numpy.zeros(nChannels)
2416 SNR = numpy.zeros(power.shape)
2415 SNR = numpy.zeros(power.shape)
2417 for i in range(nChannels):
2416 for i in range(nChannels):
2418 noise[i] = hildebrand_sekhon(power[i,:], nCohInt)
2417 noise[i] = hildebrand_sekhon(power[i,:], nCohInt)
2419 SNR[i] = (power[i]-noise[i])/noise[i]
2418 SNR[i] = (power[i]-noise[i])/noise[i]
2420 SNRm = numpy.nanmean(SNR, axis = 0)
2419 SNRm = numpy.nanmean(SNR, axis = 0)
2421 SNRdB = 10*numpy.log10(SNR)
2420 SNRdB = 10*numpy.log10(SNR)
2422
2421
2423 if mode == 'SA':
2422 if mode == 'SA':
2424 dataOut.groupList = dataOut.groupList[1]
2423 dataOut.groupList = dataOut.groupList[1]
2425 nPairs = data_ccf.shape[0]
2424 nPairs = data_ccf.shape[0]
2426 #---------------------- Coherence and Phase --------------------------
2425 #---------------------- Coherence and Phase --------------------------
2427 phase = numpy.zeros(data_ccf[:,0,:,:].shape)
2426 phase = numpy.zeros(data_ccf[:,0,:,:].shape)
2428 # phase1 = numpy.copy(phase)
2427 # phase1 = numpy.copy(phase)
2429 coh1 = numpy.zeros(data_ccf[:,0,:,:].shape)
2428 coh1 = numpy.zeros(data_ccf[:,0,:,:].shape)
2430
2429
2431 for p in range(nPairs):
2430 for p in range(nPairs):
2432 ch0 = pairsList[p][0]
2431 ch0 = pairsList[p][0]
2433 ch1 = pairsList[p][1]
2432 ch1 = pairsList[p][1]
2434 ccf = data_ccf[p,0,:,:]/numpy.sqrt(data_acf[ch0,0,:,:]*data_acf[ch1,0,:,:])
2433 ccf = data_ccf[p,0,:,:]/numpy.sqrt(data_acf[ch0,0,:,:]*data_acf[ch1,0,:,:])
2435 phase[p,:,:] = ndimage.median_filter(numpy.angle(ccf), size = (5,1)) #median filter
2434 phase[p,:,:] = ndimage.median_filter(numpy.angle(ccf), size = (5,1)) #median filter
2436 # phase1[p,:,:] = numpy.angle(ccf) #median filter
2435 # phase1[p,:,:] = numpy.angle(ccf) #median filter
2437 coh1[p,:,:] = ndimage.median_filter(numpy.abs(ccf), 5) #median filter
2436 coh1[p,:,:] = ndimage.median_filter(numpy.abs(ccf), 5) #median filter
2438 # coh1[p,:,:] = numpy.abs(ccf) #median filter
2437 # coh1[p,:,:] = numpy.abs(ccf) #median filter
2439 coh = numpy.nanmax(coh1, axis = 0)
2438 coh = numpy.nanmax(coh1, axis = 0)
2440 # struc = numpy.ones((5,1))
2439 # struc = numpy.ones((5,1))
2441 # coh = ndimage.morphology.grey_dilation(coh, size=(10,1))
2440 # coh = ndimage.morphology.grey_dilation(coh, size=(10,1))
2442 #---------------------- Radial Velocity ----------------------------
2441 #---------------------- Radial Velocity ----------------------------
2443 phaseAux = numpy.mean(numpy.angle(data_acf[:,1,:,:]), axis = 0)
2442 phaseAux = numpy.mean(numpy.angle(data_acf[:,1,:,:]), axis = 0)
2444 velRad = phaseAux*lamb/(4*numpy.pi*tSamp)
2443 velRad = phaseAux*lamb/(4*numpy.pi*tSamp)
2445
2444
2446 if allData:
2445 if allData:
2447 boolMetFin = ~numpy.isnan(SNRm)
2446 boolMetFin = ~numpy.isnan(SNRm)
2448 # coh[:-1,:] = numpy.nanmean(numpy.abs(phase[:,1:,:] - phase[:,:-1,:]),axis=0)
2447 # coh[:-1,:] = numpy.nanmean(numpy.abs(phase[:,1:,:] - phase[:,:-1,:]),axis=0)
2449 else:
2448 else:
2450 #------------------------ Meteor mask ---------------------------------
2449 #------------------------ Meteor mask ---------------------------------
2451 # #SNR mask
2450 # #SNR mask
2452 # boolMet = (SNRdB>SNRthresh)#|(~numpy.isnan(SNRdB))
2451 # boolMet = (SNRdB>SNRthresh)#|(~numpy.isnan(SNRdB))
2453 #
2452 #
2454 # #Erase small objects
2453 # #Erase small objects
2455 # boolMet1 = self.__erase_small(boolMet, 2*sec, 5)
2454 # boolMet1 = self.__erase_small(boolMet, 2*sec, 5)
2456 #
2455 #
2457 # auxEEJ = numpy.sum(boolMet1,axis=0)
2456 # auxEEJ = numpy.sum(boolMet1,axis=0)
2458 # indOver = auxEEJ>nProfiles*0.8 #Use this later
2457 # indOver = auxEEJ>nProfiles*0.8 #Use this later
2459 # indEEJ = numpy.where(indOver)[0]
2458 # indEEJ = numpy.where(indOver)[0]
2460 # indNEEJ = numpy.where(~indOver)[0]
2459 # indNEEJ = numpy.where(~indOver)[0]
2461 #
2460 #
2462 # boolMetFin = boolMet1
2461 # boolMetFin = boolMet1
2463 #
2462 #
2464 # if indEEJ.size > 0:
2463 # if indEEJ.size > 0:
2465 # boolMet1[:,indEEJ] = False #Erase heights with EEJ
2464 # boolMet1[:,indEEJ] = False #Erase heights with EEJ
2466 #
2465 #
2467 # boolMet2 = coh > cohThresh
2466 # boolMet2 = coh > cohThresh
2468 # boolMet2 = self.__erase_small(boolMet2, 2*sec,5)
2467 # boolMet2 = self.__erase_small(boolMet2, 2*sec,5)
2469 #
2468 #
2470 # #Final Meteor mask
2469 # #Final Meteor mask
2471 # boolMetFin = boolMet1|boolMet2
2470 # boolMetFin = boolMet1|boolMet2
2472
2471
2473 #Coherence mask
2472 #Coherence mask
2474 boolMet1 = coh > 0.75
2473 boolMet1 = coh > 0.75
2475 struc = numpy.ones((30,1))
2474 struc = numpy.ones((30,1))
2476 boolMet1 = ndimage.morphology.binary_dilation(boolMet1, structure=struc)
2475 boolMet1 = ndimage.morphology.binary_dilation(boolMet1, structure=struc)
2477
2476
2478 #Derivative mask
2477 #Derivative mask
2479 derPhase = numpy.nanmean(numpy.abs(phase[:,1:,:] - phase[:,:-1,:]),axis=0)
2478 derPhase = numpy.nanmean(numpy.abs(phase[:,1:,:] - phase[:,:-1,:]),axis=0)
2480 boolMet2 = derPhase < 0.2
2479 boolMet2 = derPhase < 0.2
2481 # boolMet2 = ndimage.morphology.binary_opening(boolMet2)
2480 # boolMet2 = ndimage.morphology.binary_opening(boolMet2)
2482 # boolMet2 = ndimage.morphology.binary_closing(boolMet2, structure = numpy.ones((10,1)))
2481 # boolMet2 = ndimage.morphology.binary_closing(boolMet2, structure = numpy.ones((10,1)))
2483 boolMet2 = ndimage.median_filter(boolMet2,size=5)
2482 boolMet2 = ndimage.median_filter(boolMet2,size=5)
2484 boolMet2 = numpy.vstack((boolMet2,numpy.full((1,nHeights), True, dtype=bool)))
2483 boolMet2 = numpy.vstack((boolMet2,numpy.full((1,nHeights), True, dtype=bool)))
2485 # #Final mask
2484 # #Final mask
2486 # boolMetFin = boolMet2
2485 # boolMetFin = boolMet2
2487 boolMetFin = boolMet1&boolMet2
2486 boolMetFin = boolMet1&boolMet2
2488 # boolMetFin = ndimage.morphology.binary_dilation(boolMetFin)
2487 # boolMetFin = ndimage.morphology.binary_dilation(boolMetFin)
2489 #Creating data_param
2488 #Creating data_param
2490 coordMet = numpy.where(boolMetFin)
2489 coordMet = numpy.where(boolMetFin)
2491
2490
2492 tmet = coordMet[0]
2491 tmet = coordMet[0]
2493 hmet = coordMet[1]
2492 hmet = coordMet[1]
2494
2493
2495 data_param = numpy.zeros((tmet.size, 6 + nPairs))
2494 data_param = numpy.zeros((tmet.size, 6 + nPairs))
2496 data_param[:,0] = utctime
2495 data_param[:,0] = utctime
2497 data_param[:,1] = tmet
2496 data_param[:,1] = tmet
2498 data_param[:,2] = hmet
2497 data_param[:,2] = hmet
2499 data_param[:,3] = SNRm[tmet,hmet]
2498 data_param[:,3] = SNRm[tmet,hmet]
2500 data_param[:,4] = velRad[tmet,hmet]
2499 data_param[:,4] = velRad[tmet,hmet]
2501 data_param[:,5] = coh[tmet,hmet]
2500 data_param[:,5] = coh[tmet,hmet]
2502 data_param[:,6:] = phase[:,tmet,hmet].T
2501 data_param[:,6:] = phase[:,tmet,hmet].T
2503
2502
2504 elif mode == 'DBS':
2503 elif mode == 'DBS':
2505 dataOut.groupList = numpy.arange(nChannels)
2504 dataOut.groupList = numpy.arange(nChannels)
2506
2505
2507 #Radial Velocities
2506 #Radial Velocities
2508 phase = numpy.angle(data_acf[:,1,:,:])
2507 phase = numpy.angle(data_acf[:,1,:,:])
2509 # phase = ndimage.median_filter(numpy.angle(data_acf[:,1,:,:]), size = (1,5,1))
2508 # phase = ndimage.median_filter(numpy.angle(data_acf[:,1,:,:]), size = (1,5,1))
2510 velRad = phase*lamb/(4*numpy.pi*tSamp)
2509 velRad = phase*lamb/(4*numpy.pi*tSamp)
2511
2510
2512 #Spectral width
2511 #Spectral width
2513 # acf1 = ndimage.median_filter(numpy.abs(data_acf[:,1,:,:]), size = (1,5,1))
2512 # acf1 = ndimage.median_filter(numpy.abs(data_acf[:,1,:,:]), size = (1,5,1))
2514 # acf2 = ndimage.median_filter(numpy.abs(data_acf[:,2,:,:]), size = (1,5,1))
2513 # acf2 = ndimage.median_filter(numpy.abs(data_acf[:,2,:,:]), size = (1,5,1))
2515 acf1 = data_acf[:,1,:,:]
2514 acf1 = data_acf[:,1,:,:]
2516 acf2 = data_acf[:,2,:,:]
2515 acf2 = data_acf[:,2,:,:]
2517
2516
2518 spcWidth = (lamb/(2*numpy.sqrt(6)*numpy.pi*tSamp))*numpy.sqrt(numpy.log(acf1/acf2))
2517 spcWidth = (lamb/(2*numpy.sqrt(6)*numpy.pi*tSamp))*numpy.sqrt(numpy.log(acf1/acf2))
2519 # velRad = ndimage.median_filter(velRad, size = (1,5,1))
2518 # velRad = ndimage.median_filter(velRad, size = (1,5,1))
2520 if allData:
2519 if allData:
2521 boolMetFin = ~numpy.isnan(SNRdB)
2520 boolMetFin = ~numpy.isnan(SNRdB)
2522 else:
2521 else:
2523 #SNR
2522 #SNR
2524 boolMet1 = (SNRdB>SNRthresh) #SNR mask
2523 boolMet1 = (SNRdB>SNRthresh) #SNR mask
2525 boolMet1 = ndimage.median_filter(boolMet1, size=(1,5,5))
2524 boolMet1 = ndimage.median_filter(boolMet1, size=(1,5,5))
2526
2525
2527 #Radial velocity
2526 #Radial velocity
2528 boolMet2 = numpy.abs(velRad) < 20
2527 boolMet2 = numpy.abs(velRad) < 20
2529 boolMet2 = ndimage.median_filter(boolMet2, (1,5,5))
2528 boolMet2 = ndimage.median_filter(boolMet2, (1,5,5))
2530
2529
2531 #Spectral Width
2530 #Spectral Width
2532 boolMet3 = spcWidth < 30
2531 boolMet3 = spcWidth < 30
2533 boolMet3 = ndimage.median_filter(boolMet3, (1,5,5))
2532 boolMet3 = ndimage.median_filter(boolMet3, (1,5,5))
2534 # boolMetFin = self.__erase_small(boolMet1, 10,5)
2533 # boolMetFin = self.__erase_small(boolMet1, 10,5)
2535 boolMetFin = boolMet1&boolMet2&boolMet3
2534 boolMetFin = boolMet1&boolMet2&boolMet3
2536
2535
2537 #Creating data_param
2536 #Creating data_param
2538 coordMet = numpy.where(boolMetFin)
2537 coordMet = numpy.where(boolMetFin)
2539
2538
2540 cmet = coordMet[0]
2539 cmet = coordMet[0]
2541 tmet = coordMet[1]
2540 tmet = coordMet[1]
2542 hmet = coordMet[2]
2541 hmet = coordMet[2]
2543
2542
2544 data_param = numpy.zeros((tmet.size, 7))
2543 data_param = numpy.zeros((tmet.size, 7))
2545 data_param[:,0] = utctime
2544 data_param[:,0] = utctime
2546 data_param[:,1] = cmet
2545 data_param[:,1] = cmet
2547 data_param[:,2] = tmet
2546 data_param[:,2] = tmet
2548 data_param[:,3] = hmet
2547 data_param[:,3] = hmet
2549 data_param[:,4] = SNR[cmet,tmet,hmet].T
2548 data_param[:,4] = SNR[cmet,tmet,hmet].T
2550 data_param[:,5] = velRad[cmet,tmet,hmet].T
2549 data_param[:,5] = velRad[cmet,tmet,hmet].T
2551 data_param[:,6] = spcWidth[cmet,tmet,hmet].T
2550 data_param[:,6] = spcWidth[cmet,tmet,hmet].T
2552
2551
2553 # self.dataOut.data_param = data_int
2552 # self.dataOut.data_param = data_int
2554 if len(data_param) == 0:
2553 if len(data_param) == 0:
2555 dataOut.flagNoData = True
2554 dataOut.flagNoData = True
2556 else:
2555 else:
2557 dataOut.data_param = data_param
2556 dataOut.data_param = data_param
2558
2557
2559 def __erase_small(self, binArray, threshX, threshY):
2558 def __erase_small(self, binArray, threshX, threshY):
2560 labarray, numfeat = ndimage.measurements.label(binArray)
2559 labarray, numfeat = ndimage.measurements.label(binArray)
2561 binArray1 = numpy.copy(binArray)
2560 binArray1 = numpy.copy(binArray)
2562
2561
2563 for i in range(1,numfeat + 1):
2562 for i in range(1,numfeat + 1):
2564 auxBin = (labarray==i)
2563 auxBin = (labarray==i)
2565 auxSize = auxBin.sum()
2564 auxSize = auxBin.sum()
2566
2565
2567 x,y = numpy.where(auxBin)
2566 x,y = numpy.where(auxBin)
2568 widthX = x.max() - x.min()
2567 widthX = x.max() - x.min()
2569 widthY = y.max() - y.min()
2568 widthY = y.max() - y.min()
2570
2569
2571 #width X: 3 seg -> 12.5*3
2570 #width X: 3 seg -> 12.5*3
2572 #width Y:
2571 #width Y:
2573
2572
2574 if (auxSize < 50) or (widthX < threshX) or (widthY < threshY):
2573 if (auxSize < 50) or (widthX < threshX) or (widthY < threshY):
2575 binArray1[auxBin] = False
2574 binArray1[auxBin] = False
2576
2575
2577 return binArray1
2576 return binArray1
2578
2577
2579 #--------------- Specular Meteor ----------------
2578 #--------------- Specular Meteor ----------------
2580
2579
2581 class SMDetection(Operation):
2580 class SMDetection(Operation):
2582 '''
2581 '''
2583 Function DetectMeteors()
2582 Function DetectMeteors()
2584 Project developed with paper:
2583 Project developed with paper:
2585 HOLDSWORTH ET AL. 2004
2584 HOLDSWORTH ET AL. 2004
2586
2585
2587 Input:
2586 Input:
2588 self.dataOut.data_pre
2587 self.dataOut.data_pre
2589
2588
2590 centerReceiverIndex: From the channels, which is the center receiver
2589 centerReceiverIndex: From the channels, which is the center receiver
2591
2590
2592 hei_ref: Height reference for the Beacon signal extraction
2591 hei_ref: Height reference for the Beacon signal extraction
2593 tauindex:
2592 tauindex:
2594 predefinedPhaseShifts: Predefined phase offset for the voltge signals
2593 predefinedPhaseShifts: Predefined phase offset for the voltge signals
2595
2594
2596 cohDetection: Whether to user Coherent detection or not
2595 cohDetection: Whether to user Coherent detection or not
2597 cohDet_timeStep: Coherent Detection calculation time step
2596 cohDet_timeStep: Coherent Detection calculation time step
2598 cohDet_thresh: Coherent Detection phase threshold to correct phases
2597 cohDet_thresh: Coherent Detection phase threshold to correct phases
2599
2598
2600 noise_timeStep: Noise calculation time step
2599 noise_timeStep: Noise calculation time step
2601 noise_multiple: Noise multiple to define signal threshold
2600 noise_multiple: Noise multiple to define signal threshold
2602
2601
2603 multDet_timeLimit: Multiple Detection Removal time limit in seconds
2602 multDet_timeLimit: Multiple Detection Removal time limit in seconds
2604 multDet_rangeLimit: Multiple Detection Removal range limit in km
2603 multDet_rangeLimit: Multiple Detection Removal range limit in km
2605
2604
2606 phaseThresh: Maximum phase difference between receiver to be consider a meteor
2605 phaseThresh: Maximum phase difference between receiver to be consider a meteor
2607 SNRThresh: Minimum SNR threshold of the meteor signal to be consider a meteor
2606 SNRThresh: Minimum SNR threshold of the meteor signal to be consider a meteor
2608
2607
2609 hmin: Minimum Height of the meteor to use it in the further wind estimations
2608 hmin: Minimum Height of the meteor to use it in the further wind estimations
2610 hmax: Maximum Height of the meteor to use it in the further wind estimations
2609 hmax: Maximum Height of the meteor to use it in the further wind estimations
2611 azimuth: Azimuth angle correction
2610 azimuth: Azimuth angle correction
2612
2611
2613 Affected:
2612 Affected:
2614 self.dataOut.data_param
2613 self.dataOut.data_param
2615
2614
2616 Rejection Criteria (Errors):
2615 Rejection Criteria (Errors):
2617 0: No error; analysis OK
2616 0: No error; analysis OK
2618 1: SNR < SNR threshold
2617 1: SNR < SNR threshold
2619 2: angle of arrival (AOA) ambiguously determined
2618 2: angle of arrival (AOA) ambiguously determined
2620 3: AOA estimate not feasible
2619 3: AOA estimate not feasible
2621 4: Large difference in AOAs obtained from different antenna baselines
2620 4: Large difference in AOAs obtained from different antenna baselines
2622 5: echo at start or end of time series
2621 5: echo at start or end of time series
2623 6: echo less than 5 examples long; too short for analysis
2622 6: echo less than 5 examples long; too short for analysis
2624 7: echo rise exceeds 0.3s
2623 7: echo rise exceeds 0.3s
2625 8: echo decay time less than twice rise time
2624 8: echo decay time less than twice rise time
2626 9: large power level before echo
2625 9: large power level before echo
2627 10: large power level after echo
2626 10: large power level after echo
2628 11: poor fit to amplitude for estimation of decay time
2627 11: poor fit to amplitude for estimation of decay time
2629 12: poor fit to CCF phase variation for estimation of radial drift velocity
2628 12: poor fit to CCF phase variation for estimation of radial drift velocity
2630 13: height unresolvable echo: not valid height within 70 to 110 km
2629 13: height unresolvable echo: not valid height within 70 to 110 km
2631 14: height ambiguous echo: more then one possible height within 70 to 110 km
2630 14: height ambiguous echo: more then one possible height within 70 to 110 km
2632 15: radial drift velocity or projected horizontal velocity exceeds 200 m/s
2631 15: radial drift velocity or projected horizontal velocity exceeds 200 m/s
2633 16: oscilatory echo, indicating event most likely not an underdense echo
2632 16: oscilatory echo, indicating event most likely not an underdense echo
2634
2633
2635 17: phase difference in meteor Reestimation
2634 17: phase difference in meteor Reestimation
2636
2635
2637 Data Storage:
2636 Data Storage:
2638 Meteors for Wind Estimation (8):
2637 Meteors for Wind Estimation (8):
2639 Utc Time | Range Height
2638 Utc Time | Range Height
2640 Azimuth Zenith errorCosDir
2639 Azimuth Zenith errorCosDir
2641 VelRad errorVelRad
2640 VelRad errorVelRad
2642 Phase0 Phase1 Phase2 Phase3
2641 Phase0 Phase1 Phase2 Phase3
2643 TypeError
2642 TypeError
2644
2643
2645 '''
2644 '''
2646
2645
2647 def run(self, dataOut, hei_ref = None, tauindex = 0,
2646 def run(self, dataOut, hei_ref = None, tauindex = 0,
2648 phaseOffsets = None,
2647 phaseOffsets = None,
2649 cohDetection = False, cohDet_timeStep = 1, cohDet_thresh = 25,
2648 cohDetection = False, cohDet_timeStep = 1, cohDet_thresh = 25,
2650 noise_timeStep = 4, noise_multiple = 4,
2649 noise_timeStep = 4, noise_multiple = 4,
2651 multDet_timeLimit = 1, multDet_rangeLimit = 3,
2650 multDet_timeLimit = 1, multDet_rangeLimit = 3,
2652 phaseThresh = 20, SNRThresh = 5,
2651 phaseThresh = 20, SNRThresh = 5,
2653 hmin = 50, hmax=150, azimuth = 0,
2652 hmin = 50, hmax=150, azimuth = 0,
2654 channelPositions = None) :
2653 channelPositions = None) :
2655
2654
2656
2655
2657 #Getting Pairslist
2656 #Getting Pairslist
2658 if channelPositions is None:
2657 if channelPositions is None:
2659 # channelPositions = [(2.5,0), (0,2.5), (0,0), (0,4.5), (-2,0)] #T
2658 # channelPositions = [(2.5,0), (0,2.5), (0,0), (0,4.5), (-2,0)] #T
2660 channelPositions = [(4.5,2), (2,4.5), (2,2), (2,0), (0,2)] #Estrella
2659 channelPositions = [(4.5,2), (2,4.5), (2,2), (2,0), (0,2)] #Estrella
2661 meteorOps = SMOperations()
2660 meteorOps = SMOperations()
2662 pairslist0, distances = meteorOps.getPhasePairs(channelPositions)
2661 pairslist0, distances = meteorOps.getPhasePairs(channelPositions)
2663 heiRang = dataOut.heightList
2662 heiRang = dataOut.heightList
2664 #Get Beacon signal - No Beacon signal anymore
2663 #Get Beacon signal - No Beacon signal anymore
2665 # newheis = numpy.where(self.dataOut.heightList>self.dataOut.radarControllerHeaderObj.Taus[tauindex])
2664 # newheis = numpy.where(self.dataOut.heightList>self.dataOut.radarControllerHeaderObj.Taus[tauindex])
2666 #
2665 #
2667 # if hei_ref != None:
2666 # if hei_ref != None:
2668 # newheis = numpy.where(self.dataOut.heightList>hei_ref)
2667 # newheis = numpy.where(self.dataOut.heightList>hei_ref)
2669 #
2668 #
2670
2669
2671
2670
2672 #****************REMOVING HARDWARE PHASE DIFFERENCES***************
2671 #****************REMOVING HARDWARE PHASE DIFFERENCES***************
2673 # see if the user put in pre defined phase shifts
2672 # see if the user put in pre defined phase shifts
2674 voltsPShift = dataOut.data_pre.copy()
2673 voltsPShift = dataOut.data_pre.copy()
2675
2674
2676 # if predefinedPhaseShifts != None:
2675 # if predefinedPhaseShifts != None:
2677 # hardwarePhaseShifts = numpy.array(predefinedPhaseShifts)*numpy.pi/180
2676 # hardwarePhaseShifts = numpy.array(predefinedPhaseShifts)*numpy.pi/180
2678 #
2677 #
2679 # # elif beaconPhaseShifts:
2678 # # elif beaconPhaseShifts:
2680 # # #get hardware phase shifts using beacon signal
2679 # # #get hardware phase shifts using beacon signal
2681 # # hardwarePhaseShifts = self.__getHardwarePhaseDiff(self.dataOut.data_pre, pairslist, newheis, 10)
2680 # # hardwarePhaseShifts = self.__getHardwarePhaseDiff(self.dataOut.data_pre, pairslist, newheis, 10)
2682 # # hardwarePhaseShifts = numpy.insert(hardwarePhaseShifts,centerReceiverIndex,0)
2681 # # hardwarePhaseShifts = numpy.insert(hardwarePhaseShifts,centerReceiverIndex,0)
2683 #
2682 #
2684 # else:
2683 # else:
2685 # hardwarePhaseShifts = numpy.zeros(5)
2684 # hardwarePhaseShifts = numpy.zeros(5)
2686 #
2685 #
2687 # voltsPShift = numpy.zeros((self.dataOut.data_pre.shape[0],self.dataOut.data_pre.shape[1],self.dataOut.data_pre.shape[2]), dtype = 'complex')
2686 # voltsPShift = numpy.zeros((self.dataOut.data_pre.shape[0],self.dataOut.data_pre.shape[1],self.dataOut.data_pre.shape[2]), dtype = 'complex')
2688 # for i in range(self.dataOut.data_pre.shape[0]):
2687 # for i in range(self.dataOut.data_pre.shape[0]):
2689 # voltsPShift[i,:,:] = self.__shiftPhase(self.dataOut.data_pre[i,:,:], hardwarePhaseShifts[i])
2688 # voltsPShift[i,:,:] = self.__shiftPhase(self.dataOut.data_pre[i,:,:], hardwarePhaseShifts[i])
2690
2689
2691 #******************END OF REMOVING HARDWARE PHASE DIFFERENCES*********
2690 #******************END OF REMOVING HARDWARE PHASE DIFFERENCES*********
2692
2691
2693 #Remove DC
2692 #Remove DC
2694 voltsDC = numpy.mean(voltsPShift,1)
2693 voltsDC = numpy.mean(voltsPShift,1)
2695 voltsDC = numpy.mean(voltsDC,1)
2694 voltsDC = numpy.mean(voltsDC,1)
2696 for i in range(voltsDC.shape[0]):
2695 for i in range(voltsDC.shape[0]):
2697 voltsPShift[i] = voltsPShift[i] - voltsDC[i]
2696 voltsPShift[i] = voltsPShift[i] - voltsDC[i]
2698
2697
2699 #Don't considerate last heights, theyre used to calculate Hardware Phase Shift
2698 #Don't considerate last heights, theyre used to calculate Hardware Phase Shift
2700 # voltsPShift = voltsPShift[:,:,:newheis[0][0]]
2699 # voltsPShift = voltsPShift[:,:,:newheis[0][0]]
2701
2700
2702 #************ FIND POWER OF DATA W/COH OR NON COH DETECTION (3.4) **********
2701 #************ FIND POWER OF DATA W/COH OR NON COH DETECTION (3.4) **********
2703 #Coherent Detection
2702 #Coherent Detection
2704 if cohDetection:
2703 if cohDetection:
2705 #use coherent detection to get the net power
2704 #use coherent detection to get the net power
2706 cohDet_thresh = cohDet_thresh*numpy.pi/180
2705 cohDet_thresh = cohDet_thresh*numpy.pi/180
2707 voltsPShift = self.__coherentDetection(voltsPShift, cohDet_timeStep, dataOut.timeInterval, pairslist0, cohDet_thresh)
2706 voltsPShift = self.__coherentDetection(voltsPShift, cohDet_timeStep, dataOut.timeInterval, pairslist0, cohDet_thresh)
2708
2707
2709 #Non-coherent detection!
2708 #Non-coherent detection!
2710 powerNet = numpy.nansum(numpy.abs(voltsPShift[:,:,:])**2,0)
2709 powerNet = numpy.nansum(numpy.abs(voltsPShift[:,:,:])**2,0)
2711 #********** END OF COH/NON-COH POWER CALCULATION**********************
2710 #********** END OF COH/NON-COH POWER CALCULATION**********************
2712
2711
2713 #********** FIND THE NOISE LEVEL AND POSSIBLE METEORS ****************
2712 #********** FIND THE NOISE LEVEL AND POSSIBLE METEORS ****************
2714 #Get noise
2713 #Get noise
2715 noise, noise1 = self.__getNoise(powerNet, noise_timeStep, dataOut.timeInterval)
2714 noise, noise1 = self.__getNoise(powerNet, noise_timeStep, dataOut.timeInterval)
2716 # noise = self.getNoise1(powerNet, noise_timeStep, self.dataOut.timeInterval)
2715 # noise = self.getNoise1(powerNet, noise_timeStep, self.dataOut.timeInterval)
2717 #Get signal threshold
2716 #Get signal threshold
2718 signalThresh = noise_multiple*noise
2717 signalThresh = noise_multiple*noise
2719 #Meteor echoes detection
2718 #Meteor echoes detection
2720 listMeteors = self.__findMeteors(powerNet, signalThresh)
2719 listMeteors = self.__findMeteors(powerNet, signalThresh)
2721 #******* END OF NOISE LEVEL AND POSSIBLE METEORS CACULATION **********
2720 #******* END OF NOISE LEVEL AND POSSIBLE METEORS CACULATION **********
2722
2721
2723 #************** REMOVE MULTIPLE DETECTIONS (3.5) ***************************
2722 #************** REMOVE MULTIPLE DETECTIONS (3.5) ***************************
2724 #Parameters
2723 #Parameters
2725 heiRange = dataOut.heightList
2724 heiRange = dataOut.heightList
2726 rangeInterval = heiRange[1] - heiRange[0]
2725 rangeInterval = heiRange[1] - heiRange[0]
2727 rangeLimit = multDet_rangeLimit/rangeInterval
2726 rangeLimit = multDet_rangeLimit/rangeInterval
2728 timeLimit = multDet_timeLimit/dataOut.timeInterval
2727 timeLimit = multDet_timeLimit/dataOut.timeInterval
2729 #Multiple detection removals
2728 #Multiple detection removals
2730 listMeteors1 = self.__removeMultipleDetections(listMeteors, rangeLimit, timeLimit)
2729 listMeteors1 = self.__removeMultipleDetections(listMeteors, rangeLimit, timeLimit)
2731 #************ END OF REMOVE MULTIPLE DETECTIONS **********************
2730 #************ END OF REMOVE MULTIPLE DETECTIONS **********************
2732
2731
2733 #********************* METEOR REESTIMATION (3.7, 3.8, 3.9, 3.10) ********************
2732 #********************* METEOR REESTIMATION (3.7, 3.8, 3.9, 3.10) ********************
2734 #Parameters
2733 #Parameters
2735 phaseThresh = phaseThresh*numpy.pi/180
2734 phaseThresh = phaseThresh*numpy.pi/180
2736 thresh = [phaseThresh, noise_multiple, SNRThresh]
2735 thresh = [phaseThresh, noise_multiple, SNRThresh]
2737 #Meteor reestimation (Errors N 1, 6, 12, 17)
2736 #Meteor reestimation (Errors N 1, 6, 12, 17)
2738 listMeteors2, listMeteorsPower, listMeteorsVolts = self.__meteorReestimation(listMeteors1, voltsPShift, pairslist0, thresh, noise, dataOut.timeInterval, dataOut.frequency)
2737 listMeteors2, listMeteorsPower, listMeteorsVolts = self.__meteorReestimation(listMeteors1, voltsPShift, pairslist0, thresh, noise, dataOut.timeInterval, dataOut.frequency)
2739 # listMeteors2, listMeteorsPower, listMeteorsVolts = self.meteorReestimation3(listMeteors2, listMeteorsPower, listMeteorsVolts, voltsPShift, pairslist, thresh, noise)
2738 # listMeteors2, listMeteorsPower, listMeteorsVolts = self.meteorReestimation3(listMeteors2, listMeteorsPower, listMeteorsVolts, voltsPShift, pairslist, thresh, noise)
2740 #Estimation of decay times (Errors N 7, 8, 11)
2739 #Estimation of decay times (Errors N 7, 8, 11)
2741 listMeteors3 = self.__estimateDecayTime(listMeteors2, listMeteorsPower, dataOut.timeInterval, dataOut.frequency)
2740 listMeteors3 = self.__estimateDecayTime(listMeteors2, listMeteorsPower, dataOut.timeInterval, dataOut.frequency)
2742 #******************* END OF METEOR REESTIMATION *******************
2741 #******************* END OF METEOR REESTIMATION *******************
2743
2742
2744 #********************* METEOR PARAMETERS CALCULATION (3.11, 3.12, 3.13) **************************
2743 #********************* METEOR PARAMETERS CALCULATION (3.11, 3.12, 3.13) **************************
2745 #Calculating Radial Velocity (Error N 15)
2744 #Calculating Radial Velocity (Error N 15)
2746 radialStdThresh = 10
2745 radialStdThresh = 10
2747 listMeteors4 = self.__getRadialVelocity(listMeteors3, listMeteorsVolts, radialStdThresh, pairslist0, dataOut.timeInterval)
2746 listMeteors4 = self.__getRadialVelocity(listMeteors3, listMeteorsVolts, radialStdThresh, pairslist0, dataOut.timeInterval)
2748
2747
2749 if len(listMeteors4) > 0:
2748 if len(listMeteors4) > 0:
2750 #Setting New Array
2749 #Setting New Array
2751 date = dataOut.utctime
2750 date = dataOut.utctime
2752 arrayParameters = self.__setNewArrays(listMeteors4, date, heiRang)
2751 arrayParameters = self.__setNewArrays(listMeteors4, date, heiRang)
2753
2752
2754 #Correcting phase offset
2753 #Correcting phase offset
2755 if phaseOffsets != None:
2754 if phaseOffsets != None:
2756 phaseOffsets = numpy.array(phaseOffsets)*numpy.pi/180
2755 phaseOffsets = numpy.array(phaseOffsets)*numpy.pi/180
2757 arrayParameters[:,8:12] = numpy.unwrap(arrayParameters[:,8:12] + phaseOffsets)
2756 arrayParameters[:,8:12] = numpy.unwrap(arrayParameters[:,8:12] + phaseOffsets)
2758
2757
2759 #Second Pairslist
2758 #Second Pairslist
2760 pairsList = []
2759 pairsList = []
2761 pairx = (0,1)
2760 pairx = (0,1)
2762 pairy = (2,3)
2761 pairy = (2,3)
2763 pairsList.append(pairx)
2762 pairsList.append(pairx)
2764 pairsList.append(pairy)
2763 pairsList.append(pairy)
2765
2764
2766 jph = numpy.array([0,0,0,0])
2765 jph = numpy.array([0,0,0,0])
2767 h = (hmin,hmax)
2766 h = (hmin,hmax)
2768 arrayParameters = meteorOps.getMeteorParams(arrayParameters, azimuth, h, pairsList, distances, jph)
2767 arrayParameters = meteorOps.getMeteorParams(arrayParameters, azimuth, h, pairsList, distances, jph)
2769
2768
2770 # #Calculate AOA (Error N 3, 4)
2769 # #Calculate AOA (Error N 3, 4)
2771 # #JONES ET AL. 1998
2770 # #JONES ET AL. 1998
2772 # error = arrayParameters[:,-1]
2771 # error = arrayParameters[:,-1]
2773 # AOAthresh = numpy.pi/8
2772 # AOAthresh = numpy.pi/8
2774 # phases = -arrayParameters[:,9:13]
2773 # phases = -arrayParameters[:,9:13]
2775 # arrayParameters[:,4:7], arrayParameters[:,-1] = meteorOps.getAOA(phases, pairsList, error, AOAthresh, azimuth)
2774 # arrayParameters[:,4:7], arrayParameters[:,-1] = meteorOps.getAOA(phases, pairsList, error, AOAthresh, azimuth)
2776 #
2775 #
2777 # #Calculate Heights (Error N 13 and 14)
2776 # #Calculate Heights (Error N 13 and 14)
2778 # error = arrayParameters[:,-1]
2777 # error = arrayParameters[:,-1]
2779 # Ranges = arrayParameters[:,2]
2778 # Ranges = arrayParameters[:,2]
2780 # zenith = arrayParameters[:,5]
2779 # zenith = arrayParameters[:,5]
2781 # arrayParameters[:,3], arrayParameters[:,-1] = meteorOps.getHeights(Ranges, zenith, error, hmin, hmax)
2780 # arrayParameters[:,3], arrayParameters[:,-1] = meteorOps.getHeights(Ranges, zenith, error, hmin, hmax)
2782 # error = arrayParameters[:,-1]
2781 # error = arrayParameters[:,-1]
2783 #********************* END OF PARAMETERS CALCULATION **************************
2782 #********************* END OF PARAMETERS CALCULATION **************************
2784
2783
2785 #***************************+ PASS DATA TO NEXT STEP **********************
2784 #***************************+ PASS DATA TO NEXT STEP **********************
2786 # arrayFinal = arrayParameters.reshape((1,arrayParameters.shape[0],arrayParameters.shape[1]))
2785 # arrayFinal = arrayParameters.reshape((1,arrayParameters.shape[0],arrayParameters.shape[1]))
2787 dataOut.data_param = arrayParameters
2786 dataOut.data_param = arrayParameters
2788
2787
2789 if arrayParameters is None:
2788 if arrayParameters is None:
2790 dataOut.flagNoData = True
2789 dataOut.flagNoData = True
2791 else:
2790 else:
2792 dataOut.flagNoData = True
2791 dataOut.flagNoData = True
2793
2792
2794 return
2793 return
2795
2794
2796 def __getHardwarePhaseDiff(self, voltage0, pairslist, newheis, n):
2795 def __getHardwarePhaseDiff(self, voltage0, pairslist, newheis, n):
2797
2796
2798 minIndex = min(newheis[0])
2797 minIndex = min(newheis[0])
2799 maxIndex = max(newheis[0])
2798 maxIndex = max(newheis[0])
2800
2799
2801 voltage = voltage0[:,:,minIndex:maxIndex+1]
2800 voltage = voltage0[:,:,minIndex:maxIndex+1]
2802 nLength = voltage.shape[1]/n
2801 nLength = voltage.shape[1]/n
2803 nMin = 0
2802 nMin = 0
2804 nMax = 0
2803 nMax = 0
2805 phaseOffset = numpy.zeros((len(pairslist),n))
2804 phaseOffset = numpy.zeros((len(pairslist),n))
2806
2805
2807 for i in range(n):
2806 for i in range(n):
2808 nMax += nLength
2807 nMax += nLength
2809 phaseCCF = -numpy.angle(self.__calculateCCF(voltage[:,nMin:nMax,:], pairslist, [0]))
2808 phaseCCF = -numpy.angle(self.__calculateCCF(voltage[:,nMin:nMax,:], pairslist, [0]))
2810 phaseCCF = numpy.mean(phaseCCF, axis = 2)
2809 phaseCCF = numpy.mean(phaseCCF, axis = 2)
2811 phaseOffset[:,i] = phaseCCF.transpose()
2810 phaseOffset[:,i] = phaseCCF.transpose()
2812 nMin = nMax
2811 nMin = nMax
2813 # phaseDiff, phaseArrival = self.estimatePhaseDifference(voltage, pairslist)
2812 # phaseDiff, phaseArrival = self.estimatePhaseDifference(voltage, pairslist)
2814
2813
2815 #Remove Outliers
2814 #Remove Outliers
2816 factor = 2
2815 factor = 2
2817 wt = phaseOffset - signal.medfilt(phaseOffset,(1,5))
2816 wt = phaseOffset - signal.medfilt(phaseOffset,(1,5))
2818 dw = numpy.std(wt,axis = 1)
2817 dw = numpy.std(wt,axis = 1)
2819 dw = dw.reshape((dw.size,1))
2818 dw = dw.reshape((dw.size,1))
2820 ind = numpy.where(numpy.logical_or(wt>dw*factor,wt<-dw*factor))
2819 ind = numpy.where(numpy.logical_or(wt>dw*factor,wt<-dw*factor))
2821 phaseOffset[ind] = numpy.nan
2820 phaseOffset[ind] = numpy.nan
2822 phaseOffset = stats.nanmean(phaseOffset, axis=1)
2821 phaseOffset = stats.nanmean(phaseOffset, axis=1)
2823
2822
2824 return phaseOffset
2823 return phaseOffset
2825
2824
2826 def __shiftPhase(self, data, phaseShift):
2825 def __shiftPhase(self, data, phaseShift):
2827 #this will shift the phase of a complex number
2826 #this will shift the phase of a complex number
2828 dataShifted = numpy.abs(data) * numpy.exp((numpy.angle(data)+phaseShift)*1j)
2827 dataShifted = numpy.abs(data) * numpy.exp((numpy.angle(data)+phaseShift)*1j)
2829 return dataShifted
2828 return dataShifted
2830
2829
2831 def __estimatePhaseDifference(self, array, pairslist):
2830 def __estimatePhaseDifference(self, array, pairslist):
2832 nChannel = array.shape[0]
2831 nChannel = array.shape[0]
2833 nHeights = array.shape[2]
2832 nHeights = array.shape[2]
2834 numPairs = len(pairslist)
2833 numPairs = len(pairslist)
2835 # phaseCCF = numpy.zeros((nChannel, 5, nHeights))
2834 # phaseCCF = numpy.zeros((nChannel, 5, nHeights))
2836 phaseCCF = numpy.angle(self.__calculateCCF(array, pairslist, [-2,-1,0,1,2]))
2835 phaseCCF = numpy.angle(self.__calculateCCF(array, pairslist, [-2,-1,0,1,2]))
2837
2836
2838 #Correct phases
2837 #Correct phases
2839 derPhaseCCF = phaseCCF[:,1:,:] - phaseCCF[:,0:-1,:]
2838 derPhaseCCF = phaseCCF[:,1:,:] - phaseCCF[:,0:-1,:]
2840 indDer = numpy.where(numpy.abs(derPhaseCCF) > numpy.pi)
2839 indDer = numpy.where(numpy.abs(derPhaseCCF) > numpy.pi)
2841
2840
2842 if indDer[0].shape[0] > 0:
2841 if indDer[0].shape[0] > 0:
2843 for i in range(indDer[0].shape[0]):
2842 for i in range(indDer[0].shape[0]):
2844 signo = -numpy.sign(derPhaseCCF[indDer[0][i],indDer[1][i],indDer[2][i]])
2843 signo = -numpy.sign(derPhaseCCF[indDer[0][i],indDer[1][i],indDer[2][i]])
2845 phaseCCF[indDer[0][i],indDer[1][i]+1:,:] += signo*2*numpy.pi
2844 phaseCCF[indDer[0][i],indDer[1][i]+1:,:] += signo*2*numpy.pi
2846
2845
2847 # for j in range(numSides):
2846 # for j in range(numSides):
2848 # phaseCCFAux = self.calculateCCF(arrayCenter, arraySides[j,:,:], [-2,1,0,1,2])
2847 # phaseCCFAux = self.calculateCCF(arrayCenter, arraySides[j,:,:], [-2,1,0,1,2])
2849 # phaseCCF[j,:,:] = numpy.angle(phaseCCFAux)
2848 # phaseCCF[j,:,:] = numpy.angle(phaseCCFAux)
2850 #
2849 #
2851 #Linear
2850 #Linear
2852 phaseInt = numpy.zeros((numPairs,1))
2851 phaseInt = numpy.zeros((numPairs,1))
2853 angAllCCF = phaseCCF[:,[0,1,3,4],0]
2852 angAllCCF = phaseCCF[:,[0,1,3,4],0]
2854 for j in range(numPairs):
2853 for j in range(numPairs):
2855 fit = stats.linregress([-2,-1,1,2],angAllCCF[j,:])
2854 fit = stats.linregress([-2,-1,1,2],angAllCCF[j,:])
2856 phaseInt[j] = fit[1]
2855 phaseInt[j] = fit[1]
2857 #Phase Differences
2856 #Phase Differences
2858 phaseDiff = phaseInt - phaseCCF[:,2,:]
2857 phaseDiff = phaseInt - phaseCCF[:,2,:]
2859 phaseArrival = phaseInt.reshape(phaseInt.size)
2858 phaseArrival = phaseInt.reshape(phaseInt.size)
2860
2859
2861 #Dealias
2860 #Dealias
2862 phaseArrival = numpy.angle(numpy.exp(1j*phaseArrival))
2861 phaseArrival = numpy.angle(numpy.exp(1j*phaseArrival))
2863 # indAlias = numpy.where(phaseArrival > numpy.pi)
2862 # indAlias = numpy.where(phaseArrival > numpy.pi)
2864 # phaseArrival[indAlias] -= 2*numpy.pi
2863 # phaseArrival[indAlias] -= 2*numpy.pi
2865 # indAlias = numpy.where(phaseArrival < -numpy.pi)
2864 # indAlias = numpy.where(phaseArrival < -numpy.pi)
2866 # phaseArrival[indAlias] += 2*numpy.pi
2865 # phaseArrival[indAlias] += 2*numpy.pi
2867
2866
2868 return phaseDiff, phaseArrival
2867 return phaseDiff, phaseArrival
2869
2868
2870 def __coherentDetection(self, volts, timeSegment, timeInterval, pairslist, thresh):
2869 def __coherentDetection(self, volts, timeSegment, timeInterval, pairslist, thresh):
2871 #this function will run the coherent detection used in Holdworth et al. 2004 and return the net power
2870 #this function will run the coherent detection used in Holdworth et al. 2004 and return the net power
2872 #find the phase shifts of each channel over 1 second intervals
2871 #find the phase shifts of each channel over 1 second intervals
2873 #only look at ranges below the beacon signal
2872 #only look at ranges below the beacon signal
2874 numProfPerBlock = numpy.ceil(timeSegment/timeInterval)
2873 numProfPerBlock = numpy.ceil(timeSegment/timeInterval)
2875 numBlocks = int(volts.shape[1]/numProfPerBlock)
2874 numBlocks = int(volts.shape[1]/numProfPerBlock)
2876 numHeights = volts.shape[2]
2875 numHeights = volts.shape[2]
2877 nChannel = volts.shape[0]
2876 nChannel = volts.shape[0]
2878 voltsCohDet = volts.copy()
2877 voltsCohDet = volts.copy()
2879
2878
2880 pairsarray = numpy.array(pairslist)
2879 pairsarray = numpy.array(pairslist)
2881 indSides = pairsarray[:,1]
2880 indSides = pairsarray[:,1]
2882 # indSides = numpy.array(range(nChannel))
2881 # indSides = numpy.array(range(nChannel))
2883 # indSides = numpy.delete(indSides, indCenter)
2882 # indSides = numpy.delete(indSides, indCenter)
2884 #
2883 #
2885 # listCenter = numpy.array_split(volts[indCenter,:,:], numBlocks, 0)
2884 # listCenter = numpy.array_split(volts[indCenter,:,:], numBlocks, 0)
2886 listBlocks = numpy.array_split(volts, numBlocks, 1)
2885 listBlocks = numpy.array_split(volts, numBlocks, 1)
2887
2886
2888 startInd = 0
2887 startInd = 0
2889 endInd = 0
2888 endInd = 0
2890
2889
2891 for i in range(numBlocks):
2890 for i in range(numBlocks):
2892 startInd = endInd
2891 startInd = endInd
2893 endInd = endInd + listBlocks[i].shape[1]
2892 endInd = endInd + listBlocks[i].shape[1]
2894
2893
2895 arrayBlock = listBlocks[i]
2894 arrayBlock = listBlocks[i]
2896 # arrayBlockCenter = listCenter[i]
2895 # arrayBlockCenter = listCenter[i]
2897
2896
2898 #Estimate the Phase Difference
2897 #Estimate the Phase Difference
2899 phaseDiff, aux = self.__estimatePhaseDifference(arrayBlock, pairslist)
2898 phaseDiff, aux = self.__estimatePhaseDifference(arrayBlock, pairslist)
2900 #Phase Difference RMS
2899 #Phase Difference RMS
2901 arrayPhaseRMS = numpy.abs(phaseDiff)
2900 arrayPhaseRMS = numpy.abs(phaseDiff)
2902 phaseRMSaux = numpy.sum(arrayPhaseRMS < thresh,0)
2901 phaseRMSaux = numpy.sum(arrayPhaseRMS < thresh,0)
2903 indPhase = numpy.where(phaseRMSaux==4)
2902 indPhase = numpy.where(phaseRMSaux==4)
2904 #Shifting
2903 #Shifting
2905 if indPhase[0].shape[0] > 0:
2904 if indPhase[0].shape[0] > 0:
2906 for j in range(indSides.size):
2905 for j in range(indSides.size):
2907 arrayBlock[indSides[j],:,indPhase] = self.__shiftPhase(arrayBlock[indSides[j],:,indPhase], phaseDiff[j,indPhase].transpose())
2906 arrayBlock[indSides[j],:,indPhase] = self.__shiftPhase(arrayBlock[indSides[j],:,indPhase], phaseDiff[j,indPhase].transpose())
2908 voltsCohDet[:,startInd:endInd,:] = arrayBlock
2907 voltsCohDet[:,startInd:endInd,:] = arrayBlock
2909
2908
2910 return voltsCohDet
2909 return voltsCohDet
2911
2910
2912 def __calculateCCF(self, volts, pairslist ,laglist):
2911 def __calculateCCF(self, volts, pairslist ,laglist):
2913
2912
2914 nHeights = volts.shape[2]
2913 nHeights = volts.shape[2]
2915 nPoints = volts.shape[1]
2914 nPoints = volts.shape[1]
2916 voltsCCF = numpy.zeros((len(pairslist), len(laglist), nHeights),dtype = 'complex')
2915 voltsCCF = numpy.zeros((len(pairslist), len(laglist), nHeights),dtype = 'complex')
2917
2916
2918 for i in range(len(pairslist)):
2917 for i in range(len(pairslist)):
2919 volts1 = volts[pairslist[i][0]]
2918 volts1 = volts[pairslist[i][0]]
2920 volts2 = volts[pairslist[i][1]]
2919 volts2 = volts[pairslist[i][1]]
2921
2920
2922 for t in range(len(laglist)):
2921 for t in range(len(laglist)):
2923 idxT = laglist[t]
2922 idxT = laglist[t]
2924 if idxT >= 0:
2923 if idxT >= 0:
2925 vStacked = numpy.vstack((volts2[idxT:,:],
2924 vStacked = numpy.vstack((volts2[idxT:,:],
2926 numpy.zeros((idxT, nHeights),dtype='complex')))
2925 numpy.zeros((idxT, nHeights),dtype='complex')))
2927 else:
2926 else:
2928 vStacked = numpy.vstack((numpy.zeros((-idxT, nHeights),dtype='complex'),
2927 vStacked = numpy.vstack((numpy.zeros((-idxT, nHeights),dtype='complex'),
2929 volts2[:(nPoints + idxT),:]))
2928 volts2[:(nPoints + idxT),:]))
2930 voltsCCF[i,t,:] = numpy.sum((numpy.conjugate(volts1)*vStacked),axis=0)
2929 voltsCCF[i,t,:] = numpy.sum((numpy.conjugate(volts1)*vStacked),axis=0)
2931
2930
2932 vStacked = None
2931 vStacked = None
2933 return voltsCCF
2932 return voltsCCF
2934
2933
2935 def __getNoise(self, power, timeSegment, timeInterval):
2934 def __getNoise(self, power, timeSegment, timeInterval):
2936 numProfPerBlock = numpy.ceil(timeSegment/timeInterval)
2935 numProfPerBlock = numpy.ceil(timeSegment/timeInterval)
2937 numBlocks = int(power.shape[0]/numProfPerBlock)
2936 numBlocks = int(power.shape[0]/numProfPerBlock)
2938 numHeights = power.shape[1]
2937 numHeights = power.shape[1]
2939
2938
2940 listPower = numpy.array_split(power, numBlocks, 0)
2939 listPower = numpy.array_split(power, numBlocks, 0)
2941 noise = numpy.zeros((power.shape[0], power.shape[1]))
2940 noise = numpy.zeros((power.shape[0], power.shape[1]))
2942 noise1 = numpy.zeros((power.shape[0], power.shape[1]))
2941 noise1 = numpy.zeros((power.shape[0], power.shape[1]))
2943
2942
2944 startInd = 0
2943 startInd = 0
2945 endInd = 0
2944 endInd = 0
2946
2945
2947 for i in range(numBlocks): #split por canal
2946 for i in range(numBlocks): #split por canal
2948 startInd = endInd
2947 startInd = endInd
2949 endInd = endInd + listPower[i].shape[0]
2948 endInd = endInd + listPower[i].shape[0]
2950
2949
2951 arrayBlock = listPower[i]
2950 arrayBlock = listPower[i]
2952 noiseAux = numpy.mean(arrayBlock, 0)
2951 noiseAux = numpy.mean(arrayBlock, 0)
2953 # noiseAux = numpy.median(noiseAux)
2952 # noiseAux = numpy.median(noiseAux)
2954 # noiseAux = numpy.mean(arrayBlock)
2953 # noiseAux = numpy.mean(arrayBlock)
2955 noise[startInd:endInd,:] = noise[startInd:endInd,:] + noiseAux
2954 noise[startInd:endInd,:] = noise[startInd:endInd,:] + noiseAux
2956
2955
2957 noiseAux1 = numpy.mean(arrayBlock)
2956 noiseAux1 = numpy.mean(arrayBlock)
2958 noise1[startInd:endInd,:] = noise1[startInd:endInd,:] + noiseAux1
2957 noise1[startInd:endInd,:] = noise1[startInd:endInd,:] + noiseAux1
2959
2958
2960 return noise, noise1
2959 return noise, noise1
2961
2960
2962 def __findMeteors(self, power, thresh):
2961 def __findMeteors(self, power, thresh):
2963 nProf = power.shape[0]
2962 nProf = power.shape[0]
2964 nHeights = power.shape[1]
2963 nHeights = power.shape[1]
2965 listMeteors = []
2964 listMeteors = []
2966
2965
2967 for i in range(nHeights):
2966 for i in range(nHeights):
2968 powerAux = power[:,i]
2967 powerAux = power[:,i]
2969 threshAux = thresh[:,i]
2968 threshAux = thresh[:,i]
2970
2969
2971 indUPthresh = numpy.where(powerAux > threshAux)[0]
2970 indUPthresh = numpy.where(powerAux > threshAux)[0]
2972 indDNthresh = numpy.where(powerAux <= threshAux)[0]
2971 indDNthresh = numpy.where(powerAux <= threshAux)[0]
2973
2972
2974 j = 0
2973 j = 0
2975
2974
2976 while (j < indUPthresh.size - 2):
2975 while (j < indUPthresh.size - 2):
2977 if (indUPthresh[j + 2] == indUPthresh[j] + 2):
2976 if (indUPthresh[j + 2] == indUPthresh[j] + 2):
2978 indDNAux = numpy.where(indDNthresh > indUPthresh[j])
2977 indDNAux = numpy.where(indDNthresh > indUPthresh[j])
2979 indDNthresh = indDNthresh[indDNAux]
2978 indDNthresh = indDNthresh[indDNAux]
2980
2979
2981 if (indDNthresh.size > 0):
2980 if (indDNthresh.size > 0):
2982 indEnd = indDNthresh[0] - 1
2981 indEnd = indDNthresh[0] - 1
2983 indInit = indUPthresh[j]
2982 indInit = indUPthresh[j]
2984
2983
2985 meteor = powerAux[indInit:indEnd + 1]
2984 meteor = powerAux[indInit:indEnd + 1]
2986 indPeak = meteor.argmax() + indInit
2985 indPeak = meteor.argmax() + indInit
2987 FLA = sum(numpy.conj(meteor)*numpy.hstack((meteor[1:],0)))
2986 FLA = sum(numpy.conj(meteor)*numpy.hstack((meteor[1:],0)))
2988
2987
2989 listMeteors.append(numpy.array([i,indInit,indPeak,indEnd,FLA])) #CHEQUEAR!!!!!
2988 listMeteors.append(numpy.array([i,indInit,indPeak,indEnd,FLA])) #CHEQUEAR!!!!!
2990 j = numpy.where(indUPthresh == indEnd)[0] + 1
2989 j = numpy.where(indUPthresh == indEnd)[0] + 1
2991 else: j+=1
2990 else: j+=1
2992 else: j+=1
2991 else: j+=1
2993
2992
2994 return listMeteors
2993 return listMeteors
2995
2994
2996 def __removeMultipleDetections(self,listMeteors, rangeLimit, timeLimit):
2995 def __removeMultipleDetections(self,listMeteors, rangeLimit, timeLimit):
2997
2996
2998 arrayMeteors = numpy.asarray(listMeteors)
2997 arrayMeteors = numpy.asarray(listMeteors)
2999 listMeteors1 = []
2998 listMeteors1 = []
3000
2999
3001 while arrayMeteors.shape[0] > 0:
3000 while arrayMeteors.shape[0] > 0:
3002 FLAs = arrayMeteors[:,4]
3001 FLAs = arrayMeteors[:,4]
3003 maxFLA = FLAs.argmax()
3002 maxFLA = FLAs.argmax()
3004 listMeteors1.append(arrayMeteors[maxFLA,:])
3003 listMeteors1.append(arrayMeteors[maxFLA,:])
3005
3004
3006 MeteorInitTime = arrayMeteors[maxFLA,1]
3005 MeteorInitTime = arrayMeteors[maxFLA,1]
3007 MeteorEndTime = arrayMeteors[maxFLA,3]
3006 MeteorEndTime = arrayMeteors[maxFLA,3]
3008 MeteorHeight = arrayMeteors[maxFLA,0]
3007 MeteorHeight = arrayMeteors[maxFLA,0]
3009
3008
3010 #Check neighborhood
3009 #Check neighborhood
3011 maxHeightIndex = MeteorHeight + rangeLimit
3010 maxHeightIndex = MeteorHeight + rangeLimit
3012 minHeightIndex = MeteorHeight - rangeLimit
3011 minHeightIndex = MeteorHeight - rangeLimit
3013 minTimeIndex = MeteorInitTime - timeLimit
3012 minTimeIndex = MeteorInitTime - timeLimit
3014 maxTimeIndex = MeteorEndTime + timeLimit
3013 maxTimeIndex = MeteorEndTime + timeLimit
3015
3014
3016 #Check Heights
3015 #Check Heights
3017 indHeight = numpy.logical_and(arrayMeteors[:,0] >= minHeightIndex, arrayMeteors[:,0] <= maxHeightIndex)
3016 indHeight = numpy.logical_and(arrayMeteors[:,0] >= minHeightIndex, arrayMeteors[:,0] <= maxHeightIndex)
3018 indTime = numpy.logical_and(arrayMeteors[:,3] >= minTimeIndex, arrayMeteors[:,1] <= maxTimeIndex)
3017 indTime = numpy.logical_and(arrayMeteors[:,3] >= minTimeIndex, arrayMeteors[:,1] <= maxTimeIndex)
3019 indBoth = numpy.where(numpy.logical_and(indTime,indHeight))
3018 indBoth = numpy.where(numpy.logical_and(indTime,indHeight))
3020
3019
3021 arrayMeteors = numpy.delete(arrayMeteors, indBoth, axis = 0)
3020 arrayMeteors = numpy.delete(arrayMeteors, indBoth, axis = 0)
3022
3021
3023 return listMeteors1
3022 return listMeteors1
3024
3023
3025 def __meteorReestimation(self, listMeteors, volts, pairslist, thresh, noise, timeInterval,frequency):
3024 def __meteorReestimation(self, listMeteors, volts, pairslist, thresh, noise, timeInterval,frequency):
3026 numHeights = volts.shape[2]
3025 numHeights = volts.shape[2]
3027 nChannel = volts.shape[0]
3026 nChannel = volts.shape[0]
3028
3027
3029 thresholdPhase = thresh[0]
3028 thresholdPhase = thresh[0]
3030 thresholdNoise = thresh[1]
3029 thresholdNoise = thresh[1]
3031 thresholdDB = float(thresh[2])
3030 thresholdDB = float(thresh[2])
3032
3031
3033 thresholdDB1 = 10**(thresholdDB/10)
3032 thresholdDB1 = 10**(thresholdDB/10)
3034 pairsarray = numpy.array(pairslist)
3033 pairsarray = numpy.array(pairslist)
3035 indSides = pairsarray[:,1]
3034 indSides = pairsarray[:,1]
3036
3035
3037 pairslist1 = list(pairslist)
3036 pairslist1 = list(pairslist)
3038 pairslist1.append((0,1))
3037 pairslist1.append((0,1))
3039 pairslist1.append((3,4))
3038 pairslist1.append((3,4))
3040
3039
3041 listMeteors1 = []
3040 listMeteors1 = []
3042 listPowerSeries = []
3041 listPowerSeries = []
3043 listVoltageSeries = []
3042 listVoltageSeries = []
3044 #volts has the war data
3043 #volts has the war data
3045
3044
3046 if frequency == 30e6:
3045 if frequency == 30e6:
3047 timeLag = 45*10**-3
3046 timeLag = 45*10**-3
3048 else:
3047 else:
3049 timeLag = 15*10**-3
3048 timeLag = 15*10**-3
3050 lag = numpy.ceil(timeLag/timeInterval)
3049 lag = numpy.ceil(timeLag/timeInterval)
3051
3050
3052 for i in range(len(listMeteors)):
3051 for i in range(len(listMeteors)):
3053
3052
3054 ###################### 3.6 - 3.7 PARAMETERS REESTIMATION #########################
3053 ###################### 3.6 - 3.7 PARAMETERS REESTIMATION #########################
3055 meteorAux = numpy.zeros(16)
3054 meteorAux = numpy.zeros(16)
3056
3055
3057 #Loading meteor Data (mHeight, mStart, mPeak, mEnd)
3056 #Loading meteor Data (mHeight, mStart, mPeak, mEnd)
3058 mHeight = listMeteors[i][0]
3057 mHeight = listMeteors[i][0]
3059 mStart = listMeteors[i][1]
3058 mStart = listMeteors[i][1]
3060 mPeak = listMeteors[i][2]
3059 mPeak = listMeteors[i][2]
3061 mEnd = listMeteors[i][3]
3060 mEnd = listMeteors[i][3]
3062
3061
3063 #get the volt data between the start and end times of the meteor
3062 #get the volt data between the start and end times of the meteor
3064 meteorVolts = volts[:,mStart:mEnd+1,mHeight]
3063 meteorVolts = volts[:,mStart:mEnd+1,mHeight]
3065 meteorVolts = meteorVolts.reshape(meteorVolts.shape[0], meteorVolts.shape[1], 1)
3064 meteorVolts = meteorVolts.reshape(meteorVolts.shape[0], meteorVolts.shape[1], 1)
3066
3065
3067 #3.6. Phase Difference estimation
3066 #3.6. Phase Difference estimation
3068 phaseDiff, aux = self.__estimatePhaseDifference(meteorVolts, pairslist)
3067 phaseDiff, aux = self.__estimatePhaseDifference(meteorVolts, pairslist)
3069
3068
3070 #3.7. Phase difference removal & meteor start, peak and end times reestimated
3069 #3.7. Phase difference removal & meteor start, peak and end times reestimated
3071 #meteorVolts0.- all Channels, all Profiles
3070 #meteorVolts0.- all Channels, all Profiles
3072 meteorVolts0 = volts[:,:,mHeight]
3071 meteorVolts0 = volts[:,:,mHeight]
3073 meteorThresh = noise[:,mHeight]*thresholdNoise
3072 meteorThresh = noise[:,mHeight]*thresholdNoise
3074 meteorNoise = noise[:,mHeight]
3073 meteorNoise = noise[:,mHeight]
3075 meteorVolts0[indSides,:] = self.__shiftPhase(meteorVolts0[indSides,:], phaseDiff) #Phase Shifting
3074 meteorVolts0[indSides,:] = self.__shiftPhase(meteorVolts0[indSides,:], phaseDiff) #Phase Shifting
3076 powerNet0 = numpy.nansum(numpy.abs(meteorVolts0)**2, axis = 0) #Power
3075 powerNet0 = numpy.nansum(numpy.abs(meteorVolts0)**2, axis = 0) #Power
3077
3076
3078 #Times reestimation
3077 #Times reestimation
3079 mStart1 = numpy.where(powerNet0[:mPeak] < meteorThresh[:mPeak])[0]
3078 mStart1 = numpy.where(powerNet0[:mPeak] < meteorThresh[:mPeak])[0]
3080 if mStart1.size > 0:
3079 if mStart1.size > 0:
3081 mStart1 = mStart1[-1] + 1
3080 mStart1 = mStart1[-1] + 1
3082
3081
3083 else:
3082 else:
3084 mStart1 = mPeak
3083 mStart1 = mPeak
3085
3084
3086 mEnd1 = numpy.where(powerNet0[mPeak:] < meteorThresh[mPeak:])[0][0] + mPeak - 1
3085 mEnd1 = numpy.where(powerNet0[mPeak:] < meteorThresh[mPeak:])[0][0] + mPeak - 1
3087 mEndDecayTime1 = numpy.where(powerNet0[mPeak:] < meteorNoise[mPeak:])[0]
3086 mEndDecayTime1 = numpy.where(powerNet0[mPeak:] < meteorNoise[mPeak:])[0]
3088 if mEndDecayTime1.size == 0:
3087 if mEndDecayTime1.size == 0:
3089 mEndDecayTime1 = powerNet0.size
3088 mEndDecayTime1 = powerNet0.size
3090 else:
3089 else:
3091 mEndDecayTime1 = mEndDecayTime1[0] + mPeak - 1
3090 mEndDecayTime1 = mEndDecayTime1[0] + mPeak - 1
3092 # mPeak1 = meteorVolts0[mStart1:mEnd1 + 1].argmax()
3091 # mPeak1 = meteorVolts0[mStart1:mEnd1 + 1].argmax()
3093
3092
3094 #meteorVolts1.- all Channels, from start to end
3093 #meteorVolts1.- all Channels, from start to end
3095 meteorVolts1 = meteorVolts0[:,mStart1:mEnd1 + 1]
3094 meteorVolts1 = meteorVolts0[:,mStart1:mEnd1 + 1]
3096 meteorVolts2 = meteorVolts0[:,mPeak + lag:mEnd1 + 1]
3095 meteorVolts2 = meteorVolts0[:,mPeak + lag:mEnd1 + 1]
3097 if meteorVolts2.shape[1] == 0:
3096 if meteorVolts2.shape[1] == 0:
3098 meteorVolts2 = meteorVolts0[:,mPeak:mEnd1 + 1]
3097 meteorVolts2 = meteorVolts0[:,mPeak:mEnd1 + 1]
3099 meteorVolts1 = meteorVolts1.reshape(meteorVolts1.shape[0], meteorVolts1.shape[1], 1)
3098 meteorVolts1 = meteorVolts1.reshape(meteorVolts1.shape[0], meteorVolts1.shape[1], 1)
3100 meteorVolts2 = meteorVolts2.reshape(meteorVolts2.shape[0], meteorVolts2.shape[1], 1)
3099 meteorVolts2 = meteorVolts2.reshape(meteorVolts2.shape[0], meteorVolts2.shape[1], 1)
3101 ##################### END PARAMETERS REESTIMATION #########################
3100 ##################### END PARAMETERS REESTIMATION #########################
3102
3101
3103 ##################### 3.8 PHASE DIFFERENCE REESTIMATION ########################
3102 ##################### 3.8 PHASE DIFFERENCE REESTIMATION ########################
3104 # if mEnd1 - mStart1 > 4: #Error Number 6: echo less than 5 samples long; too short for analysis
3103 # if mEnd1 - mStart1 > 4: #Error Number 6: echo less than 5 samples long; too short for analysis
3105 if meteorVolts2.shape[1] > 0:
3104 if meteorVolts2.shape[1] > 0:
3106 #Phase Difference re-estimation
3105 #Phase Difference re-estimation
3107 phaseDiff1, phaseDiffint = self.__estimatePhaseDifference(meteorVolts2, pairslist1) #Phase Difference Estimation
3106 phaseDiff1, phaseDiffint = self.__estimatePhaseDifference(meteorVolts2, pairslist1) #Phase Difference Estimation
3108 # phaseDiff1, phaseDiffint = self.estimatePhaseDifference(meteorVolts2, pairslist)
3107 # phaseDiff1, phaseDiffint = self.estimatePhaseDifference(meteorVolts2, pairslist)
3109 meteorVolts2 = meteorVolts2.reshape(meteorVolts2.shape[0], meteorVolts2.shape[1])
3108 meteorVolts2 = meteorVolts2.reshape(meteorVolts2.shape[0], meteorVolts2.shape[1])
3110 phaseDiff11 = numpy.reshape(phaseDiff1, (phaseDiff1.shape[0],1))
3109 phaseDiff11 = numpy.reshape(phaseDiff1, (phaseDiff1.shape[0],1))
3111 meteorVolts2[indSides,:] = self.__shiftPhase(meteorVolts2[indSides,:], phaseDiff11[0:4]) #Phase Shifting
3110 meteorVolts2[indSides,:] = self.__shiftPhase(meteorVolts2[indSides,:], phaseDiff11[0:4]) #Phase Shifting
3112
3111
3113 #Phase Difference RMS
3112 #Phase Difference RMS
3114 phaseRMS1 = numpy.sqrt(numpy.mean(numpy.square(phaseDiff1)))
3113 phaseRMS1 = numpy.sqrt(numpy.mean(numpy.square(phaseDiff1)))
3115 powerNet1 = numpy.nansum(numpy.abs(meteorVolts1[:,:])**2,0)
3114 powerNet1 = numpy.nansum(numpy.abs(meteorVolts1[:,:])**2,0)
3116 #Data from Meteor
3115 #Data from Meteor
3117 mPeak1 = powerNet1.argmax() + mStart1
3116 mPeak1 = powerNet1.argmax() + mStart1
3118 mPeakPower1 = powerNet1.max()
3117 mPeakPower1 = powerNet1.max()
3119 noiseAux = sum(noise[mStart1:mEnd1 + 1,mHeight])
3118 noiseAux = sum(noise[mStart1:mEnd1 + 1,mHeight])
3120 mSNR1 = (sum(powerNet1)-noiseAux)/noiseAux
3119 mSNR1 = (sum(powerNet1)-noiseAux)/noiseAux
3121 Meteor1 = numpy.array([mHeight, mStart1, mPeak1, mEnd1, mPeakPower1, mSNR1, phaseRMS1])
3120 Meteor1 = numpy.array([mHeight, mStart1, mPeak1, mEnd1, mPeakPower1, mSNR1, phaseRMS1])
3122 Meteor1 = numpy.hstack((Meteor1,phaseDiffint))
3121 Meteor1 = numpy.hstack((Meteor1,phaseDiffint))
3123 PowerSeries = powerNet0[mStart1:mEndDecayTime1 + 1]
3122 PowerSeries = powerNet0[mStart1:mEndDecayTime1 + 1]
3124 #Vectorize
3123 #Vectorize
3125 meteorAux[0:7] = [mHeight, mStart1, mPeak1, mEnd1, mPeakPower1, mSNR1, phaseRMS1]
3124 meteorAux[0:7] = [mHeight, mStart1, mPeak1, mEnd1, mPeakPower1, mSNR1, phaseRMS1]
3126 meteorAux[7:11] = phaseDiffint[0:4]
3125 meteorAux[7:11] = phaseDiffint[0:4]
3127
3126
3128 #Rejection Criterions
3127 #Rejection Criterions
3129 if phaseRMS1 > thresholdPhase: #Error Number 17: Phase variation
3128 if phaseRMS1 > thresholdPhase: #Error Number 17: Phase variation
3130 meteorAux[-1] = 17
3129 meteorAux[-1] = 17
3131 elif mSNR1 < thresholdDB1: #Error Number 1: SNR < threshold dB
3130 elif mSNR1 < thresholdDB1: #Error Number 1: SNR < threshold dB
3132 meteorAux[-1] = 1
3131 meteorAux[-1] = 1
3133
3132
3134
3133
3135 else:
3134 else:
3136 meteorAux[0:4] = [mHeight, mStart, mPeak, mEnd]
3135 meteorAux[0:4] = [mHeight, mStart, mPeak, mEnd]
3137 meteorAux[-1] = 6 #Error Number 6: echo less than 5 samples long; too short for analysis
3136 meteorAux[-1] = 6 #Error Number 6: echo less than 5 samples long; too short for analysis
3138 PowerSeries = 0
3137 PowerSeries = 0
3139
3138
3140 listMeteors1.append(meteorAux)
3139 listMeteors1.append(meteorAux)
3141 listPowerSeries.append(PowerSeries)
3140 listPowerSeries.append(PowerSeries)
3142 listVoltageSeries.append(meteorVolts1)
3141 listVoltageSeries.append(meteorVolts1)
3143
3142
3144 return listMeteors1, listPowerSeries, listVoltageSeries
3143 return listMeteors1, listPowerSeries, listVoltageSeries
3145
3144
3146 def __estimateDecayTime(self, listMeteors, listPower, timeInterval, frequency):
3145 def __estimateDecayTime(self, listMeteors, listPower, timeInterval, frequency):
3147
3146
3148 threshError = 10
3147 threshError = 10
3149 #Depending if it is 30 or 50 MHz
3148 #Depending if it is 30 or 50 MHz
3150 if frequency == 30e6:
3149 if frequency == 30e6:
3151 timeLag = 45*10**-3
3150 timeLag = 45*10**-3
3152 else:
3151 else:
3153 timeLag = 15*10**-3
3152 timeLag = 15*10**-3
3154 lag = numpy.ceil(timeLag/timeInterval)
3153 lag = numpy.ceil(timeLag/timeInterval)
3155
3154
3156 listMeteors1 = []
3155 listMeteors1 = []
3157
3156
3158 for i in range(len(listMeteors)):
3157 for i in range(len(listMeteors)):
3159 meteorPower = listPower[i]
3158 meteorPower = listPower[i]
3160 meteorAux = listMeteors[i]
3159 meteorAux = listMeteors[i]
3161
3160
3162 if meteorAux[-1] == 0:
3161 if meteorAux[-1] == 0:
3163
3162
3164 try:
3163 try:
3165 indmax = meteorPower.argmax()
3164 indmax = meteorPower.argmax()
3166 indlag = indmax + lag
3165 indlag = indmax + lag
3167
3166
3168 y = meteorPower[indlag:]
3167 y = meteorPower[indlag:]
3169 x = numpy.arange(0, y.size)*timeLag
3168 x = numpy.arange(0, y.size)*timeLag
3170
3169
3171 #first guess
3170 #first guess
3172 a = y[0]
3171 a = y[0]
3173 tau = timeLag
3172 tau = timeLag
3174 #exponential fit
3173 #exponential fit
3175 popt, pcov = optimize.curve_fit(self.__exponential_function, x, y, p0 = [a, tau])
3174 popt, pcov = optimize.curve_fit(self.__exponential_function, x, y, p0 = [a, tau])
3176 y1 = self.__exponential_function(x, *popt)
3175 y1 = self.__exponential_function(x, *popt)
3177 #error estimation
3176 #error estimation
3178 error = sum((y - y1)**2)/(numpy.var(y)*(y.size - popt.size))
3177 error = sum((y - y1)**2)/(numpy.var(y)*(y.size - popt.size))
3179
3178
3180 decayTime = popt[1]
3179 decayTime = popt[1]
3181 riseTime = indmax*timeInterval
3180 riseTime = indmax*timeInterval
3182 meteorAux[11:13] = [decayTime, error]
3181 meteorAux[11:13] = [decayTime, error]
3183
3182
3184 #Table items 7, 8 and 11
3183 #Table items 7, 8 and 11
3185 if (riseTime > 0.3): #Number 7: Echo rise exceeds 0.3s
3184 if (riseTime > 0.3): #Number 7: Echo rise exceeds 0.3s
3186 meteorAux[-1] = 7
3185 meteorAux[-1] = 7
3187 elif (decayTime < 2*riseTime) : #Number 8: Echo decay time less than than twice rise time
3186 elif (decayTime < 2*riseTime) : #Number 8: Echo decay time less than than twice rise time
3188 meteorAux[-1] = 8
3187 meteorAux[-1] = 8
3189 if (error > threshError): #Number 11: Poor fit to amplitude for estimation of decay time
3188 if (error > threshError): #Number 11: Poor fit to amplitude for estimation of decay time
3190 meteorAux[-1] = 11
3189 meteorAux[-1] = 11
3191
3190
3192
3191
3193 except:
3192 except:
3194 meteorAux[-1] = 11
3193 meteorAux[-1] = 11
3195
3194
3196
3195
3197 listMeteors1.append(meteorAux)
3196 listMeteors1.append(meteorAux)
3198
3197
3199 return listMeteors1
3198 return listMeteors1
3200
3199
3201 #Exponential Function
3200 #Exponential Function
3202
3201
3203 def __exponential_function(self, x, a, tau):
3202 def __exponential_function(self, x, a, tau):
3204 y = a*numpy.exp(-x/tau)
3203 y = a*numpy.exp(-x/tau)
3205 return y
3204 return y
3206
3205
3207 def __getRadialVelocity(self, listMeteors, listVolts, radialStdThresh, pairslist, timeInterval):
3206 def __getRadialVelocity(self, listMeteors, listVolts, radialStdThresh, pairslist, timeInterval):
3208
3207
3209 pairslist1 = list(pairslist)
3208 pairslist1 = list(pairslist)
3210 pairslist1.append((0,1))
3209 pairslist1.append((0,1))
3211 pairslist1.append((3,4))
3210 pairslist1.append((3,4))
3212 numPairs = len(pairslist1)
3211 numPairs = len(pairslist1)
3213 #Time Lag
3212 #Time Lag
3214 timeLag = 45*10**-3
3213 timeLag = 45*10**-3
3215 c = 3e8
3214 c = 3e8
3216 lag = numpy.ceil(timeLag/timeInterval)
3215 lag = numpy.ceil(timeLag/timeInterval)
3217 freq = 30e6
3216 freq = 30e6
3218
3217
3219 listMeteors1 = []
3218 listMeteors1 = []
3220
3219
3221 for i in range(len(listMeteors)):
3220 for i in range(len(listMeteors)):
3222 meteorAux = listMeteors[i]
3221 meteorAux = listMeteors[i]
3223 if meteorAux[-1] == 0:
3222 if meteorAux[-1] == 0:
3224 mStart = listMeteors[i][1]
3223 mStart = listMeteors[i][1]
3225 mPeak = listMeteors[i][2]
3224 mPeak = listMeteors[i][2]
3226 mLag = mPeak - mStart + lag
3225 mLag = mPeak - mStart + lag
3227
3226
3228 #get the volt data between the start and end times of the meteor
3227 #get the volt data between the start and end times of the meteor
3229 meteorVolts = listVolts[i]
3228 meteorVolts = listVolts[i]
3230 meteorVolts = meteorVolts.reshape(meteorVolts.shape[0], meteorVolts.shape[1], 1)
3229 meteorVolts = meteorVolts.reshape(meteorVolts.shape[0], meteorVolts.shape[1], 1)
3231
3230
3232 #Get CCF
3231 #Get CCF
3233 allCCFs = self.__calculateCCF(meteorVolts, pairslist1, [-2,-1,0,1,2])
3232 allCCFs = self.__calculateCCF(meteorVolts, pairslist1, [-2,-1,0,1,2])
3234
3233
3235 #Method 2
3234 #Method 2
3236 slopes = numpy.zeros(numPairs)
3235 slopes = numpy.zeros(numPairs)
3237 time = numpy.array([-2,-1,1,2])*timeInterval
3236 time = numpy.array([-2,-1,1,2])*timeInterval
3238 angAllCCF = numpy.angle(allCCFs[:,[0,1,3,4],0])
3237 angAllCCF = numpy.angle(allCCFs[:,[0,1,3,4],0])
3239
3238
3240 #Correct phases
3239 #Correct phases
3241 derPhaseCCF = angAllCCF[:,1:] - angAllCCF[:,0:-1]
3240 derPhaseCCF = angAllCCF[:,1:] - angAllCCF[:,0:-1]
3242 indDer = numpy.where(numpy.abs(derPhaseCCF) > numpy.pi)
3241 indDer = numpy.where(numpy.abs(derPhaseCCF) > numpy.pi)
3243
3242
3244 if indDer[0].shape[0] > 0:
3243 if indDer[0].shape[0] > 0:
3245 for i in range(indDer[0].shape[0]):
3244 for i in range(indDer[0].shape[0]):
3246 signo = -numpy.sign(derPhaseCCF[indDer[0][i],indDer[1][i]])
3245 signo = -numpy.sign(derPhaseCCF[indDer[0][i],indDer[1][i]])
3247 angAllCCF[indDer[0][i],indDer[1][i]+1:] += signo*2*numpy.pi
3246 angAllCCF[indDer[0][i],indDer[1][i]+1:] += signo*2*numpy.pi
3248
3247
3249 # fit = scipy.stats.linregress(numpy.array([-2,-1,1,2])*timeInterval, numpy.array([phaseLagN2s[i],phaseLagN1s[i],phaseLag1s[i],phaseLag2s[i]]))
3248 # fit = scipy.stats.linregress(numpy.array([-2,-1,1,2])*timeInterval, numpy.array([phaseLagN2s[i],phaseLagN1s[i],phaseLag1s[i],phaseLag2s[i]]))
3250 for j in range(numPairs):
3249 for j in range(numPairs):
3251 fit = stats.linregress(time, angAllCCF[j,:])
3250 fit = stats.linregress(time, angAllCCF[j,:])
3252 slopes[j] = fit[0]
3251 slopes[j] = fit[0]
3253
3252
3254 #Remove Outlier
3253 #Remove Outlier
3255 # indOut = numpy.argmax(numpy.abs(slopes - numpy.mean(slopes)))
3254 # indOut = numpy.argmax(numpy.abs(slopes - numpy.mean(slopes)))
3256 # slopes = numpy.delete(slopes,indOut)
3255 # slopes = numpy.delete(slopes,indOut)
3257 # indOut = numpy.argmax(numpy.abs(slopes - numpy.mean(slopes)))
3256 # indOut = numpy.argmax(numpy.abs(slopes - numpy.mean(slopes)))
3258 # slopes = numpy.delete(slopes,indOut)
3257 # slopes = numpy.delete(slopes,indOut)
3259
3258
3260 radialVelocity = -numpy.mean(slopes)*(0.25/numpy.pi)*(c/freq)
3259 radialVelocity = -numpy.mean(slopes)*(0.25/numpy.pi)*(c/freq)
3261 radialError = numpy.std(slopes)*(0.25/numpy.pi)*(c/freq)
3260 radialError = numpy.std(slopes)*(0.25/numpy.pi)*(c/freq)
3262 meteorAux[-2] = radialError
3261 meteorAux[-2] = radialError
3263 meteorAux[-3] = radialVelocity
3262 meteorAux[-3] = radialVelocity
3264
3263
3265 #Setting Error
3264 #Setting Error
3266 #Number 15: Radial Drift velocity or projected horizontal velocity exceeds 200 m/s
3265 #Number 15: Radial Drift velocity or projected horizontal velocity exceeds 200 m/s
3267 if numpy.abs(radialVelocity) > 200:
3266 if numpy.abs(radialVelocity) > 200:
3268 meteorAux[-1] = 15
3267 meteorAux[-1] = 15
3269 #Number 12: Poor fit to CCF variation for estimation of radial drift velocity
3268 #Number 12: Poor fit to CCF variation for estimation of radial drift velocity
3270 elif radialError > radialStdThresh:
3269 elif radialError > radialStdThresh:
3271 meteorAux[-1] = 12
3270 meteorAux[-1] = 12
3272
3271
3273 listMeteors1.append(meteorAux)
3272 listMeteors1.append(meteorAux)
3274 return listMeteors1
3273 return listMeteors1
3275
3274
3276 def __setNewArrays(self, listMeteors, date, heiRang):
3275 def __setNewArrays(self, listMeteors, date, heiRang):
3277
3276
3278 #New arrays
3277 #New arrays
3279 arrayMeteors = numpy.array(listMeteors)
3278 arrayMeteors = numpy.array(listMeteors)
3280 arrayParameters = numpy.zeros((len(listMeteors), 13))
3279 arrayParameters = numpy.zeros((len(listMeteors), 13))
3281
3280
3282 #Date inclusion
3281 #Date inclusion
3283 # date = re.findall(r'\((.*?)\)', date)
3282 # date = re.findall(r'\((.*?)\)', date)
3284 # date = date[0].split(',')
3283 # date = date[0].split(',')
3285 # date = map(int, date)
3284 # date = map(int, date)
3286 #
3285 #
3287 # if len(date)<6:
3286 # if len(date)<6:
3288 # date.append(0)
3287 # date.append(0)
3289 #
3288 #
3290 # date = [date[0]*10000 + date[1]*100 + date[2], date[3]*10000 + date[4]*100 + date[5]]
3289 # date = [date[0]*10000 + date[1]*100 + date[2], date[3]*10000 + date[4]*100 + date[5]]
3291 # arrayDate = numpy.tile(date, (len(listMeteors), 1))
3290 # arrayDate = numpy.tile(date, (len(listMeteors), 1))
3292 arrayDate = numpy.tile(date, (len(listMeteors)))
3291 arrayDate = numpy.tile(date, (len(listMeteors)))
3293
3292
3294 #Meteor array
3293 #Meteor array
3295 # arrayMeteors[:,0] = heiRang[arrayMeteors[:,0].astype(int)]
3294 # arrayMeteors[:,0] = heiRang[arrayMeteors[:,0].astype(int)]
3296 # arrayMeteors = numpy.hstack((arrayDate, arrayMeteors))
3295 # arrayMeteors = numpy.hstack((arrayDate, arrayMeteors))
3297
3296
3298 #Parameters Array
3297 #Parameters Array
3299 arrayParameters[:,0] = arrayDate #Date
3298 arrayParameters[:,0] = arrayDate #Date
3300 arrayParameters[:,1] = heiRang[arrayMeteors[:,0].astype(int)] #Range
3299 arrayParameters[:,1] = heiRang[arrayMeteors[:,0].astype(int)] #Range
3301 arrayParameters[:,6:8] = arrayMeteors[:,-3:-1] #Radial velocity and its error
3300 arrayParameters[:,6:8] = arrayMeteors[:,-3:-1] #Radial velocity and its error
3302 arrayParameters[:,8:12] = arrayMeteors[:,7:11] #Phases
3301 arrayParameters[:,8:12] = arrayMeteors[:,7:11] #Phases
3303 arrayParameters[:,-1] = arrayMeteors[:,-1] #Error
3302 arrayParameters[:,-1] = arrayMeteors[:,-1] #Error
3304
3303
3305
3304
3306 return arrayParameters
3305 return arrayParameters
3307
3306
3308 class CorrectSMPhases(Operation):
3307 class CorrectSMPhases(Operation):
3309
3308
3310 def run(self, dataOut, phaseOffsets, hmin = 50, hmax = 150, azimuth = 45, channelPositions = None):
3309 def run(self, dataOut, phaseOffsets, hmin = 50, hmax = 150, azimuth = 45, channelPositions = None):
3311
3310
3312 arrayParameters = dataOut.data_param
3311 arrayParameters = dataOut.data_param
3313 pairsList = []
3312 pairsList = []
3314 pairx = (0,1)
3313 pairx = (0,1)
3315 pairy = (2,3)
3314 pairy = (2,3)
3316 pairsList.append(pairx)
3315 pairsList.append(pairx)
3317 pairsList.append(pairy)
3316 pairsList.append(pairy)
3318 jph = numpy.zeros(4)
3317 jph = numpy.zeros(4)
3319
3318
3320 phaseOffsets = numpy.array(phaseOffsets)*numpy.pi/180
3319 phaseOffsets = numpy.array(phaseOffsets)*numpy.pi/180
3321 # arrayParameters[:,8:12] = numpy.unwrap(arrayParameters[:,8:12] + phaseOffsets)
3320 # arrayParameters[:,8:12] = numpy.unwrap(arrayParameters[:,8:12] + phaseOffsets)
3322 arrayParameters[:,8:12] = numpy.angle(numpy.exp(1j*(arrayParameters[:,8:12] + phaseOffsets)))
3321 arrayParameters[:,8:12] = numpy.angle(numpy.exp(1j*(arrayParameters[:,8:12] + phaseOffsets)))
3323
3322
3324 meteorOps = SMOperations()
3323 meteorOps = SMOperations()
3325 if channelPositions is None:
3324 if channelPositions is None:
3326 # channelPositions = [(2.5,0), (0,2.5), (0,0), (0,4.5), (-2,0)] #T
3325 # channelPositions = [(2.5,0), (0,2.5), (0,0), (0,4.5), (-2,0)] #T
3327 channelPositions = [(4.5,2), (2,4.5), (2,2), (2,0), (0,2)] #Estrella
3326 channelPositions = [(4.5,2), (2,4.5), (2,2), (2,0), (0,2)] #Estrella
3328
3327
3329 pairslist0, distances = meteorOps.getPhasePairs(channelPositions)
3328 pairslist0, distances = meteorOps.getPhasePairs(channelPositions)
3330 h = (hmin,hmax)
3329 h = (hmin,hmax)
3331
3330
3332 arrayParameters = meteorOps.getMeteorParams(arrayParameters, azimuth, h, pairsList, distances, jph)
3331 arrayParameters = meteorOps.getMeteorParams(arrayParameters, azimuth, h, pairsList, distances, jph)
3333
3332
3334 dataOut.data_param = arrayParameters
3333 dataOut.data_param = arrayParameters
3335 return
3334 return
3336
3335
3337 class SMPhaseCalibration(Operation):
3336 class SMPhaseCalibration(Operation):
3338
3337
3339 __buffer = None
3338 __buffer = None
3340
3339
3341 __initime = None
3340 __initime = None
3342
3341
3343 __dataReady = False
3342 __dataReady = False
3344
3343
3345 __isConfig = False
3344 __isConfig = False
3346
3345
3347 def __checkTime(self, currentTime, initTime, paramInterval, outputInterval):
3346 def __checkTime(self, currentTime, initTime, paramInterval, outputInterval):
3348
3347
3349 dataTime = currentTime + paramInterval
3348 dataTime = currentTime + paramInterval
3350 deltaTime = dataTime - initTime
3349 deltaTime = dataTime - initTime
3351
3350
3352 if deltaTime >= outputInterval or deltaTime < 0:
3351 if deltaTime >= outputInterval or deltaTime < 0:
3353 return True
3352 return True
3354
3353
3355 return False
3354 return False
3356
3355
3357 def __getGammas(self, pairs, d, phases):
3356 def __getGammas(self, pairs, d, phases):
3358 gammas = numpy.zeros(2)
3357 gammas = numpy.zeros(2)
3359
3358
3360 for i in range(len(pairs)):
3359 for i in range(len(pairs)):
3361
3360
3362 pairi = pairs[i]
3361 pairi = pairs[i]
3363
3362
3364 phip3 = phases[:,pairi[0]]
3363 phip3 = phases[:,pairi[0]]
3365 d3 = d[pairi[0]]
3364 d3 = d[pairi[0]]
3366 phip2 = phases[:,pairi[1]]
3365 phip2 = phases[:,pairi[1]]
3367 d2 = d[pairi[1]]
3366 d2 = d[pairi[1]]
3368 #Calculating gamma
3367 #Calculating gamma
3369 # jdcos = alp1/(k*d1)
3368 # jdcos = alp1/(k*d1)
3370 # jgamma = numpy.angle(numpy.exp(1j*(d0*alp1/d1 - alp0)))
3369 # jgamma = numpy.angle(numpy.exp(1j*(d0*alp1/d1 - alp0)))
3371 jgamma = -phip2*d3/d2 - phip3
3370 jgamma = -phip2*d3/d2 - phip3
3372 jgamma = numpy.angle(numpy.exp(1j*jgamma))
3371 jgamma = numpy.angle(numpy.exp(1j*jgamma))
3373 # jgamma[jgamma>numpy.pi] -= 2*numpy.pi
3372 # jgamma[jgamma>numpy.pi] -= 2*numpy.pi
3374 # jgamma[jgamma<-numpy.pi] += 2*numpy.pi
3373 # jgamma[jgamma<-numpy.pi] += 2*numpy.pi
3375
3374
3376 #Revised distribution
3375 #Revised distribution
3377 jgammaArray = numpy.hstack((jgamma,jgamma+0.5*numpy.pi,jgamma-0.5*numpy.pi))
3376 jgammaArray = numpy.hstack((jgamma,jgamma+0.5*numpy.pi,jgamma-0.5*numpy.pi))
3378
3377
3379 #Histogram
3378 #Histogram
3380 nBins = 64
3379 nBins = 64
3381 rmin = -0.5*numpy.pi
3380 rmin = -0.5*numpy.pi
3382 rmax = 0.5*numpy.pi
3381 rmax = 0.5*numpy.pi
3383 phaseHisto = numpy.histogram(jgammaArray, bins=nBins, range=(rmin,rmax))
3382 phaseHisto = numpy.histogram(jgammaArray, bins=nBins, range=(rmin,rmax))
3384
3383
3385 meteorsY = phaseHisto[0]
3384 meteorsY = phaseHisto[0]
3386 phasesX = phaseHisto[1][:-1]
3385 phasesX = phaseHisto[1][:-1]
3387 width = phasesX[1] - phasesX[0]
3386 width = phasesX[1] - phasesX[0]
3388 phasesX += width/2
3387 phasesX += width/2
3389
3388
3390 #Gaussian aproximation
3389 #Gaussian aproximation
3391 bpeak = meteorsY.argmax()
3390 bpeak = meteorsY.argmax()
3392 peak = meteorsY.max()
3391 peak = meteorsY.max()
3393 jmin = bpeak - 5
3392 jmin = bpeak - 5
3394 jmax = bpeak + 5 + 1
3393 jmax = bpeak + 5 + 1
3395
3394
3396 if jmin<0:
3395 if jmin<0:
3397 jmin = 0
3396 jmin = 0
3398 jmax = 6
3397 jmax = 6
3399 elif jmax > meteorsY.size:
3398 elif jmax > meteorsY.size:
3400 jmin = meteorsY.size - 6
3399 jmin = meteorsY.size - 6
3401 jmax = meteorsY.size
3400 jmax = meteorsY.size
3402
3401
3403 x0 = numpy.array([peak,bpeak,50])
3402 x0 = numpy.array([peak,bpeak,50])
3404 coeff = optimize.leastsq(self.__residualFunction, x0, args=(meteorsY[jmin:jmax], phasesX[jmin:jmax]))
3403 coeff = optimize.leastsq(self.__residualFunction, x0, args=(meteorsY[jmin:jmax], phasesX[jmin:jmax]))
3405
3404
3406 #Gammas
3405 #Gammas
3407 gammas[i] = coeff[0][1]
3406 gammas[i] = coeff[0][1]
3408
3407
3409 return gammas
3408 return gammas
3410
3409
3411 def __residualFunction(self, coeffs, y, t):
3410 def __residualFunction(self, coeffs, y, t):
3412
3411
3413 return y - self.__gauss_function(t, coeffs)
3412 return y - self.__gauss_function(t, coeffs)
3414
3413
3415 def __gauss_function(self, t, coeffs):
3414 def __gauss_function(self, t, coeffs):
3416
3415
3417 return coeffs[0]*numpy.exp(-0.5*((t - coeffs[1]) / coeffs[2])**2)
3416 return coeffs[0]*numpy.exp(-0.5*((t - coeffs[1]) / coeffs[2])**2)
3418
3417
3419 def __getPhases(self, azimuth, h, pairsList, d, gammas, meteorsArray):
3418 def __getPhases(self, azimuth, h, pairsList, d, gammas, meteorsArray):
3420 meteorOps = SMOperations()
3419 meteorOps = SMOperations()
3421 nchan = 4
3420 nchan = 4
3422 pairx = pairsList[0] #x es 0
3421 pairx = pairsList[0] #x es 0
3423 pairy = pairsList[1] #y es 1
3422 pairy = pairsList[1] #y es 1
3424 center_xangle = 0
3423 center_xangle = 0
3425 center_yangle = 0
3424 center_yangle = 0
3426 range_angle = numpy.array([10*numpy.pi,numpy.pi,numpy.pi/2,numpy.pi/4])
3425 range_angle = numpy.array([10*numpy.pi,numpy.pi,numpy.pi/2,numpy.pi/4])
3427 ntimes = len(range_angle)
3426 ntimes = len(range_angle)
3428
3427
3429 nstepsx = 20
3428 nstepsx = 20
3430 nstepsy = 20
3429 nstepsy = 20
3431
3430
3432 for iz in range(ntimes):
3431 for iz in range(ntimes):
3433 min_xangle = -range_angle[iz]/2 + center_xangle
3432 min_xangle = -range_angle[iz]/2 + center_xangle
3434 max_xangle = range_angle[iz]/2 + center_xangle
3433 max_xangle = range_angle[iz]/2 + center_xangle
3435 min_yangle = -range_angle[iz]/2 + center_yangle
3434 min_yangle = -range_angle[iz]/2 + center_yangle
3436 max_yangle = range_angle[iz]/2 + center_yangle
3435 max_yangle = range_angle[iz]/2 + center_yangle
3437
3436
3438 inc_x = (max_xangle-min_xangle)/nstepsx
3437 inc_x = (max_xangle-min_xangle)/nstepsx
3439 inc_y = (max_yangle-min_yangle)/nstepsy
3438 inc_y = (max_yangle-min_yangle)/nstepsy
3440
3439
3441 alpha_y = numpy.arange(nstepsy)*inc_y + min_yangle
3440 alpha_y = numpy.arange(nstepsy)*inc_y + min_yangle
3442 alpha_x = numpy.arange(nstepsx)*inc_x + min_xangle
3441 alpha_x = numpy.arange(nstepsx)*inc_x + min_xangle
3443 penalty = numpy.zeros((nstepsx,nstepsy))
3442 penalty = numpy.zeros((nstepsx,nstepsy))
3444 jph_array = numpy.zeros((nchan,nstepsx,nstepsy))
3443 jph_array = numpy.zeros((nchan,nstepsx,nstepsy))
3445 jph = numpy.zeros(nchan)
3444 jph = numpy.zeros(nchan)
3446
3445
3447 # Iterations looking for the offset
3446 # Iterations looking for the offset
3448 for iy in range(int(nstepsy)):
3447 for iy in range(int(nstepsy)):
3449 for ix in range(int(nstepsx)):
3448 for ix in range(int(nstepsx)):
3450 d3 = d[pairsList[1][0]]
3449 d3 = d[pairsList[1][0]]
3451 d2 = d[pairsList[1][1]]
3450 d2 = d[pairsList[1][1]]
3452 d5 = d[pairsList[0][0]]
3451 d5 = d[pairsList[0][0]]
3453 d4 = d[pairsList[0][1]]
3452 d4 = d[pairsList[0][1]]
3454
3453
3455 alp2 = alpha_y[iy] #gamma 1
3454 alp2 = alpha_y[iy] #gamma 1
3456 alp4 = alpha_x[ix] #gamma 0
3455 alp4 = alpha_x[ix] #gamma 0
3457
3456
3458 alp3 = -alp2*d3/d2 - gammas[1]
3457 alp3 = -alp2*d3/d2 - gammas[1]
3459 alp5 = -alp4*d5/d4 - gammas[0]
3458 alp5 = -alp4*d5/d4 - gammas[0]
3460 # jph[pairy[1]] = alpha_y[iy]
3459 # jph[pairy[1]] = alpha_y[iy]
3461 # jph[pairy[0]] = -gammas[1] - alpha_y[iy]*d[pairy[1]]/d[pairy[0]]
3460 # jph[pairy[0]] = -gammas[1] - alpha_y[iy]*d[pairy[1]]/d[pairy[0]]
3462
3461
3463 # jph[pairx[1]] = alpha_x[ix]
3462 # jph[pairx[1]] = alpha_x[ix]
3464 # jph[pairx[0]] = -gammas[0] - alpha_x[ix]*d[pairx[1]]/d[pairx[0]]
3463 # jph[pairx[0]] = -gammas[0] - alpha_x[ix]*d[pairx[1]]/d[pairx[0]]
3465 jph[pairsList[0][1]] = alp4
3464 jph[pairsList[0][1]] = alp4
3466 jph[pairsList[0][0]] = alp5
3465 jph[pairsList[0][0]] = alp5
3467 jph[pairsList[1][0]] = alp3
3466 jph[pairsList[1][0]] = alp3
3468 jph[pairsList[1][1]] = alp2
3467 jph[pairsList[1][1]] = alp2
3469 jph_array[:,ix,iy] = jph
3468 jph_array[:,ix,iy] = jph
3470 # d = [2.0,2.5,2.5,2.0]
3469 # d = [2.0,2.5,2.5,2.0]
3471 #falta chequear si va a leer bien los meteoros
3470 #falta chequear si va a leer bien los meteoros
3472 meteorsArray1 = meteorOps.getMeteorParams(meteorsArray, azimuth, h, pairsList, d, jph)
3471 meteorsArray1 = meteorOps.getMeteorParams(meteorsArray, azimuth, h, pairsList, d, jph)
3473 error = meteorsArray1[:,-1]
3472 error = meteorsArray1[:,-1]
3474 ind1 = numpy.where(error==0)[0]
3473 ind1 = numpy.where(error==0)[0]
3475 penalty[ix,iy] = ind1.size
3474 penalty[ix,iy] = ind1.size
3476
3475
3477 i,j = numpy.unravel_index(penalty.argmax(), penalty.shape)
3476 i,j = numpy.unravel_index(penalty.argmax(), penalty.shape)
3478 phOffset = jph_array[:,i,j]
3477 phOffset = jph_array[:,i,j]
3479
3478
3480 center_xangle = phOffset[pairx[1]]
3479 center_xangle = phOffset[pairx[1]]
3481 center_yangle = phOffset[pairy[1]]
3480 center_yangle = phOffset[pairy[1]]
3482
3481
3483 phOffset = numpy.angle(numpy.exp(1j*jph_array[:,i,j]))
3482 phOffset = numpy.angle(numpy.exp(1j*jph_array[:,i,j]))
3484 phOffset = phOffset*180/numpy.pi
3483 phOffset = phOffset*180/numpy.pi
3485 return phOffset
3484 return phOffset
3486
3485
3487
3486
3488 def run(self, dataOut, hmin, hmax, channelPositions=None, nHours = 1):
3487 def run(self, dataOut, hmin, hmax, channelPositions=None, nHours = 1):
3489
3488
3490 dataOut.flagNoData = True
3489 dataOut.flagNoData = True
3491 self.__dataReady = False
3490 self.__dataReady = False
3492 dataOut.outputInterval = nHours*3600
3491 dataOut.outputInterval = nHours*3600
3493
3492
3494 if self.__isConfig == False:
3493 if self.__isConfig == False:
3495 # self.__initime = dataOut.datatime.replace(minute = 0, second = 0, microsecond = 03)
3494 # self.__initime = dataOut.datatime.replace(minute = 0, second = 0, microsecond = 03)
3496 #Get Initial LTC time
3495 #Get Initial LTC time
3497 self.__initime = datetime.datetime.utcfromtimestamp(dataOut.utctime)
3496 self.__initime = datetime.datetime.utcfromtimestamp(dataOut.utctime)
3498 self.__initime = (self.__initime.replace(minute = 0, second = 0, microsecond = 0) - datetime.datetime(1970, 1, 1)).total_seconds()
3497 self.__initime = (self.__initime.replace(minute = 0, second = 0, microsecond = 0) - datetime.datetime(1970, 1, 1)).total_seconds()
3499
3498
3500 self.__isConfig = True
3499 self.__isConfig = True
3501
3500
3502 if self.__buffer is None:
3501 if self.__buffer is None:
3503 self.__buffer = dataOut.data_param.copy()
3502 self.__buffer = dataOut.data_param.copy()
3504
3503
3505 else:
3504 else:
3506 self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param))
3505 self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param))
3507
3506
3508 self.__dataReady = self.__checkTime(dataOut.utctime, self.__initime, dataOut.paramInterval, dataOut.outputInterval) #Check if the buffer is ready
3507 self.__dataReady = self.__checkTime(dataOut.utctime, self.__initime, dataOut.paramInterval, dataOut.outputInterval) #Check if the buffer is ready
3509
3508
3510 if self.__dataReady:
3509 if self.__dataReady:
3511 dataOut.utctimeInit = self.__initime
3510 dataOut.utctimeInit = self.__initime
3512 self.__initime += dataOut.outputInterval #to erase time offset
3511 self.__initime += dataOut.outputInterval #to erase time offset
3513
3512
3514 freq = dataOut.frequency
3513 freq = dataOut.frequency
3515 c = dataOut.C #m/s
3514 c = dataOut.C #m/s
3516 lamb = c/freq
3515 lamb = c/freq
3517 k = 2*numpy.pi/lamb
3516 k = 2*numpy.pi/lamb
3518 azimuth = 0
3517 azimuth = 0
3519 h = (hmin, hmax)
3518 h = (hmin, hmax)
3520 # pairs = ((0,1),(2,3)) #Estrella
3519 # pairs = ((0,1),(2,3)) #Estrella
3521 # pairs = ((1,0),(2,3)) #T
3520 # pairs = ((1,0),(2,3)) #T
3522
3521
3523 if channelPositions is None:
3522 if channelPositions is None:
3524 # channelPositions = [(2.5,0), (0,2.5), (0,0), (0,4.5), (-2,0)] #T
3523 # channelPositions = [(2.5,0), (0,2.5), (0,0), (0,4.5), (-2,0)] #T
3525 channelPositions = [(4.5,2), (2,4.5), (2,2), (2,0), (0,2)] #Estrella
3524 channelPositions = [(4.5,2), (2,4.5), (2,2), (2,0), (0,2)] #Estrella
3526 meteorOps = SMOperations()
3525 meteorOps = SMOperations()
3527 pairslist0, distances = meteorOps.getPhasePairs(channelPositions)
3526 pairslist0, distances = meteorOps.getPhasePairs(channelPositions)
3528
3527
3529 #Checking correct order of pairs
3528 #Checking correct order of pairs
3530 pairs = []
3529 pairs = []
3531 if distances[1] > distances[0]:
3530 if distances[1] > distances[0]:
3532 pairs.append((1,0))
3531 pairs.append((1,0))
3533 else:
3532 else:
3534 pairs.append((0,1))
3533 pairs.append((0,1))
3535
3534
3536 if distances[3] > distances[2]:
3535 if distances[3] > distances[2]:
3537 pairs.append((3,2))
3536 pairs.append((3,2))
3538 else:
3537 else:
3539 pairs.append((2,3))
3538 pairs.append((2,3))
3540 # distances1 = [-distances[0]*lamb, distances[1]*lamb, -distances[2]*lamb, distances[3]*lamb]
3539 # distances1 = [-distances[0]*lamb, distances[1]*lamb, -distances[2]*lamb, distances[3]*lamb]
3541
3540
3542 meteorsArray = self.__buffer
3541 meteorsArray = self.__buffer
3543 error = meteorsArray[:,-1]
3542 error = meteorsArray[:,-1]
3544 boolError = (error==0)|(error==3)|(error==4)|(error==13)|(error==14)
3543 boolError = (error==0)|(error==3)|(error==4)|(error==13)|(error==14)
3545 ind1 = numpy.where(boolError)[0]
3544 ind1 = numpy.where(boolError)[0]
3546 meteorsArray = meteorsArray[ind1,:]
3545 meteorsArray = meteorsArray[ind1,:]
3547 meteorsArray[:,-1] = 0
3546 meteorsArray[:,-1] = 0
3548 phases = meteorsArray[:,8:12]
3547 phases = meteorsArray[:,8:12]
3549
3548
3550 #Calculate Gammas
3549 #Calculate Gammas
3551 gammas = self.__getGammas(pairs, distances, phases)
3550 gammas = self.__getGammas(pairs, distances, phases)
3552 # gammas = numpy.array([-21.70409463,45.76935864])*numpy.pi/180
3551 # gammas = numpy.array([-21.70409463,45.76935864])*numpy.pi/180
3553 #Calculate Phases
3552 #Calculate Phases
3554 phasesOff = self.__getPhases(azimuth, h, pairs, distances, gammas, meteorsArray)
3553 phasesOff = self.__getPhases(azimuth, h, pairs, distances, gammas, meteorsArray)
3555 phasesOff = phasesOff.reshape((1,phasesOff.size))
3554 phasesOff = phasesOff.reshape((1,phasesOff.size))
3556 dataOut.data_output = -phasesOff
3555 dataOut.data_output = -phasesOff
3557 dataOut.flagNoData = False
3556 dataOut.flagNoData = False
3558 self.__buffer = None
3557 self.__buffer = None
3559
3558
3560
3559
3561 return
3560 return
3562
3561
3563 class SMOperations():
3562 class SMOperations():
3564
3563
3565 def __init__(self):
3564 def __init__(self):
3566
3565
3567 return
3566 return
3568
3567
3569 def getMeteorParams(self, arrayParameters0, azimuth, h, pairsList, distances, jph):
3568 def getMeteorParams(self, arrayParameters0, azimuth, h, pairsList, distances, jph):
3570
3569
3571 arrayParameters = arrayParameters0.copy()
3570 arrayParameters = arrayParameters0.copy()
3572 hmin = h[0]
3571 hmin = h[0]
3573 hmax = h[1]
3572 hmax = h[1]
3574
3573
3575 #Calculate AOA (Error N 3, 4)
3574 #Calculate AOA (Error N 3, 4)
3576 #JONES ET AL. 1998
3575 #JONES ET AL. 1998
3577 AOAthresh = numpy.pi/8
3576 AOAthresh = numpy.pi/8
3578 error = arrayParameters[:,-1]
3577 error = arrayParameters[:,-1]
3579 phases = -arrayParameters[:,8:12] + jph
3578 phases = -arrayParameters[:,8:12] + jph
3580 # phases = numpy.unwrap(phases)
3579 # phases = numpy.unwrap(phases)
3581 arrayParameters[:,3:6], arrayParameters[:,-1] = self.__getAOA(phases, pairsList, distances, error, AOAthresh, azimuth)
3580 arrayParameters[:,3:6], arrayParameters[:,-1] = self.__getAOA(phases, pairsList, distances, error, AOAthresh, azimuth)
3582
3581
3583 #Calculate Heights (Error N 13 and 14)
3582 #Calculate Heights (Error N 13 and 14)
3584 error = arrayParameters[:,-1]
3583 error = arrayParameters[:,-1]
3585 Ranges = arrayParameters[:,1]
3584 Ranges = arrayParameters[:,1]
3586 zenith = arrayParameters[:,4]
3585 zenith = arrayParameters[:,4]
3587 arrayParameters[:,2], arrayParameters[:,-1] = self.__getHeights(Ranges, zenith, error, hmin, hmax)
3586 arrayParameters[:,2], arrayParameters[:,-1] = self.__getHeights(Ranges, zenith, error, hmin, hmax)
3588
3587
3589 #----------------------- Get Final data ------------------------------------
3588 #----------------------- Get Final data ------------------------------------
3590 # error = arrayParameters[:,-1]
3589 # error = arrayParameters[:,-1]
3591 # ind1 = numpy.where(error==0)[0]
3590 # ind1 = numpy.where(error==0)[0]
3592 # arrayParameters = arrayParameters[ind1,:]
3591 # arrayParameters = arrayParameters[ind1,:]
3593
3592
3594 return arrayParameters
3593 return arrayParameters
3595
3594
3596 def __getAOA(self, phases, pairsList, directions, error, AOAthresh, azimuth):
3595 def __getAOA(self, phases, pairsList, directions, error, AOAthresh, azimuth):
3597
3596
3598 arrayAOA = numpy.zeros((phases.shape[0],3))
3597 arrayAOA = numpy.zeros((phases.shape[0],3))
3599 cosdir0, cosdir = self.__getDirectionCosines(phases, pairsList,directions)
3598 cosdir0, cosdir = self.__getDirectionCosines(phases, pairsList,directions)
3600
3599
3601 arrayAOA[:,:2] = self.__calculateAOA(cosdir, azimuth)
3600 arrayAOA[:,:2] = self.__calculateAOA(cosdir, azimuth)
3602 cosDirError = numpy.sum(numpy.abs(cosdir0 - cosdir), axis = 1)
3601 cosDirError = numpy.sum(numpy.abs(cosdir0 - cosdir), axis = 1)
3603 arrayAOA[:,2] = cosDirError
3602 arrayAOA[:,2] = cosDirError
3604
3603
3605 azimuthAngle = arrayAOA[:,0]
3604 azimuthAngle = arrayAOA[:,0]
3606 zenithAngle = arrayAOA[:,1]
3605 zenithAngle = arrayAOA[:,1]
3607
3606
3608 #Setting Error
3607 #Setting Error
3609 indError = numpy.where(numpy.logical_or(error == 3, error == 4))[0]
3608 indError = numpy.where(numpy.logical_or(error == 3, error == 4))[0]
3610 error[indError] = 0
3609 error[indError] = 0
3611 #Number 3: AOA not fesible
3610 #Number 3: AOA not fesible
3612 indInvalid = numpy.where(numpy.logical_and((numpy.logical_or(numpy.isnan(zenithAngle), numpy.isnan(azimuthAngle))),error == 0))[0]
3611 indInvalid = numpy.where(numpy.logical_and((numpy.logical_or(numpy.isnan(zenithAngle), numpy.isnan(azimuthAngle))),error == 0))[0]
3613 error[indInvalid] = 3
3612 error[indInvalid] = 3
3614 #Number 4: Large difference in AOAs obtained from different antenna baselines
3613 #Number 4: Large difference in AOAs obtained from different antenna baselines
3615 indInvalid = numpy.where(numpy.logical_and(cosDirError > AOAthresh,error == 0))[0]
3614 indInvalid = numpy.where(numpy.logical_and(cosDirError > AOAthresh,error == 0))[0]
3616 error[indInvalid] = 4
3615 error[indInvalid] = 4
3617 return arrayAOA, error
3616 return arrayAOA, error
3618
3617
3619 def __getDirectionCosines(self, arrayPhase, pairsList, distances):
3618 def __getDirectionCosines(self, arrayPhase, pairsList, distances):
3620
3619
3621 #Initializing some variables
3620 #Initializing some variables
3622 ang_aux = numpy.array([-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8])*2*numpy.pi
3621 ang_aux = numpy.array([-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8])*2*numpy.pi
3623 ang_aux = ang_aux.reshape(1,ang_aux.size)
3622 ang_aux = ang_aux.reshape(1,ang_aux.size)
3624
3623
3625 cosdir = numpy.zeros((arrayPhase.shape[0],2))
3624 cosdir = numpy.zeros((arrayPhase.shape[0],2))
3626 cosdir0 = numpy.zeros((arrayPhase.shape[0],2))
3625 cosdir0 = numpy.zeros((arrayPhase.shape[0],2))
3627
3626
3628
3627
3629 for i in range(2):
3628 for i in range(2):
3630 ph0 = arrayPhase[:,pairsList[i][0]]
3629 ph0 = arrayPhase[:,pairsList[i][0]]
3631 ph1 = arrayPhase[:,pairsList[i][1]]
3630 ph1 = arrayPhase[:,pairsList[i][1]]
3632 d0 = distances[pairsList[i][0]]
3631 d0 = distances[pairsList[i][0]]
3633 d1 = distances[pairsList[i][1]]
3632 d1 = distances[pairsList[i][1]]
3634
3633
3635 ph0_aux = ph0 + ph1
3634 ph0_aux = ph0 + ph1
3636 ph0_aux = numpy.angle(numpy.exp(1j*ph0_aux))
3635 ph0_aux = numpy.angle(numpy.exp(1j*ph0_aux))
3637 # ph0_aux[ph0_aux > numpy.pi] -= 2*numpy.pi
3636 # ph0_aux[ph0_aux > numpy.pi] -= 2*numpy.pi
3638 # ph0_aux[ph0_aux < -numpy.pi] += 2*numpy.pi
3637 # ph0_aux[ph0_aux < -numpy.pi] += 2*numpy.pi
3639 #First Estimation
3638 #First Estimation
3640 cosdir0[:,i] = (ph0_aux)/(2*numpy.pi*(d0 - d1))
3639 cosdir0[:,i] = (ph0_aux)/(2*numpy.pi*(d0 - d1))
3641
3640
3642 #Most-Accurate Second Estimation
3641 #Most-Accurate Second Estimation
3643 phi1_aux = ph0 - ph1
3642 phi1_aux = ph0 - ph1
3644 phi1_aux = phi1_aux.reshape(phi1_aux.size,1)
3643 phi1_aux = phi1_aux.reshape(phi1_aux.size,1)
3645 #Direction Cosine 1
3644 #Direction Cosine 1
3646 cosdir1 = (phi1_aux + ang_aux)/(2*numpy.pi*(d0 + d1))
3645 cosdir1 = (phi1_aux + ang_aux)/(2*numpy.pi*(d0 + d1))
3647
3646
3648 #Searching the correct Direction Cosine
3647 #Searching the correct Direction Cosine
3649 cosdir0_aux = cosdir0[:,i]
3648 cosdir0_aux = cosdir0[:,i]
3650 cosdir0_aux = cosdir0_aux.reshape(cosdir0_aux.size,1)
3649 cosdir0_aux = cosdir0_aux.reshape(cosdir0_aux.size,1)
3651 #Minimum Distance
3650 #Minimum Distance
3652 cosDiff = (cosdir1 - cosdir0_aux)**2
3651 cosDiff = (cosdir1 - cosdir0_aux)**2
3653 indcos = cosDiff.argmin(axis = 1)
3652 indcos = cosDiff.argmin(axis = 1)
3654 #Saving Value obtained
3653 #Saving Value obtained
3655 cosdir[:,i] = cosdir1[numpy.arange(len(indcos)),indcos]
3654 cosdir[:,i] = cosdir1[numpy.arange(len(indcos)),indcos]
3656
3655
3657 return cosdir0, cosdir
3656 return cosdir0, cosdir
3658
3657
3659 def __calculateAOA(self, cosdir, azimuth):
3658 def __calculateAOA(self, cosdir, azimuth):
3660 cosdirX = cosdir[:,0]
3659 cosdirX = cosdir[:,0]
3661 cosdirY = cosdir[:,1]
3660 cosdirY = cosdir[:,1]
3662
3661
3663 zenithAngle = numpy.arccos(numpy.sqrt(1 - cosdirX**2 - cosdirY**2))*180/numpy.pi
3662 zenithAngle = numpy.arccos(numpy.sqrt(1 - cosdirX**2 - cosdirY**2))*180/numpy.pi
3664 azimuthAngle = numpy.arctan2(cosdirX,cosdirY)*180/numpy.pi + azimuth#0 deg north, 90 deg east
3663 azimuthAngle = numpy.arctan2(cosdirX,cosdirY)*180/numpy.pi + azimuth#0 deg north, 90 deg east
3665 angles = numpy.vstack((azimuthAngle, zenithAngle)).transpose()
3664 angles = numpy.vstack((azimuthAngle, zenithAngle)).transpose()
3666
3665
3667 return angles
3666 return angles
3668
3667
3669 def __getHeights(self, Ranges, zenith, error, minHeight, maxHeight):
3668 def __getHeights(self, Ranges, zenith, error, minHeight, maxHeight):
3670
3669
3671 Ramb = 375 #Ramb = c/(2*PRF)
3670 Ramb = 375 #Ramb = c/(2*PRF)
3672 Re = 6371 #Earth Radius
3671 Re = 6371 #Earth Radius
3673 heights = numpy.zeros(Ranges.shape)
3672 heights = numpy.zeros(Ranges.shape)
3674
3673
3675 R_aux = numpy.array([0,1,2])*Ramb
3674 R_aux = numpy.array([0,1,2])*Ramb
3676 R_aux = R_aux.reshape(1,R_aux.size)
3675 R_aux = R_aux.reshape(1,R_aux.size)
3677
3676
3678 Ranges = Ranges.reshape(Ranges.size,1)
3677 Ranges = Ranges.reshape(Ranges.size,1)
3679
3678
3680 Ri = Ranges + R_aux
3679 Ri = Ranges + R_aux
3681 hi = numpy.sqrt(Re**2 + Ri**2 + (2*Re*numpy.cos(zenith*numpy.pi/180)*Ri.transpose()).transpose()) - Re
3680 hi = numpy.sqrt(Re**2 + Ri**2 + (2*Re*numpy.cos(zenith*numpy.pi/180)*Ri.transpose()).transpose()) - Re
3682
3681
3683 #Check if there is a height between 70 and 110 km
3682 #Check if there is a height between 70 and 110 km
3684 h_bool = numpy.sum(numpy.logical_and(hi > minHeight, hi < maxHeight), axis = 1)
3683 h_bool = numpy.sum(numpy.logical_and(hi > minHeight, hi < maxHeight), axis = 1)
3685 ind_h = numpy.where(h_bool == 1)[0]
3684 ind_h = numpy.where(h_bool == 1)[0]
3686
3685
3687 hCorr = hi[ind_h, :]
3686 hCorr = hi[ind_h, :]
3688 ind_hCorr = numpy.where(numpy.logical_and(hi > minHeight, hi < maxHeight))
3687 ind_hCorr = numpy.where(numpy.logical_and(hi > minHeight, hi < maxHeight))
3689
3688
3690 hCorr = hi[ind_hCorr][:len(ind_h)]
3689 hCorr = hi[ind_hCorr][:len(ind_h)]
3691 heights[ind_h] = hCorr
3690 heights[ind_h] = hCorr
3692
3691
3693 #Setting Error
3692 #Setting Error
3694 #Number 13: Height unresolvable echo: not valid height within 70 to 110 km
3693 #Number 13: Height unresolvable echo: not valid height within 70 to 110 km
3695 #Number 14: Height ambiguous echo: more than one possible height within 70 to 110 km
3694 #Number 14: Height ambiguous echo: more than one possible height within 70 to 110 km
3696 indError = numpy.where(numpy.logical_or(error == 13, error == 14))[0]
3695 indError = numpy.where(numpy.logical_or(error == 13, error == 14))[0]
3697 error[indError] = 0
3696 error[indError] = 0
3698 indInvalid2 = numpy.where(numpy.logical_and(h_bool > 1, error == 0))[0]
3697 indInvalid2 = numpy.where(numpy.logical_and(h_bool > 1, error == 0))[0]
3699 error[indInvalid2] = 14
3698 error[indInvalid2] = 14
3700 indInvalid1 = numpy.where(numpy.logical_and(h_bool == 0, error == 0))[0]
3699 indInvalid1 = numpy.where(numpy.logical_and(h_bool == 0, error == 0))[0]
3701 error[indInvalid1] = 13
3700 error[indInvalid1] = 13
3702
3701
3703 return heights, error
3702 return heights, error
3704
3703
3705 def getPhasePairs(self, channelPositions):
3704 def getPhasePairs(self, channelPositions):
3706 chanPos = numpy.array(channelPositions)
3705 chanPos = numpy.array(channelPositions)
3707 listOper = list(itertools.combinations(list(range(5)),2))
3706 listOper = list(itertools.combinations(list(range(5)),2))
3708
3707
3709 distances = numpy.zeros(4)
3708 distances = numpy.zeros(4)
3710 axisX = []
3709 axisX = []
3711 axisY = []
3710 axisY = []
3712 distX = numpy.zeros(3)
3711 distX = numpy.zeros(3)
3713 distY = numpy.zeros(3)
3712 distY = numpy.zeros(3)
3714 ix = 0
3713 ix = 0
3715 iy = 0
3714 iy = 0
3716
3715
3717 pairX = numpy.zeros((2,2))
3716 pairX = numpy.zeros((2,2))
3718 pairY = numpy.zeros((2,2))
3717 pairY = numpy.zeros((2,2))
3719
3718
3720 for i in range(len(listOper)):
3719 for i in range(len(listOper)):
3721 pairi = listOper[i]
3720 pairi = listOper[i]
3722
3721
3723 posDif = numpy.abs(chanPos[pairi[0],:] - chanPos[pairi[1],:])
3722 posDif = numpy.abs(chanPos[pairi[0],:] - chanPos[pairi[1],:])
3724
3723
3725 if posDif[0] == 0:
3724 if posDif[0] == 0:
3726 axisY.append(pairi)
3725 axisY.append(pairi)
3727 distY[iy] = posDif[1]
3726 distY[iy] = posDif[1]
3728 iy += 1
3727 iy += 1
3729 elif posDif[1] == 0:
3728 elif posDif[1] == 0:
3730 axisX.append(pairi)
3729 axisX.append(pairi)
3731 distX[ix] = posDif[0]
3730 distX[ix] = posDif[0]
3732 ix += 1
3731 ix += 1
3733
3732
3734 for i in range(2):
3733 for i in range(2):
3735 if i==0:
3734 if i==0:
3736 dist0 = distX
3735 dist0 = distX
3737 axis0 = axisX
3736 axis0 = axisX
3738 else:
3737 else:
3739 dist0 = distY
3738 dist0 = distY
3740 axis0 = axisY
3739 axis0 = axisY
3741
3740
3742 side = numpy.argsort(dist0)[:-1]
3741 side = numpy.argsort(dist0)[:-1]
3743 axis0 = numpy.array(axis0)[side,:]
3742 axis0 = numpy.array(axis0)[side,:]
3744 chanC = int(numpy.intersect1d(axis0[0,:], axis0[1,:])[0])
3743 chanC = int(numpy.intersect1d(axis0[0,:], axis0[1,:])[0])
3745 axis1 = numpy.unique(numpy.reshape(axis0,4))
3744 axis1 = numpy.unique(numpy.reshape(axis0,4))
3746 side = axis1[axis1 != chanC]
3745 side = axis1[axis1 != chanC]
3747 diff1 = chanPos[chanC,i] - chanPos[side[0],i]
3746 diff1 = chanPos[chanC,i] - chanPos[side[0],i]
3748 diff2 = chanPos[chanC,i] - chanPos[side[1],i]
3747 diff2 = chanPos[chanC,i] - chanPos[side[1],i]
3749 if diff1<0:
3748 if diff1<0:
3750 chan2 = side[0]
3749 chan2 = side[0]
3751 d2 = numpy.abs(diff1)
3750 d2 = numpy.abs(diff1)
3752 chan1 = side[1]
3751 chan1 = side[1]
3753 d1 = numpy.abs(diff2)
3752 d1 = numpy.abs(diff2)
3754 else:
3753 else:
3755 chan2 = side[1]
3754 chan2 = side[1]
3756 d2 = numpy.abs(diff2)
3755 d2 = numpy.abs(diff2)
3757 chan1 = side[0]
3756 chan1 = side[0]
3758 d1 = numpy.abs(diff1)
3757 d1 = numpy.abs(diff1)
3759
3758
3760 if i==0:
3759 if i==0:
3761 chanCX = chanC
3760 chanCX = chanC
3762 chan1X = chan1
3761 chan1X = chan1
3763 chan2X = chan2
3762 chan2X = chan2
3764 distances[0:2] = numpy.array([d1,d2])
3763 distances[0:2] = numpy.array([d1,d2])
3765 else:
3764 else:
3766 chanCY = chanC
3765 chanCY = chanC
3767 chan1Y = chan1
3766 chan1Y = chan1
3768 chan2Y = chan2
3767 chan2Y = chan2
3769 distances[2:4] = numpy.array([d1,d2])
3768 distances[2:4] = numpy.array([d1,d2])
3770 # axisXsides = numpy.reshape(axisX[ix,:],4)
3769 # axisXsides = numpy.reshape(axisX[ix,:],4)
3771 #
3770 #
3772 # channelCentX = int(numpy.intersect1d(pairX[0,:], pairX[1,:])[0])
3771 # channelCentX = int(numpy.intersect1d(pairX[0,:], pairX[1,:])[0])
3773 # channelCentY = int(numpy.intersect1d(pairY[0,:], pairY[1,:])[0])
3772 # channelCentY = int(numpy.intersect1d(pairY[0,:], pairY[1,:])[0])
3774 #
3773 #
3775 # ind25X = numpy.where(pairX[0,:] != channelCentX)[0][0]
3774 # ind25X = numpy.where(pairX[0,:] != channelCentX)[0][0]
3776 # ind20X = numpy.where(pairX[1,:] != channelCentX)[0][0]
3775 # ind20X = numpy.where(pairX[1,:] != channelCentX)[0][0]
3777 # channel25X = int(pairX[0,ind25X])
3776 # channel25X = int(pairX[0,ind25X])
3778 # channel20X = int(pairX[1,ind20X])
3777 # channel20X = int(pairX[1,ind20X])
3779 # ind25Y = numpy.where(pairY[0,:] != channelCentY)[0][0]
3778 # ind25Y = numpy.where(pairY[0,:] != channelCentY)[0][0]
3780 # ind20Y = numpy.where(pairY[1,:] != channelCentY)[0][0]
3779 # ind20Y = numpy.where(pairY[1,:] != channelCentY)[0][0]
3781 # channel25Y = int(pairY[0,ind25Y])
3780 # channel25Y = int(pairY[0,ind25Y])
3782 # channel20Y = int(pairY[1,ind20Y])
3781 # channel20Y = int(pairY[1,ind20Y])
3783
3782
3784 # pairslist = [(channelCentX, channel25X),(channelCentX, channel20X),(channelCentY,channel25Y),(channelCentY, channel20Y)]
3783 # pairslist = [(channelCentX, channel25X),(channelCentX, channel20X),(channelCentY,channel25Y),(channelCentY, channel20Y)]
3785 pairslist = [(chanCX, chan1X),(chanCX, chan2X),(chanCY,chan1Y),(chanCY, chan2Y)]
3784 pairslist = [(chanCX, chan1X),(chanCX, chan2X),(chanCY,chan1Y),(chanCY, chan2Y)]
3786
3785
3787 return pairslist, distances
3786 return pairslist, distances
3788 # def __getAOA(self, phases, pairsList, error, AOAthresh, azimuth):
3787 # def __getAOA(self, phases, pairsList, error, AOAthresh, azimuth):
3789 #
3788 #
3790 # arrayAOA = numpy.zeros((phases.shape[0],3))
3789 # arrayAOA = numpy.zeros((phases.shape[0],3))
3791 # cosdir0, cosdir = self.__getDirectionCosines(phases, pairsList)
3790 # cosdir0, cosdir = self.__getDirectionCosines(phases, pairsList)
3792 #
3791 #
3793 # arrayAOA[:,:2] = self.__calculateAOA(cosdir, azimuth)
3792 # arrayAOA[:,:2] = self.__calculateAOA(cosdir, azimuth)
3794 # cosDirError = numpy.sum(numpy.abs(cosdir0 - cosdir), axis = 1)
3793 # cosDirError = numpy.sum(numpy.abs(cosdir0 - cosdir), axis = 1)
3795 # arrayAOA[:,2] = cosDirError
3794 # arrayAOA[:,2] = cosDirError
3796 #
3795 #
3797 # azimuthAngle = arrayAOA[:,0]
3796 # azimuthAngle = arrayAOA[:,0]
3798 # zenithAngle = arrayAOA[:,1]
3797 # zenithAngle = arrayAOA[:,1]
3799 #
3798 #
3800 # #Setting Error
3799 # #Setting Error
3801 # #Number 3: AOA not fesible
3800 # #Number 3: AOA not fesible
3802 # indInvalid = numpy.where(numpy.logical_and((numpy.logical_or(numpy.isnan(zenithAngle), numpy.isnan(azimuthAngle))),error == 0))[0]
3801 # indInvalid = numpy.where(numpy.logical_and((numpy.logical_or(numpy.isnan(zenithAngle), numpy.isnan(azimuthAngle))),error == 0))[0]
3803 # error[indInvalid] = 3
3802 # error[indInvalid] = 3
3804 # #Number 4: Large difference in AOAs obtained from different antenna baselines
3803 # #Number 4: Large difference in AOAs obtained from different antenna baselines
3805 # indInvalid = numpy.where(numpy.logical_and(cosDirError > AOAthresh,error == 0))[0]
3804 # indInvalid = numpy.where(numpy.logical_and(cosDirError > AOAthresh,error == 0))[0]
3806 # error[indInvalid] = 4
3805 # error[indInvalid] = 4
3807 # return arrayAOA, error
3806 # return arrayAOA, error
3808 #
3807 #
3809 # def __getDirectionCosines(self, arrayPhase, pairsList):
3808 # def __getDirectionCosines(self, arrayPhase, pairsList):
3810 #
3809 #
3811 # #Initializing some variables
3810 # #Initializing some variables
3812 # ang_aux = numpy.array([-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8])*2*numpy.pi
3811 # ang_aux = numpy.array([-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8])*2*numpy.pi
3813 # ang_aux = ang_aux.reshape(1,ang_aux.size)
3812 # ang_aux = ang_aux.reshape(1,ang_aux.size)
3814 #
3813 #
3815 # cosdir = numpy.zeros((arrayPhase.shape[0],2))
3814 # cosdir = numpy.zeros((arrayPhase.shape[0],2))
3816 # cosdir0 = numpy.zeros((arrayPhase.shape[0],2))
3815 # cosdir0 = numpy.zeros((arrayPhase.shape[0],2))
3817 #
3816 #
3818 #
3817 #
3819 # for i in range(2):
3818 # for i in range(2):
3820 # #First Estimation
3819 # #First Estimation
3821 # phi0_aux = arrayPhase[:,pairsList[i][0]] + arrayPhase[:,pairsList[i][1]]
3820 # phi0_aux = arrayPhase[:,pairsList[i][0]] + arrayPhase[:,pairsList[i][1]]
3822 # #Dealias
3821 # #Dealias
3823 # indcsi = numpy.where(phi0_aux > numpy.pi)
3822 # indcsi = numpy.where(phi0_aux > numpy.pi)
3824 # phi0_aux[indcsi] -= 2*numpy.pi
3823 # phi0_aux[indcsi] -= 2*numpy.pi
3825 # indcsi = numpy.where(phi0_aux < -numpy.pi)
3824 # indcsi = numpy.where(phi0_aux < -numpy.pi)
3826 # phi0_aux[indcsi] += 2*numpy.pi
3825 # phi0_aux[indcsi] += 2*numpy.pi
3827 # #Direction Cosine 0
3826 # #Direction Cosine 0
3828 # cosdir0[:,i] = -(phi0_aux)/(2*numpy.pi*0.5)
3827 # cosdir0[:,i] = -(phi0_aux)/(2*numpy.pi*0.5)
3829 #
3828 #
3830 # #Most-Accurate Second Estimation
3829 # #Most-Accurate Second Estimation
3831 # phi1_aux = arrayPhase[:,pairsList[i][0]] - arrayPhase[:,pairsList[i][1]]
3830 # phi1_aux = arrayPhase[:,pairsList[i][0]] - arrayPhase[:,pairsList[i][1]]
3832 # phi1_aux = phi1_aux.reshape(phi1_aux.size,1)
3831 # phi1_aux = phi1_aux.reshape(phi1_aux.size,1)
3833 # #Direction Cosine 1
3832 # #Direction Cosine 1
3834 # cosdir1 = -(phi1_aux + ang_aux)/(2*numpy.pi*4.5)
3833 # cosdir1 = -(phi1_aux + ang_aux)/(2*numpy.pi*4.5)
3835 #
3834 #
3836 # #Searching the correct Direction Cosine
3835 # #Searching the correct Direction Cosine
3837 # cosdir0_aux = cosdir0[:,i]
3836 # cosdir0_aux = cosdir0[:,i]
3838 # cosdir0_aux = cosdir0_aux.reshape(cosdir0_aux.size,1)
3837 # cosdir0_aux = cosdir0_aux.reshape(cosdir0_aux.size,1)
3839 # #Minimum Distance
3838 # #Minimum Distance
3840 # cosDiff = (cosdir1 - cosdir0_aux)**2
3839 # cosDiff = (cosdir1 - cosdir0_aux)**2
3841 # indcos = cosDiff.argmin(axis = 1)
3840 # indcos = cosDiff.argmin(axis = 1)
3842 # #Saving Value obtained
3841 # #Saving Value obtained
3843 # cosdir[:,i] = cosdir1[numpy.arange(len(indcos)),indcos]
3842 # cosdir[:,i] = cosdir1[numpy.arange(len(indcos)),indcos]
3844 #
3843 #
3845 # return cosdir0, cosdir
3844 # return cosdir0, cosdir
3846 #
3845 #
3847 # def __calculateAOA(self, cosdir, azimuth):
3846 # def __calculateAOA(self, cosdir, azimuth):
3848 # cosdirX = cosdir[:,0]
3847 # cosdirX = cosdir[:,0]
3849 # cosdirY = cosdir[:,1]
3848 # cosdirY = cosdir[:,1]
3850 #
3849 #
3851 # zenithAngle = numpy.arccos(numpy.sqrt(1 - cosdirX**2 - cosdirY**2))*180/numpy.pi
3850 # zenithAngle = numpy.arccos(numpy.sqrt(1 - cosdirX**2 - cosdirY**2))*180/numpy.pi
3852 # azimuthAngle = numpy.arctan2(cosdirX,cosdirY)*180/numpy.pi + azimuth #0 deg north, 90 deg east
3851 # azimuthAngle = numpy.arctan2(cosdirX,cosdirY)*180/numpy.pi + azimuth #0 deg north, 90 deg east
3853 # angles = numpy.vstack((azimuthAngle, zenithAngle)).transpose()
3852 # angles = numpy.vstack((azimuthAngle, zenithAngle)).transpose()
3854 #
3853 #
3855 # return angles
3854 # return angles
3856 #
3855 #
3857 # def __getHeights(self, Ranges, zenith, error, minHeight, maxHeight):
3856 # def __getHeights(self, Ranges, zenith, error, minHeight, maxHeight):
3858 #
3857 #
3859 # Ramb = 375 #Ramb = c/(2*PRF)
3858 # Ramb = 375 #Ramb = c/(2*PRF)
3860 # Re = 6371 #Earth Radius
3859 # Re = 6371 #Earth Radius
3861 # heights = numpy.zeros(Ranges.shape)
3860 # heights = numpy.zeros(Ranges.shape)
3862 #
3861 #
3863 # R_aux = numpy.array([0,1,2])*Ramb
3862 # R_aux = numpy.array([0,1,2])*Ramb
3864 # R_aux = R_aux.reshape(1,R_aux.size)
3863 # R_aux = R_aux.reshape(1,R_aux.size)
3865 #
3864 #
3866 # Ranges = Ranges.reshape(Ranges.size,1)
3865 # Ranges = Ranges.reshape(Ranges.size,1)
3867 #
3866 #
3868 # Ri = Ranges + R_aux
3867 # Ri = Ranges + R_aux
3869 # hi = numpy.sqrt(Re**2 + Ri**2 + (2*Re*numpy.cos(zenith*numpy.pi/180)*Ri.transpose()).transpose()) - Re
3868 # hi = numpy.sqrt(Re**2 + Ri**2 + (2*Re*numpy.cos(zenith*numpy.pi/180)*Ri.transpose()).transpose()) - Re
3870 #
3869 #
3871 # #Check if there is a height between 70 and 110 km
3870 # #Check if there is a height between 70 and 110 km
3872 # h_bool = numpy.sum(numpy.logical_and(hi > minHeight, hi < maxHeight), axis = 1)
3871 # h_bool = numpy.sum(numpy.logical_and(hi > minHeight, hi < maxHeight), axis = 1)
3873 # ind_h = numpy.where(h_bool == 1)[0]
3872 # ind_h = numpy.where(h_bool == 1)[0]
3874 #
3873 #
3875 # hCorr = hi[ind_h, :]
3874 # hCorr = hi[ind_h, :]
3876 # ind_hCorr = numpy.where(numpy.logical_and(hi > minHeight, hi < maxHeight))
3875 # ind_hCorr = numpy.where(numpy.logical_and(hi > minHeight, hi < maxHeight))
3877 #
3876 #
3878 # hCorr = hi[ind_hCorr]
3877 # hCorr = hi[ind_hCorr]
3879 # heights[ind_h] = hCorr
3878 # heights[ind_h] = hCorr
3880 #
3879 #
3881 # #Setting Error
3880 # #Setting Error
3882 # #Number 13: Height unresolvable echo: not valid height within 70 to 110 km
3881 # #Number 13: Height unresolvable echo: not valid height within 70 to 110 km
3883 # #Number 14: Height ambiguous echo: more than one possible height within 70 to 110 km
3882 # #Number 14: Height ambiguous echo: more than one possible height within 70 to 110 km
3884 #
3883 #
3885 # indInvalid2 = numpy.where(numpy.logical_and(h_bool > 1, error == 0))[0]
3884 # indInvalid2 = numpy.where(numpy.logical_and(h_bool > 1, error == 0))[0]
3886 # error[indInvalid2] = 14
3885 # error[indInvalid2] = 14
3887 # indInvalid1 = numpy.where(numpy.logical_and(h_bool == 0, error == 0))[0]
3886 # indInvalid1 = numpy.where(numpy.logical_and(h_bool == 0, error == 0))[0]
3888 # error[indInvalid1] = 13
3887 # error[indInvalid1] = 13
3889 #
3888 #
3890 # return heights, error
3889 # return heights, error
@@ -1,1411 +1,1411
1 # Copyright (c) 2012-2020 Jicamarca Radio Observatory
1 # Copyright (c) 2012-2020 Jicamarca Radio Observatory
2 # All rights reserved.
2 # All rights reserved.
3 #
3 #
4 # Distributed under the terms of the BSD 3-clause license.
4 # Distributed under the terms of the BSD 3-clause license.
5 """Spectra processing Unit and operations
5 """Spectra processing Unit and operations
6
6
7 Here you will find the processing unit `SpectraProc` and several operations
7 Here you will find the processing unit `SpectraProc` and several operations
8 to work with Spectra data type
8 to work with Spectra data type
9 """
9 """
10
10
11 import time
11 import time
12 import itertools
12 import itertools
13
13
14 import numpy
14 import numpy
15 import math
15 import math
16
16
17 from schainpy.model.proc.jroproc_base import ProcessingUnit, MPDecorator, Operation
17 from schainpy.model.proc.jroproc_base import ProcessingUnit, MPDecorator, Operation
18 from schainpy.model.data.jrodata import Spectra
18 from schainpy.model.data.jrodata import Spectra
19 from schainpy.model.data.jrodata import hildebrand_sekhon
19 from schainpy.model.data.jrodata import hildebrand_sekhon
20 from schainpy.utils import log
20 from schainpy.utils import log
21
21
22 from scipy.optimize import curve_fit
22 from scipy.optimize import curve_fit
23
23
24
24
25 class SpectraProc(ProcessingUnit):
25 class SpectraProc(ProcessingUnit):
26
26
27 def __init__(self):
27 def __init__(self):
28
28
29 ProcessingUnit.__init__(self)
29 ProcessingUnit.__init__(self)
30
30
31 self.buffer = None
31 self.buffer = None
32 self.firstdatatime = None
32 self.firstdatatime = None
33 self.profIndex = 0
33 self.profIndex = 0
34 self.dataOut = Spectra()
34 self.dataOut = Spectra()
35 self.id_min = None
35 self.id_min = None
36 self.id_max = None
36 self.id_max = None
37 self.setupReq = False #Agregar a todas las unidades de proc
37 self.setupReq = False #Agregar a todas las unidades de proc
38
38
39 def __updateSpecFromVoltage(self):
39 def __updateSpecFromVoltage(self):
40
40
41 self.dataOut.timeZone = self.dataIn.timeZone
41 self.dataOut.timeZone = self.dataIn.timeZone
42 self.dataOut.dstFlag = self.dataIn.dstFlag
42 self.dataOut.dstFlag = self.dataIn.dstFlag
43 self.dataOut.errorCount = self.dataIn.errorCount
43 self.dataOut.errorCount = self.dataIn.errorCount
44 self.dataOut.useLocalTime = self.dataIn.useLocalTime
44 self.dataOut.useLocalTime = self.dataIn.useLocalTime
45 try:
45 try:
46 self.dataOut.processingHeaderObj = self.dataIn.processingHeaderObj.copy()
46 self.dataOut.processingHeaderObj = self.dataIn.processingHeaderObj.copy()
47 except:
47 except:
48 pass
48 pass
49 self.dataOut.radarControllerHeaderObj = self.dataIn.radarControllerHeaderObj.copy()
49 self.dataOut.radarControllerHeaderObj = self.dataIn.radarControllerHeaderObj.copy()
50 self.dataOut.systemHeaderObj = self.dataIn.systemHeaderObj.copy()
50 self.dataOut.systemHeaderObj = self.dataIn.systemHeaderObj.copy()
51 self.dataOut.channelList = self.dataIn.channelList
51 self.dataOut.channelList = self.dataIn.channelList
52 self.dataOut.heightList = self.dataIn.heightList
52 self.dataOut.heightList = self.dataIn.heightList
53 self.dataOut.dtype = numpy.dtype([('real', '<f4'), ('imag', '<f4')])
53 self.dataOut.dtype = numpy.dtype([('real', '<f4'), ('imag', '<f4')])
54 self.dataOut.nProfiles = self.dataOut.nFFTPoints
54 self.dataOut.nProfiles = self.dataOut.nFFTPoints
55 self.dataOut.flagDiscontinuousBlock = self.dataIn.flagDiscontinuousBlock
55 self.dataOut.flagDiscontinuousBlock = self.dataIn.flagDiscontinuousBlock
56 self.dataOut.utctime = self.firstdatatime
56 self.dataOut.utctime = self.firstdatatime
57 self.dataOut.flagDecodeData = self.dataIn.flagDecodeData
57 self.dataOut.flagDecodeData = self.dataIn.flagDecodeData
58 self.dataOut.flagDeflipData = self.dataIn.flagDeflipData
58 self.dataOut.flagDeflipData = self.dataIn.flagDeflipData
59 self.dataOut.flagShiftFFT = False
59 self.dataOut.flagShiftFFT = False
60 self.dataOut.nCohInt = self.dataIn.nCohInt
60 self.dataOut.nCohInt = self.dataIn.nCohInt
61 self.dataOut.nIncohInt = 1
61 self.dataOut.nIncohInt = 1
62 self.dataOut.windowOfFilter = self.dataIn.windowOfFilter
62 self.dataOut.windowOfFilter = self.dataIn.windowOfFilter
63 self.dataOut.frequency = self.dataIn.frequency
63 self.dataOut.frequency = self.dataIn.frequency
64 self.dataOut.realtime = self.dataIn.realtime
64 self.dataOut.realtime = self.dataIn.realtime
65 self.dataOut.azimuth = self.dataIn.azimuth
65 self.dataOut.azimuth = self.dataIn.azimuth
66 self.dataOut.zenith = self.dataIn.zenith
66 self.dataOut.zenith = self.dataIn.zenith
67 self.dataOut.codeList = self.dataIn.codeList
67 self.dataOut.codeList = self.dataIn.codeList
68 self.dataOut.azimuthList = self.dataIn.azimuthList
68 self.dataOut.azimuthList = self.dataIn.azimuthList
69 self.dataOut.elevationList = self.dataIn.elevationList
69 self.dataOut.elevationList = self.dataIn.elevationList
70
70
71 def __getFft(self):
71 def __getFft(self):
72 """
72 """
73 Convierte valores de Voltaje a Spectra
73 Convierte valores de Voltaje a Spectra
74
74
75 Affected:
75 Affected:
76 self.dataOut.data_spc
76 self.dataOut.data_spc
77 self.dataOut.data_cspc
77 self.dataOut.data_cspc
78 self.dataOut.data_dc
78 self.dataOut.data_dc
79 self.dataOut.heightList
79 self.dataOut.heightList
80 self.profIndex
80 self.profIndex
81 self.buffer
81 self.buffer
82 self.dataOut.flagNoData
82 self.dataOut.flagNoData
83 """
83 """
84 fft_volt = numpy.fft.fft(
84 fft_volt = numpy.fft.fft(
85 self.buffer, n=self.dataOut.nFFTPoints, axis=1)
85 self.buffer, n=self.dataOut.nFFTPoints, axis=1)
86 fft_volt = fft_volt.astype(numpy.dtype('complex'))
86 fft_volt = fft_volt.astype(numpy.dtype('complex'))
87 dc = fft_volt[:, 0, :]
87 dc = fft_volt[:, 0, :]
88
88
89 # calculo de self-spectra
89 # calculo de self-spectra
90 fft_volt = numpy.fft.fftshift(fft_volt, axes=(1,))
90 fft_volt = numpy.fft.fftshift(fft_volt, axes=(1,))
91 spc = fft_volt * numpy.conjugate(fft_volt)
91 spc = fft_volt * numpy.conjugate(fft_volt)
92 spc = spc.real
92 spc = spc.real
93
93
94 blocksize = 0
94 blocksize = 0
95 blocksize += dc.size
95 blocksize += dc.size
96 blocksize += spc.size
96 blocksize += spc.size
97
97
98 cspc = None
98 cspc = None
99 pairIndex = 0
99 pairIndex = 0
100 if self.dataOut.pairsList != None:
100 if self.dataOut.pairsList != None:
101 # calculo de cross-spectra
101 # calculo de cross-spectra
102 cspc = numpy.zeros(
102 cspc = numpy.zeros(
103 (self.dataOut.nPairs, self.dataOut.nFFTPoints, self.dataOut.nHeights), dtype='complex')
103 (self.dataOut.nPairs, self.dataOut.nFFTPoints, self.dataOut.nHeights), dtype='complex')
104 for pair in self.dataOut.pairsList:
104 for pair in self.dataOut.pairsList:
105 if pair[0] not in self.dataOut.channelList:
105 if pair[0] not in self.dataOut.channelList:
106 raise ValueError("Error getting CrossSpectra: pair 0 of %s is not in channelList = %s" % (
106 raise ValueError("Error getting CrossSpectra: pair 0 of %s is not in channelList = %s" % (
107 str(pair), str(self.dataOut.channelList)))
107 str(pair), str(self.dataOut.channelList)))
108 if pair[1] not in self.dataOut.channelList:
108 if pair[1] not in self.dataOut.channelList:
109 raise ValueError("Error getting CrossSpectra: pair 1 of %s is not in channelList = %s" % (
109 raise ValueError("Error getting CrossSpectra: pair 1 of %s is not in channelList = %s" % (
110 str(pair), str(self.dataOut.channelList)))
110 str(pair), str(self.dataOut.channelList)))
111
111
112 cspc[pairIndex, :, :] = fft_volt[pair[0], :, :] * \
112 cspc[pairIndex, :, :] = fft_volt[pair[0], :, :] * \
113 numpy.conjugate(fft_volt[pair[1], :, :])
113 numpy.conjugate(fft_volt[pair[1], :, :])
114 pairIndex += 1
114 pairIndex += 1
115 blocksize += cspc.size
115 blocksize += cspc.size
116
116
117 self.dataOut.data_spc = spc
117 self.dataOut.data_spc = spc
118 self.dataOut.data_cspc = cspc
118 self.dataOut.data_cspc = cspc
119 self.dataOut.data_dc = dc
119 self.dataOut.data_dc = dc
120 self.dataOut.blockSize = blocksize
120 self.dataOut.blockSize = blocksize
121 self.dataOut.flagShiftFFT = False
121 self.dataOut.flagShiftFFT = False
122
122
123 def run(self, nProfiles=None, nFFTPoints=None, pairsList=None, ippFactor=None, shift_fft=False):
123 def run(self, nProfiles=None, nFFTPoints=None, pairsList=None, ippFactor=None, shift_fft=False):
124
124
125 if self.dataIn.type == "Spectra":
125 if self.dataIn.type == "Spectra":
126 self.dataOut.copy(self.dataIn)
126 self.dataOut.copy(self.dataIn)
127 if shift_fft:
127 if shift_fft:
128 #desplaza a la derecha en el eje 2 determinadas posiciones
128 #desplaza a la derecha en el eje 2 determinadas posiciones
129 shift = int(self.dataOut.nFFTPoints/2)
129 shift = int(self.dataOut.nFFTPoints/2)
130 self.dataOut.data_spc = numpy.roll(self.dataOut.data_spc, shift , axis=1)
130 self.dataOut.data_spc = numpy.roll(self.dataOut.data_spc, shift , axis=1)
131
131
132 if self.dataOut.data_cspc is not None:
132 if self.dataOut.data_cspc is not None:
133 #desplaza a la derecha en el eje 2 determinadas posiciones
133 #desplaza a la derecha en el eje 2 determinadas posiciones
134 self.dataOut.data_cspc = numpy.roll(self.dataOut.data_cspc, shift, axis=1)
134 self.dataOut.data_cspc = numpy.roll(self.dataOut.data_cspc, shift, axis=1)
135 if pairsList:
135 if pairsList:
136 self.__selectPairs(pairsList)
136 self.__selectPairs(pairsList)
137
137
138 elif self.dataIn.type == "Voltage":
138 elif self.dataIn.type == "Voltage":
139
139
140 self.dataOut.flagNoData = True
140 self.dataOut.flagNoData = True
141
141
142 if nFFTPoints == None:
142 if nFFTPoints == None:
143 raise ValueError("This SpectraProc.run() need nFFTPoints input variable")
143 raise ValueError("This SpectraProc.run() need nFFTPoints input variable")
144
144
145 if nProfiles == None:
145 if nProfiles == None:
146 nProfiles = nFFTPoints
146 nProfiles = nFFTPoints
147
147
148 if ippFactor == None:
148 if ippFactor == None:
149 self.dataOut.ippFactor = 1
149 self.dataOut.ippFactor = 1
150
150
151 self.dataOut.nFFTPoints = nFFTPoints
151 self.dataOut.nFFTPoints = nFFTPoints
152
152
153 if self.buffer is None:
153 if self.buffer is None:
154 self.buffer = numpy.zeros((self.dataIn.nChannels,
154 self.buffer = numpy.zeros((self.dataIn.nChannels,
155 nProfiles,
155 nProfiles,
156 self.dataIn.nHeights),
156 self.dataIn.nHeights),
157 dtype='complex')
157 dtype='complex')
158
158
159 if self.dataIn.flagDataAsBlock:
159 if self.dataIn.flagDataAsBlock:
160 nVoltProfiles = self.dataIn.data.shape[1]
160 nVoltProfiles = self.dataIn.data.shape[1]
161
161
162 if nVoltProfiles == nProfiles:
162 if nVoltProfiles == nProfiles:
163 self.buffer = self.dataIn.data.copy()
163 self.buffer = self.dataIn.data.copy()
164 self.profIndex = nVoltProfiles
164 self.profIndex = nVoltProfiles
165
165
166 elif nVoltProfiles < nProfiles:
166 elif nVoltProfiles < nProfiles:
167
167
168 if self.profIndex == 0:
168 if self.profIndex == 0:
169 self.id_min = 0
169 self.id_min = 0
170 self.id_max = nVoltProfiles
170 self.id_max = nVoltProfiles
171
171
172 self.buffer[:, self.id_min:self.id_max,
172 self.buffer[:, self.id_min:self.id_max,
173 :] = self.dataIn.data
173 :] = self.dataIn.data
174 self.profIndex += nVoltProfiles
174 self.profIndex += nVoltProfiles
175 self.id_min += nVoltProfiles
175 self.id_min += nVoltProfiles
176 self.id_max += nVoltProfiles
176 self.id_max += nVoltProfiles
177 else:
177 else:
178 raise ValueError("The type object %s has %d profiles, it should just has %d profiles" % (
178 raise ValueError("The type object %s has %d profiles, it should just has %d profiles" % (
179 self.dataIn.type, self.dataIn.data.shape[1], nProfiles))
179 self.dataIn.type, self.dataIn.data.shape[1], nProfiles))
180 self.dataOut.flagNoData = True
180 self.dataOut.flagNoData = True
181 else:
181 else:
182 self.buffer[:, self.profIndex, :] = self.dataIn.data.copy()
182 self.buffer[:, self.profIndex, :] = self.dataIn.data.copy()
183 self.profIndex += 1
183 self.profIndex += 1
184
184
185 if self.firstdatatime == None:
185 if self.firstdatatime == None:
186 self.firstdatatime = self.dataIn.utctime
186 self.firstdatatime = self.dataIn.utctime
187
187
188 if self.profIndex == nProfiles:
188 if self.profIndex == nProfiles:
189 self.__updateSpecFromVoltage()
189 self.__updateSpecFromVoltage()
190 if pairsList == None:
190 if pairsList == None:
191 self.dataOut.pairsList = [pair for pair in itertools.combinations(self.dataOut.channelList, 2)]
191 self.dataOut.pairsList = [pair for pair in itertools.combinations(self.dataOut.channelList, 2)]
192 else:
192 else:
193 self.dataOut.pairsList = pairsList
193 self.dataOut.pairsList = pairsList
194 self.__getFft()
194 self.__getFft()
195 self.dataOut.flagNoData = False
195 self.dataOut.flagNoData = False
196 self.firstdatatime = None
196 self.firstdatatime = None
197 self.profIndex = 0
197 self.profIndex = 0
198 else:
198 else:
199 raise ValueError("The type of input object '%s' is not valid".format(
199 raise ValueError("The type of input object '%s' is not valid".format(
200 self.dataIn.type))
200 self.dataIn.type))
201
201
202 def __selectPairs(self, pairsList):
202 def __selectPairs(self, pairsList):
203
203
204 if not pairsList:
204 if not pairsList:
205 return
205 return
206
206
207 pairs = []
207 pairs = []
208 pairsIndex = []
208 pairsIndex = []
209
209
210 for pair in pairsList:
210 for pair in pairsList:
211 if pair[0] not in self.dataOut.channelList or pair[1] not in self.dataOut.channelList:
211 if pair[0] not in self.dataOut.channelList or pair[1] not in self.dataOut.channelList:
212 continue
212 continue
213 pairs.append(pair)
213 pairs.append(pair)
214 pairsIndex.append(pairs.index(pair))
214 pairsIndex.append(pairs.index(pair))
215
215
216 self.dataOut.data_cspc = self.dataOut.data_cspc[pairsIndex]
216 self.dataOut.data_cspc = self.dataOut.data_cspc[pairsIndex]
217 self.dataOut.pairsList = pairs
217 self.dataOut.pairsList = pairs
218
218
219 return
219 return
220
220
221 def selectFFTs(self, minFFT, maxFFT ):
221 def selectFFTs(self, minFFT, maxFFT ):
222 """
222 """
223 Selecciona un bloque de datos en base a un grupo de valores de puntos FFTs segun el rango
223 Selecciona un bloque de datos en base a un grupo de valores de puntos FFTs segun el rango
224 minFFT<= FFT <= maxFFT
224 minFFT<= FFT <= maxFFT
225 """
225 """
226
226
227 if (minFFT > maxFFT):
227 if (minFFT > maxFFT):
228 raise ValueError("Error selecting heights: Height range (%d,%d) is not valid" % (minFFT, maxFFT))
228 raise ValueError("Error selecting heights: Height range (%d,%d) is not valid" % (minFFT, maxFFT))
229
229
230 if (minFFT < self.dataOut.getFreqRange()[0]):
230 if (minFFT < self.dataOut.getFreqRange()[0]):
231 minFFT = self.dataOut.getFreqRange()[0]
231 minFFT = self.dataOut.getFreqRange()[0]
232
232
233 if (maxFFT > self.dataOut.getFreqRange()[-1]):
233 if (maxFFT > self.dataOut.getFreqRange()[-1]):
234 maxFFT = self.dataOut.getFreqRange()[-1]
234 maxFFT = self.dataOut.getFreqRange()[-1]
235
235
236 minIndex = 0
236 minIndex = 0
237 maxIndex = 0
237 maxIndex = 0
238 FFTs = self.dataOut.getFreqRange()
238 FFTs = self.dataOut.getFreqRange()
239
239
240 inda = numpy.where(FFTs >= minFFT)
240 inda = numpy.where(FFTs >= minFFT)
241 indb = numpy.where(FFTs <= maxFFT)
241 indb = numpy.where(FFTs <= maxFFT)
242
242
243 try:
243 try:
244 minIndex = inda[0][0]
244 minIndex = inda[0][0]
245 except:
245 except:
246 minIndex = 0
246 minIndex = 0
247
247
248 try:
248 try:
249 maxIndex = indb[0][-1]
249 maxIndex = indb[0][-1]
250 except:
250 except:
251 maxIndex = len(FFTs)
251 maxIndex = len(FFTs)
252
252
253 self.selectFFTsByIndex(minIndex, maxIndex)
253 self.selectFFTsByIndex(minIndex, maxIndex)
254
254
255 return 1
255 return 1
256
256
257 def getBeaconSignal(self, tauindex=0, channelindex=0, hei_ref=None):
257 def getBeaconSignal(self, tauindex=0, channelindex=0, hei_ref=None):
258 newheis = numpy.where(
258 newheis = numpy.where(
259 self.dataOut.heightList > self.dataOut.radarControllerHeaderObj.Taus[tauindex])
259 self.dataOut.heightList > self.dataOut.radarControllerHeaderObj.Taus[tauindex])
260
260
261 if hei_ref != None:
261 if hei_ref != None:
262 newheis = numpy.where(self.dataOut.heightList > hei_ref)
262 newheis = numpy.where(self.dataOut.heightList > hei_ref)
263
263
264 minIndex = min(newheis[0])
264 minIndex = min(newheis[0])
265 maxIndex = max(newheis[0])
265 maxIndex = max(newheis[0])
266 data_spc = self.dataOut.data_spc[:, :, minIndex:maxIndex + 1]
266 data_spc = self.dataOut.data_spc[:, :, minIndex:maxIndex + 1]
267 heightList = self.dataOut.heightList[minIndex:maxIndex + 1]
267 heightList = self.dataOut.heightList[minIndex:maxIndex + 1]
268
268
269 # determina indices
269 # determina indices
270 nheis = int(self.dataOut.radarControllerHeaderObj.txB /
270 nheis = int(self.dataOut.radarControllerHeaderObj.txB /
271 (self.dataOut.heightList[1] - self.dataOut.heightList[0]))
271 (self.dataOut.heightList[1] - self.dataOut.heightList[0]))
272 avg_dB = 10 * \
272 avg_dB = 10 * \
273 numpy.log10(numpy.sum(data_spc[channelindex, :, :], axis=0))
273 numpy.log10(numpy.sum(data_spc[channelindex, :, :], axis=0))
274 beacon_dB = numpy.sort(avg_dB)[-nheis:]
274 beacon_dB = numpy.sort(avg_dB)[-nheis:]
275 beacon_heiIndexList = []
275 beacon_heiIndexList = []
276 for val in avg_dB.tolist():
276 for val in avg_dB.tolist():
277 if val >= beacon_dB[0]:
277 if val >= beacon_dB[0]:
278 beacon_heiIndexList.append(avg_dB.tolist().index(val))
278 beacon_heiIndexList.append(avg_dB.tolist().index(val))
279
279
280 #data_spc = data_spc[:,:,beacon_heiIndexList]
280 #data_spc = data_spc[:,:,beacon_heiIndexList]
281 data_cspc = None
281 data_cspc = None
282 if self.dataOut.data_cspc is not None:
282 if self.dataOut.data_cspc is not None:
283 data_cspc = self.dataOut.data_cspc[:, :, minIndex:maxIndex + 1]
283 data_cspc = self.dataOut.data_cspc[:, :, minIndex:maxIndex + 1]
284 #data_cspc = data_cspc[:,:,beacon_heiIndexList]
284 #data_cspc = data_cspc[:,:,beacon_heiIndexList]
285
285
286 data_dc = None
286 data_dc = None
287 if self.dataOut.data_dc is not None:
287 if self.dataOut.data_dc is not None:
288 data_dc = self.dataOut.data_dc[:, minIndex:maxIndex + 1]
288 data_dc = self.dataOut.data_dc[:, minIndex:maxIndex + 1]
289 #data_dc = data_dc[:,beacon_heiIndexList]
289 #data_dc = data_dc[:,beacon_heiIndexList]
290
290
291 self.dataOut.data_spc = data_spc
291 self.dataOut.data_spc = data_spc
292 self.dataOut.data_cspc = data_cspc
292 self.dataOut.data_cspc = data_cspc
293 self.dataOut.data_dc = data_dc
293 self.dataOut.data_dc = data_dc
294 self.dataOut.heightList = heightList
294 self.dataOut.heightList = heightList
295 self.dataOut.beacon_heiIndexList = beacon_heiIndexList
295 self.dataOut.beacon_heiIndexList = beacon_heiIndexList
296
296
297 return 1
297 return 1
298
298
299 def selectFFTsByIndex(self, minIndex, maxIndex):
299 def selectFFTsByIndex(self, minIndex, maxIndex):
300 """
300 """
301
301
302 """
302 """
303
303
304 if (minIndex < 0) or (minIndex > maxIndex):
304 if (minIndex < 0) or (minIndex > maxIndex):
305 raise ValueError("Error selecting heights: Index range (%d,%d) is not valid" % (minIndex, maxIndex))
305 raise ValueError("Error selecting heights: Index range (%d,%d) is not valid" % (minIndex, maxIndex))
306
306
307 if (maxIndex >= self.dataOut.nProfiles):
307 if (maxIndex >= self.dataOut.nProfiles):
308 maxIndex = self.dataOut.nProfiles-1
308 maxIndex = self.dataOut.nProfiles-1
309
309
310 #Spectra
310 #Spectra
311 data_spc = self.dataOut.data_spc[:,minIndex:maxIndex+1,:]
311 data_spc = self.dataOut.data_spc[:,minIndex:maxIndex+1,:]
312
312
313 data_cspc = None
313 data_cspc = None
314 if self.dataOut.data_cspc is not None:
314 if self.dataOut.data_cspc is not None:
315 data_cspc = self.dataOut.data_cspc[:,minIndex:maxIndex+1,:]
315 data_cspc = self.dataOut.data_cspc[:,minIndex:maxIndex+1,:]
316
316
317 data_dc = None
317 data_dc = None
318 if self.dataOut.data_dc is not None:
318 if self.dataOut.data_dc is not None:
319 data_dc = self.dataOut.data_dc[minIndex:maxIndex+1,:]
319 data_dc = self.dataOut.data_dc[minIndex:maxIndex+1,:]
320
320
321 self.dataOut.data_spc = data_spc
321 self.dataOut.data_spc = data_spc
322 self.dataOut.data_cspc = data_cspc
322 self.dataOut.data_cspc = data_cspc
323 self.dataOut.data_dc = data_dc
323 self.dataOut.data_dc = data_dc
324
324
325 self.dataOut.ippSeconds = self.dataOut.ippSeconds*(self.dataOut.nFFTPoints / numpy.shape(data_cspc)[1])
325 self.dataOut.ippSeconds = self.dataOut.ippSeconds*(self.dataOut.nFFTPoints / numpy.shape(data_cspc)[1])
326 self.dataOut.nFFTPoints = numpy.shape(data_cspc)[1]
326 self.dataOut.nFFTPoints = numpy.shape(data_cspc)[1]
327 self.dataOut.profilesPerBlock = numpy.shape(data_cspc)[1]
327 self.dataOut.profilesPerBlock = numpy.shape(data_cspc)[1]
328
328
329 return 1
329 return 1
330
330
331 def getNoise(self, minHei=None, maxHei=None, minVel=None, maxVel=None):
331 def getNoise(self, minHei=None, maxHei=None, minVel=None, maxVel=None):
332 # validacion de rango
332 # validacion de rango
333 if minHei == None:
333 if minHei == None:
334 minHei = self.dataOut.heightList[0]
334 minHei = self.dataOut.heightList[0]
335
335
336 if maxHei == None:
336 if maxHei == None:
337 maxHei = self.dataOut.heightList[-1]
337 maxHei = self.dataOut.heightList[-1]
338
338
339 if (minHei < self.dataOut.heightList[0]) or (minHei > maxHei):
339 if (minHei < self.dataOut.heightList[0]) or (minHei > maxHei):
340 print('minHei: %.2f is out of the heights range' % (minHei))
340 print('minHei: %.2f is out of the heights range' % (minHei))
341 print('minHei is setting to %.2f' % (self.dataOut.heightList[0]))
341 print('minHei is setting to %.2f' % (self.dataOut.heightList[0]))
342 minHei = self.dataOut.heightList[0]
342 minHei = self.dataOut.heightList[0]
343
343
344 if (maxHei > self.dataOut.heightList[-1]) or (maxHei < minHei):
344 if (maxHei > self.dataOut.heightList[-1]) or (maxHei < minHei):
345 print('maxHei: %.2f is out of the heights range' % (maxHei))
345 print('maxHei: %.2f is out of the heights range' % (maxHei))
346 print('maxHei is setting to %.2f' % (self.dataOut.heightList[-1]))
346 print('maxHei is setting to %.2f' % (self.dataOut.heightList[-1]))
347 maxHei = self.dataOut.heightList[-1]
347 maxHei = self.dataOut.heightList[-1]
348
348
349 # validacion de velocidades
349 # validacion de velocidades
350 velrange = self.dataOut.getVelRange(1)
350 velrange = self.dataOut.getVelRange(1)
351
351
352 if minVel == None:
352 if minVel == None:
353 minVel = velrange[0]
353 minVel = velrange[0]
354
354
355 if maxVel == None:
355 if maxVel == None:
356 maxVel = velrange[-1]
356 maxVel = velrange[-1]
357
357
358 if (minVel < velrange[0]) or (minVel > maxVel):
358 if (minVel < velrange[0]) or (minVel > maxVel):
359 print('minVel: %.2f is out of the velocity range' % (minVel))
359 print('minVel: %.2f is out of the velocity range' % (minVel))
360 print('minVel is setting to %.2f' % (velrange[0]))
360 print('minVel is setting to %.2f' % (velrange[0]))
361 minVel = velrange[0]
361 minVel = velrange[0]
362
362
363 if (maxVel > velrange[-1]) or (maxVel < minVel):
363 if (maxVel > velrange[-1]) or (maxVel < minVel):
364 print('maxVel: %.2f is out of the velocity range' % (maxVel))
364 print('maxVel: %.2f is out of the velocity range' % (maxVel))
365 print('maxVel is setting to %.2f' % (velrange[-1]))
365 print('maxVel is setting to %.2f' % (velrange[-1]))
366 maxVel = velrange[-1]
366 maxVel = velrange[-1]
367
367
368 # seleccion de indices para rango
368 # seleccion de indices para rango
369 minIndex = 0
369 minIndex = 0
370 maxIndex = 0
370 maxIndex = 0
371 heights = self.dataOut.heightList
371 heights = self.dataOut.heightList
372
372
373 inda = numpy.where(heights >= minHei)
373 inda = numpy.where(heights >= minHei)
374 indb = numpy.where(heights <= maxHei)
374 indb = numpy.where(heights <= maxHei)
375
375
376 try:
376 try:
377 minIndex = inda[0][0]
377 minIndex = inda[0][0]
378 except:
378 except:
379 minIndex = 0
379 minIndex = 0
380
380
381 try:
381 try:
382 maxIndex = indb[0][-1]
382 maxIndex = indb[0][-1]
383 except:
383 except:
384 maxIndex = len(heights)
384 maxIndex = len(heights)
385
385
386 if (minIndex < 0) or (minIndex > maxIndex):
386 if (minIndex < 0) or (minIndex > maxIndex):
387 raise ValueError("some value in (%d,%d) is not valid" % (
387 raise ValueError("some value in (%d,%d) is not valid" % (
388 minIndex, maxIndex))
388 minIndex, maxIndex))
389
389
390 if (maxIndex >= self.dataOut.nHeights):
390 if (maxIndex >= self.dataOut.nHeights):
391 maxIndex = self.dataOut.nHeights - 1
391 maxIndex = self.dataOut.nHeights - 1
392
392
393 # seleccion de indices para velocidades
393 # seleccion de indices para velocidades
394 indminvel = numpy.where(velrange >= minVel)
394 indminvel = numpy.where(velrange >= minVel)
395 indmaxvel = numpy.where(velrange <= maxVel)
395 indmaxvel = numpy.where(velrange <= maxVel)
396 try:
396 try:
397 minIndexVel = indminvel[0][0]
397 minIndexVel = indminvel[0][0]
398 except:
398 except:
399 minIndexVel = 0
399 minIndexVel = 0
400
400
401 try:
401 try:
402 maxIndexVel = indmaxvel[0][-1]
402 maxIndexVel = indmaxvel[0][-1]
403 except:
403 except:
404 maxIndexVel = len(velrange)
404 maxIndexVel = len(velrange)
405
405
406 # seleccion del espectro
406 # seleccion del espectro
407 data_spc = self.dataOut.data_spc[:,
407 data_spc = self.dataOut.data_spc[:,
408 minIndexVel:maxIndexVel + 1, minIndex:maxIndex + 1]
408 minIndexVel:maxIndexVel + 1, minIndex:maxIndex + 1]
409 # estimacion de ruido
409 # estimacion de ruido
410 noise = numpy.zeros(self.dataOut.nChannels)
410 noise = numpy.zeros(self.dataOut.nChannels)
411
411
412 for channel in range(self.dataOut.nChannels):
412 for channel in range(self.dataOut.nChannels):
413 daux = data_spc[channel, :, :]
413 daux = data_spc[channel, :, :]
414 sortdata = numpy.sort(daux, axis=None)
414 sortdata = numpy.sort(daux, axis=None)
415 noise[channel] = hildebrand_sekhon(sortdata, self.dataOut.nIncohInt)
415 noise[channel] = hildebrand_sekhon(sortdata, self.dataOut.nIncohInt)
416
416
417 self.dataOut.noise_estimation = noise.copy()
417 self.dataOut.noise_estimation = noise.copy()
418
418
419 return 1
419 return 1
420
420
421 class removeDC(Operation):
421 class removeDC(Operation):
422
422
423 def run(self, dataOut, mode=2):
423 def run(self, dataOut, mode=2):
424 self.dataOut = dataOut
424 self.dataOut = dataOut
425 jspectra = self.dataOut.data_spc
425 jspectra = self.dataOut.data_spc
426 jcspectra = self.dataOut.data_cspc
426 jcspectra = self.dataOut.data_cspc
427
427
428 num_chan = jspectra.shape[0]
428 num_chan = jspectra.shape[0]
429 num_hei = jspectra.shape[2]
429 num_hei = jspectra.shape[2]
430
430
431 if jcspectra is not None:
431 if jcspectra is not None:
432 jcspectraExist = True
432 jcspectraExist = True
433 num_pairs = jcspectra.shape[0]
433 num_pairs = jcspectra.shape[0]
434 else:
434 else:
435 jcspectraExist = False
435 jcspectraExist = False
436
436
437 freq_dc = int(jspectra.shape[1] / 2)
437 freq_dc = int(jspectra.shape[1] / 2)
438 ind_vel = numpy.array([-2, -1, 1, 2]) + freq_dc
438 ind_vel = numpy.array([-2, -1, 1, 2]) + freq_dc
439 ind_vel = ind_vel.astype(int)
439 ind_vel = ind_vel.astype(int)
440
440
441 if ind_vel[0] < 0:
441 if ind_vel[0] < 0:
442 ind_vel[list(range(0, 1))] = ind_vel[list(range(0, 1))] + self.num_prof
442 ind_vel[list(range(0, 1))] = ind_vel[list(range(0, 1))] + self.num_prof
443
443
444 if mode == 1:
444 if mode == 1:
445 jspectra[:, freq_dc, :] = (
445 jspectra[:, freq_dc, :] = (
446 jspectra[:, ind_vel[1], :] + jspectra[:, ind_vel[2], :]) / 2 # CORRECCION
446 jspectra[:, ind_vel[1], :] + jspectra[:, ind_vel[2], :]) / 2 # CORRECCION
447
447
448 if jcspectraExist:
448 if jcspectraExist:
449 jcspectra[:, freq_dc, :] = (
449 jcspectra[:, freq_dc, :] = (
450 jcspectra[:, ind_vel[1], :] + jcspectra[:, ind_vel[2], :]) / 2
450 jcspectra[:, ind_vel[1], :] + jcspectra[:, ind_vel[2], :]) / 2
451
451
452 if mode == 2:
452 if mode == 2:
453
453
454 vel = numpy.array([-2, -1, 1, 2])
454 vel = numpy.array([-2, -1, 1, 2])
455 xx = numpy.zeros([4, 4])
455 xx = numpy.zeros([4, 4])
456
456
457 for fil in range(4):
457 for fil in range(4):
458 xx[fil, :] = vel[fil]**numpy.asarray(list(range(4)))
458 xx[fil, :] = vel[fil]**numpy.asarray(list(range(4)))
459
459
460 xx_inv = numpy.linalg.inv(xx)
460 xx_inv = numpy.linalg.inv(xx)
461 xx_aux = xx_inv[0, :]
461 xx_aux = xx_inv[0, :]
462
462
463 for ich in range(num_chan):
463 for ich in range(num_chan):
464 yy = jspectra[ich, ind_vel, :]
464 yy = jspectra[ich, ind_vel, :]
465 jspectra[ich, freq_dc, :] = numpy.dot(xx_aux, yy)
465 jspectra[ich, freq_dc, :] = numpy.dot(xx_aux, yy)
466
466
467 junkid = jspectra[ich, freq_dc, :] <= 0
467 junkid = jspectra[ich, freq_dc, :] <= 0
468 cjunkid = sum(junkid)
468 cjunkid = sum(junkid)
469
469
470 if cjunkid.any():
470 if cjunkid.any():
471 jspectra[ich, freq_dc, junkid.nonzero()] = (
471 jspectra[ich, freq_dc, junkid.nonzero()] = (
472 jspectra[ich, ind_vel[1], junkid] + jspectra[ich, ind_vel[2], junkid]) / 2
472 jspectra[ich, ind_vel[1], junkid] + jspectra[ich, ind_vel[2], junkid]) / 2
473
473
474 if jcspectraExist:
474 if jcspectraExist:
475 for ip in range(num_pairs):
475 for ip in range(num_pairs):
476 yy = jcspectra[ip, ind_vel, :]
476 yy = jcspectra[ip, ind_vel, :]
477 jcspectra[ip, freq_dc, :] = numpy.dot(xx_aux, yy)
477 jcspectra[ip, freq_dc, :] = numpy.dot(xx_aux, yy)
478
478
479 self.dataOut.data_spc = jspectra
479 self.dataOut.data_spc = jspectra
480 self.dataOut.data_cspc = jcspectra
480 self.dataOut.data_cspc = jcspectra
481
481
482 return self.dataOut
482 return self.dataOut
483
483
484 # import matplotlib.pyplot as plt
484 # import matplotlib.pyplot as plt
485
485
486 def fit_func( x, a0, a1, a2): #, a3, a4, a5):
486 def fit_func( x, a0, a1, a2): #, a3, a4, a5):
487 z = (x - a1) / a2
487 z = (x - a1) / a2
488 y = a0 * numpy.exp(-z**2 / a2) #+ a3 + a4 * x + a5 * x**2
488 y = a0 * numpy.exp(-z**2 / a2) #+ a3 + a4 * x + a5 * x**2
489 return y
489 return y
490 class CleanRayleigh(Operation):
490 class CleanRayleigh(Operation):
491
491
492 def __init__(self):
492 def __init__(self):
493
493
494 Operation.__init__(self)
494 Operation.__init__(self)
495 self.i=0
495 self.i=0
496 self.isConfig = False
496 self.isConfig = False
497 self.__dataReady = False
497 self.__dataReady = False
498 self.__profIndex = 0
498 self.__profIndex = 0
499 self.byTime = False
499 self.byTime = False
500 self.byProfiles = False
500 self.byProfiles = False
501
501
502 self.bloques = None
502 self.bloques = None
503 self.bloque0 = None
503 self.bloque0 = None
504
504
505 self.index = 0
505 self.index = 0
506
506
507 self.buffer = 0
507 self.buffer = 0
508 self.buffer2 = 0
508 self.buffer2 = 0
509 self.buffer3 = 0
509 self.buffer3 = 0
510
510
511
511
512 def setup(self,dataOut,min_hei,max_hei,n, timeInterval,factor_stdv):
512 def setup(self,dataOut,min_hei,max_hei,n, timeInterval,factor_stdv):
513
513
514 self.nChannels = dataOut.nChannels
514 self.nChannels = dataOut.nChannels
515 self.nProf = dataOut.nProfiles
515 self.nProf = dataOut.nProfiles
516 self.nPairs = dataOut.data_cspc.shape[0]
516 self.nPairs = dataOut.data_cspc.shape[0]
517 self.pairsArray = numpy.array(dataOut.pairsList)
517 self.pairsArray = numpy.array(dataOut.pairsList)
518 self.spectra = dataOut.data_spc
518 self.spectra = dataOut.data_spc
519 self.cspectra = dataOut.data_cspc
519 self.cspectra = dataOut.data_cspc
520 self.heights = dataOut.heightList #alturas totales
520 self.heights = dataOut.heightList #alturas totales
521 self.nHeights = len(self.heights)
521 self.nHeights = len(self.heights)
522 self.min_hei = min_hei
522 self.min_hei = min_hei
523 self.max_hei = max_hei
523 self.max_hei = max_hei
524 if (self.min_hei == None):
524 if (self.min_hei == None):
525 self.min_hei = 0
525 self.min_hei = 0
526 if (self.max_hei == None):
526 if (self.max_hei == None):
527 self.max_hei = dataOut.heightList[-1]
527 self.max_hei = dataOut.heightList[-1]
528 self.hval = ((self.max_hei>=self.heights) & (self.heights >= self.min_hei)).nonzero()
528 self.hval = ((self.max_hei>=self.heights) & (self.heights >= self.min_hei)).nonzero()
529 self.heightsClean = self.heights[self.hval] #alturas filtradas
529 self.heightsClean = self.heights[self.hval] #alturas filtradas
530 self.hval = self.hval[0] # forma (N,), an solo N elementos -> Indices de alturas
530 self.hval = self.hval[0] # forma (N,), an solo N elementos -> Indices de alturas
531 self.nHeightsClean = len(self.heightsClean)
531 self.nHeightsClean = len(self.heightsClean)
532 self.channels = dataOut.channelList
532 self.channels = dataOut.channelList
533 self.nChan = len(self.channels)
533 self.nChan = len(self.channels)
534 self.nIncohInt = dataOut.nIncohInt
534 self.nIncohInt = dataOut.nIncohInt
535 self.__initime = dataOut.utctime
535 self.__initime = dataOut.utctime
536 self.maxAltInd = self.hval[-1]+1
536 self.maxAltInd = self.hval[-1]+1
537 self.minAltInd = self.hval[0]
537 self.minAltInd = self.hval[0]
538
538
539 self.crosspairs = dataOut.pairsList
539 self.crosspairs = dataOut.pairsList
540 self.nPairs = len(self.crosspairs)
540 self.nPairs = len(self.crosspairs)
541 self.normFactor = dataOut.normFactor
541 self.normFactor = dataOut.normFactor
542 self.nFFTPoints = dataOut.nFFTPoints
542 self.nFFTPoints = dataOut.nFFTPoints
543 self.ippSeconds = dataOut.ippSeconds
543 self.ippSeconds = dataOut.ippSeconds
544 self.currentTime = self.__initime
544 self.currentTime = self.__initime
545 self.pairsArray = numpy.array(dataOut.pairsList)
545 self.pairsArray = numpy.array(dataOut.pairsList)
546 self.factor_stdv = factor_stdv
546 self.factor_stdv = factor_stdv
547 print("CHANNELS: ",[x for x in self.channels])
547 #print("CHANNELS: ",[x for x in self.channels])
548
548
549 if n != None :
549 if n != None :
550 self.byProfiles = True
550 self.byProfiles = True
551 self.nIntProfiles = n
551 self.nIntProfiles = n
552 else:
552 else:
553 self.__integrationtime = timeInterval
553 self.__integrationtime = timeInterval
554
554
555 self.__dataReady = False
555 self.__dataReady = False
556 self.isConfig = True
556 self.isConfig = True
557
557
558
558
559
559
560 def run(self, dataOut,min_hei=None,max_hei=None, n=None, timeInterval=10,factor_stdv=2.5):
560 def run(self, dataOut,min_hei=None,max_hei=None, n=None, timeInterval=10,factor_stdv=2.5):
561 #print (dataOut.utctime)
561 #print (dataOut.utctime)
562 if not self.isConfig :
562 if not self.isConfig :
563 #print("Setting config")
563 #print("Setting config")
564 self.setup(dataOut, min_hei,max_hei,n,timeInterval,factor_stdv)
564 self.setup(dataOut, min_hei,max_hei,n,timeInterval,factor_stdv)
565 #print("Config Done")
565 #print("Config Done")
566 tini=dataOut.utctime
566 tini=dataOut.utctime
567
567
568 if self.byProfiles:
568 if self.byProfiles:
569 if self.__profIndex == self.nIntProfiles:
569 if self.__profIndex == self.nIntProfiles:
570 self.__dataReady = True
570 self.__dataReady = True
571 else:
571 else:
572 if (tini - self.__initime) >= self.__integrationtime:
572 if (tini - self.__initime) >= self.__integrationtime:
573 #print(tini - self.__initime,self.__profIndex)
573 #print(tini - self.__initime,self.__profIndex)
574 self.__dataReady = True
574 self.__dataReady = True
575 self.__initime = tini
575 self.__initime = tini
576
576
577 #if (tini.tm_min % 2) == 0 and (tini.tm_sec < 5 and self.fint==0):
577 #if (tini.tm_min % 2) == 0 and (tini.tm_sec < 5 and self.fint==0):
578
578
579 if self.__dataReady:
579 if self.__dataReady:
580 print("Data ready",self.__profIndex)
580 #print("Data ready",self.__profIndex)
581 self.__profIndex = 0
581 self.__profIndex = 0
582 jspc = self.buffer
582 jspc = self.buffer
583 jcspc = self.buffer2
583 jcspc = self.buffer2
584 #jnoise = self.buffer3
584 #jnoise = self.buffer3
585 self.buffer = dataOut.data_spc
585 self.buffer = dataOut.data_spc
586 self.buffer2 = dataOut.data_cspc
586 self.buffer2 = dataOut.data_cspc
587 #self.buffer3 = dataOut.noise
587 #self.buffer3 = dataOut.noise
588 self.currentTime = dataOut.utctime
588 self.currentTime = dataOut.utctime
589 if numpy.any(jspc) :
589 if numpy.any(jspc) :
590 #print( jspc.shape, jcspc.shape)
590 #print( jspc.shape, jcspc.shape)
591 jspc = numpy.reshape(jspc,(int(len(jspc)/self.nChannels),self.nChannels,self.nFFTPoints,self.nHeights))
591 jspc = numpy.reshape(jspc,(int(len(jspc)/self.nChannels),self.nChannels,self.nFFTPoints,self.nHeights))
592 jcspc= numpy.reshape(jcspc,(int(len(jcspc)/self.nPairs),self.nPairs,self.nFFTPoints,self.nHeights))
592 jcspc= numpy.reshape(jcspc,(int(len(jcspc)/self.nPairs),self.nPairs,self.nFFTPoints,self.nHeights))
593 self.__dataReady = False
593 self.__dataReady = False
594 #print( jspc.shape, jcspc.shape)
594 #print( jspc.shape, jcspc.shape)
595 dataOut.flagNoData = False
595 dataOut.flagNoData = False
596 else:
596 else:
597 dataOut.flagNoData = True
597 dataOut.flagNoData = True
598 self.__dataReady = False
598 self.__dataReady = False
599 return dataOut
599 return dataOut
600 else:
600 else:
601 #print( len(self.buffer))
601 #print( len(self.buffer))
602 if numpy.any(self.buffer):
602 if numpy.any(self.buffer):
603 self.buffer = numpy.concatenate((self.buffer,dataOut.data_spc), axis=0)
603 self.buffer = numpy.concatenate((self.buffer,dataOut.data_spc), axis=0)
604 self.buffer2 = numpy.concatenate((self.buffer2,dataOut.data_cspc), axis=0)
604 self.buffer2 = numpy.concatenate((self.buffer2,dataOut.data_cspc), axis=0)
605 self.buffer3 += dataOut.data_dc
605 self.buffer3 += dataOut.data_dc
606 else:
606 else:
607 self.buffer = dataOut.data_spc
607 self.buffer = dataOut.data_spc
608 self.buffer2 = dataOut.data_cspc
608 self.buffer2 = dataOut.data_cspc
609 self.buffer3 = dataOut.data_dc
609 self.buffer3 = dataOut.data_dc
610 #print self.index, self.fint
610 #print self.index, self.fint
611 #print self.buffer2.shape
611 #print self.buffer2.shape
612 dataOut.flagNoData = True ## NOTE: ?? revisar LUEGO
612 dataOut.flagNoData = True ## NOTE: ?? revisar LUEGO
613 self.__profIndex += 1
613 self.__profIndex += 1
614 return dataOut ## NOTE: REV
614 return dataOut ## NOTE: REV
615
615
616
616
617 #index = tini.tm_hour*12+tini.tm_min/5
617 #index = tini.tm_hour*12+tini.tm_min/5
618 '''REVISAR'''
618 '''REVISAR'''
619 # jspc = jspc/self.nFFTPoints/self.normFactor
619 # jspc = jspc/self.nFFTPoints/self.normFactor
620 # jcspc = jcspc/self.nFFTPoints/self.normFactor
620 # jcspc = jcspc/self.nFFTPoints/self.normFactor
621
621
622
622
623 #dataOut.data_spc,dataOut.data_cspc = self.CleanRayleigh(dataOut,jspc,jcspc,crosspairs,heights,channels,nProf,nHei,nChan,nPairs,nIncohInt,nBlocks=nBlocks)
624 #tmp_spectra,tmp_cspectra,sat_spectra,sat_cspectra = self.cleanRayleigh(dataOut,jspc,jcspc,self.min_hei,self.max_hei)
625 tmp_spectra,tmp_cspectra = self.cleanRayleigh(dataOut,jspc,jcspc,self.factor_stdv)
626 #jspectra = tmp_spectra*len(jspc[:,0,0,0])
627 #jcspectra = tmp_cspectra*len(jspc[:,0,0,0])
628
623
624 tmp_spectra,tmp_cspectra = self.cleanRayleigh(dataOut,jspc,jcspc,self.factor_stdv)
629 dataOut.data_spc = tmp_spectra
625 dataOut.data_spc = tmp_spectra
630 dataOut.data_cspc = tmp_cspectra
626 dataOut.data_cspc = tmp_cspectra
627
628 #dataOut.data_spc,dataOut.data_cspc = self.cleanRayleigh(dataOut,jspc,jcspc,self.factor_stdv)
629
631 dataOut.data_dc = self.buffer3
630 dataOut.data_dc = self.buffer3
632 dataOut.nIncohInt *= self.nIntProfiles
631 dataOut.nIncohInt *= self.nIntProfiles
633 dataOut.utctime = self.currentTime #tiempo promediado
632 dataOut.utctime = self.currentTime #tiempo promediado
634 #print("Time: ",time.localtime(dataOut.utctime))
633 #print("Time: ",time.localtime(dataOut.utctime))
635 # dataOut.data_spc = sat_spectra
634 # dataOut.data_spc = sat_spectra
636 # dataOut.data_cspc = sat_cspectra
635 # dataOut.data_cspc = sat_cspectra
637 self.buffer = 0
636 self.buffer = 0
638 self.buffer2 = 0
637 self.buffer2 = 0
639 self.buffer3 = 0
638 self.buffer3 = 0
640
639
641 return dataOut
640 return dataOut
642
641
643 def cleanRayleigh(self,dataOut,spectra,cspectra,factor_stdv):
642 def cleanRayleigh(self,dataOut,spectra,cspectra,factor_stdv):
644 print("OP cleanRayleigh")
643 #print("OP cleanRayleigh")
645 #import matplotlib.pyplot as plt
644 #import matplotlib.pyplot as plt
646 #for k in range(149):
645 #for k in range(149):
647
646
648 rfunc = cspectra.copy() #self.bloques
647 rfunc = cspectra.copy() #self.bloques
649 val_spc = spectra*0.0 #self.bloque0*0.0
648 #rfunc = cspectra
650 val_cspc = cspectra*0.0 #self.bloques*0.0
649 #val_spc = spectra*0.0 #self.bloque0*0.0
651 in_sat_spectra = spectra.copy() #self.bloque0
650 #val_cspc = cspectra*0.0 #self.bloques*0.0
652 in_sat_cspectra = cspectra.copy() #self.bloques
651 #in_sat_spectra = spectra.copy() #self.bloque0
652 #in_sat_cspectra = cspectra.copy() #self.bloques
653
653
654 raxs = math.ceil(math.sqrt(self.nPairs))
654 #raxs = math.ceil(math.sqrt(self.nPairs))
655 caxs = math.ceil(self.nPairs/raxs)
655 #caxs = math.ceil(self.nPairs/raxs)
656
656
657 #print(self.hval)
657 #print(self.hval)
658 #print numpy.absolute(rfunc[:,0,0,14])
658 #print numpy.absolute(rfunc[:,0,0,14])
659 gauss_fit, covariance = None, None
659 for ih in range(self.minAltInd,self.maxAltInd):
660 for ih in range(self.minAltInd,self.maxAltInd):
660 for ifreq in range(self.nFFTPoints):
661 for ifreq in range(self.nFFTPoints):
661 # fig, axs = plt.subplots(raxs, caxs)
662 # fig, axs = plt.subplots(raxs, caxs)
662 # fig2, axs2 = plt.subplots(raxs, caxs)
663 # fig2, axs2 = plt.subplots(raxs, caxs)
663 col_ax = 0
664 # col_ax = 0
664 row_ax = 0
665 # row_ax = 0
666 #print(len(self.nPairs))
665 for ii in range(self.nPairs): #PARES DE CANALES SELF y CROSS
667 for ii in range(self.nPairs): #PARES DE CANALES SELF y CROSS
666 #print("ii: ",ii)
668 #print("ii: ",ii)
667 if (col_ax%caxs==0 and col_ax!=0):
669 # if (col_ax%caxs==0 and col_ax!=0):
668 col_ax = 0
670 # col_ax = 0
669 row_ax += 1
671 # row_ax += 1
670 func2clean = 10*numpy.log10(numpy.absolute(rfunc[:,ii,ifreq,ih])) #Potencia?
672 func2clean = 10*numpy.log10(numpy.absolute(rfunc[:,ii,ifreq,ih])) #Potencia?
671 #print(func2clean.shape)
673 #print(func2clean.shape)
672 val = (numpy.isfinite(func2clean)==True).nonzero()
674 val = (numpy.isfinite(func2clean)==True).nonzero()
673
675
674 if len(val)>0: #limitador
676 if len(val)>0: #limitador
675 min_val = numpy.around(numpy.amin(func2clean)-2) #> (-40)
677 min_val = numpy.around(numpy.amin(func2clean)-2) #> (-40)
676 if min_val <= -40 :
678 if min_val <= -40 :
677 min_val = -40
679 min_val = -40
678 max_val = numpy.around(numpy.amax(func2clean)+2) #< 200
680 max_val = numpy.around(numpy.amax(func2clean)+2) #< 200
679 if max_val >= 200 :
681 if max_val >= 200 :
680 max_val = 200
682 max_val = 200
681 #print min_val, max_val
683 #print min_val, max_val
682 step = 1
684 step = 1
683 #print("Getting bins and the histogram")
685 #print("Getting bins and the histogram")
684 x_dist = min_val + numpy.arange(1 + ((max_val-(min_val))/step))*step
686 x_dist = min_val + numpy.arange(1 + ((max_val-(min_val))/step))*step
685 y_dist,binstep = numpy.histogram(func2clean,bins=range(int(min_val),int(max_val+2),step))
687 y_dist,binstep = numpy.histogram(func2clean,bins=range(int(min_val),int(max_val+2),step))
686 #print(len(y_dist),len(binstep[:-1]))
688 #print(len(y_dist),len(binstep[:-1]))
687 #print(row_ax,col_ax, " ..")
689 #print(row_ax,col_ax, " ..")
688 #print(self.pairsArray[ii][0],self.pairsArray[ii][1])
690 #print(self.pairsArray[ii][0],self.pairsArray[ii][1])
689 mean = numpy.sum(x_dist * y_dist) / numpy.sum(y_dist)
691 mean = numpy.sum(x_dist * y_dist) / numpy.sum(y_dist)
690 sigma = numpy.sqrt(numpy.sum(y_dist * (x_dist - mean)**2) / numpy.sum(y_dist))
692 sigma = numpy.sqrt(numpy.sum(y_dist * (x_dist - mean)**2) / numpy.sum(y_dist))
691 parg = [numpy.amax(y_dist),mean,sigma]
693 parg = [numpy.amax(y_dist),mean,sigma]
692 gauss_fit, covariance = None, None
694
693 newY = None
695 #newY = None
696
694 try :
697 try :
695 gauss_fit, covariance = curve_fit(fit_func, x_dist, y_dist,p0=parg)
698 gauss_fit, covariance = curve_fit(fit_func, x_dist, y_dist,p0=parg)
696 mode = gauss_fit[1]
699 mode = gauss_fit[1]
697 stdv = gauss_fit[2]
700 stdv = gauss_fit[2]
698 #print(" FIT OK",gauss_fit)
701 #print(" FIT OK",gauss_fit)
699 '''
702 '''
700 newY = fit_func(x_dist,gauss_fit[0],gauss_fit[1],gauss_fit[2])
703 newY = fit_func(x_dist,gauss_fit[0],gauss_fit[1],gauss_fit[2])
701 axs[row_ax,col_ax].plot(binstep[:-1],y_dist,color='green')
704 axs[row_ax,col_ax].plot(binstep[:-1],y_dist,color='green')
702 axs[row_ax,col_ax].plot(binstep[:-1],newY,color='red')
705 axs[row_ax,col_ax].plot(binstep[:-1],newY,color='red')
703 axs[row_ax,col_ax].set_title("Pair "+str(self.crosspairs[ii]))'''
706 axs[row_ax,col_ax].set_title("Pair "+str(self.crosspairs[ii]))'''
704 except:
707 except:
705 mode = mean
708 mode = mean
706 stdv = sigma
709 stdv = sigma
707 #print("FIT FAIL")
710 #print("FIT FAIL")
708
711
709
712
710 #print(mode,stdv)
713 #print(mode,stdv)
711 #Removing echoes greater than mode + 3*stdv
714 #Removing echoes greater than mode + std_factor*stdv
712 #factor_stdv = 2
713 noval = (abs(func2clean - mode)>=(factor_stdv*stdv)).nonzero()
715 noval = (abs(func2clean - mode)>=(factor_stdv*stdv)).nonzero()
714 #noval tiene los indices que se van a remover
716 #noval tiene los indices que se van a remover
715 #print("Pair ",ii," novals: ",len(noval[0]))
717 #print("Pair ",ii," novals: ",len(noval[0]))
716 if len(noval[0]) > 0: #forma de array (N,) es igual a longitud (N)
718 if len(noval[0]) > 0: #forma de array (N,) es igual a longitud (N)
717 novall = ((func2clean - mode) >= (factor_stdv*stdv)).nonzero()
719 novall = ((func2clean - mode) >= (factor_stdv*stdv)).nonzero()
718 #print(novall)
720 #print(novall)
719 #print(" ",self.pairsArray[ii])
721 #print(" ",self.pairsArray[ii])
720 cross_pairs = self.pairsArray[ii]
722 cross_pairs = self.pairsArray[ii]
721 #Getting coherent echoes which are removed.
723 #Getting coherent echoes which are removed.
722 # if len(novall[0]) > 0:
724 # if len(novall[0]) > 0:
723 #
725 #
724 # val_spc[novall[0],cross_pairs[0],ifreq,ih] = 1
726 # val_spc[novall[0],cross_pairs[0],ifreq,ih] = 1
725 # val_spc[novall[0],cross_pairs[1],ifreq,ih] = 1
727 # val_spc[novall[0],cross_pairs[1],ifreq,ih] = 1
726 # val_cspc[novall[0],ii,ifreq,ih] = 1
728 # val_cspc[novall[0],ii,ifreq,ih] = 1
727 #print("OUT NOVALL 1")
729 #print("OUT NOVALL 1")
728 #Removing coherent from ISR data
730 #Removing coherent from ISR data
729 chA = self.channels.index(cross_pairs[0])
731 chA = self.channels.index(cross_pairs[0])
730 chB = self.channels.index(cross_pairs[1])
732 chB = self.channels.index(cross_pairs[1])
731
733
732 new_a = numpy.delete(cspectra[:,ii,ifreq,ih], noval[0])
734 new_a = numpy.delete(cspectra[:,ii,ifreq,ih], noval[0])
733 mean_cspc = numpy.mean(new_a)
735 cspectra[noval,ii,ifreq,ih] = numpy.mean(new_a) #mean CrossSpectra
734 new_b = numpy.delete(spectra[:,chA,ifreq,ih], noval[0])
736 new_b = numpy.delete(spectra[:,chA,ifreq,ih], noval[0])
735 mean_spc0 = numpy.mean(new_b)
737 spectra[noval,chA,ifreq,ih] = numpy.mean(new_b) #mean Spectra Pair A
736 new_c = numpy.delete(spectra[:,chB,ifreq,ih], noval[0])
738 new_c = numpy.delete(spectra[:,chB,ifreq,ih], noval[0])
737 mean_spc1 = numpy.mean(new_c)
739 spectra[noval,chB,ifreq,ih] = numpy.mean(new_c) #mean Spectra Pair B
738 spectra[noval,chA,ifreq,ih] = mean_spc0
740
739 spectra[noval,chB,ifreq,ih] = mean_spc1
740 cspectra[noval,ii,ifreq,ih] = mean_cspc
741
741
742 '''
742 '''
743 func2clean = 10*numpy.log10(numpy.absolute(cspectra[:,ii,ifreq,ih]))
743 func2clean = 10*numpy.log10(numpy.absolute(cspectra[:,ii,ifreq,ih]))
744 y_dist,binstep = numpy.histogram(func2clean,bins=range(int(min_val),int(max_val+2),step))
744 y_dist,binstep = numpy.histogram(func2clean,bins=range(int(min_val),int(max_val+2),step))
745 axs2[row_ax,col_ax].plot(binstep[:-1],newY,color='red')
745 axs2[row_ax,col_ax].plot(binstep[:-1],newY,color='red')
746 axs2[row_ax,col_ax].plot(binstep[:-1],y_dist,color='green')
746 axs2[row_ax,col_ax].plot(binstep[:-1],y_dist,color='green')
747 axs2[row_ax,col_ax].set_title("Pair "+str(self.crosspairs[ii]))
747 axs2[row_ax,col_ax].set_title("Pair "+str(self.crosspairs[ii]))
748 '''
748 '''
749
749
750 col_ax += 1 #contador de ploteo columnas
750 #col_ax += 1 #contador de ploteo columnas
751 ##print(col_ax)
751 ##print(col_ax)
752 '''
752 '''
753 title = str(dataOut.datatime)+" nFFT: "+str(ifreq)+" Alt: "+str(self.heights[ih])+ " km"
753 title = str(dataOut.datatime)+" nFFT: "+str(ifreq)+" Alt: "+str(self.heights[ih])+ " km"
754 title2 = str(dataOut.datatime)+" nFFT: "+str(ifreq)+" Alt: "+str(self.heights[ih])+ " km CLEANED"
754 title2 = str(dataOut.datatime)+" nFFT: "+str(ifreq)+" Alt: "+str(self.heights[ih])+ " km CLEANED"
755 fig.suptitle(title)
755 fig.suptitle(title)
756 fig2.suptitle(title2)
756 fig2.suptitle(title2)
757 plt.show()'''
757 plt.show()'''
758
758
759 ''' channels = channels
759 ''' channels = channels
760 cross_pairs = cross_pairs
760 cross_pairs = cross_pairs
761 #print("OUT NOVALL 2")
761 #print("OUT NOVALL 2")
762
762
763 vcross0 = (cross_pairs[0] == channels[ii]).nonzero()
763 vcross0 = (cross_pairs[0] == channels[ii]).nonzero()
764 vcross1 = (cross_pairs[1] == channels[ii]).nonzero()
764 vcross1 = (cross_pairs[1] == channels[ii]).nonzero()
765 vcross = numpy.concatenate((vcross0,vcross1),axis=None)
765 vcross = numpy.concatenate((vcross0,vcross1),axis=None)
766 #print('vcros =', vcross)
766 #print('vcros =', vcross)
767
767
768 #Getting coherent echoes which are removed.
768 #Getting coherent echoes which are removed.
769 if len(novall) > 0:
769 if len(novall) > 0:
770 #val_spc[novall,ii,ifreq,ih] = 1
770 #val_spc[novall,ii,ifreq,ih] = 1
771 val_spc[ii,ifreq,ih,novall] = 1
771 val_spc[ii,ifreq,ih,novall] = 1
772 if len(vcross) > 0:
772 if len(vcross) > 0:
773 val_cspc[vcross,ifreq,ih,novall] = 1
773 val_cspc[vcross,ifreq,ih,novall] = 1
774
774
775 #Removing coherent from ISR data.
775 #Removing coherent from ISR data.
776 self.bloque0[ii,ifreq,ih,noval] = numpy.nan
776 self.bloque0[ii,ifreq,ih,noval] = numpy.nan
777 if len(vcross) > 0:
777 if len(vcross) > 0:
778 self.bloques[vcross,ifreq,ih,noval] = numpy.nan
778 self.bloques[vcross,ifreq,ih,noval] = numpy.nan
779 '''
779 '''
780
780
781 print("Getting average of the spectra and cross-spectra from incoherent echoes.")
781 #print("Getting average of the spectra and cross-spectra from incoherent echoes.")
782 out_spectra = numpy.zeros([self.nChan,self.nFFTPoints,self.nHeights], dtype=float) #+numpy.nan
782 out_spectra = numpy.zeros([self.nChan,self.nFFTPoints,self.nHeights], dtype=float) #+numpy.nan
783 out_cspectra = numpy.zeros([self.nPairs,self.nFFTPoints,self.nHeights], dtype=complex) #+numpy.nan
783 out_cspectra = numpy.zeros([self.nPairs,self.nFFTPoints,self.nHeights], dtype=complex) #+numpy.nan
784 for ih in range(self.nHeights):
784 for ih in range(self.nHeights):
785 for ifreq in range(self.nFFTPoints):
785 for ifreq in range(self.nFFTPoints):
786 for ich in range(self.nChan):
786 for ich in range(self.nChan):
787 tmp = spectra[:,ich,ifreq,ih]
787 tmp = spectra[:,ich,ifreq,ih]
788 valid = (numpy.isfinite(tmp[:])==True).nonzero()
788 valid = (numpy.isfinite(tmp[:])==True).nonzero()
789 # if ich == 0 and ifreq == 0 and ih == 17 :
789 # if ich == 0 and ifreq == 0 and ih == 17 :
790 # print tmp
790 # print tmp
791 # print valid
791 # print valid
792 # print len(valid[0])
792 # print len(valid[0])
793 #print('TMP',tmp)
793 #print('TMP',tmp)
794 if len(valid[0]) >0 :
794 if len(valid[0]) >0 :
795 out_spectra[ich,ifreq,ih] = numpy.nansum(tmp)#/len(valid[0])
795 out_spectra[ich,ifreq,ih] = numpy.nansum(tmp)#/len(valid[0])
796 #for icr in range(nPairs):
796 #for icr in range(nPairs):
797 for icr in range(self.nPairs):
797 for icr in range(self.nPairs):
798 tmp = numpy.squeeze(cspectra[:,icr,ifreq,ih])
798 tmp = numpy.squeeze(cspectra[:,icr,ifreq,ih])
799 valid = (numpy.isfinite(tmp)==True).nonzero()
799 valid = (numpy.isfinite(tmp)==True).nonzero()
800 if len(valid[0]) > 0:
800 if len(valid[0]) > 0:
801 out_cspectra[icr,ifreq,ih] = numpy.nansum(tmp)#/len(valid[0])
801 out_cspectra[icr,ifreq,ih] = numpy.nansum(tmp)#/len(valid[0])
802 '''
802 '''
803 # print('##########################################################')
803 # print('##########################################################')
804 print("Removing fake coherent echoes (at least 4 points around the point)")
804 print("Removing fake coherent echoes (at least 4 points around the point)")
805
805
806 val_spectra = numpy.sum(val_spc,0)
806 val_spectra = numpy.sum(val_spc,0)
807 val_cspectra = numpy.sum(val_cspc,0)
807 val_cspectra = numpy.sum(val_cspc,0)
808
808
809 val_spectra = self.REM_ISOLATED_POINTS(val_spectra,4)
809 val_spectra = self.REM_ISOLATED_POINTS(val_spectra,4)
810 val_cspectra = self.REM_ISOLATED_POINTS(val_cspectra,4)
810 val_cspectra = self.REM_ISOLATED_POINTS(val_cspectra,4)
811
811
812 for i in range(nChan):
812 for i in range(nChan):
813 for j in range(nProf):
813 for j in range(nProf):
814 for k in range(nHeights):
814 for k in range(nHeights):
815 if numpy.isfinite(val_spectra[i,j,k]) and val_spectra[i,j,k] < 1 :
815 if numpy.isfinite(val_spectra[i,j,k]) and val_spectra[i,j,k] < 1 :
816 val_spc[:,i,j,k] = 0.0
816 val_spc[:,i,j,k] = 0.0
817 for i in range(nPairs):
817 for i in range(nPairs):
818 for j in range(nProf):
818 for j in range(nProf):
819 for k in range(nHeights):
819 for k in range(nHeights):
820 if numpy.isfinite(val_cspectra[i,j,k]) and val_cspectra[i,j,k] < 1 :
820 if numpy.isfinite(val_cspectra[i,j,k]) and val_cspectra[i,j,k] < 1 :
821 val_cspc[:,i,j,k] = 0.0
821 val_cspc[:,i,j,k] = 0.0
822
822
823 # val_spc = numpy.reshape(val_spc, (len(spectra[:,0,0,0]),nProf*nHeights*nChan))
823 # val_spc = numpy.reshape(val_spc, (len(spectra[:,0,0,0]),nProf*nHeights*nChan))
824 # if numpy.isfinite(val_spectra)==str(True):
824 # if numpy.isfinite(val_spectra)==str(True):
825 # noval = (val_spectra<1).nonzero()
825 # noval = (val_spectra<1).nonzero()
826 # if len(noval) > 0:
826 # if len(noval) > 0:
827 # val_spc[:,noval] = 0.0
827 # val_spc[:,noval] = 0.0
828 # val_spc = numpy.reshape(val_spc, (149,nChan,nProf,nHeights))
828 # val_spc = numpy.reshape(val_spc, (149,nChan,nProf,nHeights))
829
829
830 #val_cspc = numpy.reshape(val_spc, (149,nChan*nHeights*nProf))
830 #val_cspc = numpy.reshape(val_spc, (149,nChan*nHeights*nProf))
831 #if numpy.isfinite(val_cspectra)==str(True):
831 #if numpy.isfinite(val_cspectra)==str(True):
832 # noval = (val_cspectra<1).nonzero()
832 # noval = (val_cspectra<1).nonzero()
833 # if len(noval) > 0:
833 # if len(noval) > 0:
834 # val_cspc[:,noval] = 0.0
834 # val_cspc[:,noval] = 0.0
835 # val_cspc = numpy.reshape(val_cspc, (149,nChan,nProf,nHeights))
835 # val_cspc = numpy.reshape(val_cspc, (149,nChan,nProf,nHeights))
836 tmp_sat_spectra = spectra.copy()
836 tmp_sat_spectra = spectra.copy()
837 tmp_sat_spectra = tmp_sat_spectra*numpy.nan
837 tmp_sat_spectra = tmp_sat_spectra*numpy.nan
838 tmp_sat_cspectra = cspectra.copy()
838 tmp_sat_cspectra = cspectra.copy()
839 tmp_sat_cspectra = tmp_sat_cspectra*numpy.nan
839 tmp_sat_cspectra = tmp_sat_cspectra*numpy.nan
840 '''
840 '''
841 # fig = plt.figure(figsize=(6,5))
841 # fig = plt.figure(figsize=(6,5))
842 # left, bottom, width, height = 0.1, 0.1, 0.8, 0.8
842 # left, bottom, width, height = 0.1, 0.1, 0.8, 0.8
843 # ax = fig.add_axes([left, bottom, width, height])
843 # ax = fig.add_axes([left, bottom, width, height])
844 # cp = ax.contour(10*numpy.log10(numpy.absolute(spectra[0,0,:,:])))
844 # cp = ax.contour(10*numpy.log10(numpy.absolute(spectra[0,0,:,:])))
845 # ax.clabel(cp, inline=True,fontsize=10)
845 # ax.clabel(cp, inline=True,fontsize=10)
846 # plt.show()
846 # plt.show()
847 '''
847 '''
848 val = (val_spc > 0).nonzero()
848 val = (val_spc > 0).nonzero()
849 if len(val[0]) > 0:
849 if len(val[0]) > 0:
850 tmp_sat_spectra[val] = in_sat_spectra[val]
850 tmp_sat_spectra[val] = in_sat_spectra[val]
851 val = (val_cspc > 0).nonzero()
851 val = (val_cspc > 0).nonzero()
852 if len(val[0]) > 0:
852 if len(val[0]) > 0:
853 tmp_sat_cspectra[val] = in_sat_cspectra[val]
853 tmp_sat_cspectra[val] = in_sat_cspectra[val]
854
854
855 print("Getting average of the spectra and cross-spectra from incoherent echoes 2")
855 print("Getting average of the spectra and cross-spectra from incoherent echoes 2")
856 sat_spectra = numpy.zeros((nChan,nProf,nHeights), dtype=float)
856 sat_spectra = numpy.zeros((nChan,nProf,nHeights), dtype=float)
857 sat_cspectra = numpy.zeros((nPairs,nProf,nHeights), dtype=complex)
857 sat_cspectra = numpy.zeros((nPairs,nProf,nHeights), dtype=complex)
858 for ih in range(nHeights):
858 for ih in range(nHeights):
859 for ifreq in range(nProf):
859 for ifreq in range(nProf):
860 for ich in range(nChan):
860 for ich in range(nChan):
861 tmp = numpy.squeeze(tmp_sat_spectra[:,ich,ifreq,ih])
861 tmp = numpy.squeeze(tmp_sat_spectra[:,ich,ifreq,ih])
862 valid = (numpy.isfinite(tmp)).nonzero()
862 valid = (numpy.isfinite(tmp)).nonzero()
863 if len(valid[0]) > 0:
863 if len(valid[0]) > 0:
864 sat_spectra[ich,ifreq,ih] = numpy.nansum(tmp)/len(valid[0])
864 sat_spectra[ich,ifreq,ih] = numpy.nansum(tmp)/len(valid[0])
865
865
866 for icr in range(nPairs):
866 for icr in range(nPairs):
867 tmp = numpy.squeeze(tmp_sat_cspectra[:,icr,ifreq,ih])
867 tmp = numpy.squeeze(tmp_sat_cspectra[:,icr,ifreq,ih])
868 valid = (numpy.isfinite(tmp)).nonzero()
868 valid = (numpy.isfinite(tmp)).nonzero()
869 if len(valid[0]) > 0:
869 if len(valid[0]) > 0:
870 sat_cspectra[icr,ifreq,ih] = numpy.nansum(tmp)/len(valid[0])
870 sat_cspectra[icr,ifreq,ih] = numpy.nansum(tmp)/len(valid[0])
871 '''
871 '''
872 #self.__dataReady= True
872 #self.__dataReady= True
873 #sat_spectra, sat_cspectra= sat_spectra, sat_cspectra
873 #sat_spectra, sat_cspectra= sat_spectra, sat_cspectra
874 #if not self.__dataReady:
874 #if not self.__dataReady:
875 #return None, None
875 #return None, None
876 #return out_spectra, out_cspectra ,sat_spectra,sat_cspectra
876 #return out_spectra, out_cspectra ,sat_spectra,sat_cspectra
877 return out_spectra, out_cspectra
877 return out_spectra, out_cspectra
878
878
879 def REM_ISOLATED_POINTS(self,array,rth):
879 def REM_ISOLATED_POINTS(self,array,rth):
880 # import matplotlib.pyplot as plt
880 # import matplotlib.pyplot as plt
881 if rth == None :
881 if rth == None :
882 rth = 4
882 rth = 4
883 print("REM ISO")
883 print("REM ISO")
884 num_prof = len(array[0,:,0])
884 num_prof = len(array[0,:,0])
885 num_hei = len(array[0,0,:])
885 num_hei = len(array[0,0,:])
886 n2d = len(array[:,0,0])
886 n2d = len(array[:,0,0])
887
887
888 for ii in range(n2d) :
888 for ii in range(n2d) :
889 #print ii,n2d
889 #print ii,n2d
890 tmp = array[ii,:,:]
890 tmp = array[ii,:,:]
891 #print tmp.shape, array[ii,101,:],array[ii,102,:]
891 #print tmp.shape, array[ii,101,:],array[ii,102,:]
892
892
893 # fig = plt.figure(figsize=(6,5))
893 # fig = plt.figure(figsize=(6,5))
894 # left, bottom, width, height = 0.1, 0.1, 0.8, 0.8
894 # left, bottom, width, height = 0.1, 0.1, 0.8, 0.8
895 # ax = fig.add_axes([left, bottom, width, height])
895 # ax = fig.add_axes([left, bottom, width, height])
896 # x = range(num_prof)
896 # x = range(num_prof)
897 # y = range(num_hei)
897 # y = range(num_hei)
898 # cp = ax.contour(y,x,tmp)
898 # cp = ax.contour(y,x,tmp)
899 # ax.clabel(cp, inline=True,fontsize=10)
899 # ax.clabel(cp, inline=True,fontsize=10)
900 # plt.show()
900 # plt.show()
901
901
902 #indxs = WHERE(FINITE(tmp) AND tmp GT 0,cindxs)
902 #indxs = WHERE(FINITE(tmp) AND tmp GT 0,cindxs)
903 tmp = numpy.reshape(tmp,num_prof*num_hei)
903 tmp = numpy.reshape(tmp,num_prof*num_hei)
904 indxs1 = (numpy.isfinite(tmp)==True).nonzero()
904 indxs1 = (numpy.isfinite(tmp)==True).nonzero()
905 indxs2 = (tmp > 0).nonzero()
905 indxs2 = (tmp > 0).nonzero()
906
906
907 indxs1 = (indxs1[0])
907 indxs1 = (indxs1[0])
908 indxs2 = indxs2[0]
908 indxs2 = indxs2[0]
909 #indxs1 = numpy.array(indxs1[0])
909 #indxs1 = numpy.array(indxs1[0])
910 #indxs2 = numpy.array(indxs2[0])
910 #indxs2 = numpy.array(indxs2[0])
911 indxs = None
911 indxs = None
912 #print indxs1 , indxs2
912 #print indxs1 , indxs2
913 for iv in range(len(indxs2)):
913 for iv in range(len(indxs2)):
914 indv = numpy.array((indxs1 == indxs2[iv]).nonzero())
914 indv = numpy.array((indxs1 == indxs2[iv]).nonzero())
915 #print len(indxs2), indv
915 #print len(indxs2), indv
916 if len(indv[0]) > 0 :
916 if len(indv[0]) > 0 :
917 indxs = numpy.concatenate((indxs,indxs2[iv]), axis=None)
917 indxs = numpy.concatenate((indxs,indxs2[iv]), axis=None)
918 # print indxs
918 # print indxs
919 indxs = indxs[1:]
919 indxs = indxs[1:]
920 #print(indxs, len(indxs))
920 #print(indxs, len(indxs))
921 if len(indxs) < 4 :
921 if len(indxs) < 4 :
922 array[ii,:,:] = 0.
922 array[ii,:,:] = 0.
923 return
923 return
924
924
925 xpos = numpy.mod(indxs ,num_hei)
925 xpos = numpy.mod(indxs ,num_hei)
926 ypos = (indxs / num_hei)
926 ypos = (indxs / num_hei)
927 sx = numpy.argsort(xpos) # Ordering respect to "x" (time)
927 sx = numpy.argsort(xpos) # Ordering respect to "x" (time)
928 #print sx
928 #print sx
929 xpos = xpos[sx]
929 xpos = xpos[sx]
930 ypos = ypos[sx]
930 ypos = ypos[sx]
931
931
932 # *********************************** Cleaning isolated points **********************************
932 # *********************************** Cleaning isolated points **********************************
933 ic = 0
933 ic = 0
934 while True :
934 while True :
935 r = numpy.sqrt(list(numpy.power((xpos[ic]-xpos),2)+ numpy.power((ypos[ic]-ypos),2)))
935 r = numpy.sqrt(list(numpy.power((xpos[ic]-xpos),2)+ numpy.power((ypos[ic]-ypos),2)))
936 #no_coh = WHERE(FINITE(r) AND (r LE rth),cno_coh)
936 #no_coh = WHERE(FINITE(r) AND (r LE rth),cno_coh)
937 #plt.plot(r)
937 #plt.plot(r)
938 #plt.show()
938 #plt.show()
939 no_coh1 = (numpy.isfinite(r)==True).nonzero()
939 no_coh1 = (numpy.isfinite(r)==True).nonzero()
940 no_coh2 = (r <= rth).nonzero()
940 no_coh2 = (r <= rth).nonzero()
941 #print r, no_coh1, no_coh2
941 #print r, no_coh1, no_coh2
942 no_coh1 = numpy.array(no_coh1[0])
942 no_coh1 = numpy.array(no_coh1[0])
943 no_coh2 = numpy.array(no_coh2[0])
943 no_coh2 = numpy.array(no_coh2[0])
944 no_coh = None
944 no_coh = None
945 #print valid1 , valid2
945 #print valid1 , valid2
946 for iv in range(len(no_coh2)):
946 for iv in range(len(no_coh2)):
947 indv = numpy.array((no_coh1 == no_coh2[iv]).nonzero())
947 indv = numpy.array((no_coh1 == no_coh2[iv]).nonzero())
948 if len(indv[0]) > 0 :
948 if len(indv[0]) > 0 :
949 no_coh = numpy.concatenate((no_coh,no_coh2[iv]), axis=None)
949 no_coh = numpy.concatenate((no_coh,no_coh2[iv]), axis=None)
950 no_coh = no_coh[1:]
950 no_coh = no_coh[1:]
951 #print len(no_coh), no_coh
951 #print len(no_coh), no_coh
952 if len(no_coh) < 4 :
952 if len(no_coh) < 4 :
953 #print xpos[ic], ypos[ic], ic
953 #print xpos[ic], ypos[ic], ic
954 # plt.plot(r)
954 # plt.plot(r)
955 # plt.show()
955 # plt.show()
956 xpos[ic] = numpy.nan
956 xpos[ic] = numpy.nan
957 ypos[ic] = numpy.nan
957 ypos[ic] = numpy.nan
958
958
959 ic = ic + 1
959 ic = ic + 1
960 if (ic == len(indxs)) :
960 if (ic == len(indxs)) :
961 break
961 break
962 #print( xpos, ypos)
962 #print( xpos, ypos)
963
963
964 indxs = (numpy.isfinite(list(xpos))==True).nonzero()
964 indxs = (numpy.isfinite(list(xpos))==True).nonzero()
965 #print indxs[0]
965 #print indxs[0]
966 if len(indxs[0]) < 4 :
966 if len(indxs[0]) < 4 :
967 array[ii,:,:] = 0.
967 array[ii,:,:] = 0.
968 return
968 return
969
969
970 xpos = xpos[indxs[0]]
970 xpos = xpos[indxs[0]]
971 ypos = ypos[indxs[0]]
971 ypos = ypos[indxs[0]]
972 for i in range(0,len(ypos)):
972 for i in range(0,len(ypos)):
973 ypos[i]=int(ypos[i])
973 ypos[i]=int(ypos[i])
974 junk = tmp
974 junk = tmp
975 tmp = junk*0.0
975 tmp = junk*0.0
976
976
977 tmp[list(xpos + (ypos*num_hei))] = junk[list(xpos + (ypos*num_hei))]
977 tmp[list(xpos + (ypos*num_hei))] = junk[list(xpos + (ypos*num_hei))]
978 array[ii,:,:] = numpy.reshape(tmp,(num_prof,num_hei))
978 array[ii,:,:] = numpy.reshape(tmp,(num_prof,num_hei))
979
979
980 #print array.shape
980 #print array.shape
981 #tmp = numpy.reshape(tmp,(num_prof,num_hei))
981 #tmp = numpy.reshape(tmp,(num_prof,num_hei))
982 #print tmp.shape
982 #print tmp.shape
983
983
984 # fig = plt.figure(figsize=(6,5))
984 # fig = plt.figure(figsize=(6,5))
985 # left, bottom, width, height = 0.1, 0.1, 0.8, 0.8
985 # left, bottom, width, height = 0.1, 0.1, 0.8, 0.8
986 # ax = fig.add_axes([left, bottom, width, height])
986 # ax = fig.add_axes([left, bottom, width, height])
987 # x = range(num_prof)
987 # x = range(num_prof)
988 # y = range(num_hei)
988 # y = range(num_hei)
989 # cp = ax.contour(y,x,array[ii,:,:])
989 # cp = ax.contour(y,x,array[ii,:,:])
990 # ax.clabel(cp, inline=True,fontsize=10)
990 # ax.clabel(cp, inline=True,fontsize=10)
991 # plt.show()
991 # plt.show()
992 return array
992 return array
993
993
994 class removeInterference(Operation):
994 class removeInterference(Operation):
995
995
996 def removeInterference2(self):
996 def removeInterference2(self):
997
997
998 cspc = self.dataOut.data_cspc
998 cspc = self.dataOut.data_cspc
999 spc = self.dataOut.data_spc
999 spc = self.dataOut.data_spc
1000 Heights = numpy.arange(cspc.shape[2])
1000 Heights = numpy.arange(cspc.shape[2])
1001 realCspc = numpy.abs(cspc)
1001 realCspc = numpy.abs(cspc)
1002
1002
1003 for i in range(cspc.shape[0]):
1003 for i in range(cspc.shape[0]):
1004 LinePower= numpy.sum(realCspc[i], axis=0)
1004 LinePower= numpy.sum(realCspc[i], axis=0)
1005 Threshold = numpy.amax(LinePower)-numpy.sort(LinePower)[len(Heights)-int(len(Heights)*0.1)]
1005 Threshold = numpy.amax(LinePower)-numpy.sort(LinePower)[len(Heights)-int(len(Heights)*0.1)]
1006 SelectedHeights = Heights[ numpy.where( LinePower < Threshold ) ]
1006 SelectedHeights = Heights[ numpy.where( LinePower < Threshold ) ]
1007 InterferenceSum = numpy.sum( realCspc[i,:,SelectedHeights], axis=0 )
1007 InterferenceSum = numpy.sum( realCspc[i,:,SelectedHeights], axis=0 )
1008 InterferenceThresholdMin = numpy.sort(InterferenceSum)[int(len(InterferenceSum)*0.98)]
1008 InterferenceThresholdMin = numpy.sort(InterferenceSum)[int(len(InterferenceSum)*0.98)]
1009 InterferenceThresholdMax = numpy.sort(InterferenceSum)[int(len(InterferenceSum)*0.99)]
1009 InterferenceThresholdMax = numpy.sort(InterferenceSum)[int(len(InterferenceSum)*0.99)]
1010
1010
1011
1011
1012 InterferenceRange = numpy.where( ([InterferenceSum > InterferenceThresholdMin]))# , InterferenceSum < InterferenceThresholdMax]) )
1012 InterferenceRange = numpy.where( ([InterferenceSum > InterferenceThresholdMin]))# , InterferenceSum < InterferenceThresholdMax]) )
1013 #InterferenceRange = numpy.where( ([InterferenceRange < InterferenceThresholdMax]))
1013 #InterferenceRange = numpy.where( ([InterferenceRange < InterferenceThresholdMax]))
1014 if len(InterferenceRange)<int(cspc.shape[1]*0.3):
1014 if len(InterferenceRange)<int(cspc.shape[1]*0.3):
1015 cspc[i,InterferenceRange,:] = numpy.NaN
1015 cspc[i,InterferenceRange,:] = numpy.NaN
1016
1016
1017 self.dataOut.data_cspc = cspc
1017 self.dataOut.data_cspc = cspc
1018
1018
1019 def removeInterference(self, interf = 2, hei_interf = None, nhei_interf = None, offhei_interf = None):
1019 def removeInterference(self, interf = 2, hei_interf = None, nhei_interf = None, offhei_interf = None):
1020
1020
1021 jspectra = self.dataOut.data_spc
1021 jspectra = self.dataOut.data_spc
1022 jcspectra = self.dataOut.data_cspc
1022 jcspectra = self.dataOut.data_cspc
1023 jnoise = self.dataOut.getNoise()
1023 jnoise = self.dataOut.getNoise()
1024 num_incoh = self.dataOut.nIncohInt
1024 num_incoh = self.dataOut.nIncohInt
1025
1025
1026 num_channel = jspectra.shape[0]
1026 num_channel = jspectra.shape[0]
1027 num_prof = jspectra.shape[1]
1027 num_prof = jspectra.shape[1]
1028 num_hei = jspectra.shape[2]
1028 num_hei = jspectra.shape[2]
1029
1029
1030 # hei_interf
1030 # hei_interf
1031 if hei_interf is None:
1031 if hei_interf is None:
1032 count_hei = int(num_hei / 2)
1032 count_hei = int(num_hei / 2)
1033 hei_interf = numpy.asmatrix(list(range(count_hei))) + num_hei - count_hei
1033 hei_interf = numpy.asmatrix(list(range(count_hei))) + num_hei - count_hei
1034 hei_interf = numpy.asarray(hei_interf)[0]
1034 hei_interf = numpy.asarray(hei_interf)[0]
1035 # nhei_interf
1035 # nhei_interf
1036 if (nhei_interf == None):
1036 if (nhei_interf == None):
1037 nhei_interf = 5
1037 nhei_interf = 5
1038 if (nhei_interf < 1):
1038 if (nhei_interf < 1):
1039 nhei_interf = 1
1039 nhei_interf = 1
1040 if (nhei_interf > count_hei):
1040 if (nhei_interf > count_hei):
1041 nhei_interf = count_hei
1041 nhei_interf = count_hei
1042 if (offhei_interf == None):
1042 if (offhei_interf == None):
1043 offhei_interf = 0
1043 offhei_interf = 0
1044
1044
1045 ind_hei = list(range(num_hei))
1045 ind_hei = list(range(num_hei))
1046 # mask_prof = numpy.asarray(range(num_prof - 2)) + 1
1046 # mask_prof = numpy.asarray(range(num_prof - 2)) + 1
1047 # mask_prof[range(num_prof/2 - 1,len(mask_prof))] += 1
1047 # mask_prof[range(num_prof/2 - 1,len(mask_prof))] += 1
1048 mask_prof = numpy.asarray(list(range(num_prof)))
1048 mask_prof = numpy.asarray(list(range(num_prof)))
1049 num_mask_prof = mask_prof.size
1049 num_mask_prof = mask_prof.size
1050 comp_mask_prof = [0, num_prof / 2]
1050 comp_mask_prof = [0, num_prof / 2]
1051
1051
1052 # noise_exist: Determina si la variable jnoise ha sido definida y contiene la informacion del ruido de cada canal
1052 # noise_exist: Determina si la variable jnoise ha sido definida y contiene la informacion del ruido de cada canal
1053 if (jnoise.size < num_channel or numpy.isnan(jnoise).any()):
1053 if (jnoise.size < num_channel or numpy.isnan(jnoise).any()):
1054 jnoise = numpy.nan
1054 jnoise = numpy.nan
1055 noise_exist = jnoise[0] < numpy.Inf
1055 noise_exist = jnoise[0] < numpy.Inf
1056
1056
1057 # Subrutina de Remocion de la Interferencia
1057 # Subrutina de Remocion de la Interferencia
1058 for ich in range(num_channel):
1058 for ich in range(num_channel):
1059 # Se ordena los espectros segun su potencia (menor a mayor)
1059 # Se ordena los espectros segun su potencia (menor a mayor)
1060 power = jspectra[ich, mask_prof, :]
1060 power = jspectra[ich, mask_prof, :]
1061 power = power[:, hei_interf]
1061 power = power[:, hei_interf]
1062 power = power.sum(axis=0)
1062 power = power.sum(axis=0)
1063 psort = power.ravel().argsort()
1063 psort = power.ravel().argsort()
1064
1064
1065 # Se estima la interferencia promedio en los Espectros de Potencia empleando
1065 # Se estima la interferencia promedio en los Espectros de Potencia empleando
1066 junkspc_interf = jspectra[ich, :, hei_interf[psort[list(range(
1066 junkspc_interf = jspectra[ich, :, hei_interf[psort[list(range(
1067 offhei_interf, nhei_interf + offhei_interf))]]]
1067 offhei_interf, nhei_interf + offhei_interf))]]]
1068
1068
1069 if noise_exist:
1069 if noise_exist:
1070 # tmp_noise = jnoise[ich] / num_prof
1070 # tmp_noise = jnoise[ich] / num_prof
1071 tmp_noise = jnoise[ich]
1071 tmp_noise = jnoise[ich]
1072 junkspc_interf = junkspc_interf - tmp_noise
1072 junkspc_interf = junkspc_interf - tmp_noise
1073 #junkspc_interf[:,comp_mask_prof] = 0
1073 #junkspc_interf[:,comp_mask_prof] = 0
1074
1074
1075 jspc_interf = junkspc_interf.sum(axis=0) / nhei_interf
1075 jspc_interf = junkspc_interf.sum(axis=0) / nhei_interf
1076 jspc_interf = jspc_interf.transpose()
1076 jspc_interf = jspc_interf.transpose()
1077 # Calculando el espectro de interferencia promedio
1077 # Calculando el espectro de interferencia promedio
1078 noiseid = numpy.where(
1078 noiseid = numpy.where(
1079 jspc_interf <= tmp_noise / numpy.sqrt(num_incoh))
1079 jspc_interf <= tmp_noise / numpy.sqrt(num_incoh))
1080 noiseid = noiseid[0]
1080 noiseid = noiseid[0]
1081 cnoiseid = noiseid.size
1081 cnoiseid = noiseid.size
1082 interfid = numpy.where(
1082 interfid = numpy.where(
1083 jspc_interf > tmp_noise / numpy.sqrt(num_incoh))
1083 jspc_interf > tmp_noise / numpy.sqrt(num_incoh))
1084 interfid = interfid[0]
1084 interfid = interfid[0]
1085 cinterfid = interfid.size
1085 cinterfid = interfid.size
1086
1086
1087 if (cnoiseid > 0):
1087 if (cnoiseid > 0):
1088 jspc_interf[noiseid] = 0
1088 jspc_interf[noiseid] = 0
1089
1089
1090 # Expandiendo los perfiles a limpiar
1090 # Expandiendo los perfiles a limpiar
1091 if (cinterfid > 0):
1091 if (cinterfid > 0):
1092 new_interfid = (
1092 new_interfid = (
1093 numpy.r_[interfid - 1, interfid, interfid + 1] + num_prof) % num_prof
1093 numpy.r_[interfid - 1, interfid, interfid + 1] + num_prof) % num_prof
1094 new_interfid = numpy.asarray(new_interfid)
1094 new_interfid = numpy.asarray(new_interfid)
1095 new_interfid = {x for x in new_interfid}
1095 new_interfid = {x for x in new_interfid}
1096 new_interfid = numpy.array(list(new_interfid))
1096 new_interfid = numpy.array(list(new_interfid))
1097 new_cinterfid = new_interfid.size
1097 new_cinterfid = new_interfid.size
1098 else:
1098 else:
1099 new_cinterfid = 0
1099 new_cinterfid = 0
1100
1100
1101 for ip in range(new_cinterfid):
1101 for ip in range(new_cinterfid):
1102 ind = junkspc_interf[:, new_interfid[ip]].ravel().argsort()
1102 ind = junkspc_interf[:, new_interfid[ip]].ravel().argsort()
1103 jspc_interf[new_interfid[ip]
1103 jspc_interf[new_interfid[ip]
1104 ] = junkspc_interf[ind[nhei_interf // 2], new_interfid[ip]]
1104 ] = junkspc_interf[ind[nhei_interf // 2], new_interfid[ip]]
1105
1105
1106 jspectra[ich, :, ind_hei] = jspectra[ich, :,
1106 jspectra[ich, :, ind_hei] = jspectra[ich, :,
1107 ind_hei] - jspc_interf # Corregir indices
1107 ind_hei] - jspc_interf # Corregir indices
1108
1108
1109 # Removiendo la interferencia del punto de mayor interferencia
1109 # Removiendo la interferencia del punto de mayor interferencia
1110 ListAux = jspc_interf[mask_prof].tolist()
1110 ListAux = jspc_interf[mask_prof].tolist()
1111 maxid = ListAux.index(max(ListAux))
1111 maxid = ListAux.index(max(ListAux))
1112
1112
1113 if cinterfid > 0:
1113 if cinterfid > 0:
1114 for ip in range(cinterfid * (interf == 2) - 1):
1114 for ip in range(cinterfid * (interf == 2) - 1):
1115 ind = (jspectra[ich, interfid[ip], :] < tmp_noise *
1115 ind = (jspectra[ich, interfid[ip], :] < tmp_noise *
1116 (1 + 1 / numpy.sqrt(num_incoh))).nonzero()
1116 (1 + 1 / numpy.sqrt(num_incoh))).nonzero()
1117 cind = len(ind)
1117 cind = len(ind)
1118
1118
1119 if (cind > 0):
1119 if (cind > 0):
1120 jspectra[ich, interfid[ip], ind] = tmp_noise * \
1120 jspectra[ich, interfid[ip], ind] = tmp_noise * \
1121 (1 + (numpy.random.uniform(cind) - 0.5) /
1121 (1 + (numpy.random.uniform(cind) - 0.5) /
1122 numpy.sqrt(num_incoh))
1122 numpy.sqrt(num_incoh))
1123
1123
1124 ind = numpy.array([-2, -1, 1, 2])
1124 ind = numpy.array([-2, -1, 1, 2])
1125 xx = numpy.zeros([4, 4])
1125 xx = numpy.zeros([4, 4])
1126
1126
1127 for id1 in range(4):
1127 for id1 in range(4):
1128 xx[:, id1] = ind[id1]**numpy.asarray(list(range(4)))
1128 xx[:, id1] = ind[id1]**numpy.asarray(list(range(4)))
1129
1129
1130 xx_inv = numpy.linalg.inv(xx)
1130 xx_inv = numpy.linalg.inv(xx)
1131 xx = xx_inv[:, 0]
1131 xx = xx_inv[:, 0]
1132 ind = (ind + maxid + num_mask_prof) % num_mask_prof
1132 ind = (ind + maxid + num_mask_prof) % num_mask_prof
1133 yy = jspectra[ich, mask_prof[ind], :]
1133 yy = jspectra[ich, mask_prof[ind], :]
1134 jspectra[ich, mask_prof[maxid], :] = numpy.dot(
1134 jspectra[ich, mask_prof[maxid], :] = numpy.dot(
1135 yy.transpose(), xx)
1135 yy.transpose(), xx)
1136
1136
1137 indAux = (jspectra[ich, :, :] < tmp_noise *
1137 indAux = (jspectra[ich, :, :] < tmp_noise *
1138 (1 - 1 / numpy.sqrt(num_incoh))).nonzero()
1138 (1 - 1 / numpy.sqrt(num_incoh))).nonzero()
1139 jspectra[ich, indAux[0], indAux[1]] = tmp_noise * \
1139 jspectra[ich, indAux[0], indAux[1]] = tmp_noise * \
1140 (1 - 1 / numpy.sqrt(num_incoh))
1140 (1 - 1 / numpy.sqrt(num_incoh))
1141
1141
1142 # Remocion de Interferencia en el Cross Spectra
1142 # Remocion de Interferencia en el Cross Spectra
1143 if jcspectra is None:
1143 if jcspectra is None:
1144 return jspectra, jcspectra
1144 return jspectra, jcspectra
1145 num_pairs = int(jcspectra.size / (num_prof * num_hei))
1145 num_pairs = int(jcspectra.size / (num_prof * num_hei))
1146 jcspectra = jcspectra.reshape(num_pairs, num_prof, num_hei)
1146 jcspectra = jcspectra.reshape(num_pairs, num_prof, num_hei)
1147
1147
1148 for ip in range(num_pairs):
1148 for ip in range(num_pairs):
1149
1149
1150 #-------------------------------------------
1150 #-------------------------------------------
1151
1151
1152 cspower = numpy.abs(jcspectra[ip, mask_prof, :])
1152 cspower = numpy.abs(jcspectra[ip, mask_prof, :])
1153 cspower = cspower[:, hei_interf]
1153 cspower = cspower[:, hei_interf]
1154 cspower = cspower.sum(axis=0)
1154 cspower = cspower.sum(axis=0)
1155
1155
1156 cspsort = cspower.ravel().argsort()
1156 cspsort = cspower.ravel().argsort()
1157 junkcspc_interf = jcspectra[ip, :, hei_interf[cspsort[list(range(
1157 junkcspc_interf = jcspectra[ip, :, hei_interf[cspsort[list(range(
1158 offhei_interf, nhei_interf + offhei_interf))]]]
1158 offhei_interf, nhei_interf + offhei_interf))]]]
1159 junkcspc_interf = junkcspc_interf.transpose()
1159 junkcspc_interf = junkcspc_interf.transpose()
1160 jcspc_interf = junkcspc_interf.sum(axis=1) / nhei_interf
1160 jcspc_interf = junkcspc_interf.sum(axis=1) / nhei_interf
1161
1161
1162 ind = numpy.abs(jcspc_interf[mask_prof]).ravel().argsort()
1162 ind = numpy.abs(jcspc_interf[mask_prof]).ravel().argsort()
1163
1163
1164 median_real = int(numpy.median(numpy.real(
1164 median_real = int(numpy.median(numpy.real(
1165 junkcspc_interf[mask_prof[ind[list(range(3 * num_prof // 4))]], :])))
1165 junkcspc_interf[mask_prof[ind[list(range(3 * num_prof // 4))]], :])))
1166 median_imag = int(numpy.median(numpy.imag(
1166 median_imag = int(numpy.median(numpy.imag(
1167 junkcspc_interf[mask_prof[ind[list(range(3 * num_prof // 4))]], :])))
1167 junkcspc_interf[mask_prof[ind[list(range(3 * num_prof // 4))]], :])))
1168 comp_mask_prof = [int(e) for e in comp_mask_prof]
1168 comp_mask_prof = [int(e) for e in comp_mask_prof]
1169 junkcspc_interf[comp_mask_prof, :] = numpy.complex(
1169 junkcspc_interf[comp_mask_prof, :] = numpy.complex(
1170 median_real, median_imag)
1170 median_real, median_imag)
1171
1171
1172 for iprof in range(num_prof):
1172 for iprof in range(num_prof):
1173 ind = numpy.abs(junkcspc_interf[iprof, :]).ravel().argsort()
1173 ind = numpy.abs(junkcspc_interf[iprof, :]).ravel().argsort()
1174 jcspc_interf[iprof] = junkcspc_interf[iprof, ind[nhei_interf // 2]]
1174 jcspc_interf[iprof] = junkcspc_interf[iprof, ind[nhei_interf // 2]]
1175
1175
1176 # Removiendo la Interferencia
1176 # Removiendo la Interferencia
1177 jcspectra[ip, :, ind_hei] = jcspectra[ip,
1177 jcspectra[ip, :, ind_hei] = jcspectra[ip,
1178 :, ind_hei] - jcspc_interf
1178 :, ind_hei] - jcspc_interf
1179
1179
1180 ListAux = numpy.abs(jcspc_interf[mask_prof]).tolist()
1180 ListAux = numpy.abs(jcspc_interf[mask_prof]).tolist()
1181 maxid = ListAux.index(max(ListAux))
1181 maxid = ListAux.index(max(ListAux))
1182
1182
1183 ind = numpy.array([-2, -1, 1, 2])
1183 ind = numpy.array([-2, -1, 1, 2])
1184 xx = numpy.zeros([4, 4])
1184 xx = numpy.zeros([4, 4])
1185
1185
1186 for id1 in range(4):
1186 for id1 in range(4):
1187 xx[:, id1] = ind[id1]**numpy.asarray(list(range(4)))
1187 xx[:, id1] = ind[id1]**numpy.asarray(list(range(4)))
1188
1188
1189 xx_inv = numpy.linalg.inv(xx)
1189 xx_inv = numpy.linalg.inv(xx)
1190 xx = xx_inv[:, 0]
1190 xx = xx_inv[:, 0]
1191
1191
1192 ind = (ind + maxid + num_mask_prof) % num_mask_prof
1192 ind = (ind + maxid + num_mask_prof) % num_mask_prof
1193 yy = jcspectra[ip, mask_prof[ind], :]
1193 yy = jcspectra[ip, mask_prof[ind], :]
1194 jcspectra[ip, mask_prof[maxid], :] = numpy.dot(yy.transpose(), xx)
1194 jcspectra[ip, mask_prof[maxid], :] = numpy.dot(yy.transpose(), xx)
1195
1195
1196 # Guardar Resultados
1196 # Guardar Resultados
1197 self.dataOut.data_spc = jspectra
1197 self.dataOut.data_spc = jspectra
1198 self.dataOut.data_cspc = jcspectra
1198 self.dataOut.data_cspc = jcspectra
1199
1199
1200 return 1
1200 return 1
1201
1201
1202 def run(self, dataOut, interf = 2,hei_interf = None, nhei_interf = None, offhei_interf = None, mode=1):
1202 def run(self, dataOut, interf = 2,hei_interf = None, nhei_interf = None, offhei_interf = None, mode=1):
1203
1203
1204 self.dataOut = dataOut
1204 self.dataOut = dataOut
1205
1205
1206 if mode == 1:
1206 if mode == 1:
1207 self.removeInterference(interf = 2,hei_interf = None, nhei_interf = None, offhei_interf = None)
1207 self.removeInterference(interf = 2,hei_interf = None, nhei_interf = None, offhei_interf = None)
1208 elif mode == 2:
1208 elif mode == 2:
1209 self.removeInterference2()
1209 self.removeInterference2()
1210
1210
1211 return self.dataOut
1211 return self.dataOut
1212
1212
1213
1213
1214 class IncohInt(Operation):
1214 class IncohInt(Operation):
1215
1215
1216 __profIndex = 0
1216 __profIndex = 0
1217 __withOverapping = False
1217 __withOverapping = False
1218
1218
1219 __byTime = False
1219 __byTime = False
1220 __initime = None
1220 __initime = None
1221 __lastdatatime = None
1221 __lastdatatime = None
1222 __integrationtime = None
1222 __integrationtime = None
1223
1223
1224 __buffer_spc = None
1224 __buffer_spc = None
1225 __buffer_cspc = None
1225 __buffer_cspc = None
1226 __buffer_dc = None
1226 __buffer_dc = None
1227
1227
1228 __dataReady = False
1228 __dataReady = False
1229
1229
1230 __timeInterval = None
1230 __timeInterval = None
1231
1231
1232 n = None
1232 n = None
1233
1233
1234 def __init__(self):
1234 def __init__(self):
1235
1235
1236 Operation.__init__(self)
1236 Operation.__init__(self)
1237
1237
1238 def setup(self, n=None, timeInterval=None, overlapping=False):
1238 def setup(self, n=None, timeInterval=None, overlapping=False):
1239 """
1239 """
1240 Set the parameters of the integration class.
1240 Set the parameters of the integration class.
1241
1241
1242 Inputs:
1242 Inputs:
1243
1243
1244 n : Number of coherent integrations
1244 n : Number of coherent integrations
1245 timeInterval : Time of integration. If the parameter "n" is selected this one does not work
1245 timeInterval : Time of integration. If the parameter "n" is selected this one does not work
1246 overlapping :
1246 overlapping :
1247
1247
1248 """
1248 """
1249
1249
1250 self.__initime = None
1250 self.__initime = None
1251 self.__lastdatatime = 0
1251 self.__lastdatatime = 0
1252
1252
1253 self.__buffer_spc = 0
1253 self.__buffer_spc = 0
1254 self.__buffer_cspc = 0
1254 self.__buffer_cspc = 0
1255 self.__buffer_dc = 0
1255 self.__buffer_dc = 0
1256
1256
1257 self.__profIndex = 0
1257 self.__profIndex = 0
1258 self.__dataReady = False
1258 self.__dataReady = False
1259 self.__byTime = False
1259 self.__byTime = False
1260
1260
1261 if n is None and timeInterval is None:
1261 if n is None and timeInterval is None:
1262 raise ValueError("n or timeInterval should be specified ...")
1262 raise ValueError("n or timeInterval should be specified ...")
1263
1263
1264 if n is not None:
1264 if n is not None:
1265 self.n = int(n)
1265 self.n = int(n)
1266 else:
1266 else:
1267
1267
1268 self.__integrationtime = int(timeInterval)
1268 self.__integrationtime = int(timeInterval)
1269 self.n = None
1269 self.n = None
1270 self.__byTime = True
1270 self.__byTime = True
1271
1271
1272 def putData(self, data_spc, data_cspc, data_dc):
1272 def putData(self, data_spc, data_cspc, data_dc):
1273 """
1273 """
1274 Add a profile to the __buffer_spc and increase in one the __profileIndex
1274 Add a profile to the __buffer_spc and increase in one the __profileIndex
1275
1275
1276 """
1276 """
1277
1277
1278 self.__buffer_spc += data_spc
1278 self.__buffer_spc += data_spc
1279
1279
1280 if data_cspc is None:
1280 if data_cspc is None:
1281 self.__buffer_cspc = None
1281 self.__buffer_cspc = None
1282 else:
1282 else:
1283 self.__buffer_cspc += data_cspc
1283 self.__buffer_cspc += data_cspc
1284
1284
1285 if data_dc is None:
1285 if data_dc is None:
1286 self.__buffer_dc = None
1286 self.__buffer_dc = None
1287 else:
1287 else:
1288 self.__buffer_dc += data_dc
1288 self.__buffer_dc += data_dc
1289
1289
1290 self.__profIndex += 1
1290 self.__profIndex += 1
1291
1291
1292 return
1292 return
1293
1293
1294 def pushData(self):
1294 def pushData(self):
1295 """
1295 """
1296 Return the sum of the last profiles and the profiles used in the sum.
1296 Return the sum of the last profiles and the profiles used in the sum.
1297
1297
1298 Affected:
1298 Affected:
1299
1299
1300 self.__profileIndex
1300 self.__profileIndex
1301
1301
1302 """
1302 """
1303
1303
1304 data_spc = self.__buffer_spc
1304 data_spc = self.__buffer_spc
1305 data_cspc = self.__buffer_cspc
1305 data_cspc = self.__buffer_cspc
1306 data_dc = self.__buffer_dc
1306 data_dc = self.__buffer_dc
1307 n = self.__profIndex
1307 n = self.__profIndex
1308
1308
1309 self.__buffer_spc = 0
1309 self.__buffer_spc = 0
1310 self.__buffer_cspc = 0
1310 self.__buffer_cspc = 0
1311 self.__buffer_dc = 0
1311 self.__buffer_dc = 0
1312 self.__profIndex = 0
1312 self.__profIndex = 0
1313
1313
1314 return data_spc, data_cspc, data_dc, n
1314 return data_spc, data_cspc, data_dc, n
1315
1315
1316 def byProfiles(self, *args):
1316 def byProfiles(self, *args):
1317
1317
1318 self.__dataReady = False
1318 self.__dataReady = False
1319 avgdata_spc = None
1319 avgdata_spc = None
1320 avgdata_cspc = None
1320 avgdata_cspc = None
1321 avgdata_dc = None
1321 avgdata_dc = None
1322
1322
1323 self.putData(*args)
1323 self.putData(*args)
1324
1324
1325 if self.__profIndex == self.n:
1325 if self.__profIndex == self.n:
1326
1326
1327 avgdata_spc, avgdata_cspc, avgdata_dc, n = self.pushData()
1327 avgdata_spc, avgdata_cspc, avgdata_dc, n = self.pushData()
1328 self.n = n
1328 self.n = n
1329 self.__dataReady = True
1329 self.__dataReady = True
1330
1330
1331 return avgdata_spc, avgdata_cspc, avgdata_dc
1331 return avgdata_spc, avgdata_cspc, avgdata_dc
1332
1332
1333 def byTime(self, datatime, *args):
1333 def byTime(self, datatime, *args):
1334
1334
1335 self.__dataReady = False
1335 self.__dataReady = False
1336 avgdata_spc = None
1336 avgdata_spc = None
1337 avgdata_cspc = None
1337 avgdata_cspc = None
1338 avgdata_dc = None
1338 avgdata_dc = None
1339
1339
1340 self.putData(*args)
1340 self.putData(*args)
1341
1341
1342 if (datatime - self.__initime) >= self.__integrationtime:
1342 if (datatime - self.__initime) >= self.__integrationtime:
1343 avgdata_spc, avgdata_cspc, avgdata_dc, n = self.pushData()
1343 avgdata_spc, avgdata_cspc, avgdata_dc, n = self.pushData()
1344 self.n = n
1344 self.n = n
1345 self.__dataReady = True
1345 self.__dataReady = True
1346
1346
1347 return avgdata_spc, avgdata_cspc, avgdata_dc
1347 return avgdata_spc, avgdata_cspc, avgdata_dc
1348
1348
1349 def integrate(self, datatime, *args):
1349 def integrate(self, datatime, *args):
1350
1350
1351 if self.__profIndex == 0:
1351 if self.__profIndex == 0:
1352 self.__initime = datatime
1352 self.__initime = datatime
1353
1353
1354 if self.__byTime:
1354 if self.__byTime:
1355 avgdata_spc, avgdata_cspc, avgdata_dc = self.byTime(
1355 avgdata_spc, avgdata_cspc, avgdata_dc = self.byTime(
1356 datatime, *args)
1356 datatime, *args)
1357 else:
1357 else:
1358 avgdata_spc, avgdata_cspc, avgdata_dc = self.byProfiles(*args)
1358 avgdata_spc, avgdata_cspc, avgdata_dc = self.byProfiles(*args)
1359
1359
1360 if not self.__dataReady:
1360 if not self.__dataReady:
1361 return None, None, None, None
1361 return None, None, None, None
1362
1362
1363 return self.__initime, avgdata_spc, avgdata_cspc, avgdata_dc
1363 return self.__initime, avgdata_spc, avgdata_cspc, avgdata_dc
1364
1364
1365 def run(self, dataOut, n=None, timeInterval=None, overlapping=False):
1365 def run(self, dataOut, n=None, timeInterval=None, overlapping=False):
1366 if n == 1:
1366 if n == 1:
1367 return dataOut
1367 return dataOut
1368
1368
1369 dataOut.flagNoData = True
1369 dataOut.flagNoData = True
1370
1370
1371 if not self.isConfig:
1371 if not self.isConfig:
1372 self.setup(n, timeInterval, overlapping)
1372 self.setup(n, timeInterval, overlapping)
1373 self.isConfig = True
1373 self.isConfig = True
1374
1374
1375 avgdatatime, avgdata_spc, avgdata_cspc, avgdata_dc = self.integrate(dataOut.utctime,
1375 avgdatatime, avgdata_spc, avgdata_cspc, avgdata_dc = self.integrate(dataOut.utctime,
1376 dataOut.data_spc,
1376 dataOut.data_spc,
1377 dataOut.data_cspc,
1377 dataOut.data_cspc,
1378 dataOut.data_dc)
1378 dataOut.data_dc)
1379
1379
1380 if self.__dataReady:
1380 if self.__dataReady:
1381
1381
1382 dataOut.data_spc = avgdata_spc
1382 dataOut.data_spc = avgdata_spc
1383 dataOut.data_cspc = avgdata_cspc
1383 dataOut.data_cspc = avgdata_cspc
1384 dataOut.data_dc = avgdata_dc
1384 dataOut.data_dc = avgdata_dc
1385 dataOut.nIncohInt *= self.n
1385 dataOut.nIncohInt *= self.n
1386 dataOut.utctime = avgdatatime
1386 dataOut.utctime = avgdatatime
1387 dataOut.flagNoData = False
1387 dataOut.flagNoData = False
1388
1388
1389 return dataOut
1389 return dataOut
1390
1390
1391 class dopplerFlip(Operation):
1391 class dopplerFlip(Operation):
1392
1392
1393 def run(self, dataOut):
1393 def run(self, dataOut):
1394 # arreglo 1: (num_chan, num_profiles, num_heights)
1394 # arreglo 1: (num_chan, num_profiles, num_heights)
1395 self.dataOut = dataOut
1395 self.dataOut = dataOut
1396 # JULIA-oblicua, indice 2
1396 # JULIA-oblicua, indice 2
1397 # arreglo 2: (num_profiles, num_heights)
1397 # arreglo 2: (num_profiles, num_heights)
1398 jspectra = self.dataOut.data_spc[2]
1398 jspectra = self.dataOut.data_spc[2]
1399 jspectra_tmp = numpy.zeros(jspectra.shape)
1399 jspectra_tmp = numpy.zeros(jspectra.shape)
1400 num_profiles = jspectra.shape[0]
1400 num_profiles = jspectra.shape[0]
1401 freq_dc = int(num_profiles / 2)
1401 freq_dc = int(num_profiles / 2)
1402 # Flip con for
1402 # Flip con for
1403 for j in range(num_profiles):
1403 for j in range(num_profiles):
1404 jspectra_tmp[num_profiles-j-1]= jspectra[j]
1404 jspectra_tmp[num_profiles-j-1]= jspectra[j]
1405 # Intercambio perfil de DC con perfil inmediato anterior
1405 # Intercambio perfil de DC con perfil inmediato anterior
1406 jspectra_tmp[freq_dc-1]= jspectra[freq_dc-1]
1406 jspectra_tmp[freq_dc-1]= jspectra[freq_dc-1]
1407 jspectra_tmp[freq_dc]= jspectra[freq_dc]
1407 jspectra_tmp[freq_dc]= jspectra[freq_dc]
1408 # canal modificado es re-escrito en el arreglo de canales
1408 # canal modificado es re-escrito en el arreglo de canales
1409 self.dataOut.data_spc[2] = jspectra_tmp
1409 self.dataOut.data_spc[2] = jspectra_tmp
1410
1410
1411 return self.dataOut
1411 return self.dataOut
General Comments 0
You need to be logged in to leave comments. Login now