##// END OF EJS Templates
Danny Scipión -
r1362:036afbeb089e merge
parent child
Show More
@@ -1,688 +1,691
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.localtime = kwargs.pop('localtime', True)
205 self.localtime = kwargs.pop('localtime', True)
206 self.show = kwargs.get('show', True)
206 self.show = kwargs.get('show', True)
207 self.save = kwargs.get('save', False)
207 self.save = kwargs.get('save', False)
208 self.save_period = kwargs.get('save_period', 0)
208 self.save_period = kwargs.get('save_period', 0)
209 self.colormap = kwargs.get('colormap', self.colormap)
209 self.colormap = kwargs.get('colormap', self.colormap)
210 self.colormap_coh = kwargs.get('colormap_coh', 'jet')
210 self.colormap_coh = kwargs.get('colormap_coh', 'jet')
211 self.colormap_phase = kwargs.get('colormap_phase', 'RdBu_r')
211 self.colormap_phase = kwargs.get('colormap_phase', 'RdBu_r')
212 self.colormaps = kwargs.get('colormaps', None)
212 self.colormaps = kwargs.get('colormaps', None)
213 self.bgcolor = kwargs.get('bgcolor', self.bgcolor)
213 self.bgcolor = kwargs.get('bgcolor', self.bgcolor)
214 self.showprofile = kwargs.get('showprofile', False)
214 self.showprofile = kwargs.get('showprofile', False)
215 self.title = kwargs.get('wintitle', self.CODE.upper())
215 self.title = kwargs.get('wintitle', self.CODE.upper())
216 self.cb_label = kwargs.get('cb_label', None)
216 self.cb_label = kwargs.get('cb_label', None)
217 self.cb_labels = kwargs.get('cb_labels', None)
217 self.cb_labels = kwargs.get('cb_labels', None)
218 self.labels = kwargs.get('labels', None)
218 self.labels = kwargs.get('labels', None)
219 self.xaxis = kwargs.get('xaxis', 'frequency')
219 self.xaxis = kwargs.get('xaxis', 'frequency')
220 self.zmin = kwargs.get('zmin', None)
220 self.zmin = kwargs.get('zmin', None)
221 self.zmax = kwargs.get('zmax', None)
221 self.zmax = kwargs.get('zmax', None)
222 self.zlimits = kwargs.get('zlimits', None)
222 self.zlimits = kwargs.get('zlimits', None)
223 self.xmin = kwargs.get('xmin', None)
223 self.xmin = kwargs.get('xmin', None)
224 self.xmax = kwargs.get('xmax', None)
224 self.xmax = kwargs.get('xmax', None)
225 self.xrange = kwargs.get('xrange', 12)
225 self.xrange = kwargs.get('xrange', 12)
226 self.xscale = kwargs.get('xscale', None)
226 self.xscale = kwargs.get('xscale', None)
227 self.ymin = kwargs.get('ymin', None)
227 self.ymin = kwargs.get('ymin', None)
228 self.ymax = kwargs.get('ymax', None)
228 self.ymax = kwargs.get('ymax', None)
229 self.yscale = kwargs.get('yscale', None)
229 self.yscale = kwargs.get('yscale', None)
230 self.xlabel = kwargs.get('xlabel', None)
230 self.xlabel = kwargs.get('xlabel', None)
231 self.attr_time = kwargs.get('attr_time', 'utctime')
231 self.attr_time = kwargs.get('attr_time', 'utctime')
232 self.attr_data = kwargs.get('attr_data', 'data_param')
232 self.attr_data = kwargs.get('attr_data', 'data_param')
233 self.decimation = kwargs.get('decimation', None)
233 self.decimation = kwargs.get('decimation', None)
234 self.showSNR = kwargs.get('showSNR', False)
235 self.oneFigure = kwargs.get('oneFigure', True)
234 self.oneFigure = kwargs.get('oneFigure', True)
236 self.width = kwargs.get('width', None)
235 self.width = kwargs.get('width', None)
237 self.height = kwargs.get('height', None)
236 self.height = kwargs.get('height', None)
238 self.colorbar = kwargs.get('colorbar', True)
237 self.colorbar = kwargs.get('colorbar', True)
239 self.factors = kwargs.get('factors', [1, 1, 1, 1, 1, 1, 1, 1])
238 self.factors = kwargs.get('factors', [1, 1, 1, 1, 1, 1, 1, 1])
240 self.channels = kwargs.get('channels', None)
239 self.channels = kwargs.get('channels', None)
241 self.titles = kwargs.get('titles', [])
240 self.titles = kwargs.get('titles', [])
242 self.polar = False
241 self.polar = False
243 self.type = kwargs.get('type', 'iq')
242 self.type = kwargs.get('type', 'iq')
244 self.grid = kwargs.get('grid', False)
243 self.grid = kwargs.get('grid', False)
245 self.pause = kwargs.get('pause', False)
244 self.pause = kwargs.get('pause', False)
246 self.save_code = kwargs.get('save_code', self.CODE)
245 self.save_code = kwargs.get('save_code', self.CODE)
247 self.throttle = kwargs.get('throttle', 0)
246 self.throttle = kwargs.get('throttle', 0)
248 self.exp_code = kwargs.get('exp_code', None)
247 self.exp_code = kwargs.get('exp_code', None)
249 self.server = kwargs.get('server', False)
248 self.server = kwargs.get('server', False)
250 self.sender_period = kwargs.get('sender_period', 60)
249 self.sender_period = kwargs.get('sender_period', 60)
251 self.tag = kwargs.get('tag', '')
250 self.tag = kwargs.get('tag', '')
252 self.height_index = kwargs.get('height_index', None)
251 self.height_index = kwargs.get('height_index', None)
253 self.__throttle_plot = apply_throttle(self.throttle)
252 self.__throttle_plot = apply_throttle(self.throttle)
254 code = self.attr_data if self.attr_data else self.CODE
253 code = self.attr_data if self.attr_data else self.CODE
255 self.data = PlotterData(self.CODE, self.exp_code, self.localtime)
254 self.data = PlotterData(self.CODE, self.exp_code, self.localtime)
256
255
257 if self.server:
256 if self.server:
258 if not self.server.startswith('tcp://'):
257 if not self.server.startswith('tcp://'):
259 self.server = 'tcp://{}'.format(self.server)
258 self.server = 'tcp://{}'.format(self.server)
260 log.success(
259 log.success(
261 'Sending to server: {}'.format(self.server),
260 'Sending to server: {}'.format(self.server),
262 self.name
261 self.name
263 )
262 )
264
263
264 if isinstance(self.attr_data, str):
265 self.attr_data = [self.attr_data]
266
265 def __setup_plot(self):
267 def __setup_plot(self):
266 '''
268 '''
267 Common setup for all figures, here figures and axes are created
269 Common setup for all figures, here figures and axes are created
268 '''
270 '''
269
271
270 self.setup()
272 self.setup()
271
273
272 self.time_label = 'LT' if self.localtime else 'UTC'
274 self.time_label = 'LT' if self.localtime else 'UTC'
273
275
274 if self.width is None:
276 if self.width is None:
275 self.width = 8
277 self.width = 8
276
278
277 self.figures = []
279 self.figures = []
278 self.axes = []
280 self.axes = []
279 self.cb_axes = []
281 self.cb_axes = []
280 self.pf_axes = []
282 self.pf_axes = []
281 self.cmaps = []
283 self.cmaps = []
282
284
283 size = '15%' if self.ncols == 1 else '30%'
285 size = '15%' if self.ncols == 1 else '30%'
284 pad = '4%' if self.ncols == 1 else '8%'
286 pad = '4%' if self.ncols == 1 else '8%'
285
287
286 if self.oneFigure:
288 if self.oneFigure:
287 if self.height is None:
289 if self.height is None:
288 self.height = 1.4 * self.nrows + 1
290 self.height = 1.4 * self.nrows + 1
289 fig = plt.figure(figsize=(self.width, self.height),
291 fig = plt.figure(figsize=(self.width, self.height),
290 edgecolor='k',
292 edgecolor='k',
291 facecolor='w')
293 facecolor='w')
292 self.figures.append(fig)
294 self.figures.append(fig)
293 for n in range(self.nplots):
295 for n in range(self.nplots):
294 ax = fig.add_subplot(self.nrows, self.ncols,
296 ax = fig.add_subplot(self.nrows, self.ncols,
295 n + 1, polar=self.polar)
297 n + 1, polar=self.polar)
296 ax.tick_params(labelsize=8)
298 ax.tick_params(labelsize=8)
297 ax.firsttime = True
299 ax.firsttime = True
298 ax.index = 0
300 ax.index = 0
299 ax.press = None
301 ax.press = None
300 self.axes.append(ax)
302 self.axes.append(ax)
301 if self.showprofile:
303 if self.showprofile:
302 cax = self.__add_axes(ax, size=size, pad=pad)
304 cax = self.__add_axes(ax, size=size, pad=pad)
303 cax.tick_params(labelsize=8)
305 cax.tick_params(labelsize=8)
304 self.pf_axes.append(cax)
306 self.pf_axes.append(cax)
305 else:
307 else:
306 if self.height is None:
308 if self.height is None:
307 self.height = 3
309 self.height = 3
308 for n in range(self.nplots):
310 for n in range(self.nplots):
309 fig = plt.figure(figsize=(self.width, self.height),
311 fig = plt.figure(figsize=(self.width, self.height),
310 edgecolor='k',
312 edgecolor='k',
311 facecolor='w')
313 facecolor='w')
312 ax = fig.add_subplot(1, 1, 1, polar=self.polar)
314 ax = fig.add_subplot(1, 1, 1, polar=self.polar)
313 ax.tick_params(labelsize=8)
315 ax.tick_params(labelsize=8)
314 ax.firsttime = True
316 ax.firsttime = True
315 ax.index = 0
317 ax.index = 0
316 ax.press = None
318 ax.press = None
317 self.figures.append(fig)
319 self.figures.append(fig)
318 self.axes.append(ax)
320 self.axes.append(ax)
319 if self.showprofile:
321 if self.showprofile:
320 cax = self.__add_axes(ax, size=size, pad=pad)
322 cax = self.__add_axes(ax, size=size, pad=pad)
321 cax.tick_params(labelsize=8)
323 cax.tick_params(labelsize=8)
322 self.pf_axes.append(cax)
324 self.pf_axes.append(cax)
323
325
324 for n in range(self.nrows):
326 for n in range(self.nrows):
327 print(self.nrows)
325 if self.colormaps is not None:
328 if self.colormaps is not None:
326 cmap = plt.get_cmap(self.colormaps[n])
329 cmap = plt.get_cmap(self.colormaps[n])
327 else:
330 else:
328 cmap = plt.get_cmap(self.colormap)
331 cmap = plt.get_cmap(self.colormap)
329 cmap.set_bad(self.bgcolor, 1.)
332 cmap.set_bad(self.bgcolor, 1.)
330 self.cmaps.append(cmap)
333 self.cmaps.append(cmap)
331
334
332 def __add_axes(self, ax, size='30%', pad='8%'):
335 def __add_axes(self, ax, size='30%', pad='8%'):
333 '''
336 '''
334 Add new axes to the given figure
337 Add new axes to the given figure
335 '''
338 '''
336 divider = make_axes_locatable(ax)
339 divider = make_axes_locatable(ax)
337 nax = divider.new_horizontal(size=size, pad=pad)
340 nax = divider.new_horizontal(size=size, pad=pad)
338 ax.figure.add_axes(nax)
341 ax.figure.add_axes(nax)
339 return nax
342 return nax
340
343
341 def fill_gaps(self, x_buffer, y_buffer, z_buffer):
344 def fill_gaps(self, x_buffer, y_buffer, z_buffer):
342 '''
345 '''
343 Create a masked array for missing data
346 Create a masked array for missing data
344 '''
347 '''
345 if x_buffer.shape[0] < 2:
348 if x_buffer.shape[0] < 2:
346 return x_buffer, y_buffer, z_buffer
349 return x_buffer, y_buffer, z_buffer
347
350
348 deltas = x_buffer[1:] - x_buffer[0:-1]
351 deltas = x_buffer[1:] - x_buffer[0:-1]
349 x_median = numpy.median(deltas)
352 x_median = numpy.median(deltas)
350
353
351 index = numpy.where(deltas > 5 * x_median)
354 index = numpy.where(deltas > 5 * x_median)
352
355
353 if len(index[0]) != 0:
356 if len(index[0]) != 0:
354 z_buffer[::, index[0], ::] = self.__missing
357 z_buffer[::, index[0], ::] = self.__missing
355 z_buffer = numpy.ma.masked_inside(z_buffer,
358 z_buffer = numpy.ma.masked_inside(z_buffer,
356 0.99 * self.__missing,
359 0.99 * self.__missing,
357 1.01 * self.__missing)
360 1.01 * self.__missing)
358
361
359 return x_buffer, y_buffer, z_buffer
362 return x_buffer, y_buffer, z_buffer
360
363
361 def decimate(self):
364 def decimate(self):
362
365
363 # dx = int(len(self.x)/self.__MAXNUMX) + 1
366 # dx = int(len(self.x)/self.__MAXNUMX) + 1
364 dy = int(len(self.y) / self.decimation) + 1
367 dy = int(len(self.y) / self.decimation) + 1
365
368
366 # x = self.x[::dx]
369 # x = self.x[::dx]
367 x = self.x
370 x = self.x
368 y = self.y[::dy]
371 y = self.y[::dy]
369 z = self.z[::, ::, ::dy]
372 z = self.z[::, ::, ::dy]
370
373
371 return x, y, z
374 return x, y, z
372
375
373 def format(self):
376 def format(self):
374 '''
377 '''
375 Set min and max values, labels, ticks and titles
378 Set min and max values, labels, ticks and titles
376 '''
379 '''
377
380
378 for n, ax in enumerate(self.axes):
381 for n, ax in enumerate(self.axes):
379 if ax.firsttime:
382 if ax.firsttime:
380 if self.xaxis != 'time':
383 if self.xaxis != 'time':
381 xmin = self.xmin
384 xmin = self.xmin
382 xmax = self.xmax
385 xmax = self.xmax
383 else:
386 else:
384 xmin = self.tmin
387 xmin = self.tmin
385 xmax = self.tmin + self.xrange*60*60
388 xmax = self.tmin + self.xrange*60*60
386 ax.xaxis.set_major_formatter(FuncFormatter(self.__fmtTime))
389 ax.xaxis.set_major_formatter(FuncFormatter(self.__fmtTime))
387 ax.xaxis.set_major_locator(LinearLocator(9))
390 ax.xaxis.set_major_locator(LinearLocator(9))
388 ymin = self.ymin if self.ymin is not None else numpy.nanmin(self.y[numpy.isfinite(self.y)])
391 ymin = self.ymin if self.ymin is not None else numpy.nanmin(self.y[numpy.isfinite(self.y)])
389 ymax = self.ymax if self.ymax is not None else numpy.nanmax(self.y[numpy.isfinite(self.y)])
392 ymax = self.ymax if self.ymax is not None else numpy.nanmax(self.y[numpy.isfinite(self.y)])
390 ax.set_facecolor(self.bgcolor)
393 ax.set_facecolor(self.bgcolor)
391 if self.xscale:
394 if self.xscale:
392 ax.xaxis.set_major_formatter(FuncFormatter(
395 ax.xaxis.set_major_formatter(FuncFormatter(
393 lambda x, pos: '{0:g}'.format(x*self.xscale)))
396 lambda x, pos: '{0:g}'.format(x*self.xscale)))
394 if self.yscale:
397 if self.yscale:
395 ax.yaxis.set_major_formatter(FuncFormatter(
398 ax.yaxis.set_major_formatter(FuncFormatter(
396 lambda x, pos: '{0:g}'.format(x*self.yscale)))
399 lambda x, pos: '{0:g}'.format(x*self.yscale)))
397 if self.xlabel is not None:
400 if self.xlabel is not None:
398 ax.set_xlabel(self.xlabel)
401 ax.set_xlabel(self.xlabel)
399 if self.ylabel is not None:
402 if self.ylabel is not None:
400 ax.set_ylabel(self.ylabel)
403 ax.set_ylabel(self.ylabel)
401 if self.showprofile:
404 if self.showprofile:
402 self.pf_axes[n].set_ylim(ymin, ymax)
405 self.pf_axes[n].set_ylim(ymin, ymax)
403 self.pf_axes[n].set_xlim(self.zmin, self.zmax)
406 self.pf_axes[n].set_xlim(self.zmin, self.zmax)
404 self.pf_axes[n].set_xlabel('dB')
407 self.pf_axes[n].set_xlabel('dB')
405 self.pf_axes[n].grid(b=True, axis='x')
408 self.pf_axes[n].grid(b=True, axis='x')
406 [tick.set_visible(False)
409 [tick.set_visible(False)
407 for tick in self.pf_axes[n].get_yticklabels()]
410 for tick in self.pf_axes[n].get_yticklabels()]
408 if self.colorbar:
411 if self.colorbar:
409 ax.cbar = plt.colorbar(
412 ax.cbar = plt.colorbar(
410 ax.plt, ax=ax, fraction=0.05, pad=0.02, aspect=10)
413 ax.plt, ax=ax, fraction=0.05, pad=0.02, aspect=10)
411 ax.cbar.ax.tick_params(labelsize=8)
414 ax.cbar.ax.tick_params(labelsize=8)
412 ax.cbar.ax.press = None
415 ax.cbar.ax.press = None
413 if self.cb_label:
416 if self.cb_label:
414 ax.cbar.set_label(self.cb_label, size=8)
417 ax.cbar.set_label(self.cb_label, size=8)
415 elif self.cb_labels:
418 elif self.cb_labels:
416 ax.cbar.set_label(self.cb_labels[n], size=8)
419 ax.cbar.set_label(self.cb_labels[n], size=8)
417 else:
420 else:
418 ax.cbar = None
421 ax.cbar = None
419 ax.set_xlim(xmin, xmax)
422 ax.set_xlim(xmin, xmax)
420 ax.set_ylim(ymin, ymax)
423 ax.set_ylim(ymin, ymax)
421 ax.firsttime = False
424 ax.firsttime = False
422 if self.grid:
425 if self.grid:
423 ax.grid(True)
426 ax.grid(True)
424 if not self.polar:
427 if not self.polar:
425 ax.set_title('{} {} {}'.format(
428 ax.set_title('{} {} {}'.format(
426 self.titles[n],
429 self.titles[n],
427 self.getDateTime(self.data.max_time).strftime(
430 self.getDateTime(self.data.max_time).strftime(
428 '%Y-%m-%d %H:%M:%S'),
431 '%Y-%m-%d %H:%M:%S'),
429 self.time_label),
432 self.time_label),
430 size=8)
433 size=8)
431 else:
434 else:
432 ax.set_title('{}'.format(self.titles[n]), size=8)
435 ax.set_title('{}'.format(self.titles[n]), size=8)
433 ax.set_ylim(0, 90)
436 ax.set_ylim(0, 90)
434 ax.set_yticks(numpy.arange(0, 90, 20))
437 ax.set_yticks(numpy.arange(0, 90, 20))
435 ax.yaxis.labelpad = 40
438 ax.yaxis.labelpad = 40
436
439
437 if self.firsttime:
440 if self.firsttime:
438 for n, fig in enumerate(self.figures):
441 for n, fig in enumerate(self.figures):
439 fig.subplots_adjust(**self.plots_adjust)
442 fig.subplots_adjust(**self.plots_adjust)
440 self.firsttime = False
443 self.firsttime = False
441
444
442 def clear_figures(self):
445 def clear_figures(self):
443 '''
446 '''
444 Reset axes for redraw plots
447 Reset axes for redraw plots
445 '''
448 '''
446
449
447 for ax in self.axes+self.pf_axes+self.cb_axes:
450 for ax in self.axes+self.pf_axes+self.cb_axes:
448 ax.clear()
451 ax.clear()
449 ax.firsttime = True
452 ax.firsttime = True
450 if hasattr(ax, 'cbar') and ax.cbar:
453 if hasattr(ax, 'cbar') and ax.cbar:
451 ax.cbar.remove()
454 ax.cbar.remove()
452
455
453 def __plot(self):
456 def __plot(self):
454 '''
457 '''
455 Main function to plot, format and save figures
458 Main function to plot, format and save figures
456 '''
459 '''
457
460
458 self.plot()
461 self.plot()
459 self.format()
462 self.format()
460
463
461 for n, fig in enumerate(self.figures):
464 for n, fig in enumerate(self.figures):
462 if self.nrows == 0 or self.nplots == 0:
465 if self.nrows == 0 or self.nplots == 0:
463 log.warning('No data', self.name)
466 log.warning('No data', self.name)
464 fig.text(0.5, 0.5, 'No Data', fontsize='large', ha='center')
467 fig.text(0.5, 0.5, 'No Data', fontsize='large', ha='center')
465 fig.canvas.manager.set_window_title(self.CODE)
468 fig.canvas.manager.set_window_title(self.CODE)
466 continue
469 continue
467
470
468 fig.canvas.manager.set_window_title('{} - {}'.format(self.title,
471 fig.canvas.manager.set_window_title('{} - {}'.format(self.title,
469 self.getDateTime(self.data.max_time).strftime('%Y/%m/%d')))
472 self.getDateTime(self.data.max_time).strftime('%Y/%m/%d')))
470 fig.canvas.draw()
473 fig.canvas.draw()
471 if self.show:
474 if self.show:
472 fig.show()
475 fig.show()
473 figpause(0.01)
476 figpause(0.01)
474
477
475 if self.save:
478 if self.save:
476 self.save_figure(n)
479 self.save_figure(n)
477
480
478 if self.server:
481 if self.server:
479 self.send_to_server()
482 self.send_to_server()
480
483
481 def __update(self, dataOut, timestamp):
484 def __update(self, dataOut, timestamp):
482 '''
485 '''
483 '''
486 '''
484
487
485 metadata = {
488 metadata = {
486 'yrange': dataOut.heightList,
489 'yrange': dataOut.heightList,
487 'interval': dataOut.timeInterval,
490 'interval': dataOut.timeInterval,
488 'channels': dataOut.channelList
491 'channels': dataOut.channelList
489 }
492 }
490
493
491 data, meta = self.update(dataOut)
494 data, meta = self.update(dataOut)
492 metadata.update(meta)
495 metadata.update(meta)
493 self.data.update(data, timestamp, metadata)
496 self.data.update(data, timestamp, metadata)
494
497
495 def save_figure(self, n):
498 def save_figure(self, n):
496 '''
499 '''
497 '''
500 '''
498
501
499 if (self.data.max_time - self.save_time) <= self.save_period:
502 if (self.data.max_time - self.save_time) <= self.save_period:
500 return
503 return
501
504
502 self.save_time = self.data.max_time
505 self.save_time = self.data.max_time
503
506
504 fig = self.figures[n]
507 fig = self.figures[n]
505
508
506 figname = os.path.join(
507 self.save,
508 self.save_code,
509 '{}_{}.png'.format(
510 self.save_code,
511 self.getDateTime(self.data.max_time).strftime(
512 '%Y%m%d_%H%M%S'
513 ),
514 )
515 )
516 log.log('Saving figure: {}'.format(figname), self.name)
517 if not os.path.isdir(os.path.dirname(figname)):
518 os.makedirs(os.path.dirname(figname))
519 fig.savefig(figname)
520
521 if self.throttle == 0:
509 if self.throttle == 0:
522 figname = os.path.join(
510 figname = os.path.join(
523 self.save,
511 self.save,
524 '{}_{}.png'.format(
512 self.save_code,
513 '{}_{}.png'.format(
525 self.save_code,
514 self.save_code,
526 self.getDateTime(self.data.min_time).strftime(
515 self.getDateTime(self.data.max_time).strftime(
527 '%Y%m%d'
516 '%Y%m%d_%H%M%S'
528 ),
517 ),
529 )
518 )
530 )
519 )
520 log.log('Saving figure: {}'.format(figname), self.name)
521 if not os.path.isdir(os.path.dirname(figname)):
522 os.makedirs(os.path.dirname(figname))
531 fig.savefig(figname)
523 fig.savefig(figname)
532
524
525 figname = os.path.join(
526 self.save,
527 '{}_{}.png'.format(
528 self.save_code,
529 self.getDateTime(self.data.min_time).strftime(
530 '%Y%m%d'
531 ),
532 )
533 )
534 fig.savefig(figname)
535
533 def send_to_server(self):
536 def send_to_server(self):
534 '''
537 '''
535 '''
538 '''
536
539
537 if self.exp_code == None:
540 if self.exp_code == None:
538 log.warning('Missing `exp_code` skipping sending to server...')
541 log.warning('Missing `exp_code` skipping sending to server...')
539
542
540 last_time = self.data.max_time
543 last_time = self.data.max_time
541 interval = last_time - self.sender_time
544 interval = last_time - self.sender_time
542 if interval < self.sender_period:
545 if interval < self.sender_period:
543 return
546 return
544
547
545 self.sender_time = last_time
548 self.sender_time = last_time
546
549
547 attrs = ['titles', 'zmin', 'zmax', 'tag', 'ymin', 'ymax']
550 attrs = ['titles', 'zmin', 'zmax', 'tag', 'ymin', 'ymax']
548 for attr in attrs:
551 for attr in attrs:
549 value = getattr(self, attr)
552 value = getattr(self, attr)
550 if value:
553 if value:
551 if isinstance(value, (numpy.float32, numpy.float64)):
554 if isinstance(value, (numpy.float32, numpy.float64)):
552 value = round(float(value), 2)
555 value = round(float(value), 2)
553 self.data.meta[attr] = value
556 self.data.meta[attr] = value
554 if self.colormap == 'jet':
557 if self.colormap == 'jet':
555 self.data.meta['colormap'] = 'Jet'
558 self.data.meta['colormap'] = 'Jet'
556 elif 'RdBu' in self.colormap:
559 elif 'RdBu' in self.colormap:
557 self.data.meta['colormap'] = 'RdBu'
560 self.data.meta['colormap'] = 'RdBu'
558 else:
561 else:
559 self.data.meta['colormap'] = 'Viridis'
562 self.data.meta['colormap'] = 'Viridis'
560 self.data.meta['interval'] = int(interval)
563 self.data.meta['interval'] = int(interval)
561
564
562 self.sender_queue.append(last_time)
565 self.sender_queue.append(last_time)
563
566
564 while True:
567 while True:
565 try:
568 try:
566 tm = self.sender_queue.popleft()
569 tm = self.sender_queue.popleft()
567 except IndexError:
570 except IndexError:
568 break
571 break
569 msg = self.data.jsonify(tm, self.save_code, self.plot_type)
572 msg = self.data.jsonify(tm, self.save_code, self.plot_type)
570 self.socket.send_string(msg)
573 self.socket.send_string(msg)
571 socks = dict(self.poll.poll(2000))
574 socks = dict(self.poll.poll(2000))
572 if socks.get(self.socket) == zmq.POLLIN:
575 if socks.get(self.socket) == zmq.POLLIN:
573 reply = self.socket.recv_string()
576 reply = self.socket.recv_string()
574 if reply == 'ok':
577 if reply == 'ok':
575 log.log("Response from server ok", self.name)
578 log.log("Response from server ok", self.name)
576 time.sleep(0.1)
579 time.sleep(0.1)
577 continue
580 continue
578 else:
581 else:
579 log.warning(
582 log.warning(
580 "Malformed reply from server: {}".format(reply), self.name)
583 "Malformed reply from server: {}".format(reply), self.name)
581 else:
584 else:
582 log.warning(
585 log.warning(
583 "No response from server, retrying...", self.name)
586 "No response from server, retrying...", self.name)
584 self.sender_queue.appendleft(tm)
587 self.sender_queue.appendleft(tm)
585 self.socket.setsockopt(zmq.LINGER, 0)
588 self.socket.setsockopt(zmq.LINGER, 0)
586 self.socket.close()
589 self.socket.close()
587 self.poll.unregister(self.socket)
590 self.poll.unregister(self.socket)
588 self.socket = self.context.socket(zmq.REQ)
591 self.socket = self.context.socket(zmq.REQ)
589 self.socket.connect(self.server)
592 self.socket.connect(self.server)
590 self.poll.register(self.socket, zmq.POLLIN)
593 self.poll.register(self.socket, zmq.POLLIN)
591 break
594 break
592
595
593 def setup(self):
596 def setup(self):
594 '''
597 '''
595 This method should be implemented in the child class, the following
598 This method should be implemented in the child class, the following
596 attributes should be set:
599 attributes should be set:
597
600
598 self.nrows: number of rows
601 self.nrows: number of rows
599 self.ncols: number of cols
602 self.ncols: number of cols
600 self.nplots: number of plots (channels or pairs)
603 self.nplots: number of plots (channels or pairs)
601 self.ylabel: label for Y axes
604 self.ylabel: label for Y axes
602 self.titles: list of axes title
605 self.titles: list of axes title
603
606
604 '''
607 '''
605 raise NotImplementedError
608 raise NotImplementedError
606
609
607 def plot(self):
610 def plot(self):
608 '''
611 '''
609 Must be defined in the child class, the actual plotting method
612 Must be defined in the child class, the actual plotting method
610 '''
613 '''
611 raise NotImplementedError
614 raise NotImplementedError
612
615
613 def update(self, dataOut):
616 def update(self, dataOut):
614 '''
617 '''
615 Must be defined in the child class, update self.data with new data
618 Must be defined in the child class, update self.data with new data
616 '''
619 '''
617
620
618 data = {
621 data = {
619 self.CODE: getattr(dataOut, 'data_{}'.format(self.CODE))
622 self.CODE: getattr(dataOut, 'data_{}'.format(self.CODE))
620 }
623 }
621 meta = {}
624 meta = {}
622
625
623 return data, meta
626 return data, meta
624
627
625 def run(self, dataOut, **kwargs):
628 def run(self, dataOut, **kwargs):
626 '''
629 '''
627 Main plotting routine
630 Main plotting routine
628 '''
631 '''
629
632
630 if self.isConfig is False:
633 if self.isConfig is False:
631 self.__setup(**kwargs)
634 self.__setup(**kwargs)
632
635
633 if self.localtime:
636 if self.localtime:
634 self.getDateTime = datetime.datetime.fromtimestamp
637 self.getDateTime = datetime.datetime.fromtimestamp
635 else:
638 else:
636 self.getDateTime = datetime.datetime.utcfromtimestamp
639 self.getDateTime = datetime.datetime.utcfromtimestamp
637
640
638 self.data.setup()
641 self.data.setup()
639 self.isConfig = True
642 self.isConfig = True
640 if self.server:
643 if self.server:
641 self.context = zmq.Context()
644 self.context = zmq.Context()
642 self.socket = self.context.socket(zmq.REQ)
645 self.socket = self.context.socket(zmq.REQ)
643 self.socket.connect(self.server)
646 self.socket.connect(self.server)
644 self.poll = zmq.Poller()
647 self.poll = zmq.Poller()
645 self.poll.register(self.socket, zmq.POLLIN)
648 self.poll.register(self.socket, zmq.POLLIN)
646
649
647 tm = getattr(dataOut, self.attr_time)
650 tm = getattr(dataOut, self.attr_time)
648
651
649 if self.data and 'time' in self.xaxis and (tm - self.tmin) >= self.xrange*60*60:
652 if self.data and 'time' in self.xaxis and (tm - self.tmin) >= self.xrange*60*60:
650 self.save_time = tm
653 self.save_time = tm
651 self.__plot()
654 self.__plot()
652 self.tmin += self.xrange*60*60
655 self.tmin += self.xrange*60*60
653 self.data.setup()
656 self.data.setup()
654 self.clear_figures()
657 self.clear_figures()
655
658
656 self.__update(dataOut, tm)
659 self.__update(dataOut, tm)
657
660
658 if self.isPlotConfig is False:
661 if self.isPlotConfig is False:
659 self.__setup_plot()
662 self.__setup_plot()
660 self.isPlotConfig = True
663 self.isPlotConfig = True
661 if self.xaxis == 'time':
664 if self.xaxis == 'time':
662 dt = self.getDateTime(tm)
665 dt = self.getDateTime(tm)
663 if self.xmin is None:
666 if self.xmin is None:
664 self.tmin = tm
667 self.tmin = tm
665 self.xmin = dt.hour
668 self.xmin = dt.hour
666 minutes = (self.xmin-int(self.xmin)) * 60
669 minutes = (self.xmin-int(self.xmin)) * 60
667 seconds = (minutes - int(minutes)) * 60
670 seconds = (minutes - int(minutes)) * 60
668 self.tmin = (dt.replace(hour=int(self.xmin), minute=int(minutes), second=int(seconds)) -
671 self.tmin = (dt.replace(hour=int(self.xmin), minute=int(minutes), second=int(seconds)) -
669 datetime.datetime(1970, 1, 1)).total_seconds()
672 datetime.datetime(1970, 1, 1)).total_seconds()
670 if self.localtime:
673 if self.localtime:
671 self.tmin += time.timezone
674 self.tmin += time.timezone
672
675
673 if self.xmin is not None and self.xmax is not None:
676 if self.xmin is not None and self.xmax is not None:
674 self.xrange = self.xmax - self.xmin
677 self.xrange = self.xmax - self.xmin
675
678
676 if self.throttle == 0:
679 if self.throttle == 0:
677 self.__plot()
680 self.__plot()
678 else:
681 else:
679 self.__throttle_plot(self.__plot)#, coerce=coerce)
682 self.__throttle_plot(self.__plot)#, coerce=coerce)
680
683
681 def close(self):
684 def close(self):
682
685
683 if self.data and not self.data.flagNoData:
686 if self.data and not self.data.flagNoData:
684 self.save_time = self.data.max_time
687 self.save_time = self.data.max_time
685 self.__plot()
688 self.__plot()
686 if self.data and not self.data.flagNoData and self.pause:
689 if self.data and not self.data.flagNoData and self.pause:
687 figpause(10)
690 figpause(10)
688
691
@@ -1,371 +1,370
1 import os
1 import os
2 import datetime
2 import datetime
3 import numpy
3 import numpy
4
4
5 from schainpy.model.graphics.jroplot_base import Plot, plt
5 from schainpy.model.graphics.jroplot_base import Plot, plt
6 from schainpy.model.graphics.jroplot_spectra import SpectraPlot, RTIPlot, CoherencePlot, SpectraCutPlot
6 from schainpy.model.graphics.jroplot_spectra import SpectraPlot, RTIPlot, CoherencePlot, SpectraCutPlot
7 from schainpy.utils import log
7 from schainpy.utils import log
8
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 class DobleGaussianPlot(SpectraPlot):
41 class DobleGaussianPlot(SpectraPlot):
42 '''
42 '''
43 Plot for Double Gaussian Plot
43 Plot for Double Gaussian Plot
44 '''
44 '''
45 CODE = 'gaussian_fit'
45 CODE = 'gaussian_fit'
46 # colormap = 'jet'
46 # colormap = 'jet'
47 # plot_type = 'pcolor'
47 # plot_type = 'pcolor'
48
48
49 class DoubleGaussianSpectraCutPlot(SpectraCutPlot):
49 class DoubleGaussianSpectraCutPlot(SpectraCutPlot):
50 '''
50 '''
51 Plot SpectraCut with Double Gaussian Fit
51 Plot SpectraCut with Double Gaussian Fit
52 '''
52 '''
53 CODE = 'cut_gaussian_fit'
53 CODE = 'cut_gaussian_fit'
54
54
55 class SnrPlot(RTIPlot):
55 class SnrPlot(RTIPlot):
56 '''
56 '''
57 Plot for SNR Data
57 Plot for SNR Data
58 '''
58 '''
59
59
60 CODE = 'snr'
60 CODE = 'snr'
61 colormap = 'jet'
61 colormap = 'jet'
62
62
63 def update(self, dataOut):
63 def update(self, dataOut):
64
64
65 data = {
65 data = {
66 'snr': 10*numpy.log10(dataOut.data_snr)
66 'snr': 10*numpy.log10(dataOut.data_snr)
67 }
67 }
68
68
69 return data, {}
69 return data, {}
70
70
71 class DopplerPlot(RTIPlot):
71 class DopplerPlot(RTIPlot):
72 '''
72 '''
73 Plot for DOPPLER Data (1st moment)
73 Plot for DOPPLER Data (1st moment)
74 '''
74 '''
75
75
76 CODE = 'dop'
76 CODE = 'dop'
77 colormap = 'jet'
77 colormap = 'jet'
78
78
79 def update(self, dataOut):
79 def update(self, dataOut):
80
80
81 data = {
81 data = {
82 'dop': 10*numpy.log10(dataOut.data_dop)
82 'dop': 10*numpy.log10(dataOut.data_dop)
83 }
83 }
84
84
85 return data, {}
85 return data, {}
86
86
87 class PowerPlot(RTIPlot):
87 class PowerPlot(RTIPlot):
88 '''
88 '''
89 Plot for Power Data (0 moment)
89 Plot for Power Data (0 moment)
90 '''
90 '''
91
91
92 CODE = 'pow'
92 CODE = 'pow'
93 colormap = 'jet'
93 colormap = 'jet'
94
94
95 def update(self, dataOut):
95 def update(self, dataOut):
96
96
97 data = {
97 data = {
98 'pow': 10*numpy.log10(dataOut.data_pow/dataOut.normFactor)
98 'pow': 10*numpy.log10(dataOut.data_pow/dataOut.normFactor)
99 }
99 }
100
100
101 return data, {}
101 return data, {}
102
102
103 class SpectralWidthPlot(RTIPlot):
103 class SpectralWidthPlot(RTIPlot):
104 '''
104 '''
105 Plot for Spectral Width Data (2nd moment)
105 Plot for Spectral Width Data (2nd moment)
106 '''
106 '''
107
107
108 CODE = 'width'
108 CODE = 'width'
109 colormap = 'jet'
109 colormap = 'jet'
110
110
111 def update(self, dataOut):
111 def update(self, dataOut):
112
112
113 data = {
113 data = {
114 'width': dataOut.data_width
114 'width': dataOut.data_width
115 }
115 }
116
116
117 return data, {}
117 return data, {}
118
118
119 class SkyMapPlot(Plot):
119 class SkyMapPlot(Plot):
120 '''
120 '''
121 Plot for meteors detection data
121 Plot for meteors detection data
122 '''
122 '''
123
123
124 CODE = 'param'
124 CODE = 'param'
125
125
126 def setup(self):
126 def setup(self):
127
127
128 self.ncols = 1
128 self.ncols = 1
129 self.nrows = 1
129 self.nrows = 1
130 self.width = 7.2
130 self.width = 7.2
131 self.height = 7.2
131 self.height = 7.2
132 self.nplots = 1
132 self.nplots = 1
133 self.xlabel = 'Zonal Zenith Angle (deg)'
133 self.xlabel = 'Zonal Zenith Angle (deg)'
134 self.ylabel = 'Meridional Zenith Angle (deg)'
134 self.ylabel = 'Meridional Zenith Angle (deg)'
135 self.polar = True
135 self.polar = True
136 self.ymin = -180
136 self.ymin = -180
137 self.ymax = 180
137 self.ymax = 180
138 self.colorbar = False
138 self.colorbar = False
139
139
140 def plot(self):
140 def plot(self):
141
141
142 arrayParameters = numpy.concatenate(self.data['param'])
142 arrayParameters = numpy.concatenate(self.data['param'])
143 error = arrayParameters[:, -1]
143 error = arrayParameters[:, -1]
144 indValid = numpy.where(error == 0)[0]
144 indValid = numpy.where(error == 0)[0]
145 finalMeteor = arrayParameters[indValid, :]
145 finalMeteor = arrayParameters[indValid, :]
146 finalAzimuth = finalMeteor[:, 3]
146 finalAzimuth = finalMeteor[:, 3]
147 finalZenith = finalMeteor[:, 4]
147 finalZenith = finalMeteor[:, 4]
148
148
149 x = finalAzimuth * numpy.pi / 180
149 x = finalAzimuth * numpy.pi / 180
150 y = finalZenith
150 y = finalZenith
151
151
152 ax = self.axes[0]
152 ax = self.axes[0]
153
153
154 if ax.firsttime:
154 if ax.firsttime:
155 ax.plot = ax.plot(x, y, 'bo', markersize=5)[0]
155 ax.plot = ax.plot(x, y, 'bo', markersize=5)[0]
156 else:
156 else:
157 ax.plot.set_data(x, y)
157 ax.plot.set_data(x, y)
158
158
159 dt1 = self.getDateTime(self.data.min_time).strftime('%y/%m/%d %H:%M:%S')
159 dt1 = self.getDateTime(self.data.min_time).strftime('%y/%m/%d %H:%M:%S')
160 dt2 = self.getDateTime(self.data.max_time).strftime('%y/%m/%d %H:%M:%S')
160 dt2 = self.getDateTime(self.data.max_time).strftime('%y/%m/%d %H:%M:%S')
161 title = 'Meteor Detection Sky Map\n %s - %s \n Number of events: %5.0f\n' % (dt1,
161 title = 'Meteor Detection Sky Map\n %s - %s \n Number of events: %5.0f\n' % (dt1,
162 dt2,
162 dt2,
163 len(x))
163 len(x))
164 self.titles[0] = title
164 self.titles[0] = title
165
165
166
166
167 class GenericRTIPlot(Plot):
167 class GenericRTIPlot(Plot):
168 '''
168 '''
169 Plot for data_xxxx object
169 Plot for data_xxxx object
170 '''
170 '''
171
171
172 CODE = 'param'
172 CODE = 'param'
173 colormap = 'viridis'
173 colormap = 'viridis'
174 plot_type = 'pcolorbuffer'
174 plot_type = 'pcolorbuffer'
175
175
176 def setup(self):
176 def setup(self):
177 self.xaxis = 'time'
177 self.xaxis = 'time'
178 self.ncols = 1
178 self.ncols = 1
179 self.nrows = self.data.shape(self.attr_data)[0]
179 self.nrows = self.data.shape('param')[0]
180 self.nplots = self.nrows
180 self.nplots = self.nrows
181 self.plots_adjust.update({'hspace':0.8, 'left': 0.1, 'bottom': 0.08, 'right':0.95, 'top': 0.95})
181 self.plots_adjust.update({'hspace':0.8, 'left': 0.1, 'bottom': 0.08, 'right':0.95, 'top': 0.95})
182
182
183 if not self.xlabel:
183 if not self.xlabel:
184 self.xlabel = 'Time'
184 self.xlabel = 'Time'
185
185
186 self.ylabel = 'Range [km]'
186 self.ylabel = 'Range [km]'
187 if not self.titles:
187 if not self.titles:
188 self.titles = self.data.parameters \
188 self.titles = ['Param {}'.format(x) for x in range(self.nrows)]
189 if self.data.parameters else ['Param {}'.format(x) for x in range(self.nrows)]
190
189
191 def update(self, dataOut):
190 def update(self, dataOut):
192
191
193 data = {
192 data = {
194 self.attr_data : getattr(dataOut, self.attr_data)
193 'param' : numpy.concatenate([getattr(dataOut, attr) for attr in self.attr_data], axis=0)
195 }
194 }
196
195
197 meta = {}
196 meta = {}
198
197
199 return data, meta
198 return data, meta
200
199
201 def plot(self):
200 def plot(self):
202 # self.data.normalize_heights()
201 # self.data.normalize_heights()
203 self.x = self.data.times
202 self.x = self.data.times
204 self.y = self.data.yrange
203 self.y = self.data.yrange
205 self.z = self.data[self.attr_data]
204 self.z = self.data['param']
206
205
207 self.z = numpy.ma.masked_invalid(self.z)
206 self.z = numpy.ma.masked_invalid(self.z)
208
207
209 if self.decimation is None:
208 if self.decimation is None:
210 x, y, z = self.fill_gaps(self.x, self.y, self.z)
209 x, y, z = self.fill_gaps(self.x, self.y, self.z)
211 else:
210 else:
212 x, y, z = self.fill_gaps(*self.decimate())
211 x, y, z = self.fill_gaps(*self.decimate())
213
212
214 for n, ax in enumerate(self.axes):
213 for n, ax in enumerate(self.axes):
215
214
216 self.zmax = self.zmax if self.zmax is not None else numpy.max(
215 self.zmax = self.zmax if self.zmax is not None else numpy.max(
217 self.z[n])
216 self.z[n])
218 self.zmin = self.zmin if self.zmin is not None else numpy.min(
217 self.zmin = self.zmin if self.zmin is not None else numpy.min(
219 self.z[n])
218 self.z[n])
220
219
221 if ax.firsttime:
220 if ax.firsttime:
222 if self.zlimits is not None:
221 if self.zlimits is not None:
223 self.zmin, self.zmax = self.zlimits[n]
222 self.zmin, self.zmax = self.zlimits[n]
224
223
225 ax.plt = ax.pcolormesh(x, y, z[n].T * self.factors[n],
224 ax.plt = ax.pcolormesh(x, y, z[n].T * self.factors[n],
226 vmin=self.zmin,
225 vmin=self.zmin,
227 vmax=self.zmax,
226 vmax=self.zmax,
228 cmap=self.cmaps[n]
227 cmap=self.cmaps[n]
229 )
228 )
230 else:
229 else:
231 if self.zlimits is not None:
230 if self.zlimits is not None:
232 self.zmin, self.zmax = self.zlimits[n]
231 self.zmin, self.zmax = self.zlimits[n]
233 ax.collections.remove(ax.collections[0])
232 ax.collections.remove(ax.collections[0])
234 ax.plt = ax.pcolormesh(x, y, z[n].T * self.factors[n],
233 ax.plt = ax.pcolormesh(x, y, z[n].T * self.factors[n],
235 vmin=self.zmin,
234 vmin=self.zmin,
236 vmax=self.zmax,
235 vmax=self.zmax,
237 cmap=self.cmaps[n]
236 cmap=self.cmaps[n]
238 )
237 )
239
238
240
239
241 class PolarMapPlot(Plot):
240 class PolarMapPlot(Plot):
242 '''
241 '''
243 Plot for weather radar
242 Plot for weather radar
244 '''
243 '''
245
244
246 CODE = 'param'
245 CODE = 'param'
247 colormap = 'seismic'
246 colormap = 'seismic'
248
247
249 def setup(self):
248 def setup(self):
250 self.ncols = 1
249 self.ncols = 1
251 self.nrows = 1
250 self.nrows = 1
252 self.width = 9
251 self.width = 9
253 self.height = 8
252 self.height = 8
254 self.mode = self.data.meta['mode']
253 self.mode = self.data.meta['mode']
255 if self.channels is not None:
254 if self.channels is not None:
256 self.nplots = len(self.channels)
255 self.nplots = len(self.channels)
257 self.nrows = len(self.channels)
256 self.nrows = len(self.channels)
258 else:
257 else:
259 self.nplots = self.data.shape(self.CODE)[0]
258 self.nplots = self.data.shape(self.CODE)[0]
260 self.nrows = self.nplots
259 self.nrows = self.nplots
261 self.channels = list(range(self.nplots))
260 self.channels = list(range(self.nplots))
262 if self.mode == 'E':
261 if self.mode == 'E':
263 self.xlabel = 'Longitude'
262 self.xlabel = 'Longitude'
264 self.ylabel = 'Latitude'
263 self.ylabel = 'Latitude'
265 else:
264 else:
266 self.xlabel = 'Range (km)'
265 self.xlabel = 'Range (km)'
267 self.ylabel = 'Height (km)'
266 self.ylabel = 'Height (km)'
268 self.bgcolor = 'white'
267 self.bgcolor = 'white'
269 self.cb_labels = self.data.meta['units']
268 self.cb_labels = self.data.meta['units']
270 self.lat = self.data.meta['latitude']
269 self.lat = self.data.meta['latitude']
271 self.lon = self.data.meta['longitude']
270 self.lon = self.data.meta['longitude']
272 self.xmin, self.xmax = float(
271 self.xmin, self.xmax = float(
273 km2deg(self.xmin) + self.lon), float(km2deg(self.xmax) + self.lon)
272 km2deg(self.xmin) + self.lon), float(km2deg(self.xmax) + self.lon)
274 self.ymin, self.ymax = float(
273 self.ymin, self.ymax = float(
275 km2deg(self.ymin) + self.lat), float(km2deg(self.ymax) + self.lat)
274 km2deg(self.ymin) + self.lat), float(km2deg(self.ymax) + self.lat)
276 # self.polar = True
275 # self.polar = True
277
276
278 def plot(self):
277 def plot(self):
279
278
280 for n, ax in enumerate(self.axes):
279 for n, ax in enumerate(self.axes):
281 data = self.data['param'][self.channels[n]]
280 data = self.data['param'][self.channels[n]]
282
281
283 zeniths = numpy.linspace(
282 zeniths = numpy.linspace(
284 0, self.data.meta['max_range'], data.shape[1])
283 0, self.data.meta['max_range'], data.shape[1])
285 if self.mode == 'E':
284 if self.mode == 'E':
286 azimuths = -numpy.radians(self.data.yrange)+numpy.pi/2
285 azimuths = -numpy.radians(self.data.yrange)+numpy.pi/2
287 r, theta = numpy.meshgrid(zeniths, azimuths)
286 r, theta = numpy.meshgrid(zeniths, azimuths)
288 x, y = r*numpy.cos(theta)*numpy.cos(numpy.radians(self.data.meta['elevation'])), r*numpy.sin(
287 x, y = r*numpy.cos(theta)*numpy.cos(numpy.radians(self.data.meta['elevation'])), r*numpy.sin(
289 theta)*numpy.cos(numpy.radians(self.data.meta['elevation']))
288 theta)*numpy.cos(numpy.radians(self.data.meta['elevation']))
290 x = km2deg(x) + self.lon
289 x = km2deg(x) + self.lon
291 y = km2deg(y) + self.lat
290 y = km2deg(y) + self.lat
292 else:
291 else:
293 azimuths = numpy.radians(self.data.yrange)
292 azimuths = numpy.radians(self.data.yrange)
294 r, theta = numpy.meshgrid(zeniths, azimuths)
293 r, theta = numpy.meshgrid(zeniths, azimuths)
295 x, y = r*numpy.cos(theta), r*numpy.sin(theta)
294 x, y = r*numpy.cos(theta), r*numpy.sin(theta)
296 self.y = zeniths
295 self.y = zeniths
297
296
298 if ax.firsttime:
297 if ax.firsttime:
299 if self.zlimits is not None:
298 if self.zlimits is not None:
300 self.zmin, self.zmax = self.zlimits[n]
299 self.zmin, self.zmax = self.zlimits[n]
301 ax.plt = ax.pcolormesh( # r, theta, numpy.ma.array(data, mask=numpy.isnan(data)),
300 ax.plt = ax.pcolormesh( # r, theta, numpy.ma.array(data, mask=numpy.isnan(data)),
302 x, y, numpy.ma.array(data, mask=numpy.isnan(data)),
301 x, y, numpy.ma.array(data, mask=numpy.isnan(data)),
303 vmin=self.zmin,
302 vmin=self.zmin,
304 vmax=self.zmax,
303 vmax=self.zmax,
305 cmap=self.cmaps[n])
304 cmap=self.cmaps[n])
306 else:
305 else:
307 if self.zlimits is not None:
306 if self.zlimits is not None:
308 self.zmin, self.zmax = self.zlimits[n]
307 self.zmin, self.zmax = self.zlimits[n]
309 ax.collections.remove(ax.collections[0])
308 ax.collections.remove(ax.collections[0])
310 ax.plt = ax.pcolormesh( # r, theta, numpy.ma.array(data, mask=numpy.isnan(data)),
309 ax.plt = ax.pcolormesh( # r, theta, numpy.ma.array(data, mask=numpy.isnan(data)),
311 x, y, numpy.ma.array(data, mask=numpy.isnan(data)),
310 x, y, numpy.ma.array(data, mask=numpy.isnan(data)),
312 vmin=self.zmin,
311 vmin=self.zmin,
313 vmax=self.zmax,
312 vmax=self.zmax,
314 cmap=self.cmaps[n])
313 cmap=self.cmaps[n])
315
314
316 if self.mode == 'A':
315 if self.mode == 'A':
317 continue
316 continue
318
317
319 # plot district names
318 # plot district names
320 f = open('/data/workspace/schain_scripts/distrito.csv')
319 f = open('/data/workspace/schain_scripts/distrito.csv')
321 for line in f:
320 for line in f:
322 label, lon, lat = [s.strip() for s in line.split(',') if s]
321 label, lon, lat = [s.strip() for s in line.split(',') if s]
323 lat = float(lat)
322 lat = float(lat)
324 lon = float(lon)
323 lon = float(lon)
325 # ax.plot(lon, lat, '.b', ms=2)
324 # ax.plot(lon, lat, '.b', ms=2)
326 ax.text(lon, lat, label.decode('utf8'), ha='center',
325 ax.text(lon, lat, label.decode('utf8'), ha='center',
327 va='bottom', size='8', color='black')
326 va='bottom', size='8', color='black')
328
327
329 # plot limites
328 # plot limites
330 limites = []
329 limites = []
331 tmp = []
330 tmp = []
332 for line in open('/data/workspace/schain_scripts/lima.csv'):
331 for line in open('/data/workspace/schain_scripts/lima.csv'):
333 if '#' in line:
332 if '#' in line:
334 if tmp:
333 if tmp:
335 limites.append(tmp)
334 limites.append(tmp)
336 tmp = []
335 tmp = []
337 continue
336 continue
338 values = line.strip().split(',')
337 values = line.strip().split(',')
339 tmp.append((float(values[0]), float(values[1])))
338 tmp.append((float(values[0]), float(values[1])))
340 for points in limites:
339 for points in limites:
341 ax.add_patch(
340 ax.add_patch(
342 Polygon(points, ec='k', fc='none', ls='--', lw=0.5))
341 Polygon(points, ec='k', fc='none', ls='--', lw=0.5))
343
342
344 # plot Cuencas
343 # plot Cuencas
345 for cuenca in ('rimac', 'lurin', 'mala', 'chillon', 'chilca', 'chancay-huaral'):
344 for cuenca in ('rimac', 'lurin', 'mala', 'chillon', 'chilca', 'chancay-huaral'):
346 f = open('/data/workspace/schain_scripts/{}.csv'.format(cuenca))
345 f = open('/data/workspace/schain_scripts/{}.csv'.format(cuenca))
347 values = [line.strip().split(',') for line in f]
346 values = [line.strip().split(',') for line in f]
348 points = [(float(s[0]), float(s[1])) for s in values]
347 points = [(float(s[0]), float(s[1])) for s in values]
349 ax.add_patch(Polygon(points, ec='b', fc='none'))
348 ax.add_patch(Polygon(points, ec='b', fc='none'))
350
349
351 # plot grid
350 # plot grid
352 for r in (15, 30, 45, 60):
351 for r in (15, 30, 45, 60):
353 ax.add_artist(plt.Circle((self.lon, self.lat),
352 ax.add_artist(plt.Circle((self.lon, self.lat),
354 km2deg(r), color='0.6', fill=False, lw=0.2))
353 km2deg(r), color='0.6', fill=False, lw=0.2))
355 ax.text(
354 ax.text(
356 self.lon + (km2deg(r))*numpy.cos(60*numpy.pi/180),
355 self.lon + (km2deg(r))*numpy.cos(60*numpy.pi/180),
357 self.lat + (km2deg(r))*numpy.sin(60*numpy.pi/180),
356 self.lat + (km2deg(r))*numpy.sin(60*numpy.pi/180),
358 '{}km'.format(r),
357 '{}km'.format(r),
359 ha='center', va='bottom', size='8', color='0.6', weight='heavy')
358 ha='center', va='bottom', size='8', color='0.6', weight='heavy')
360
359
361 if self.mode == 'E':
360 if self.mode == 'E':
362 title = 'El={}$^\circ$'.format(self.data.meta['elevation'])
361 title = 'El={}$^\circ$'.format(self.data.meta['elevation'])
363 label = 'E{:02d}'.format(int(self.data.meta['elevation']))
362 label = 'E{:02d}'.format(int(self.data.meta['elevation']))
364 else:
363 else:
365 title = 'Az={}$^\circ$'.format(self.data.meta['azimuth'])
364 title = 'Az={}$^\circ$'.format(self.data.meta['azimuth'])
366 label = 'A{:02d}'.format(int(self.data.meta['azimuth']))
365 label = 'A{:02d}'.format(int(self.data.meta['azimuth']))
367
366
368 self.save_labels = ['{}-{}'.format(lbl, label) for lbl in self.labels]
367 self.save_labels = ['{}-{}'.format(lbl, label) for lbl in self.labels]
369 self.titles = ['{} {}'.format(
368 self.titles = ['{} {}'.format(
370 self.data.parameters[x], title) for x in self.channels]
369 self.data.parameters[x], title) for x in self.channels]
371
370
@@ -1,462 +1,453
1 import os
1 import os
2 import sys
2 import sys
3 import glob
3 import glob
4 import fnmatch
5 import datetime
6 import time
7 import re
8 import h5py
9 import numpy
4 import numpy
10
5
11 import pylab as plb
12 from scipy.optimize import curve_fit
13 from scipy import asarray as ar, exp
14
6
15 SPEED_OF_LIGHT = 299792458
7 SPEED_OF_LIGHT = 299792458
16 SPEED_OF_LIGHT = 3e8
8 SPEED_OF_LIGHT = 3e8
17
9
18 from .utils import folder_in_range
10 from .utils import folder_in_range
19
11
20 import schainpy.admin
12 import schainpy.admin
21 from schainpy.model.data.jrodata import Spectra
13 from schainpy.model.data.jrodata import Spectra
22 from schainpy.model.proc.jroproc_base import ProcessingUnit, Operation, MPDecorator
14 from schainpy.model.proc.jroproc_base import ProcessingUnit
23 from schainpy.utils import log
15 from schainpy.utils import log
24 from schainpy.model.io.jroIO_base import JRODataReader
16
25
17
26 def pol2cart(rho, phi):
18 def pol2cart(rho, phi):
27 x = rho * numpy.cos(phi)
19 x = rho * numpy.cos(phi)
28 y = rho * numpy.sin(phi)
20 y = rho * numpy.sin(phi)
29 return(x, y)
21 return(x, y)
30
22
31 FILE_STRUCTURE = numpy.dtype([ # HEADER 48bytes
23 FILE_STRUCTURE = numpy.dtype([ # HEADER 48bytes
32 ('FileMgcNumber', '<u4'), # 0x23020100
24 ('FileMgcNumber', '<u4'), # 0x23020100
33 ('nFDTdataRecors', '<u4'),
25 ('nFDTdataRecors', '<u4'),
34 ('OffsetStartHeader', '<u4'),
26 ('OffsetStartHeader', '<u4'),
35 ('RadarUnitId', '<u4'),
27 ('RadarUnitId', '<u4'),
36 ('SiteName', 'S32'), # Null terminated
28 ('SiteName', 'S32'), # Null terminated
37 ])
29 ])
38
30
39
31
40 class FileHeaderBLTR():
32 class FileHeaderBLTR():
41
33
42 def __init__(self, fo):
34 def __init__(self, fo):
43
35
44 self.fo = fo
36 self.fo = fo
45 self.size = 48
37 self.size = 48
46 self.read()
38 self.read()
47
39
48 def read(self):
40 def read(self):
49
41
50 header = numpy.fromfile(self.fo, FILE_STRUCTURE, 1)
42 header = numpy.fromfile(self.fo, FILE_STRUCTURE, 1)
51 self.FileMgcNumber = hex(header['FileMgcNumber'][0])
43 self.FileMgcNumber = hex(header['FileMgcNumber'][0])
52 self.nFDTdataRecors = int(header['nFDTdataRecors'][0])
44 self.nFDTdataRecors = int(header['nFDTdataRecors'][0])
53 self.RadarUnitId = int(header['RadarUnitId'][0])
45 self.RadarUnitId = int(header['RadarUnitId'][0])
54 self.OffsetStartHeader = int(header['OffsetStartHeader'][0])
46 self.OffsetStartHeader = int(header['OffsetStartHeader'][0])
55 self.SiteName = header['SiteName'][0]
47 self.SiteName = header['SiteName'][0]
56
48
57 def write(self, fp):
49 def write(self, fp):
58
50
59 headerTuple = (self.FileMgcNumber,
51 headerTuple = (self.FileMgcNumber,
60 self.nFDTdataRecors,
52 self.nFDTdataRecors,
61 self.RadarUnitId,
53 self.RadarUnitId,
62 self.SiteName,
54 self.SiteName,
63 self.size)
55 self.size)
64
56
65 header = numpy.array(headerTuple, FILE_STRUCTURE)
57 header = numpy.array(headerTuple, FILE_STRUCTURE)
66 header.tofile(fp)
58 header.tofile(fp)
67 ''' ndarray.tofile(fid, sep, format) Write array to a file as text or binary (default).
59 ''' ndarray.tofile(fid, sep, format) Write array to a file as text or binary (default).
68
60
69 fid : file or str
61 fid : file or str
70 An open file object, or a string containing a filename.
62 An open file object, or a string containing a filename.
71
63
72 sep : str
64 sep : str
73 Separator between array items for text output. If "" (empty), a binary file is written,
65 Separator between array items for text output. If "" (empty), a binary file is written,
74 equivalent to file.write(a.tobytes()).
66 equivalent to file.write(a.tobytes()).
75
67
76 format : str
68 format : str
77 Format string for text file output. Each entry in the array is formatted to text by
69 Format string for text file output. Each entry in the array is formatted to text by
78 first converting it to the closest Python type, and then using "format" % item.
70 first converting it to the closest Python type, and then using "format" % item.
79
71
80 '''
72 '''
81
73
82 return 1
74 return 1
83
75
84
76
85 RECORD_STRUCTURE = numpy.dtype([ # RECORD HEADER 180+20N bytes
77 RECORD_STRUCTURE = numpy.dtype([ # RECORD HEADER 180+20N bytes
86 ('RecMgcNumber', '<u4'), # 0x23030001
78 ('RecMgcNumber', '<u4'), # 0x23030001
87 ('RecCounter', '<u4'), # Record counter(0,1, ...)
79 ('RecCounter', '<u4'), # Record counter(0,1, ...)
88 # Offset to start of next record form start of this record
80 # Offset to start of next record form start of this record
89 ('Off2StartNxtRec', '<u4'),
81 ('Off2StartNxtRec', '<u4'),
90 # Offset to start of data from start of this record
82 # Offset to start of data from start of this record
91 ('Off2StartData', '<u4'),
83 ('Off2StartData', '<u4'),
92 # Epoch time stamp of start of acquisition (seconds)
84 # Epoch time stamp of start of acquisition (seconds)
93 ('nUtime', '<i4'),
85 ('nUtime', '<i4'),
94 # Millisecond component of time stamp (0,...,999)
86 # Millisecond component of time stamp (0,...,999)
95 ('nMilisec', '<u4'),
87 ('nMilisec', '<u4'),
96 # Experiment tag name (null terminated)
88 # Experiment tag name (null terminated)
97 ('ExpTagName', 'S32'),
89 ('ExpTagName', 'S32'),
98 # Experiment comment (null terminated)
90 # Experiment comment (null terminated)
99 ('ExpComment', 'S32'),
91 ('ExpComment', 'S32'),
100 # Site latitude (from GPS) in degrees (positive implies North)
92 # Site latitude (from GPS) in degrees (positive implies North)
101 ('SiteLatDegrees', '<f4'),
93 ('SiteLatDegrees', '<f4'),
102 # Site longitude (from GPS) in degrees (positive implies East)
94 # Site longitude (from GPS) in degrees (positive implies East)
103 ('SiteLongDegrees', '<f4'),
95 ('SiteLongDegrees', '<f4'),
104 # RTC GPS engine status (0=SEEK, 1=LOCK, 2=NOT FITTED, 3=UNAVAILABLE)
96 # RTC GPS engine status (0=SEEK, 1=LOCK, 2=NOT FITTED, 3=UNAVAILABLE)
105 ('RTCgpsStatus', '<u4'),
97 ('RTCgpsStatus', '<u4'),
106 ('TransmitFrec', '<u4'), # Transmit frequency (Hz)
98 ('TransmitFrec', '<u4'), # Transmit frequency (Hz)
107 ('ReceiveFrec', '<u4'), # Receive frequency
99 ('ReceiveFrec', '<u4'), # Receive frequency
108 # First local oscillator frequency (Hz)
100 # First local oscillator frequency (Hz)
109 ('FirstOsciFrec', '<u4'),
101 ('FirstOsciFrec', '<u4'),
110 # (0="O", 1="E", 2="linear 1", 3="linear2")
102 # (0="O", 1="E", 2="linear 1", 3="linear2")
111 ('Polarisation', '<u4'),
103 ('Polarisation', '<u4'),
112 # Receiver filter settings (0,1,2,3)
104 # Receiver filter settings (0,1,2,3)
113 ('ReceiverFiltSett', '<u4'),
105 ('ReceiverFiltSett', '<u4'),
114 # Number of modes in use (1 or 2)
106 # Number of modes in use (1 or 2)
115 ('nModesInUse', '<u4'),
107 ('nModesInUse', '<u4'),
116 # Dual Mode index number for these data (0 or 1)
108 # Dual Mode index number for these data (0 or 1)
117 ('DualModeIndex', '<u4'),
109 ('DualModeIndex', '<u4'),
118 # Dual Mode range correction for these data (m)
110 # Dual Mode range correction for these data (m)
119 ('DualModeRange', '<u4'),
111 ('DualModeRange', '<u4'),
120 # Number of digital channels acquired (2*N)
112 # Number of digital channels acquired (2*N)
121 ('nDigChannels', '<u4'),
113 ('nDigChannels', '<u4'),
122 # Sampling resolution (meters)
114 # Sampling resolution (meters)
123 ('SampResolution', '<u4'),
115 ('SampResolution', '<u4'),
124 # Number of range gates sampled
116 # Number of range gates sampled
125 ('nHeights', '<u4'),
117 ('nHeights', '<u4'),
126 # Start range of sampling (meters)
118 # Start range of sampling (meters)
127 ('StartRangeSamp', '<u4'),
119 ('StartRangeSamp', '<u4'),
128 ('PRFhz', '<u4'), # PRF (Hz)
120 ('PRFhz', '<u4'), # PRF (Hz)
129 ('nCohInt', '<u4'), # Integrations
121 ('nCohInt', '<u4'), # Integrations
130 # Number of data points transformed
122 # Number of data points transformed
131 ('nProfiles', '<u4'),
123 ('nProfiles', '<u4'),
132 # Number of receive beams stored in file (1 or N)
124 # Number of receive beams stored in file (1 or N)
133 ('nChannels', '<u4'),
125 ('nChannels', '<u4'),
134 ('nIncohInt', '<u4'), # Number of spectral averages
126 ('nIncohInt', '<u4'), # Number of spectral averages
135 # FFT windowing index (0 = no window)
127 # FFT windowing index (0 = no window)
136 ('FFTwindowingInd', '<u4'),
128 ('FFTwindowingInd', '<u4'),
137 # Beam steer angle (azimuth) in degrees (clockwise from true North)
129 # Beam steer angle (azimuth) in degrees (clockwise from true North)
138 ('BeamAngleAzim', '<f4'),
130 ('BeamAngleAzim', '<f4'),
139 # Beam steer angle (zenith) in degrees (0=> vertical)
131 # Beam steer angle (zenith) in degrees (0=> vertical)
140 ('BeamAngleZen', '<f4'),
132 ('BeamAngleZen', '<f4'),
141 # Antenna coordinates (Range(meters), Bearing(degrees)) - N pairs
133 # Antenna coordinates (Range(meters), Bearing(degrees)) - N pairs
142 ('AntennaCoord0', '<f4'),
134 ('AntennaCoord0', '<f4'),
143 # Antenna coordinates (Range(meters), Bearing(degrees)) - N pairs
135 # Antenna coordinates (Range(meters), Bearing(degrees)) - N pairs
144 ('AntennaAngl0', '<f4'),
136 ('AntennaAngl0', '<f4'),
145 # Antenna coordinates (Range(meters), Bearing(degrees)) - N pairs
137 # Antenna coordinates (Range(meters), Bearing(degrees)) - N pairs
146 ('AntennaCoord1', '<f4'),
138 ('AntennaCoord1', '<f4'),
147 # Antenna coordinates (Range(meters), Bearing(degrees)) - N pairs
139 # Antenna coordinates (Range(meters), Bearing(degrees)) - N pairs
148 ('AntennaAngl1', '<f4'),
140 ('AntennaAngl1', '<f4'),
149 # Antenna coordinates (Range(meters), Bearing(degrees)) - N pairs
141 # Antenna coordinates (Range(meters), Bearing(degrees)) - N pairs
150 ('AntennaCoord2', '<f4'),
142 ('AntennaCoord2', '<f4'),
151 # Antenna coordinates (Range(meters), Bearing(degrees)) - N pairs
143 # Antenna coordinates (Range(meters), Bearing(degrees)) - N pairs
152 ('AntennaAngl2', '<f4'),
144 ('AntennaAngl2', '<f4'),
153 # Receiver phase calibration (degrees) - N values
145 # Receiver phase calibration (degrees) - N values
154 ('RecPhaseCalibr0', '<f4'),
146 ('RecPhaseCalibr0', '<f4'),
155 # Receiver phase calibration (degrees) - N values
147 # Receiver phase calibration (degrees) - N values
156 ('RecPhaseCalibr1', '<f4'),
148 ('RecPhaseCalibr1', '<f4'),
157 # Receiver phase calibration (degrees) - N values
149 # Receiver phase calibration (degrees) - N values
158 ('RecPhaseCalibr2', '<f4'),
150 ('RecPhaseCalibr2', '<f4'),
159 # Receiver amplitude calibration (ratio relative to receiver one) - N values
151 # Receiver amplitude calibration (ratio relative to receiver one) - N values
160 ('RecAmpCalibr0', '<f4'),
152 ('RecAmpCalibr0', '<f4'),
161 # Receiver amplitude calibration (ratio relative to receiver one) - N values
153 # Receiver amplitude calibration (ratio relative to receiver one) - N values
162 ('RecAmpCalibr1', '<f4'),
154 ('RecAmpCalibr1', '<f4'),
163 # Receiver amplitude calibration (ratio relative to receiver one) - N values
155 # Receiver amplitude calibration (ratio relative to receiver one) - N values
164 ('RecAmpCalibr2', '<f4'),
156 ('RecAmpCalibr2', '<f4'),
165 # Receiver gains in dB - N values
157 # Receiver gains in dB - N values
166 ('ReceiverGaindB0', '<i4'),
158 ('ReceiverGaindB0', '<i4'),
167 # Receiver gains in dB - N values
159 # Receiver gains in dB - N values
168 ('ReceiverGaindB1', '<i4'),
160 ('ReceiverGaindB1', '<i4'),
169 # Receiver gains in dB - N values
161 # Receiver gains in dB - N values
170 ('ReceiverGaindB2', '<i4'),
162 ('ReceiverGaindB2', '<i4'),
171 ])
163 ])
172
164
173
165
174 class RecordHeaderBLTR():
166 class RecordHeaderBLTR():
175
167
176 def __init__(self, fo):
168 def __init__(self, fo):
177
169
178 self.fo = fo
170 self.fo = fo
179 self.OffsetStartHeader = 48
171 self.OffsetStartHeader = 48
180 self.Off2StartNxtRec = 811248
172 self.Off2StartNxtRec = 811248
181
173
182 def read(self, block):
174 def read(self, block):
183 OffRHeader = self.OffsetStartHeader + block * self.Off2StartNxtRec
175 OffRHeader = self.OffsetStartHeader + block * self.Off2StartNxtRec
184 self.fo.seek(OffRHeader, os.SEEK_SET)
176 self.fo.seek(OffRHeader, os.SEEK_SET)
185 header = numpy.fromfile(self.fo, RECORD_STRUCTURE, 1)
177 header = numpy.fromfile(self.fo, RECORD_STRUCTURE, 1)
186 self.RecMgcNumber = hex(header['RecMgcNumber'][0]) # 0x23030001
178 self.RecMgcNumber = hex(header['RecMgcNumber'][0]) # 0x23030001
187 self.RecCounter = int(header['RecCounter'][0])
179 self.RecCounter = int(header['RecCounter'][0])
188 self.Off2StartNxtRec = int(header['Off2StartNxtRec'][0])
180 self.Off2StartNxtRec = int(header['Off2StartNxtRec'][0])
189 self.Off2StartData = int(header['Off2StartData'][0])
181 self.Off2StartData = int(header['Off2StartData'][0])
190 self.nUtime = header['nUtime'][0]
182 self.nUtime = header['nUtime'][0]
191 self.nMilisec = header['nMilisec'][0]
183 self.nMilisec = header['nMilisec'][0]
192 self.ExpTagName = '' # str(header['ExpTagName'][0])
184 self.ExpTagName = '' # str(header['ExpTagName'][0])
193 self.ExpComment = '' # str(header['ExpComment'][0])
185 self.ExpComment = '' # str(header['ExpComment'][0])
194 self.SiteLatDegrees = header['SiteLatDegrees'][0]
186 self.SiteLatDegrees = header['SiteLatDegrees'][0]
195 self.SiteLongDegrees = header['SiteLongDegrees'][0]
187 self.SiteLongDegrees = header['SiteLongDegrees'][0]
196 self.RTCgpsStatus = header['RTCgpsStatus'][0]
188 self.RTCgpsStatus = header['RTCgpsStatus'][0]
197 self.TransmitFrec = header['TransmitFrec'][0]
189 self.TransmitFrec = header['TransmitFrec'][0]
198 self.ReceiveFrec = header['ReceiveFrec'][0]
190 self.ReceiveFrec = header['ReceiveFrec'][0]
199 self.FirstOsciFrec = header['FirstOsciFrec'][0]
191 self.FirstOsciFrec = header['FirstOsciFrec'][0]
200 self.Polarisation = header['Polarisation'][0]
192 self.Polarisation = header['Polarisation'][0]
201 self.ReceiverFiltSett = header['ReceiverFiltSett'][0]
193 self.ReceiverFiltSett = header['ReceiverFiltSett'][0]
202 self.nModesInUse = header['nModesInUse'][0]
194 self.nModesInUse = header['nModesInUse'][0]
203 self.DualModeIndex = header['DualModeIndex'][0]
195 self.DualModeIndex = header['DualModeIndex'][0]
204 self.DualModeRange = header['DualModeRange'][0]
196 self.DualModeRange = header['DualModeRange'][0]
205 self.nDigChannels = header['nDigChannels'][0]
197 self.nDigChannels = header['nDigChannels'][0]
206 self.SampResolution = header['SampResolution'][0]
198 self.SampResolution = header['SampResolution'][0]
207 self.nHeights = header['nHeights'][0]
199 self.nHeights = header['nHeights'][0]
208 self.StartRangeSamp = header['StartRangeSamp'][0]
200 self.StartRangeSamp = header['StartRangeSamp'][0]
209 self.PRFhz = header['PRFhz'][0]
201 self.PRFhz = header['PRFhz'][0]
210 self.nCohInt = header['nCohInt'][0]
202 self.nCohInt = header['nCohInt'][0]
211 self.nProfiles = header['nProfiles'][0]
203 self.nProfiles = header['nProfiles'][0]
212 self.nChannels = header['nChannels'][0]
204 self.nChannels = header['nChannels'][0]
213 self.nIncohInt = header['nIncohInt'][0]
205 self.nIncohInt = header['nIncohInt'][0]
214 self.FFTwindowingInd = header['FFTwindowingInd'][0]
206 self.FFTwindowingInd = header['FFTwindowingInd'][0]
215 self.BeamAngleAzim = header['BeamAngleAzim'][0]
207 self.BeamAngleAzim = header['BeamAngleAzim'][0]
216 self.BeamAngleZen = header['BeamAngleZen'][0]
208 self.BeamAngleZen = header['BeamAngleZen'][0]
217 self.AntennaCoord0 = header['AntennaCoord0'][0]
209 self.AntennaCoord0 = header['AntennaCoord0'][0]
218 self.AntennaAngl0 = header['AntennaAngl0'][0]
210 self.AntennaAngl0 = header['AntennaAngl0'][0]
219 self.AntennaCoord1 = header['AntennaCoord1'][0]
211 self.AntennaCoord1 = header['AntennaCoord1'][0]
220 self.AntennaAngl1 = header['AntennaAngl1'][0]
212 self.AntennaAngl1 = header['AntennaAngl1'][0]
221 self.AntennaCoord2 = header['AntennaCoord2'][0]
213 self.AntennaCoord2 = header['AntennaCoord2'][0]
222 self.AntennaAngl2 = header['AntennaAngl2'][0]
214 self.AntennaAngl2 = header['AntennaAngl2'][0]
223 self.RecPhaseCalibr0 = header['RecPhaseCalibr0'][0]
215 self.RecPhaseCalibr0 = header['RecPhaseCalibr0'][0]
224 self.RecPhaseCalibr1 = header['RecPhaseCalibr1'][0]
216 self.RecPhaseCalibr1 = header['RecPhaseCalibr1'][0]
225 self.RecPhaseCalibr2 = header['RecPhaseCalibr2'][0]
217 self.RecPhaseCalibr2 = header['RecPhaseCalibr2'][0]
226 self.RecAmpCalibr0 = header['RecAmpCalibr0'][0]
218 self.RecAmpCalibr0 = header['RecAmpCalibr0'][0]
227 self.RecAmpCalibr1 = header['RecAmpCalibr1'][0]
219 self.RecAmpCalibr1 = header['RecAmpCalibr1'][0]
228 self.RecAmpCalibr2 = header['RecAmpCalibr2'][0]
220 self.RecAmpCalibr2 = header['RecAmpCalibr2'][0]
229 self.ReceiverGaindB0 = header['ReceiverGaindB0'][0]
221 self.ReceiverGaindB0 = header['ReceiverGaindB0'][0]
230 self.ReceiverGaindB1 = header['ReceiverGaindB1'][0]
222 self.ReceiverGaindB1 = header['ReceiverGaindB1'][0]
231 self.ReceiverGaindB2 = header['ReceiverGaindB2'][0]
223 self.ReceiverGaindB2 = header['ReceiverGaindB2'][0]
232 self.ipp = 0.5 * (SPEED_OF_LIGHT / self.PRFhz)
224 self.ipp = 0.5 * (SPEED_OF_LIGHT / self.PRFhz)
233 self.RHsize = 180 + 20 * self.nChannels
225 self.RHsize = 180 + 20 * self.nChannels
234 self.Datasize = self.nProfiles * self.nChannels * self.nHeights * 2 * 4
226 self.Datasize = self.nProfiles * self.nChannels * self.nHeights * 2 * 4
235 endFp = self.OffsetStartHeader + self.RecCounter * self.Off2StartNxtRec
227 endFp = self.OffsetStartHeader + self.RecCounter * self.Off2StartNxtRec
236
228
237
229
238 if OffRHeader > endFp:
230 if OffRHeader > endFp:
239 sys.stderr.write(
231 sys.stderr.write(
240 "Warning %s: Size value read from System Header is lower than it has to be\n" % fp)
232 "Warning %s: Size value read from System Header is lower than it has to be\n" % fp)
241 return 0
233 return 0
242
234
243 if OffRHeader < endFp:
235 if OffRHeader < endFp:
244 sys.stderr.write(
236 sys.stderr.write(
245 "Warning %s: Size value read from System Header size is greater than it has to be\n" % fp)
237 "Warning %s: Size value read from System Header size is greater than it has to be\n" % fp)
246 return 0
238 return 0
247
239
248 return 1
240 return 1
249
241
250
242
251 class BLTRSpectraReader (ProcessingUnit):
243 class BLTRSpectraReader (ProcessingUnit):
252
244
253 def __init__(self):
245 def __init__(self):
254
246
255 ProcessingUnit.__init__(self)
247 ProcessingUnit.__init__(self)
256
248
257 self.ext = ".fdt"
249 self.ext = ".fdt"
258 self.optchar = "P"
250 self.optchar = "P"
259 self.fpFile = None
251 self.fpFile = None
260 self.fp = None
252 self.fp = None
261 self.BlockCounter = 0
253 self.BlockCounter = 0
262 self.fileSizeByHeader = None
254 self.fileSizeByHeader = None
263 self.filenameList = []
255 self.filenameList = []
264 self.fileSelector = 0
256 self.fileSelector = 0
265 self.Off2StartNxtRec = 0
257 self.Off2StartNxtRec = 0
266 self.RecCounter = 0
258 self.RecCounter = 0
267 self.flagNoMoreFiles = 0
259 self.flagNoMoreFiles = 0
268 self.data_spc = None
260 self.data_spc = None
269 self.data_cspc = None
261 self.data_cspc = None
270 self.path = None
262 self.path = None
271 self.OffsetStartHeader = 0
263 self.OffsetStartHeader = 0
272 self.Off2StartData = 0
264 self.Off2StartData = 0
273 self.ipp = 0
265 self.ipp = 0
274 self.nFDTdataRecors = 0
266 self.nFDTdataRecors = 0
275 self.blocksize = 0
267 self.blocksize = 0
276 self.dataOut = Spectra()
268 self.dataOut = Spectra()
277 self.dataOut.flagNoData = False
269 self.dataOut.flagNoData = False
278
270
279 def search_files(self):
271 def search_files(self):
280 '''
272 '''
281 Function that indicates the number of .fdt files that exist in the folder to be read.
273 Function that indicates the number of .fdt files that exist in the folder to be read.
282 It also creates an organized list with the names of the files to read.
274 It also creates an organized list with the names of the files to read.
283 '''
275 '''
284
276
285 files = glob.glob(os.path.join(self.path, '*{}'.format(self.ext)))
277 files = glob.glob(os.path.join(self.path, '*{}'.format(self.ext)))
286 files = sorted(files)
278 files = sorted(files)
287 for f in files:
279 for f in files:
288 filename = f.split('/')[-1]
280 filename = f.split('/')[-1]
289 if folder_in_range(filename.split('.')[1], self.startDate, self.endDate, '%Y%m%d'):
281 if folder_in_range(filename.split('.')[1], self.startDate, self.endDate, '%Y%m%d'):
290 self.filenameList.append(f)
282 self.filenameList.append(f)
291
283
292 def run(self, **kwargs):
284 def run(self, **kwargs):
293 '''
285 '''
294 This method will be the one that will initiate the data entry, will be called constantly.
286 This method will be the one that will initiate the data entry, will be called constantly.
295 You should first verify that your Setup () is set up and then continue to acquire
287 You should first verify that your Setup () is set up and then continue to acquire
296 the data to be processed with getData ().
288 the data to be processed with getData ().
297 '''
289 '''
298 if not self.isConfig:
290 if not self.isConfig:
299 self.setup(**kwargs)
291 self.setup(**kwargs)
300 self.isConfig = True
292 self.isConfig = True
301
293
302 self.getData()
294 self.getData()
303
295
304 def setup(self,
296 def setup(self,
305 path=None,
297 path=None,
306 startDate=None,
298 startDate=None,
307 endDate=None,
299 endDate=None,
308 startTime=None,
300 startTime=None,
309 endTime=None,
301 endTime=None,
310 walk=True,
302 walk=True,
311 code=None,
303 code=None,
312 online=False,
304 online=False,
313 mode=None,
305 mode=None,
314 **kwargs):
306 **kwargs):
315
307
316 self.isConfig = True
308 self.isConfig = True
317
309
318 self.path = path
310 self.path = path
319 self.startDate = startDate
311 self.startDate = startDate
320 self.endDate = endDate
312 self.endDate = endDate
321 self.startTime = startTime
313 self.startTime = startTime
322 self.endTime = endTime
314 self.endTime = endTime
323 self.walk = walk
315 self.walk = walk
324 self.mode = int(mode)
316 self.mode = int(mode)
325 self.search_files()
317 self.search_files()
326 if self.filenameList:
318 if self.filenameList:
327 self.readFile()
319 self.readFile()
328
320
329 def getData(self):
321 def getData(self):
330 '''
322 '''
331 Before starting this function, you should check that there is still an unread file,
323 Before starting this function, you should check that there is still an unread file,
332 If there are still blocks to read or if the data block is empty.
324 If there are still blocks to read or if the data block is empty.
333
325
334 You should call the file "read".
326 You should call the file "read".
335
327
336 '''
328 '''
337
329
338 if self.flagNoMoreFiles:
330 if self.flagNoMoreFiles:
339 self.dataOut.flagNoData = True
331 self.dataOut.flagNoData = True
340 raise schainpy.admin.SchainError('No more files')
332 raise schainpy.admin.SchainError('No more files')
341
333
342 self.readBlock()
334 self.readBlock()
343
335
344 def readFile(self):
336 def readFile(self):
345 '''
337 '''
346 You must indicate if you are reading in Online or Offline mode and load the
338 You must indicate if you are reading in Online or Offline mode and load the
347 The parameters for this file reading mode.
339 The parameters for this file reading mode.
348
340
349 Then you must do 2 actions:
341 Then you must do 2 actions:
350
342
351 1. Get the BLTR FileHeader.
343 1. Get the BLTR FileHeader.
352 2. Start reading the first block.
344 2. Start reading the first block.
353 '''
345 '''
354
346
355 if self.fileSelector < len(self.filenameList):
347 if self.fileSelector < len(self.filenameList):
356 log.success('Opening file: {}'.format(self.filenameList[self.fileSelector]), self.name)
348 log.success('Opening file: {}'.format(self.filenameList[self.fileSelector]), self.name)
357 self.fp = open(self.filenameList[self.fileSelector])
349 self.fp = open(self.filenameList[self.fileSelector])
358 self.fheader = FileHeaderBLTR(self.fp)
350 self.fheader = FileHeaderBLTR(self.fp)
359 self.rheader = RecordHeaderBLTR(self.fp)
351 self.rheader = RecordHeaderBLTR(self.fp)
360 self.nFDTdataRecors = self.fheader.nFDTdataRecors
352 self.nFDTdataRecors = self.fheader.nFDTdataRecors
361 self.fileSelector += 1
353 self.fileSelector += 1
362 self.BlockCounter = 0
354 self.BlockCounter = 0
363 return 1
355 return 1
364 else:
356 else:
365 self.flagNoMoreFiles = True
357 self.flagNoMoreFiles = True
366 self.dataOut.flagNoData = True
358 self.dataOut.flagNoData = True
367 return 0
359 return 0
368
360
369 def readBlock(self):
361 def readBlock(self):
370 '''
362 '''
371 It should be checked if the block has data, if it is not passed to the next file.
363 It should be checked if the block has data, if it is not passed to the next file.
372
364
373 Then the following is done:
365 Then the following is done:
374
366
375 1. Read the RecordHeader
367 1. Read the RecordHeader
376 2. Fill the buffer with the current block number.
368 2. Fill the buffer with the current block number.
377
369
378 '''
370 '''
379
371
380 if self.BlockCounter == self.nFDTdataRecors:
372 if self.BlockCounter == self.nFDTdataRecors:
381 if not self.readFile():
373 if not self.readFile():
382 return
374 return
383
375
384 if self.mode == 1:
376 if self.mode == 1:
385 self.rheader.read(self.BlockCounter+1)
377 self.rheader.read(self.BlockCounter+1)
386 elif self.mode == 0:
378 elif self.mode == 0:
387 self.rheader.read(self.BlockCounter)
379 self.rheader.read(self.BlockCounter)
388
380
389 self.RecCounter = self.rheader.RecCounter
381 self.RecCounter = self.rheader.RecCounter
390 self.OffsetStartHeader = self.rheader.OffsetStartHeader
382 self.OffsetStartHeader = self.rheader.OffsetStartHeader
391 self.Off2StartNxtRec = self.rheader.Off2StartNxtRec
383 self.Off2StartNxtRec = self.rheader.Off2StartNxtRec
392 self.Off2StartData = self.rheader.Off2StartData
384 self.Off2StartData = self.rheader.Off2StartData
393 self.nProfiles = self.rheader.nProfiles
385 self.nProfiles = self.rheader.nProfiles
394 self.nChannels = self.rheader.nChannels
386 self.nChannels = self.rheader.nChannels
395 self.nHeights = self.rheader.nHeights
387 self.nHeights = self.rheader.nHeights
396 self.frequency = self.rheader.TransmitFrec
388 self.frequency = self.rheader.TransmitFrec
397 self.DualModeIndex = self.rheader.DualModeIndex
389 self.DualModeIndex = self.rheader.DualModeIndex
398 self.pairsList = [(0, 1), (0, 2), (1, 2)]
390 self.pairsList = [(0, 1), (0, 2), (1, 2)]
399 self.dataOut.pairsList = self.pairsList
391 self.dataOut.pairsList = self.pairsList
400 self.nRdPairs = len(self.dataOut.pairsList)
392 self.nRdPairs = len(self.dataOut.pairsList)
401 self.dataOut.nRdPairs = self.nRdPairs
393 self.dataOut.nRdPairs = self.nRdPairs
402 self.dataOut.heightList = (self.rheader.StartRangeSamp + numpy.arange(self.nHeights) * self.rheader.SampResolution) / 1000.
394 self.dataOut.heightList = (self.rheader.StartRangeSamp + numpy.arange(self.nHeights) * self.rheader.SampResolution) / 1000.
403 self.dataOut.channelList = range(self.nChannels)
395 self.dataOut.channelList = range(self.nChannels)
404 self.dataOut.nProfiles=self.rheader.nProfiles
396 self.dataOut.nProfiles=self.rheader.nProfiles
405 self.dataOut.nIncohInt=self.rheader.nIncohInt
397 self.dataOut.nIncohInt=self.rheader.nIncohInt
406 self.dataOut.nCohInt=self.rheader.nCohInt
398 self.dataOut.nCohInt=self.rheader.nCohInt
407 self.dataOut.ippSeconds= 1/float(self.rheader.PRFhz)
399 self.dataOut.ippSeconds= 1/float(self.rheader.PRFhz)
408 self.dataOut.PRF=self.rheader.PRFhz
400 self.dataOut.PRF=self.rheader.PRFhz
409 self.dataOut.nFFTPoints=self.rheader.nProfiles
401 self.dataOut.nFFTPoints=self.rheader.nProfiles
410 self.dataOut.utctime = self.rheader.nUtime + self.rheader.nMilisec/1000.
402 self.dataOut.utctime = self.rheader.nUtime + self.rheader.nMilisec/1000.
411 self.dataOut.timeZone = 0
403 self.dataOut.timeZone = 0
412 self.dataOut.useLocalTime = False
404 self.dataOut.useLocalTime = False
413 self.dataOut.nmodes = 2
405 self.dataOut.nmodes = 2
414 log.log('Reading block {} - {}'.format(self.BlockCounter, self.dataOut.datatime), self.name)
406 log.log('Reading block {} - {}'.format(self.BlockCounter, self.dataOut.datatime), self.name)
415 OffDATA = self.OffsetStartHeader + self.RecCounter * \
407 OffDATA = self.OffsetStartHeader + self.RecCounter * \
416 self.Off2StartNxtRec + self.Off2StartData
408 self.Off2StartNxtRec + self.Off2StartData
417 self.fp.seek(OffDATA, os.SEEK_SET)
409 self.fp.seek(OffDATA, os.SEEK_SET)
418
410
419 self.data_fft = numpy.fromfile(self.fp, [('complex','<c8')], self.nProfiles*self.nChannels*self.nHeights )
411 self.data_fft = numpy.fromfile(self.fp, [('complex','<c8')], self.nProfiles*self.nChannels*self.nHeights )
420 self.data_fft = self.data_fft.astype(numpy.dtype('complex'))
412 self.data_fft = self.data_fft.astype(numpy.dtype('complex'))
421 self.data_block = numpy.reshape(self.data_fft,(self.nHeights, self.nChannels, self.nProfiles))
413 self.data_block = numpy.reshape(self.data_fft,(self.nHeights, self.nChannels, self.nProfiles))
422 self.data_block = numpy.transpose(self.data_block, (1,2,0))
414 self.data_block = numpy.transpose(self.data_block, (1,2,0))
423 copy = self.data_block.copy()
415 copy = self.data_block.copy()
424 spc = copy * numpy.conjugate(copy)
416 spc = copy * numpy.conjugate(copy)
425 self.data_spc = numpy.absolute(spc) # valor absoluto o magnitud
417 self.data_spc = numpy.absolute(spc) # valor absoluto o magnitud
426 self.dataOut.data_spc = self.data_spc
427
418
428 cspc = self.data_block.copy()
419 cspc = self.data_block.copy()
429 self.data_cspc = self.data_block.copy()
420 self.data_cspc = self.data_block.copy()
430
421
431 for i in range(self.nRdPairs):
422 for i in range(self.nRdPairs):
432
423
433 chan_index0 = self.dataOut.pairsList[i][0]
424 chan_index0 = self.dataOut.pairsList[i][0]
434 chan_index1 = self.dataOut.pairsList[i][1]
425 chan_index1 = self.dataOut.pairsList[i][1]
435
426
436 self.data_cspc[i, :, :] = cspc[chan_index0, :, :] * numpy.conjugate(cspc[chan_index1, :, :])
427 self.data_cspc[i, :, :] = cspc[chan_index0, :, :] * numpy.conjugate(cspc[chan_index1, :, :])
437
428
438 '''Getting Eij and Nij'''
429 '''Getting Eij and Nij'''
439 (AntennaX0, AntennaY0) = pol2cart(
430 (AntennaX0, AntennaY0) = pol2cart(
440 self.rheader.AntennaCoord0, self.rheader.AntennaAngl0 * numpy.pi / 180)
431 self.rheader.AntennaCoord0, self.rheader.AntennaAngl0 * numpy.pi / 180)
441 (AntennaX1, AntennaY1) = pol2cart(
432 (AntennaX1, AntennaY1) = pol2cart(
442 self.rheader.AntennaCoord1, self.rheader.AntennaAngl1 * numpy.pi / 180)
433 self.rheader.AntennaCoord1, self.rheader.AntennaAngl1 * numpy.pi / 180)
443 (AntennaX2, AntennaY2) = pol2cart(
434 (AntennaX2, AntennaY2) = pol2cart(
444 self.rheader.AntennaCoord2, self.rheader.AntennaAngl2 * numpy.pi / 180)
435 self.rheader.AntennaCoord2, self.rheader.AntennaAngl2 * numpy.pi / 180)
445
436
446 E01 = AntennaX0 - AntennaX1
437 E01 = AntennaX0 - AntennaX1
447 N01 = AntennaY0 - AntennaY1
438 N01 = AntennaY0 - AntennaY1
448
439
449 E02 = AntennaX0 - AntennaX2
440 E02 = AntennaX0 - AntennaX2
450 N02 = AntennaY0 - AntennaY2
441 N02 = AntennaY0 - AntennaY2
451
442
452 E12 = AntennaX1 - AntennaX2
443 E12 = AntennaX1 - AntennaX2
453 N12 = AntennaY1 - AntennaY2
444 N12 = AntennaY1 - AntennaY2
454
445
455 self.ChanDist = numpy.array(
446 self.ChanDist = numpy.array(
456 [[E01, N01], [E02, N02], [E12, N12]])
447 [[E01, N01], [E02, N02], [E12, N12]])
457
448
458 self.dataOut.ChanDist = self.ChanDist
449 self.dataOut.ChanDist = self.ChanDist
459
450
460 self.BlockCounter += 2
451 self.BlockCounter += 2
461 self.dataOut.data_spc = self.data_spc
452 self.dataOut.data_spc = self.data_spc
462 self.dataOut.data_cspc =self.data_cspc
453 self.dataOut.data_cspc =self.data_cspc
@@ -1,627 +1,627
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
96
97 def setup(self, **kwargs):
97 def setup(self, **kwargs):
98
98
99 self.set_kwargs(**kwargs)
99 self.set_kwargs(**kwargs)
100 if not self.ext.startswith('.'):
100 if not self.ext.startswith('.'):
101 self.ext = '.{}'.format(self.ext)
101 self.ext = '.{}'.format(self.ext)
102
102
103 if self.online:
103 if self.online:
104 log.log("Searching files in online mode...", self.name)
104 log.log("Searching files in online mode...", self.name)
105
105
106 for nTries in range(self.nTries):
106 for nTries in range(self.nTries):
107 fullpath = self.searchFilesOnLine(self.path, self.startDate,
107 fullpath = self.searchFilesOnLine(self.path, self.startDate,
108 self.endDate, self.expLabel, self.ext, self.walk,
108 self.endDate, self.expLabel, self.ext, self.walk,
109 self.filefmt, self.folderfmt)
109 self.filefmt, self.folderfmt)
110 try:
110 try:
111 fullpath = next(fullpath)
111 fullpath = next(fullpath)
112 except:
112 except:
113 fullpath = None
113 fullpath = None
114
114
115 if fullpath:
115 if fullpath:
116 break
116 break
117
117
118 log.warning(
118 log.warning(
119 'Waiting {} sec for a valid file in {}: try {} ...'.format(
119 'Waiting {} sec for a valid file in {}: try {} ...'.format(
120 self.delay, self.path, nTries + 1),
120 self.delay, self.path, nTries + 1),
121 self.name)
121 self.name)
122 time.sleep(self.delay)
122 time.sleep(self.delay)
123
123
124 if not(fullpath):
124 if not(fullpath):
125 raise schainpy.admin.SchainError(
125 raise schainpy.admin.SchainError(
126 'There isn\'t any valid file in {}'.format(self.path))
126 'There isn\'t any valid file in {}'.format(self.path))
127
127
128 pathname, filename = os.path.split(fullpath)
128 pathname, filename = os.path.split(fullpath)
129 self.year = int(filename[1:5])
129 self.year = int(filename[1:5])
130 self.doy = int(filename[5:8])
130 self.doy = int(filename[5:8])
131 self.set = int(filename[8:11]) - 1
131 self.set = int(filename[8:11]) - 1
132 else:
132 else:
133 log.log("Searching files in {}".format(self.path), self.name)
133 log.log("Searching files in {}".format(self.path), self.name)
134 self.filenameList = self.searchFilesOffLine(self.path, self.startDate,
134 self.filenameList = self.searchFilesOffLine(self.path, self.startDate,
135 self.endDate, self.expLabel, self.ext, self.walk, self.filefmt, self.folderfmt)
135 self.endDate, self.expLabel, self.ext, self.walk, self.filefmt, self.folderfmt)
136
136
137 self.setNextFile()
137 self.setNextFile()
138
138
139 return
139 return
140
140
141 def readFirstHeader(self):
141 def readFirstHeader(self):
142 '''Read metadata and data'''
142 '''Read metadata and data'''
143
143
144 self.__readMetadata()
144 self.__readMetadata()
145 self.__readData()
145 self.__readData()
146 self.__setBlockList()
146 self.__setBlockList()
147
147
148 if 'type' in self.meta:
148 if 'type' in self.meta:
149 self.dataOut = eval(self.meta['type'])()
149 self.dataOut = eval(self.meta['type'])()
150
150
151 for attr in self.meta:
151 for attr in self.meta:
152 setattr(self.dataOut, attr, self.meta[attr])
152 setattr(self.dataOut, attr, self.meta[attr])
153
153
154 self.blockIndex = 0
154 self.blockIndex = 0
155
155
156 return
156 return
157
157
158 def __setBlockList(self):
158 def __setBlockList(self):
159 '''
159 '''
160 Selects the data within the times defined
160 Selects the data within the times defined
161
161
162 self.fp
162 self.fp
163 self.startTime
163 self.startTime
164 self.endTime
164 self.endTime
165 self.blockList
165 self.blockList
166 self.blocksPerFile
166 self.blocksPerFile
167
167
168 '''
168 '''
169
169
170 startTime = self.startTime
170 startTime = self.startTime
171 endTime = self.endTime
171 endTime = self.endTime
172
172
173 thisUtcTime = self.data['utctime']
173 thisUtcTime = self.data['utctime']
174 self.interval = numpy.min(thisUtcTime[1:] - thisUtcTime[:-1])
174 self.interval = numpy.min(thisUtcTime[1:] - thisUtcTime[:-1])
175
175
176 thisDatetime = datetime.datetime.utcfromtimestamp(thisUtcTime[0])
176 thisDatetime = datetime.datetime.utcfromtimestamp(thisUtcTime[0])
177
177
178 thisDate = thisDatetime.date()
178 thisDate = thisDatetime.date()
179 thisTime = thisDatetime.time()
179 thisTime = thisDatetime.time()
180
180
181 startUtcTime = (datetime.datetime.combine(thisDate, startTime) - datetime.datetime(1970, 1, 1)).total_seconds()
181 startUtcTime = (datetime.datetime.combine(thisDate, startTime) - datetime.datetime(1970, 1, 1)).total_seconds()
182 endUtcTime = (datetime.datetime.combine(thisDate, endTime) - datetime.datetime(1970, 1, 1)).total_seconds()
182 endUtcTime = (datetime.datetime.combine(thisDate, endTime) - datetime.datetime(1970, 1, 1)).total_seconds()
183
183
184 ind = numpy.where(numpy.logical_and(thisUtcTime >= startUtcTime, thisUtcTime < endUtcTime))[0]
184 ind = numpy.where(numpy.logical_and(thisUtcTime >= startUtcTime, thisUtcTime < endUtcTime))[0]
185
185
186 self.blockList = ind
186 self.blockList = ind
187 self.blocksPerFile = len(ind)
187 self.blocksPerFile = len(ind)
188 return
188 return
189
189
190 def __readMetadata(self):
190 def __readMetadata(self):
191 '''
191 '''
192 Reads Metadata
192 Reads Metadata
193 '''
193 '''
194
194
195 meta = {}
195 meta = {}
196
196
197 if self.description:
197 if self.description:
198 for key, value in self.description['Metadata'].items():
198 for key, value in self.description['Metadata'].items():
199 meta[key] = self.fp[value].value
199 meta[key] = self.fp[value][()]
200 else:
200 else:
201 grp = self.fp['Metadata']
201 grp = self.fp['Metadata']
202 for name in grp:
202 for name in grp:
203 meta[name] = grp[name].value
203 meta[name] = grp[name][()]
204
204
205 if self.extras:
205 if self.extras:
206 for key, value in self.extras.items():
206 for key, value in self.extras.items():
207 meta[key] = value
207 meta[key] = value
208 self.meta = meta
208 self.meta = meta
209
209
210 return
210 return
211
211
212 def __readData(self):
212 def __readData(self):
213
213
214 data = {}
214 data = {}
215
215
216 if self.description:
216 if self.description:
217 for key, value in self.description['Data'].items():
217 for key, value in self.description['Data'].items():
218 if isinstance(value, str):
218 if isinstance(value, str):
219 if isinstance(self.fp[value], h5py.Dataset):
219 if isinstance(self.fp[value], h5py.Dataset):
220 data[key] = self.fp[value].value
220 data[key] = self.fp[value][()]
221 elif isinstance(self.fp[value], h5py.Group):
221 elif isinstance(self.fp[value], h5py.Group):
222 array = []
222 array = []
223 for ch in self.fp[value]:
223 for ch in self.fp[value]:
224 array.append(self.fp[value][ch].value)
224 array.append(self.fp[value][ch][()])
225 data[key] = numpy.array(array)
225 data[key] = numpy.array(array)
226 elif isinstance(value, list):
226 elif isinstance(value, list):
227 array = []
227 array = []
228 for ch in value:
228 for ch in value:
229 array.append(self.fp[ch].value)
229 array.append(self.fp[ch][()])
230 data[key] = numpy.array(array)
230 data[key] = numpy.array(array)
231 else:
231 else:
232 grp = self.fp['Data']
232 grp = self.fp['Data']
233 for name in grp:
233 for name in grp:
234 if isinstance(grp[name], h5py.Dataset):
234 if isinstance(grp[name], h5py.Dataset):
235 array = grp[name].value
235 array = grp[name][()]
236 elif isinstance(grp[name], h5py.Group):
236 elif isinstance(grp[name], h5py.Group):
237 array = []
237 array = []
238 for ch in grp[name]:
238 for ch in grp[name]:
239 array.append(grp[name][ch].value)
239 array.append(grp[name][ch][()])
240 array = numpy.array(array)
240 array = numpy.array(array)
241 else:
241 else:
242 log.warning('Unknown type: {}'.format(name))
242 log.warning('Unknown type: {}'.format(name))
243
243
244 if name in self.description:
244 if name in self.description:
245 key = self.description[name]
245 key = self.description[name]
246 else:
246 else:
247 key = name
247 key = name
248 data[key] = array
248 data[key] = array
249
249
250 self.data = data
250 self.data = data
251 return
251 return
252
252
253 def getData(self):
253 def getData(self):
254
254
255 for attr in self.data:
255 for attr in self.data:
256 if self.data[attr].ndim == 1:
256 if self.data[attr].ndim == 1:
257 setattr(self.dataOut, attr, self.data[attr][self.blockIndex])
257 setattr(self.dataOut, attr, self.data[attr][self.blockIndex])
258 else:
258 else:
259 setattr(self.dataOut, attr, self.data[attr][:, self.blockIndex])
259 setattr(self.dataOut, attr, self.data[attr][:, self.blockIndex])
260
260
261 self.dataOut.flagNoData = False
261 self.dataOut.flagNoData = False
262 self.blockIndex += 1
262 self.blockIndex += 1
263
263
264 log.log("Block No. {}/{} -> {}".format(
264 log.log("Block No. {}/{} -> {}".format(
265 self.blockIndex,
265 self.blockIndex,
266 self.blocksPerFile,
266 self.blocksPerFile,
267 self.dataOut.datatime.ctime()), self.name)
267 self.dataOut.datatime.ctime()), self.name)
268
268
269 return
269 return
270
270
271 def run(self, **kwargs):
271 def run(self, **kwargs):
272
272
273 if not(self.isConfig):
273 if not(self.isConfig):
274 self.setup(**kwargs)
274 self.setup(**kwargs)
275 self.isConfig = True
275 self.isConfig = True
276
276
277 if self.blockIndex == self.blocksPerFile:
277 if self.blockIndex == self.blocksPerFile:
278 self.setNextFile()
278 self.setNextFile()
279
279
280 self.getData()
280 self.getData()
281
281
282 return
282 return
283
283
284 @MPDecorator
284 @MPDecorator
285 class HDFWriter(Operation):
285 class HDFWriter(Operation):
286 """Operation to write HDF5 files.
286 """Operation to write HDF5 files.
287
287
288 The HDF5 file contains by default two groups Data and Metadata where
288 The HDF5 file contains by default two groups Data and Metadata where
289 you can save any `dataOut` attribute specified by `dataList` and `metadataList`
289 you can save any `dataOut` attribute specified by `dataList` and `metadataList`
290 parameters, data attributes are normaly time dependent where the metadata
290 parameters, data attributes are normaly time dependent where the metadata
291 are not.
291 are not.
292 It is possible to customize the structure of the HDF5 file with the
292 It is possible to customize the structure of the HDF5 file with the
293 optional description parameter see the examples.
293 optional description parameter see the examples.
294
294
295 Parameters:
295 Parameters:
296 -----------
296 -----------
297 path : str
297 path : str
298 Path where files will be saved.
298 Path where files will be saved.
299 blocksPerFile : int
299 blocksPerFile : int
300 Number of blocks per file
300 Number of blocks per file
301 metadataList : list
301 metadataList : list
302 List of the dataOut attributes that will be saved as metadata
302 List of the dataOut attributes that will be saved as metadata
303 dataList : int
303 dataList : int
304 List of the dataOut attributes that will be saved as data
304 List of the dataOut attributes that will be saved as data
305 setType : bool
305 setType : bool
306 If True the name of the files corresponds to the timestamp of the data
306 If True the name of the files corresponds to the timestamp of the data
307 description : dict, optional
307 description : dict, optional
308 Dictionary with the desired description of the HDF5 file
308 Dictionary with the desired description of the HDF5 file
309
309
310 Examples
310 Examples
311 --------
311 --------
312
312
313 desc = {
313 desc = {
314 'data_output': {'winds': ['z', 'w', 'v']},
314 'data_output': {'winds': ['z', 'w', 'v']},
315 'utctime': 'timestamps',
315 'utctime': 'timestamps',
316 'heightList': 'heights'
316 'heightList': 'heights'
317 }
317 }
318 desc = {
318 desc = {
319 'data_output': ['z', 'w', 'v'],
319 'data_output': ['z', 'w', 'v'],
320 'utctime': 'timestamps',
320 'utctime': 'timestamps',
321 'heightList': 'heights'
321 'heightList': 'heights'
322 }
322 }
323 desc = {
323 desc = {
324 'Data': {
324 'Data': {
325 'data_output': 'winds',
325 'data_output': 'winds',
326 'utctime': 'timestamps'
326 'utctime': 'timestamps'
327 },
327 },
328 'Metadata': {
328 'Metadata': {
329 'heightList': 'heights'
329 'heightList': 'heights'
330 }
330 }
331 }
331 }
332
332
333 writer = proc_unit.addOperation(name='HDFWriter')
333 writer = proc_unit.addOperation(name='HDFWriter')
334 writer.addParameter(name='path', value='/path/to/file')
334 writer.addParameter(name='path', value='/path/to/file')
335 writer.addParameter(name='blocksPerFile', value='32')
335 writer.addParameter(name='blocksPerFile', value='32')
336 writer.addParameter(name='metadataList', value='heightList,timeZone')
336 writer.addParameter(name='metadataList', value='heightList,timeZone')
337 writer.addParameter(name='dataList',value='data_output,utctime')
337 writer.addParameter(name='dataList',value='data_output,utctime')
338 # writer.addParameter(name='description',value=json.dumps(desc))
338 # writer.addParameter(name='description',value=json.dumps(desc))
339
339
340 """
340 """
341
341
342 ext = ".hdf5"
342 ext = ".hdf5"
343 optchar = "D"
343 optchar = "D"
344 filename = None
344 filename = None
345 path = None
345 path = None
346 setFile = None
346 setFile = None
347 fp = None
347 fp = None
348 firsttime = True
348 firsttime = True
349 #Configurations
349 #Configurations
350 blocksPerFile = None
350 blocksPerFile = None
351 blockIndex = None
351 blockIndex = None
352 dataOut = None
352 dataOut = None
353 #Data Arrays
353 #Data Arrays
354 dataList = None
354 dataList = None
355 metadataList = None
355 metadataList = None
356 currentDay = None
356 currentDay = None
357 lastTime = None
357 lastTime = None
358
358
359 def __init__(self):
359 def __init__(self):
360
360
361 Operation.__init__(self)
361 Operation.__init__(self)
362 return
362 return
363
363
364 def setup(self, path=None, blocksPerFile=10, metadataList=None, dataList=None, setType=None, description=None):
364 def setup(self, path=None, blocksPerFile=10, metadataList=None, dataList=None, setType=None, description=None):
365 self.path = path
365 self.path = path
366 self.blocksPerFile = blocksPerFile
366 self.blocksPerFile = blocksPerFile
367 self.metadataList = metadataList
367 self.metadataList = metadataList
368 self.dataList = [s.strip() for s in dataList]
368 self.dataList = [s.strip() for s in dataList]
369 self.setType = setType
369 self.setType = setType
370 self.description = description
370 self.description = description
371
371
372 if self.metadataList is None:
372 if self.metadataList is None:
373 self.metadataList = self.dataOut.metadata_list
373 self.metadataList = self.dataOut.metadata_list
374
374
375 tableList = []
375 tableList = []
376 dsList = []
376 dsList = []
377
377
378 for i in range(len(self.dataList)):
378 for i in range(len(self.dataList)):
379 dsDict = {}
379 dsDict = {}
380 if hasattr(self.dataOut, self.dataList[i]):
380 if hasattr(self.dataOut, self.dataList[i]):
381 dataAux = getattr(self.dataOut, self.dataList[i])
381 dataAux = getattr(self.dataOut, self.dataList[i])
382 dsDict['variable'] = self.dataList[i]
382 dsDict['variable'] = self.dataList[i]
383 else:
383 else:
384 log.warning('Attribute {} not found in dataOut', self.name)
384 log.warning('Attribute {} not found in dataOut', self.name)
385 continue
385 continue
386
386
387 if dataAux is None:
387 if dataAux is None:
388 continue
388 continue
389 elif isinstance(dataAux, (int, float, numpy.integer, numpy.float)):
389 elif isinstance(dataAux, (int, float, numpy.integer, numpy.float)):
390 dsDict['nDim'] = 0
390 dsDict['nDim'] = 0
391 else:
391 else:
392 dsDict['nDim'] = len(dataAux.shape)
392 dsDict['nDim'] = len(dataAux.shape)
393 dsDict['shape'] = dataAux.shape
393 dsDict['shape'] = dataAux.shape
394 dsDict['dsNumber'] = dataAux.shape[0]
394 dsDict['dsNumber'] = dataAux.shape[0]
395 dsDict['dtype'] = dataAux.dtype
395 dsDict['dtype'] = dataAux.dtype
396
396
397 dsList.append(dsDict)
397 dsList.append(dsDict)
398
398
399 self.dsList = dsList
399 self.dsList = dsList
400 self.currentDay = self.dataOut.datatime.date()
400 self.currentDay = self.dataOut.datatime.date()
401
401
402 def timeFlag(self):
402 def timeFlag(self):
403 currentTime = self.dataOut.utctime
403 currentTime = self.dataOut.utctime
404 timeTuple = time.localtime(currentTime)
404 timeTuple = time.localtime(currentTime)
405 dataDay = timeTuple.tm_yday
405 dataDay = timeTuple.tm_yday
406
406
407 if self.lastTime is None:
407 if self.lastTime is None:
408 self.lastTime = currentTime
408 self.lastTime = currentTime
409 self.currentDay = dataDay
409 self.currentDay = dataDay
410 return False
410 return False
411
411
412 timeDiff = currentTime - self.lastTime
412 timeDiff = currentTime - self.lastTime
413
413
414 #Si el dia es diferente o si la diferencia entre un dato y otro supera la hora
414 #Si el dia es diferente o si la diferencia entre un dato y otro supera la hora
415 if dataDay != self.currentDay:
415 if dataDay != self.currentDay:
416 self.currentDay = dataDay
416 self.currentDay = dataDay
417 return True
417 return True
418 elif timeDiff > 3*60*60:
418 elif timeDiff > 3*60*60:
419 self.lastTime = currentTime
419 self.lastTime = currentTime
420 return True
420 return True
421 else:
421 else:
422 self.lastTime = currentTime
422 self.lastTime = currentTime
423 return False
423 return False
424
424
425 def run(self, dataOut, path, blocksPerFile=10, metadataList=None,
425 def run(self, dataOut, path, blocksPerFile=10, metadataList=None,
426 dataList=[], setType=None, description={}):
426 dataList=[], setType=None, description={}):
427
427
428 self.dataOut = dataOut
428 self.dataOut = dataOut
429 if not(self.isConfig):
429 if not(self.isConfig):
430 self.setup(path=path, blocksPerFile=blocksPerFile,
430 self.setup(path=path, blocksPerFile=blocksPerFile,
431 metadataList=metadataList, dataList=dataList,
431 metadataList=metadataList, dataList=dataList,
432 setType=setType, description=description)
432 setType=setType, description=description)
433
433
434 self.isConfig = True
434 self.isConfig = True
435 self.setNextFile()
435 self.setNextFile()
436
436
437 self.putData()
437 self.putData()
438 return
438 return
439
439
440 def setNextFile(self):
440 def setNextFile(self):
441
441
442 ext = self.ext
442 ext = self.ext
443 path = self.path
443 path = self.path
444 setFile = self.setFile
444 setFile = self.setFile
445
445
446 timeTuple = time.localtime(self.dataOut.utctime)
446 timeTuple = time.localtime(self.dataOut.utctime)
447 subfolder = 'd%4.4d%3.3d' % (timeTuple.tm_year,timeTuple.tm_yday)
447 subfolder = 'd%4.4d%3.3d' % (timeTuple.tm_year,timeTuple.tm_yday)
448 fullpath = os.path.join(path, subfolder)
448 fullpath = os.path.join(path, subfolder)
449
449
450 if os.path.exists(fullpath):
450 if os.path.exists(fullpath):
451 filesList = os.listdir(fullpath)
451 filesList = os.listdir(fullpath)
452 filesList = [k for k in filesList if k.startswith(self.optchar)]
452 filesList = [k for k in filesList if k.startswith(self.optchar)]
453 if len( filesList ) > 0:
453 if len( filesList ) > 0:
454 filesList = sorted(filesList, key=str.lower)
454 filesList = sorted(filesList, key=str.lower)
455 filen = filesList[-1]
455 filen = filesList[-1]
456 # el filename debera tener el siguiente formato
456 # el filename debera tener el siguiente formato
457 # 0 1234 567 89A BCDE (hex)
457 # 0 1234 567 89A BCDE (hex)
458 # x YYYY DDD SSS .ext
458 # x YYYY DDD SSS .ext
459 if isNumber(filen[8:11]):
459 if isNumber(filen[8:11]):
460 setFile = int(filen[8:11]) #inicializo mi contador de seteo al seteo del ultimo file
460 setFile = int(filen[8:11]) #inicializo mi contador de seteo al seteo del ultimo file
461 else:
461 else:
462 setFile = -1
462 setFile = -1
463 else:
463 else:
464 setFile = -1 #inicializo mi contador de seteo
464 setFile = -1 #inicializo mi contador de seteo
465 else:
465 else:
466 os.makedirs(fullpath)
466 os.makedirs(fullpath)
467 setFile = -1 #inicializo mi contador de seteo
467 setFile = -1 #inicializo mi contador de seteo
468
468
469 if self.setType is None:
469 if self.setType is None:
470 setFile += 1
470 setFile += 1
471 file = '%s%4.4d%3.3d%03d%s' % (self.optchar,
471 file = '%s%4.4d%3.3d%03d%s' % (self.optchar,
472 timeTuple.tm_year,
472 timeTuple.tm_year,
473 timeTuple.tm_yday,
473 timeTuple.tm_yday,
474 setFile,
474 setFile,
475 ext )
475 ext )
476 else:
476 else:
477 setFile = timeTuple.tm_hour*60+timeTuple.tm_min
477 setFile = timeTuple.tm_hour*60+timeTuple.tm_min
478 file = '%s%4.4d%3.3d%04d%s' % (self.optchar,
478 file = '%s%4.4d%3.3d%04d%s' % (self.optchar,
479 timeTuple.tm_year,
479 timeTuple.tm_year,
480 timeTuple.tm_yday,
480 timeTuple.tm_yday,
481 setFile,
481 setFile,
482 ext )
482 ext )
483
483
484 self.filename = os.path.join( path, subfolder, file )
484 self.filename = os.path.join( path, subfolder, file )
485
485
486 #Setting HDF5 File
486 #Setting HDF5 File
487 self.fp = h5py.File(self.filename, 'w')
487 self.fp = h5py.File(self.filename, 'w')
488 #write metadata
488 #write metadata
489 self.writeMetadata(self.fp)
489 self.writeMetadata(self.fp)
490 #Write data
490 #Write data
491 self.writeData(self.fp)
491 self.writeData(self.fp)
492
492
493 def getLabel(self, name, x=None):
493 def getLabel(self, name, x=None):
494
494
495 if x is None:
495 if x is None:
496 if 'Data' in self.description:
496 if 'Data' in self.description:
497 data = self.description['Data']
497 data = self.description['Data']
498 if 'Metadata' in self.description:
498 if 'Metadata' in self.description:
499 data.update(self.description['Metadata'])
499 data.update(self.description['Metadata'])
500 else:
500 else:
501 data = self.description
501 data = self.description
502 if name in data:
502 if name in data:
503 if isinstance(data[name], str):
503 if isinstance(data[name], str):
504 return data[name]
504 return data[name]
505 elif isinstance(data[name], list):
505 elif isinstance(data[name], list):
506 return None
506 return None
507 elif isinstance(data[name], dict):
507 elif isinstance(data[name], dict):
508 for key, value in data[name].items():
508 for key, value in data[name].items():
509 return key
509 return key
510 return name
510 return name
511 else:
511 else:
512 if 'Metadata' in self.description:
512 if 'Metadata' in self.description:
513 meta = self.description['Metadata']
513 meta = self.description['Metadata']
514 else:
514 else:
515 meta = self.description
515 meta = self.description
516 if name in meta:
516 if name in meta:
517 if isinstance(meta[name], list):
517 if isinstance(meta[name], list):
518 return meta[name][x]
518 return meta[name][x]
519 elif isinstance(meta[name], dict):
519 elif isinstance(meta[name], dict):
520 for key, value in meta[name].items():
520 for key, value in meta[name].items():
521 return value[x]
521 return value[x]
522 if 'cspc' in name:
522 if 'cspc' in name:
523 return 'pair{:02d}'.format(x)
523 return 'pair{:02d}'.format(x)
524 else:
524 else:
525 return 'channel{:02d}'.format(x)
525 return 'channel{:02d}'.format(x)
526
526
527 def writeMetadata(self, fp):
527 def writeMetadata(self, fp):
528
528
529 if self.description:
529 if self.description:
530 if 'Metadata' in self.description:
530 if 'Metadata' in self.description:
531 grp = fp.create_group('Metadata')
531 grp = fp.create_group('Metadata')
532 else:
532 else:
533 grp = fp
533 grp = fp
534 else:
534 else:
535 grp = fp.create_group('Metadata')
535 grp = fp.create_group('Metadata')
536
536
537 for i in range(len(self.metadataList)):
537 for i in range(len(self.metadataList)):
538 if not hasattr(self.dataOut, self.metadataList[i]):
538 if not hasattr(self.dataOut, self.metadataList[i]):
539 log.warning('Metadata: `{}` not found'.format(self.metadataList[i]), self.name)
539 log.warning('Metadata: `{}` not found'.format(self.metadataList[i]), self.name)
540 continue
540 continue
541 value = getattr(self.dataOut, self.metadataList[i])
541 value = getattr(self.dataOut, self.metadataList[i])
542 if isinstance(value, bool):
542 if isinstance(value, bool):
543 if value is True:
543 if value is True:
544 value = 1
544 value = 1
545 else:
545 else:
546 value = 0
546 value = 0
547 grp.create_dataset(self.getLabel(self.metadataList[i]), data=value)
547 grp.create_dataset(self.getLabel(self.metadataList[i]), data=value)
548 return
548 return
549
549
550 def writeData(self, fp):
550 def writeData(self, fp):
551
551
552 if self.description:
552 if self.description:
553 if 'Data' in self.description:
553 if 'Data' in self.description:
554 grp = fp.create_group('Data')
554 grp = fp.create_group('Data')
555 else:
555 else:
556 grp = fp
556 grp = fp
557 else:
557 else:
558 grp = fp.create_group('Data')
558 grp = fp.create_group('Data')
559
559
560 dtsets = []
560 dtsets = []
561 data = []
561 data = []
562
562
563 for dsInfo in self.dsList:
563 for dsInfo in self.dsList:
564 if dsInfo['nDim'] == 0:
564 if dsInfo['nDim'] == 0:
565 ds = grp.create_dataset(
565 ds = grp.create_dataset(
566 self.getLabel(dsInfo['variable']),
566 self.getLabel(dsInfo['variable']),
567 (self.blocksPerFile, ),
567 (self.blocksPerFile, ),
568 chunks=True,
568 chunks=True,
569 dtype=numpy.float64)
569 dtype=numpy.float64)
570 dtsets.append(ds)
570 dtsets.append(ds)
571 data.append((dsInfo['variable'], -1))
571 data.append((dsInfo['variable'], -1))
572 else:
572 else:
573 label = self.getLabel(dsInfo['variable'])
573 label = self.getLabel(dsInfo['variable'])
574 if label is not None:
574 if label is not None:
575 sgrp = grp.create_group(label)
575 sgrp = grp.create_group(label)
576 else:
576 else:
577 sgrp = grp
577 sgrp = grp
578 for i in range(dsInfo['dsNumber']):
578 for i in range(dsInfo['dsNumber']):
579 ds = sgrp.create_dataset(
579 ds = sgrp.create_dataset(
580 self.getLabel(dsInfo['variable'], i),
580 self.getLabel(dsInfo['variable'], i),
581 (self.blocksPerFile, ) + dsInfo['shape'][1:],
581 (self.blocksPerFile, ) + dsInfo['shape'][1:],
582 chunks=True,
582 chunks=True,
583 dtype=dsInfo['dtype'])
583 dtype=dsInfo['dtype'])
584 dtsets.append(ds)
584 dtsets.append(ds)
585 data.append((dsInfo['variable'], i))
585 data.append((dsInfo['variable'], i))
586 fp.flush()
586 fp.flush()
587
587
588 log.log('Creating file: {}'.format(fp.filename), self.name)
588 log.log('Creating file: {}'.format(fp.filename), self.name)
589
589
590 self.ds = dtsets
590 self.ds = dtsets
591 self.data = data
591 self.data = data
592 self.firsttime = True
592 self.firsttime = True
593 self.blockIndex = 0
593 self.blockIndex = 0
594 return
594 return
595
595
596 def putData(self):
596 def putData(self):
597
597
598 if (self.blockIndex == self.blocksPerFile) or self.timeFlag():
598 if (self.blockIndex == self.blocksPerFile) or self.timeFlag():
599 self.closeFile()
599 self.closeFile()
600 self.setNextFile()
600 self.setNextFile()
601
601
602 for i, ds in enumerate(self.ds):
602 for i, ds in enumerate(self.ds):
603 attr, ch = self.data[i]
603 attr, ch = self.data[i]
604 if ch == -1:
604 if ch == -1:
605 ds[self.blockIndex] = getattr(self.dataOut, attr)
605 ds[self.blockIndex] = getattr(self.dataOut, attr)
606 else:
606 else:
607 ds[self.blockIndex] = getattr(self.dataOut, attr)[ch]
607 ds[self.blockIndex] = getattr(self.dataOut, attr)[ch]
608
608
609 self.fp.flush()
609 self.fp.flush()
610 self.blockIndex += 1
610 self.blockIndex += 1
611 log.log('Block No. {}/{}'.format(self.blockIndex, self.blocksPerFile), self.name)
611 log.log('Block No. {}/{}'.format(self.blockIndex, self.blocksPerFile), self.name)
612
612
613 return
613 return
614
614
615 def closeFile(self):
615 def closeFile(self):
616
616
617 if self.blockIndex != self.blocksPerFile:
617 if self.blockIndex != self.blocksPerFile:
618 for ds in self.ds:
618 for ds in self.ds:
619 ds.resize(self.blockIndex, axis=0)
619 ds.resize(self.blockIndex, axis=0)
620
620
621 if self.fp:
621 if self.fp:
622 self.fp.flush()
622 self.fp.flush()
623 self.fp.close()
623 self.fp.close()
624
624
625 def close(self):
625 def close(self):
626
626
627 self.closeFile()
627 self.closeFile()
@@ -1,413 +1,400
1 '''
1 '''
2 Created on Oct 24, 2016
2 Created on Oct 24, 2016
3
3
4 @author: roj- LouVD
4 @author: roj- LouVD
5 '''
5 '''
6
6
7 import numpy
7 import numpy
8 import copy
9 import datetime
8 import datetime
10 import time
9 import time
11 from time import gmtime
12
10
13 from numpy import transpose
11 from schainpy.model.proc.jroproc_base import ProcessingUnit, Operation
14
15 from schainpy.model.proc.jroproc_base import ProcessingUnit, Operation, MPDecorator
16 from schainpy.model.data.jrodata import Parameters
12 from schainpy.model.data.jrodata import Parameters
17
13
18
14
19 class BLTRParametersProc(ProcessingUnit):
15 class BLTRParametersProc(ProcessingUnit):
20 '''
16 '''
21 Processing unit for BLTR parameters data (winds)
17 Processing unit for BLTR parameters data (winds)
22
18
23 Inputs:
19 Inputs:
24 self.dataOut.nmodes - Number of operation modes
20 self.dataOut.nmodes - Number of operation modes
25 self.dataOut.nchannels - Number of channels
21 self.dataOut.nchannels - Number of channels
26 self.dataOut.nranges - Number of ranges
22 self.dataOut.nranges - Number of ranges
27
23
28 self.dataOut.data_snr - SNR array
24 self.dataOut.data_snr - SNR array
29 self.dataOut.data_output - Zonal, Vertical and Meridional velocity array
25 self.dataOut.data_output - Zonal, Vertical and Meridional velocity array
30 self.dataOut.height - Height array (km)
26 self.dataOut.height - Height array (km)
31 self.dataOut.time - Time array (seconds)
27 self.dataOut.time - Time array (seconds)
32
28
33 self.dataOut.fileIndex -Index of the file currently read
29 self.dataOut.fileIndex -Index of the file currently read
34 self.dataOut.lat - Latitude coordinate of BLTR location
30 self.dataOut.lat - Latitude coordinate of BLTR location
35
31
36 self.dataOut.doy - Experiment doy (number of the day in the current year)
32 self.dataOut.doy - Experiment doy (number of the day in the current year)
37 self.dataOut.month - Experiment month
33 self.dataOut.month - Experiment month
38 self.dataOut.day - Experiment day
34 self.dataOut.day - Experiment day
39 self.dataOut.year - Experiment year
35 self.dataOut.year - Experiment year
40 '''
36 '''
41
37
42 def __init__(self):
38 def __init__(self):
43 '''
39 '''
44 Inputs: None
40 Inputs: None
45 '''
41 '''
46 ProcessingUnit.__init__(self)
42 ProcessingUnit.__init__(self)
47 self.dataOut = Parameters()
43 self.dataOut = Parameters()
48
44
49 def setup(self, mode):
45 def setup(self, mode):
50 '''
46 '''
51 '''
47 '''
52 self.dataOut.mode = mode
48 self.dataOut.mode = mode
53
49
54 def run(self, mode, snr_threshold=None):
50 def run(self, mode, snr_threshold=None):
55 '''
51 '''
56 Inputs:
52 Inputs:
57 mode = High resolution (0) or Low resolution (1) data
53 mode = High resolution (0) or Low resolution (1) data
58 snr_threshold = snr filter value
54 snr_threshold = snr filter value
59 '''
55 '''
60
56
61 if not self.isConfig:
57 if not self.isConfig:
62 self.setup(mode)
58 self.setup(mode)
63 self.isConfig = True
59 self.isConfig = True
64
60
65 if self.dataIn.type == 'Parameters':
61 if self.dataIn.type == 'Parameters':
66 self.dataOut.copy(self.dataIn)
62 self.dataOut.copy(self.dataIn)
67
63
68 self.dataOut.data_param = self.dataOut.data[mode]
64 self.dataOut.data_param = self.dataOut.data[mode]
69 self.dataOut.heightList = self.dataOut.height[0]
65 self.dataOut.heightList = self.dataOut.height[0]
70 self.dataOut.data_snr = self.dataOut.data_snr[mode]
66 self.dataOut.data_snr = self.dataOut.data_snr[mode]
71
72 data_param = numpy.zeros([4, len(self.dataOut.heightList)])
73
74 SNRavg = numpy.average(self.dataOut.data_snr, axis=0)
67 SNRavg = numpy.average(self.dataOut.data_snr, axis=0)
75 SNRavgdB = 10*numpy.log10(SNRavg)
68 SNRavgdB = 10*numpy.log10(SNRavg)
69 self.dataOut.data_snr_avg_db = SNRavgdB.reshape(1, *SNRavgdB.shape)
70
76 # Censoring Data
71 # Censoring Data
77 if snr_threshold is not None:
72 if snr_threshold is not None:
78 for i in range(3):
73 for i in range(3):
79 self.dataOut.data_param[i][SNRavgdB <= snr_threshold] = numpy.nan
74 self.dataOut.data_param[i][SNRavgdB <= snr_threshold] = numpy.nan
80 # Including AvgSNR in data_param
81 for i in range(data_param.shape[0]):
82 if i == 3:
83 data_param[i] = SNRavgdB
84 else:
85 data_param[i] = self.dataOut.data_param[i]
86
87 self.dataOut.data_param = data_param
88
75
89 # TODO
76 # TODO
90
77
91 class OutliersFilter(Operation):
78 class OutliersFilter(Operation):
92
79
93 def __init__(self):
80 def __init__(self):
94 '''
81 '''
95 '''
82 '''
96 Operation.__init__(self)
83 Operation.__init__(self)
97
84
98 def run(self, svalue2, method, factor, filter, npoints=9):
85 def run(self, svalue2, method, factor, filter, npoints=9):
99 '''
86 '''
100 Inputs:
87 Inputs:
101 svalue - string to select array velocity
88 svalue - string to select array velocity
102 svalue2 - string to choose axis filtering
89 svalue2 - string to choose axis filtering
103 method - 0 for SMOOTH or 1 for MEDIAN
90 method - 0 for SMOOTH or 1 for MEDIAN
104 factor - number used to set threshold
91 factor - number used to set threshold
105 filter - 1 for data filtering using the standard deviation criteria else 0
92 filter - 1 for data filtering using the standard deviation criteria else 0
106 npoints - number of points for mask filter
93 npoints - number of points for mask filter
107 '''
94 '''
108
95
109 print(' Outliers Filter {} {} / threshold = {}'.format(svalue, svalue, factor))
96 print(' Outliers Filter {} {} / threshold = {}'.format(svalue, svalue, factor))
110
97
111
98
112 yaxis = self.dataOut.heightList
99 yaxis = self.dataOut.heightList
113 xaxis = numpy.array([[self.dataOut.utctime]])
100 xaxis = numpy.array([[self.dataOut.utctime]])
114
101
115 # Zonal
102 # Zonal
116 value_temp = self.dataOut.data_output[0]
103 value_temp = self.dataOut.data_output[0]
117
104
118 # Zonal
105 # Zonal
119 value_temp = self.dataOut.data_output[1]
106 value_temp = self.dataOut.data_output[1]
120
107
121 # Vertical
108 # Vertical
122 value_temp = numpy.transpose(self.dataOut.data_output[2])
109 value_temp = numpy.transpose(self.dataOut.data_output[2])
123
110
124 htemp = yaxis
111 htemp = yaxis
125 std = value_temp
112 std = value_temp
126 for h in range(len(htemp)):
113 for h in range(len(htemp)):
127 nvalues_valid = len(numpy.where(numpy.isfinite(value_temp[h]))[0])
114 nvalues_valid = len(numpy.where(numpy.isfinite(value_temp[h]))[0])
128 minvalid = npoints
115 minvalid = npoints
129
116
130 #only if valid values greater than the minimum required (10%)
117 #only if valid values greater than the minimum required (10%)
131 if nvalues_valid > minvalid:
118 if nvalues_valid > minvalid:
132
119
133 if method == 0:
120 if method == 0:
134 #SMOOTH
121 #SMOOTH
135 w = value_temp[h] - self.Smooth(input=value_temp[h], width=npoints, edge_truncate=1)
122 w = value_temp[h] - self.Smooth(input=value_temp[h], width=npoints, edge_truncate=1)
136
123
137
124
138 if method == 1:
125 if method == 1:
139 #MEDIAN
126 #MEDIAN
140 w = value_temp[h] - self.Median(input=value_temp[h], width = npoints)
127 w = value_temp[h] - self.Median(input=value_temp[h], width = npoints)
141
128
142 dw = numpy.std(w[numpy.where(numpy.isfinite(w))],ddof = 1)
129 dw = numpy.std(w[numpy.where(numpy.isfinite(w))],ddof = 1)
143
130
144 threshold = dw*factor
131 threshold = dw*factor
145 value_temp[numpy.where(w > threshold),h] = numpy.nan
132 value_temp[numpy.where(w > threshold),h] = numpy.nan
146 value_temp[numpy.where(w < -1*threshold),h] = numpy.nan
133 value_temp[numpy.where(w < -1*threshold),h] = numpy.nan
147
134
148
135
149 #At the end
136 #At the end
150 if svalue2 == 'inHeight':
137 if svalue2 == 'inHeight':
151 value_temp = numpy.transpose(value_temp)
138 value_temp = numpy.transpose(value_temp)
152 output_array[:,m] = value_temp
139 output_array[:,m] = value_temp
153
140
154 if svalue == 'zonal':
141 if svalue == 'zonal':
155 self.dataOut.data_output[0] = output_array
142 self.dataOut.data_output[0] = output_array
156
143
157 elif svalue == 'meridional':
144 elif svalue == 'meridional':
158 self.dataOut.data_output[1] = output_array
145 self.dataOut.data_output[1] = output_array
159
146
160 elif svalue == 'vertical':
147 elif svalue == 'vertical':
161 self.dataOut.data_output[2] = output_array
148 self.dataOut.data_output[2] = output_array
162
149
163 return self.dataOut.data_output
150 return self.dataOut.data_output
164
151
165
152
166 def Median(self,input,width):
153 def Median(self,input,width):
167 '''
154 '''
168 Inputs:
155 Inputs:
169 input - Velocity array
156 input - Velocity array
170 width - Number of points for mask filter
157 width - Number of points for mask filter
171
158
172 '''
159 '''
173
160
174 if numpy.mod(width,2) == 1:
161 if numpy.mod(width,2) == 1:
175 pc = int((width - 1) / 2)
162 pc = int((width - 1) / 2)
176 cont = 0
163 cont = 0
177 output = []
164 output = []
178
165
179 for i in range(len(input)):
166 for i in range(len(input)):
180 if i >= pc and i < len(input) - pc:
167 if i >= pc and i < len(input) - pc:
181 new2 = input[i-pc:i+pc+1]
168 new2 = input[i-pc:i+pc+1]
182 temp = numpy.where(numpy.isfinite(new2))
169 temp = numpy.where(numpy.isfinite(new2))
183 new = new2[temp]
170 new = new2[temp]
184 value = numpy.median(new)
171 value = numpy.median(new)
185 output.append(value)
172 output.append(value)
186
173
187 output = numpy.array(output)
174 output = numpy.array(output)
188 output = numpy.hstack((input[0:pc],output))
175 output = numpy.hstack((input[0:pc],output))
189 output = numpy.hstack((output,input[-pc:len(input)]))
176 output = numpy.hstack((output,input[-pc:len(input)]))
190
177
191 return output
178 return output
192
179
193 def Smooth(self,input,width,edge_truncate = None):
180 def Smooth(self,input,width,edge_truncate = None):
194 '''
181 '''
195 Inputs:
182 Inputs:
196 input - Velocity array
183 input - Velocity array
197 width - Number of points for mask filter
184 width - Number of points for mask filter
198 edge_truncate - 1 for truncate the convolution product else
185 edge_truncate - 1 for truncate the convolution product else
199
186
200 '''
187 '''
201
188
202 if numpy.mod(width,2) == 0:
189 if numpy.mod(width,2) == 0:
203 real_width = width + 1
190 real_width = width + 1
204 nzeros = width / 2
191 nzeros = width / 2
205 else:
192 else:
206 real_width = width
193 real_width = width
207 nzeros = (width - 1) / 2
194 nzeros = (width - 1) / 2
208
195
209 half_width = int(real_width)/2
196 half_width = int(real_width)/2
210 length = len(input)
197 length = len(input)
211
198
212 gate = numpy.ones(real_width,dtype='float')
199 gate = numpy.ones(real_width,dtype='float')
213 norm_of_gate = numpy.sum(gate)
200 norm_of_gate = numpy.sum(gate)
214
201
215 nan_process = 0
202 nan_process = 0
216 nan_id = numpy.where(numpy.isnan(input))
203 nan_id = numpy.where(numpy.isnan(input))
217 if len(nan_id[0]) > 0:
204 if len(nan_id[0]) > 0:
218 nan_process = 1
205 nan_process = 1
219 pb = numpy.zeros(len(input))
206 pb = numpy.zeros(len(input))
220 pb[nan_id] = 1.
207 pb[nan_id] = 1.
221 input[nan_id] = 0.
208 input[nan_id] = 0.
222
209
223 if edge_truncate == True:
210 if edge_truncate == True:
224 output = numpy.convolve(input/norm_of_gate,gate,mode='same')
211 output = numpy.convolve(input/norm_of_gate,gate,mode='same')
225 elif edge_truncate == False or edge_truncate == None:
212 elif edge_truncate == False or edge_truncate == None:
226 output = numpy.convolve(input/norm_of_gate,gate,mode='valid')
213 output = numpy.convolve(input/norm_of_gate,gate,mode='valid')
227 output = numpy.hstack((input[0:half_width],output))
214 output = numpy.hstack((input[0:half_width],output))
228 output = numpy.hstack((output,input[len(input)-half_width:len(input)]))
215 output = numpy.hstack((output,input[len(input)-half_width:len(input)]))
229
216
230 if nan_process:
217 if nan_process:
231 pb = numpy.convolve(pb/norm_of_gate,gate,mode='valid')
218 pb = numpy.convolve(pb/norm_of_gate,gate,mode='valid')
232 pb = numpy.hstack((numpy.zeros(half_width),pb))
219 pb = numpy.hstack((numpy.zeros(half_width),pb))
233 pb = numpy.hstack((pb,numpy.zeros(half_width)))
220 pb = numpy.hstack((pb,numpy.zeros(half_width)))
234 output[numpy.where(pb > 0.9999)] = numpy.nan
221 output[numpy.where(pb > 0.9999)] = numpy.nan
235 input[nan_id] = numpy.nan
222 input[nan_id] = numpy.nan
236 return output
223 return output
237
224
238 def Average(self,aver=0,nhaver=1):
225 def Average(self,aver=0,nhaver=1):
239 '''
226 '''
240 Inputs:
227 Inputs:
241 aver - Indicates the time period over which is averaged or consensus data
228 aver - Indicates the time period over which is averaged or consensus data
242 nhaver - Indicates the decimation factor in heights
229 nhaver - Indicates the decimation factor in heights
243
230
244 '''
231 '''
245 nhpoints = 48
232 nhpoints = 48
246
233
247 lat_piura = -5.17
234 lat_piura = -5.17
248 lat_huancayo = -12.04
235 lat_huancayo = -12.04
249 lat_porcuya = -5.8
236 lat_porcuya = -5.8
250
237
251 if '%2.2f'%self.dataOut.lat == '%2.2f'%lat_piura:
238 if '%2.2f'%self.dataOut.lat == '%2.2f'%lat_piura:
252 hcm = 3.
239 hcm = 3.
253 if self.dataOut.year == 2003 :
240 if self.dataOut.year == 2003 :
254 if self.dataOut.doy >= 25 and self.dataOut.doy < 64:
241 if self.dataOut.doy >= 25 and self.dataOut.doy < 64:
255 nhpoints = 12
242 nhpoints = 12
256
243
257 elif '%2.2f'%self.dataOut.lat == '%2.2f'%lat_huancayo:
244 elif '%2.2f'%self.dataOut.lat == '%2.2f'%lat_huancayo:
258 hcm = 3.
245 hcm = 3.
259 if self.dataOut.year == 2003 :
246 if self.dataOut.year == 2003 :
260 if self.dataOut.doy >= 25 and self.dataOut.doy < 64:
247 if self.dataOut.doy >= 25 and self.dataOut.doy < 64:
261 nhpoints = 12
248 nhpoints = 12
262
249
263
250
264 elif '%2.2f'%self.dataOut.lat == '%2.2f'%lat_porcuya:
251 elif '%2.2f'%self.dataOut.lat == '%2.2f'%lat_porcuya:
265 hcm = 5.#2
252 hcm = 5.#2
266
253
267 pdata = 0.2
254 pdata = 0.2
268 taver = [1,2,3,4,6,8,12,24]
255 taver = [1,2,3,4,6,8,12,24]
269 t0 = 0
256 t0 = 0
270 tf = 24
257 tf = 24
271 ntime =(tf-t0)/taver[aver]
258 ntime =(tf-t0)/taver[aver]
272 ti = numpy.arange(ntime)
259 ti = numpy.arange(ntime)
273 tf = numpy.arange(ntime) + taver[aver]
260 tf = numpy.arange(ntime) + taver[aver]
274
261
275
262
276 old_height = self.dataOut.heightList
263 old_height = self.dataOut.heightList
277
264
278 if nhaver > 1:
265 if nhaver > 1:
279 num_hei = len(self.dataOut.heightList)/nhaver/self.dataOut.nmodes
266 num_hei = len(self.dataOut.heightList)/nhaver/self.dataOut.nmodes
280 deltha = 0.05*nhaver
267 deltha = 0.05*nhaver
281 minhvalid = pdata*nhaver
268 minhvalid = pdata*nhaver
282 for im in range(self.dataOut.nmodes):
269 for im in range(self.dataOut.nmodes):
283 new_height = numpy.arange(num_hei)*deltha + self.dataOut.height[im,0] + deltha/2.
270 new_height = numpy.arange(num_hei)*deltha + self.dataOut.height[im,0] + deltha/2.
284
271
285
272
286 data_fHeigths_List = []
273 data_fHeigths_List = []
287 data_fZonal_List = []
274 data_fZonal_List = []
288 data_fMeridional_List = []
275 data_fMeridional_List = []
289 data_fVertical_List = []
276 data_fVertical_List = []
290 startDTList = []
277 startDTList = []
291
278
292
279
293 for i in range(ntime):
280 for i in range(ntime):
294 height = old_height
281 height = old_height
295
282
296 start = datetime.datetime(self.dataOut.year,self.dataOut.month,self.dataOut.day) + datetime.timedelta(hours = int(ti[i])) - datetime.timedelta(hours = 5)
283 start = datetime.datetime(self.dataOut.year,self.dataOut.month,self.dataOut.day) + datetime.timedelta(hours = int(ti[i])) - datetime.timedelta(hours = 5)
297 stop = datetime.datetime(self.dataOut.year,self.dataOut.month,self.dataOut.day) + datetime.timedelta(hours = int(tf[i])) - datetime.timedelta(hours = 5)
284 stop = datetime.datetime(self.dataOut.year,self.dataOut.month,self.dataOut.day) + datetime.timedelta(hours = int(tf[i])) - datetime.timedelta(hours = 5)
298
285
299
286
300 limit_sec1 = time.mktime(start.timetuple())
287 limit_sec1 = time.mktime(start.timetuple())
301 limit_sec2 = time.mktime(stop.timetuple())
288 limit_sec2 = time.mktime(stop.timetuple())
302
289
303 t1 = numpy.where(self.f_timesec >= limit_sec1)
290 t1 = numpy.where(self.f_timesec >= limit_sec1)
304 t2 = numpy.where(self.f_timesec < limit_sec2)
291 t2 = numpy.where(self.f_timesec < limit_sec2)
305 time_select = []
292 time_select = []
306 for val_sec in t1[0]:
293 for val_sec in t1[0]:
307 if val_sec in t2[0]:
294 if val_sec in t2[0]:
308 time_select.append(val_sec)
295 time_select.append(val_sec)
309
296
310
297
311 time_select = numpy.array(time_select,dtype = 'int')
298 time_select = numpy.array(time_select,dtype = 'int')
312 minvalid = numpy.ceil(pdata*nhpoints)
299 minvalid = numpy.ceil(pdata*nhpoints)
313
300
314 zon_aver = numpy.zeros([self.dataOut.nranges,self.dataOut.nmodes],dtype='f4') + numpy.nan
301 zon_aver = numpy.zeros([self.dataOut.nranges,self.dataOut.nmodes],dtype='f4') + numpy.nan
315 mer_aver = numpy.zeros([self.dataOut.nranges,self.dataOut.nmodes],dtype='f4') + numpy.nan
302 mer_aver = numpy.zeros([self.dataOut.nranges,self.dataOut.nmodes],dtype='f4') + numpy.nan
316 ver_aver = numpy.zeros([self.dataOut.nranges,self.dataOut.nmodes],dtype='f4') + numpy.nan
303 ver_aver = numpy.zeros([self.dataOut.nranges,self.dataOut.nmodes],dtype='f4') + numpy.nan
317
304
318 if nhaver > 1:
305 if nhaver > 1:
319 new_zon_aver = numpy.zeros([num_hei,self.dataOut.nmodes],dtype='f4') + numpy.nan
306 new_zon_aver = numpy.zeros([num_hei,self.dataOut.nmodes],dtype='f4') + numpy.nan
320 new_mer_aver = numpy.zeros([num_hei,self.dataOut.nmodes],dtype='f4') + numpy.nan
307 new_mer_aver = numpy.zeros([num_hei,self.dataOut.nmodes],dtype='f4') + numpy.nan
321 new_ver_aver = numpy.zeros([num_hei,self.dataOut.nmodes],dtype='f4') + numpy.nan
308 new_ver_aver = numpy.zeros([num_hei,self.dataOut.nmodes],dtype='f4') + numpy.nan
322
309
323 if len(time_select) > minvalid:
310 if len(time_select) > minvalid:
324 time_average = self.f_timesec[time_select]
311 time_average = self.f_timesec[time_select]
325
312
326 for im in range(self.dataOut.nmodes):
313 for im in range(self.dataOut.nmodes):
327
314
328 for ih in range(self.dataOut.nranges):
315 for ih in range(self.dataOut.nranges):
329 if numpy.sum(numpy.isfinite(self.f_zon[time_select,ih,im])) >= minvalid:
316 if numpy.sum(numpy.isfinite(self.f_zon[time_select,ih,im])) >= minvalid:
330 zon_aver[ih,im] = numpy.nansum(self.f_zon[time_select,ih,im]) / numpy.sum(numpy.isfinite(self.f_zon[time_select,ih,im]))
317 zon_aver[ih,im] = numpy.nansum(self.f_zon[time_select,ih,im]) / numpy.sum(numpy.isfinite(self.f_zon[time_select,ih,im]))
331
318
332 if numpy.sum(numpy.isfinite(self.f_mer[time_select,ih,im])) >= minvalid:
319 if numpy.sum(numpy.isfinite(self.f_mer[time_select,ih,im])) >= minvalid:
333 mer_aver[ih,im] = numpy.nansum(self.f_mer[time_select,ih,im]) / numpy.sum(numpy.isfinite(self.f_mer[time_select,ih,im]))
320 mer_aver[ih,im] = numpy.nansum(self.f_mer[time_select,ih,im]) / numpy.sum(numpy.isfinite(self.f_mer[time_select,ih,im]))
334
321
335 if numpy.sum(numpy.isfinite(self.f_ver[time_select,ih,im])) >= minvalid:
322 if numpy.sum(numpy.isfinite(self.f_ver[time_select,ih,im])) >= minvalid:
336 ver_aver[ih,im] = numpy.nansum(self.f_ver[time_select,ih,im]) / numpy.sum(numpy.isfinite(self.f_ver[time_select,ih,im]))
323 ver_aver[ih,im] = numpy.nansum(self.f_ver[time_select,ih,im]) / numpy.sum(numpy.isfinite(self.f_ver[time_select,ih,im]))
337
324
338 if nhaver > 1:
325 if nhaver > 1:
339 for ih in range(num_hei):
326 for ih in range(num_hei):
340 hvalid = numpy.arange(nhaver) + nhaver*ih
327 hvalid = numpy.arange(nhaver) + nhaver*ih
341
328
342 if numpy.sum(numpy.isfinite(zon_aver[hvalid,im])) >= minvalid:
329 if numpy.sum(numpy.isfinite(zon_aver[hvalid,im])) >= minvalid:
343 new_zon_aver[ih,im] = numpy.nansum(zon_aver[hvalid,im]) / numpy.sum(numpy.isfinite(zon_aver[hvalid,im]))
330 new_zon_aver[ih,im] = numpy.nansum(zon_aver[hvalid,im]) / numpy.sum(numpy.isfinite(zon_aver[hvalid,im]))
344
331
345 if numpy.sum(numpy.isfinite(mer_aver[hvalid,im])) >= minvalid:
332 if numpy.sum(numpy.isfinite(mer_aver[hvalid,im])) >= minvalid:
346 new_mer_aver[ih,im] = numpy.nansum(mer_aver[hvalid,im]) / numpy.sum(numpy.isfinite(mer_aver[hvalid,im]))
333 new_mer_aver[ih,im] = numpy.nansum(mer_aver[hvalid,im]) / numpy.sum(numpy.isfinite(mer_aver[hvalid,im]))
347
334
348 if numpy.sum(numpy.isfinite(ver_aver[hvalid,im])) >= minvalid:
335 if numpy.sum(numpy.isfinite(ver_aver[hvalid,im])) >= minvalid:
349 new_ver_aver[ih,im] = numpy.nansum(ver_aver[hvalid,im]) / numpy.sum(numpy.isfinite(ver_aver[hvalid,im]))
336 new_ver_aver[ih,im] = numpy.nansum(ver_aver[hvalid,im]) / numpy.sum(numpy.isfinite(ver_aver[hvalid,im]))
350 if nhaver > 1:
337 if nhaver > 1:
351 zon_aver = new_zon_aver
338 zon_aver = new_zon_aver
352 mer_aver = new_mer_aver
339 mer_aver = new_mer_aver
353 ver_aver = new_ver_aver
340 ver_aver = new_ver_aver
354 height = new_height
341 height = new_height
355
342
356
343
357 tstart = time_average[0]
344 tstart = time_average[0]
358 tend = time_average[-1]
345 tend = time_average[-1]
359 startTime = time.gmtime(tstart)
346 startTime = time.gmtime(tstart)
360
347
361 year = startTime.tm_year
348 year = startTime.tm_year
362 month = startTime.tm_mon
349 month = startTime.tm_mon
363 day = startTime.tm_mday
350 day = startTime.tm_mday
364 hour = startTime.tm_hour
351 hour = startTime.tm_hour
365 minute = startTime.tm_min
352 minute = startTime.tm_min
366 second = startTime.tm_sec
353 second = startTime.tm_sec
367
354
368 startDTList.append(datetime.datetime(year,month,day,hour,minute,second))
355 startDTList.append(datetime.datetime(year,month,day,hour,minute,second))
369
356
370
357
371 o_height = numpy.array([])
358 o_height = numpy.array([])
372 o_zon_aver = numpy.array([])
359 o_zon_aver = numpy.array([])
373 o_mer_aver = numpy.array([])
360 o_mer_aver = numpy.array([])
374 o_ver_aver = numpy.array([])
361 o_ver_aver = numpy.array([])
375 if self.dataOut.nmodes > 1:
362 if self.dataOut.nmodes > 1:
376 for im in range(self.dataOut.nmodes):
363 for im in range(self.dataOut.nmodes):
377
364
378 if im == 0:
365 if im == 0:
379 h_select = numpy.where(numpy.bitwise_and(height[0,:] >=0,height[0,:] <= hcm,numpy.isfinite(height[0,:])))
366 h_select = numpy.where(numpy.bitwise_and(height[0,:] >=0,height[0,:] <= hcm,numpy.isfinite(height[0,:])))
380 else:
367 else:
381 h_select = numpy.where(numpy.bitwise_and(height[1,:] > hcm,height[1,:] < 20,numpy.isfinite(height[1,:])))
368 h_select = numpy.where(numpy.bitwise_and(height[1,:] > hcm,height[1,:] < 20,numpy.isfinite(height[1,:])))
382
369
383
370
384 ht = h_select[0]
371 ht = h_select[0]
385
372
386 o_height = numpy.hstack((o_height,height[im,ht]))
373 o_height = numpy.hstack((o_height,height[im,ht]))
387 o_zon_aver = numpy.hstack((o_zon_aver,zon_aver[ht,im]))
374 o_zon_aver = numpy.hstack((o_zon_aver,zon_aver[ht,im]))
388 o_mer_aver = numpy.hstack((o_mer_aver,mer_aver[ht,im]))
375 o_mer_aver = numpy.hstack((o_mer_aver,mer_aver[ht,im]))
389 o_ver_aver = numpy.hstack((o_ver_aver,ver_aver[ht,im]))
376 o_ver_aver = numpy.hstack((o_ver_aver,ver_aver[ht,im]))
390
377
391 data_fHeigths_List.append(o_height)
378 data_fHeigths_List.append(o_height)
392 data_fZonal_List.append(o_zon_aver)
379 data_fZonal_List.append(o_zon_aver)
393 data_fMeridional_List.append(o_mer_aver)
380 data_fMeridional_List.append(o_mer_aver)
394 data_fVertical_List.append(o_ver_aver)
381 data_fVertical_List.append(o_ver_aver)
395
382
396
383
397 else:
384 else:
398 h_select = numpy.where(numpy.bitwise_and(height[0,:] <= hcm,numpy.isfinite(height[0,:])))
385 h_select = numpy.where(numpy.bitwise_and(height[0,:] <= hcm,numpy.isfinite(height[0,:])))
399 ht = h_select[0]
386 ht = h_select[0]
400 o_height = numpy.hstack((o_height,height[im,ht]))
387 o_height = numpy.hstack((o_height,height[im,ht]))
401 o_zon_aver = numpy.hstack((o_zon_aver,zon_aver[ht,im]))
388 o_zon_aver = numpy.hstack((o_zon_aver,zon_aver[ht,im]))
402 o_mer_aver = numpy.hstack((o_mer_aver,mer_aver[ht,im]))
389 o_mer_aver = numpy.hstack((o_mer_aver,mer_aver[ht,im]))
403 o_ver_aver = numpy.hstack((o_ver_aver,ver_aver[ht,im]))
390 o_ver_aver = numpy.hstack((o_ver_aver,ver_aver[ht,im]))
404
391
405 data_fHeigths_List.append(o_height)
392 data_fHeigths_List.append(o_height)
406 data_fZonal_List.append(o_zon_aver)
393 data_fZonal_List.append(o_zon_aver)
407 data_fMeridional_List.append(o_mer_aver)
394 data_fMeridional_List.append(o_mer_aver)
408 data_fVertical_List.append(o_ver_aver)
395 data_fVertical_List.append(o_ver_aver)
409
396
410
397
411 return startDTList, data_fHeigths_List, data_fZonal_List, data_fMeridional_List, data_fVertical_List
398 return startDTList, data_fHeigths_List, data_fZonal_List, data_fMeridional_List, data_fVertical_List
412
399
413
400
General Comments 0
You need to be logged in to leave comments. Login now