##// END OF EJS Templates
Update WeatherParamPlot maps and xlmits ylmits
jespinoza -
r1715:e1fb60c9a537
parent child
Show More
@@ -1,752 +1,768
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,re
18 import matplotlib,re
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 import cartopy.crs as ccrs
37
36 from .plotting_codes import register_cmap
38 from .plotting_codes import register_cmap
37
39
38 from schainpy.model.data.jrodata import PlotterData
40 from schainpy.model.data.jrodata import PlotterData
39 from schainpy.model.proc.jroproc_base import ProcessingUnit, Operation, MPDecorator
41 from schainpy.model.proc.jroproc_base import ProcessingUnit, Operation, MPDecorator
40 from schainpy.utils import log
42 from schainpy.utils import log
41
43
42
44
43 EARTH_RADIUS = 6.3710e3
45 EARTH_RADIUS = 6.3710e3
44
46
45 register_cmap()
47 register_cmap()
46
48
47 def ll2xy(lat1, lon1, lat2, lon2):
49 def ll2xy(lat1, lon1, lat2, lon2):
48
50
49 p = 0.017453292519943295
51 p = 0.017453292519943295
50 a = 0.5 - numpy.cos((lat2 - lat1) * p)/2 + numpy.cos(lat1 * p) * \
52 a = 0.5 - numpy.cos((lat2 - lat1) * p)/2 + numpy.cos(lat1 * p) * \
51 numpy.cos(lat2 * p) * (1 - numpy.cos((lon2 - lon1) * p)) / 2
53 numpy.cos(lat2 * p) * (1 - numpy.cos((lon2 - lon1) * p)) / 2
52 r = 12742 * numpy.arcsin(numpy.sqrt(a))
54 r = 12742 * numpy.arcsin(numpy.sqrt(a))
53 theta = numpy.arctan2(numpy.sin((lon2-lon1)*p)*numpy.cos(lat2*p), numpy.cos(lat1*p)
55 theta = numpy.arctan2(numpy.sin((lon2-lon1)*p)*numpy.cos(lat2*p), numpy.cos(lat1*p)
54 * numpy.sin(lat2*p)-numpy.sin(lat1*p)*numpy.cos(lat2*p)*numpy.cos((lon2-lon1)*p))
56 * numpy.sin(lat2*p)-numpy.sin(lat1*p)*numpy.cos(lat2*p)*numpy.cos((lon2-lon1)*p))
55 theta = -theta + numpy.pi/2
57 theta = -theta + numpy.pi/2
56 return r*numpy.cos(theta), r*numpy.sin(theta)
58 return r*numpy.cos(theta), r*numpy.sin(theta)
57
59
58
60
59 def km2deg(km):
61 def km2deg(km):
60 '''
62 '''
61 Convert distance in km to degrees
63 Convert distance in km to degrees
62 '''
64 '''
63
65
64 return numpy.rad2deg(km/EARTH_RADIUS)
66 return numpy.rad2deg(km/EARTH_RADIUS)
65
67
66
68
67 def figpause(interval):
69 def figpause(interval):
68 backend = plt.rcParams['backend']
70 backend = plt.rcParams['backend']
69 if backend in matplotlib.rcsetup.interactive_bk:
71 if backend in matplotlib.rcsetup.interactive_bk:
70 figManager = matplotlib._pylab_helpers.Gcf.get_active()
72 figManager = matplotlib._pylab_helpers.Gcf.get_active()
71 if figManager is not None:
73 if figManager is not None:
72 canvas = figManager.canvas
74 canvas = figManager.canvas
73 if canvas.figure.stale:
75 if canvas.figure.stale:
74 canvas.draw()
76 canvas.draw()
75 try:
77 try:
76 canvas.start_event_loop(interval)
78 canvas.start_event_loop(interval)
77 except:
79 except:
78 pass
80 pass
79 return
81 return
80
82
81 def popup(message):
83 def popup(message):
82 '''
84 '''
83 '''
85 '''
84
86
85 fig = plt.figure(figsize=(12, 8), facecolor='r')
87 fig = plt.figure(figsize=(12, 8), facecolor='r')
86 text = '\n'.join([s.strip() for s in message.split(':')])
88 text = '\n'.join([s.strip() for s in message.split(':')])
87 fig.text(0.01, 0.5, text, ha='left', va='center',
89 fig.text(0.01, 0.5, text, ha='left', va='center',
88 size='20', weight='heavy', color='w')
90 size='20', weight='heavy', color='w')
89 fig.show()
91 fig.show()
90 figpause(1000)
92 figpause(1000)
91
93
92
94
93 class Throttle(object):
95 class Throttle(object):
94 '''
96 '''
95 Decorator that prevents a function from being called more than once every
97 Decorator that prevents a function from being called more than once every
96 time period.
98 time period.
97 To create a function that cannot be called more than once a minute, but
99 To create a function that cannot be called more than once a minute, but
98 will sleep until it can be called:
100 will sleep until it can be called:
99 @Throttle(minutes=1)
101 @Throttle(minutes=1)
100 def foo():
102 def foo():
101 pass
103 pass
102
104
103 for i in range(10):
105 for i in range(10):
104 foo()
106 foo()
105 print "This function has run %s times." % i
107 print "This function has run %s times." % i
106 '''
108 '''
107
109
108 def __init__(self, seconds=0, minutes=0, hours=0):
110 def __init__(self, seconds=0, minutes=0, hours=0):
109 self.throttle_period = datetime.timedelta(
111 self.throttle_period = datetime.timedelta(
110 seconds=seconds, minutes=minutes, hours=hours
112 seconds=seconds, minutes=minutes, hours=hours
111 )
113 )
112
114
113 self.time_of_last_call = datetime.datetime.min
115 self.time_of_last_call = datetime.datetime.min
114
116
115 def __call__(self, fn):
117 def __call__(self, fn):
116 @wraps(fn)
118 @wraps(fn)
117 def wrapper(*args, **kwargs):
119 def wrapper(*args, **kwargs):
118 coerce = kwargs.pop('coerce', None)
120 coerce = kwargs.pop('coerce', None)
119 if coerce:
121 if coerce:
120 self.time_of_last_call = datetime.datetime.now()
122 self.time_of_last_call = datetime.datetime.now()
121 return fn(*args, **kwargs)
123 return fn(*args, **kwargs)
122 else:
124 else:
123 now = datetime.datetime.now()
125 now = datetime.datetime.now()
124 time_since_last_call = now - self.time_of_last_call
126 time_since_last_call = now - self.time_of_last_call
125 time_left = self.throttle_period - time_since_last_call
127 time_left = self.throttle_period - time_since_last_call
126
128
127 if time_left > datetime.timedelta(seconds=0):
129 if time_left > datetime.timedelta(seconds=0):
128 return
130 return
129
131
130 self.time_of_last_call = datetime.datetime.now()
132 self.time_of_last_call = datetime.datetime.now()
131 return fn(*args, **kwargs)
133 return fn(*args, **kwargs)
132
134
133 return wrapper
135 return wrapper
134
136
135 def apply_throttle(value):
137 def apply_throttle(value):
136
138
137 @Throttle(seconds=value)
139 @Throttle(seconds=value)
138 def fnThrottled(fn):
140 def fnThrottled(fn):
139 fn()
141 fn()
140
142
141 return fnThrottled
143 return fnThrottled
142
144
143
145
144 @MPDecorator
146 @MPDecorator
145 class Plot(Operation):
147 class Plot(Operation):
146 """Base class for Schain plotting operations
148 """Base class for Schain plotting operations
147
149
148 This class should never be use directtly you must subclass a new operation,
150 This class should never be use directtly you must subclass a new operation,
149 children classes must be defined as follow:
151 children classes must be defined as follow:
150
152
151 ExamplePlot(Plot):
153 ExamplePlot(Plot):
152
154
153 CODE = 'code'
155 CODE = 'code'
154 colormap = 'jet'
156 colormap = 'jet'
155 plot_type = 'pcolor' # options are ('pcolor', 'pcolorbuffer', 'scatter', 'scatterbuffer')
157 plot_type = 'pcolor' # options are ('pcolor', 'pcolorbuffer', 'scatter', 'scatterbuffer')
156
158
157 def setup(self):
159 def setup(self):
158 pass
160 pass
159
161
160 def plot(self):
162 def plot(self):
161 pass
163 pass
162
164
163 """
165 """
164
166
165 CODE = 'Figure'
167 CODE = 'Figure'
166 colormap = 'jet'
168 colormap = 'jet'
167 bgcolor = 'white'
169 bgcolor = 'white'
168 buffering = True
170 buffering = True
169 __missing = 1E30
171 __missing = 1E30
170 projection = None
172 projection = None
171
173
172 __attrs__ = ['show', 'save', 'ymin', 'ymax', 'zmin', 'zmax', 'title',
174 __attrs__ = ['show', 'save', 'ymin', 'ymax', 'zmin', 'zmax', 'title',
173 'showprofile']
175 'showprofile']
174
176
175 def __init__(self):
177 def __init__(self):
176
178
177 Operation.__init__(self)
179 Operation.__init__(self)
178 self.isConfig = False
180 self.isConfig = False
179 self.isPlotConfig = False
181 self.isPlotConfig = False
180 self.save_time = 0
182 self.save_time = 0
181 self.sender_time = 0
183 self.sender_time = 0
182 self.data = None
184 self.data = None
183 self.firsttime = True
185 self.firsttime = True
184 self.sender_queue = deque(maxlen=10)
186 self.sender_queue = deque(maxlen=10)
185 self.plots_adjust = {'left': 0.125, 'right': 0.9, 'bottom': 0.15, 'top': 0.9, 'wspace': 0.2, 'hspace': 0.2}
187 self.plots_adjust = {'left': 0.125, 'right': 0.9, 'bottom': 0.15, 'top': 0.9, 'wspace': 0.2, 'hspace': 0.2}
186
188
187 def __fmtTime(self, x, pos):
189 def __fmtTime(self, x, pos):
188 '''
190 '''
189 '''
191 '''
190
192
191 return '{}'.format(self.getDateTime(x).strftime('%H:%M'))
193 return '{}'.format(self.getDateTime(x).strftime('%H:%M'))
192
194
193 def __setup(self, **kwargs):
195 def __setup(self, **kwargs):
194 '''
196 '''
195 Initialize variables
197 Initialize variables
196 '''
198 '''
197
199
198 self.figures = []
200 self.figures = []
199 self.axes = []
201 self.axes = []
200 self.cb_axes = []
202 self.cb_axes = []
201 self.localtime = kwargs.pop('localtime', True)
203 self.localtime = kwargs.pop('localtime', True)
202 self.show = kwargs.get('show', True)
204 self.show = kwargs.get('show', True)
203 self.save = kwargs.get('save', False)
205 self.save = kwargs.get('save', False)
204 self.save_period = kwargs.get('save_period', 0)
206 self.save_period = kwargs.get('save_period', 0)
205 self.colormap = kwargs.get('colormap', self.colormap)
207 self.colormap = kwargs.get('colormap', self.colormap)
206 self.colormap_coh = kwargs.get('colormap_coh', 'jet')
208 self.colormap_coh = kwargs.get('colormap_coh', 'jet')
207 self.colormap_phase = kwargs.get('colormap_phase', 'RdBu_r')
209 self.colormap_phase = kwargs.get('colormap_phase', 'RdBu_r')
208 self.colormaps = kwargs.get('colormaps', None)
210 self.colormaps = kwargs.get('colormaps', None)
209 self.bgcolor = kwargs.get('bgcolor', self.bgcolor)
211 self.bgcolor = kwargs.get('bgcolor', self.bgcolor)
210 self.showprofile = kwargs.get('showprofile', False)
212 self.showprofile = kwargs.get('showprofile', False)
211 self.title = kwargs.get('wintitle', self.CODE.upper())
213 self.title = kwargs.get('wintitle', self.CODE.upper())
212 self.cb_label = kwargs.get('cb_label', None)
214 self.cb_label = kwargs.get('cb_label', None)
213 self.cb_labels = kwargs.get('cb_labels', None)
215 self.cb_labels = kwargs.get('cb_labels', None)
214 self.labels = kwargs.get('labels', None)
216 self.labels = kwargs.get('labels', None)
215 self.xaxis = kwargs.get('xaxis', 'frequency')
217 self.xaxis = kwargs.get('xaxis', 'frequency')
216 self.zmin = kwargs.get('zmin', None)
218 self.zmin = kwargs.get('zmin', None)
217 self.zmax = kwargs.get('zmax', None)
219 self.zmax = kwargs.get('zmax', None)
218 self.zlimits = kwargs.get('zlimits', None)
220 self.zlimits = kwargs.get('zlimits', None)
219 self.xmin = kwargs.get('xmin', None)
221 self.xmin = kwargs.get('xmin', None)
220 self.xmax = kwargs.get('xmax', None)
222 self.xmax = kwargs.get('xmax', None)
221 self.xrange = kwargs.get('xrange', 12)
223 self.yrange = kwargs.get('yrange', None)
224 self.xrange = kwargs.get('xrange', None)
222 self.xscale = kwargs.get('xscale', None)
225 self.xscale = kwargs.get('xscale', None)
223 self.ymin = kwargs.get('ymin', None)
226 self.ymin = kwargs.get('ymin', None)
224 self.ymax = kwargs.get('ymax', None)
227 self.ymax = kwargs.get('ymax', None)
225 self.yscale = kwargs.get('yscale', None)
228 self.yscale = kwargs.get('yscale', None)
226 self.xlabel = kwargs.get('xlabel', None)
229 self.xlabel = kwargs.get('xlabel', None)
227 self.attr_time = kwargs.get('attr_time', 'utctime')
230 self.attr_time = kwargs.get('attr_time', 'utctime')
228 self.attr_data = kwargs.get('attr_data', 'data_param')
231 self.attr_data = kwargs.get('attr_data', 'data_param')
229 self.decimation = kwargs.get('decimation', None)
232 self.decimation = kwargs.get('decimation', None)
230 self.oneFigure = kwargs.get('oneFigure', True)
233 self.oneFigure = kwargs.get('oneFigure', True)
231 self.width = kwargs.get('width', None)
234 self.width = kwargs.get('width', None)
232 self.height = kwargs.get('height', None)
235 self.height = kwargs.get('height', None)
233 self.colorbar = kwargs.get('colorbar', True)
236 self.colorbar = kwargs.get('colorbar', True)
234 self.factors = kwargs.get('factors', [1, 1, 1, 1, 1, 1, 1, 1])
237 self.factors = kwargs.get('factors', [1, 1, 1, 1, 1, 1, 1, 1])
235 self.channels = kwargs.get('channels', None)
238 self.channels = kwargs.get('channels', None)
236 self.titles = kwargs.get('titles', [])
239 self.titles = kwargs.get('titles', [])
237 self.polar = False
240 self.polar = False
238 self.type = kwargs.get('type', 'iq')
241 self.type = kwargs.get('type', 'iq')
239 self.grid = kwargs.get('grid', False)
242 self.grid = kwargs.get('grid', False)
240 self.pause = kwargs.get('pause', False)
243 self.pause = kwargs.get('pause', False)
241 self.save_code = kwargs.get('save_code', self.CODE)
244 self.save_code = kwargs.get('save_code', self.CODE)
242 self.throttle = kwargs.get('throttle', 0)
245 self.throttle = kwargs.get('throttle', 0)
243 self.exp_code = kwargs.get('exp_code', None)
246 self.exp_code = kwargs.get('exp_code', None)
244 self.server = kwargs.get('server', False)
247 self.server = kwargs.get('server', False)
245 self.sender_period = kwargs.get('sender_period', 60)
248 self.sender_period = kwargs.get('sender_period', 60)
246 self.tag = kwargs.get('tag', '')
249 self.tag = kwargs.get('tag', '')
247 self.height_index = kwargs.get('height_index', None)
250 self.height_index = kwargs.get('height_index', None)
248 self.__throttle_plot = apply_throttle(self.throttle)
251 self.__throttle_plot = apply_throttle(self.throttle)
249 code = self.attr_data if self.attr_data else self.CODE
252 code = self.attr_data if self.attr_data else self.CODE
250 self.data = PlotterData(self.CODE, self.exp_code, self.localtime)
253 self.data = PlotterData(self.CODE, self.exp_code, self.localtime)
251 self.ang_min = kwargs.get('ang_min', None)
254 self.ang_min = kwargs.get('ang_min', None)
252 self.ang_max = kwargs.get('ang_max', None)
255 self.ang_max = kwargs.get('ang_max', None)
253 self.mode = kwargs.get('mode', None)
256 self.mode = kwargs.get('mode', None)
254 self.mask = kwargs.get('mask', False)
257 self.mask = kwargs.get('mask', False)
255 self.shapes = kwargs.get('shapes', './')
258 self.shapes = kwargs.get('shapes', './')
259 self.map = kwargs.get('map', False)
260 self.latitude = kwargs.get('latitude', -12)
261 self.longitude = kwargs.get('longitude', -74)
256
262
257 if self.server:
263 if self.server:
258 if not self.server.startswith('tcp://'):
264 if not self.server.startswith('tcp://'):
259 self.server = 'tcp://{}'.format(self.server)
265 self.server = 'tcp://{}'.format(self.server)
260 log.success(
266 log.success(
261 'Sending to server: {}'.format(self.server),
267 'Sending to server: {}'.format(self.server),
262 self.name
268 self.name
263 )
269 )
264
270
265 if isinstance(self.attr_data, str):
271 if isinstance(self.attr_data, str):
266 self.attr_data = [self.attr_data]
272 self.attr_data = [self.attr_data]
267
273
274
268 def __setup_plot(self):
275 def __setup_plot(self):
269 '''
276 '''
270 Common setup for all figures, here figures and axes are created
277 Common setup for all figures, here figures and axes are created
271 '''
278 '''
272
279
273 self.setup()
280 self.setup()
274
281
275 self.time_label = 'LT' if self.localtime else 'UTC'
282 self.time_label = 'LT' if self.localtime else 'UTC'
276
283
277 if self.width is None:
284 if self.width is None:
278 self.width = 8
285 self.width = 8
279
286
280 self.figures = {'PPI':[], 'RHI':[]}
287 self.figures = {'PPI':[], 'RHI':[]}
281 self.axes = {'PPI':[], 'RHI':[]}
288 self.axes = {'PPI':[], 'RHI':[]}
282 self.cb_axes = []
289 self.cb_axes = []
283 self.pf_axes = []
290 self.pf_axes = []
284 self.cmaps = []
291 self.cmaps = []
285
292
286 size = '15%' if self.ncols == 1 else '30%'
293 size = '15%' if self.ncols == 1 else '30%'
287 pad = '4%' if self.ncols == 1 else '8%'
294 pad = '4%' if self.ncols == 1 else '8%'
288
295
289 if self.oneFigure:
296 if self.oneFigure:
290 if self.height is None:
297 if self.height is None:
291 self.height = 1.4 * self.nrows + 1
298 self.height = 1.4 * self.nrows + 1
292 fig_p = plt.figure(figsize=(self.width, self.height),
299 fig_p = plt.figure(figsize=(self.width, self.height),
293 edgecolor='k',
300 edgecolor='k',
294 facecolor='w')
301 facecolor='w')
295 fig_r = plt.figure(figsize=(self.width, 4),
302 fig_r = plt.figure(figsize=(self.width, 4),
296 edgecolor='k',
303 edgecolor='k',
297 facecolor='w')
304 facecolor='w')
298 self.figures['PPI'].append(fig_p)
305 self.figures['PPI'].append(fig_p)
299 self.figures['RHI'].append(fig_r)
306 self.figures['RHI'].append(fig_r)
300 for n in range(self.nplots):
307 for n in range(self.nplots):
301 ax_p = fig_p.add_subplot(self.nrows, self.ncols, n+1, polar=self.polar, projection=self.projection)
308 if self.map:
309 ax_p = fig_p.add_subplot(self.nrows, self.ncols, n+1, polar=self.polar, projection=ccrs.PlateCarree())
310 else:
311 ax_p = fig_p.add_subplot(self.nrows, self.ncols, n+1, polar=self.polar)
312 print('sin projection')
302 ax_r = fig_r.add_subplot(self.nrows, self.ncols, n+1, polar=self.polar)
313 ax_r = fig_r.add_subplot(self.nrows, self.ncols, n+1, polar=self.polar)
303 ax_p.tick_params(labelsize=8)
314 ax_p.tick_params(labelsize=8)
304 ax_p.firsttime = True
315 ax_p.firsttime = True
305 ax_p.index = 0
316 ax_p.index = 0
306 ax_p.press = None
317 ax_p.press = None
307 ax_r.tick_params(labelsize=8)
318 ax_r.tick_params(labelsize=8)
308 ax_r.firsttime = True
319 ax_r.firsttime = True
309 ax_r.index = 0
320 ax_r.index = 0
310 ax_r.press = None
321 ax_r.press = None
311
322
312 self.axes['PPI'].append(ax_p)
323 self.axes['PPI'].append(ax_p)
313 self.axes['RHI'].append(ax_r)
324 self.axes['RHI'].append(ax_r)
314
325
315 if self.showprofile:
326 if self.showprofile:
316 cax = self.__add_axes(ax, size=size, pad=pad)
327 cax = self.__add_axes(ax, size=size, pad=pad)
317 cax.tick_params(labelsize=8)
328 cax.tick_params(labelsize=8)
318 self.pf_axes.append(cax)
329 self.pf_axes.append(cax)
319 else:
330 else:
320 if self.height is None:
331 if self.height is None:
321 self.height = 3
332 self.height = 3
322 for n in range(self.nplots):
333 for n in range(self.nplots):
323 fig = plt.figure(figsize=(self.width, self.height),
334 fig = plt.figure(figsize=(self.width, self.height),
324 edgecolor='k',
335 edgecolor='k',
325 facecolor='w')
336 facecolor='w')
326 ax_p = fig.add_subplot(1, 1, 1, polar=self.polar, projection=self.projection)
337 if self.map:
338 ax_p = fig.add_subplot(1, 1, 1, polar=self.polar, projection=ccrs.PlateCarree())
339 else:
340 ax_p = fig.add_subplot(1, 1, 1, polar=self.polar)
341 print('sin projection')
342
327 ax_r = fig.add_subplot(1, 1, 1, polar=self.polar)
343 ax_r = fig.add_subplot(1, 1, 1, polar=self.polar)
328 ax_p.tick_params(labelsize=8)
344 ax_p.tick_params(labelsize=8)
329 ax_p.firsttime = True
345 ax_p.firsttime = True
330 ax_p.index = 0
346 ax_p.index = 0
331 ax_p.press = None
347 ax_p.press = None
332 ax_r.tick_params(labelsize=8)
348 ax_r.tick_params(labelsize=8)
333 ax_r.firsttime = True
349 ax_r.firsttime = True
334 ax_r.index = 0
350 ax_r.index = 0
335 ax_r.press = None
351 ax_r.press = None
336 self.figures.append(fig)
352 self.figures.append(fig)
337 self.axes['PPI'].append(ax_p)
353 self.axes['PPI'].append(ax_p)
338 self.axes['RHI'].append(ax_r)
354 self.axes['RHI'].append(ax_r)
339 if self.showprofile:
355 if self.showprofile:
340 cax = self.__add_axes(ax, size=size, pad=pad)
356 cax = self.__add_axes(ax, size=size, pad=pad)
341 cax.tick_params(labelsize=8)
357 cax.tick_params(labelsize=8)
342 self.pf_axes.append(cax)
358 self.pf_axes.append(cax)
343
359
344 # for n in range(self.nrows):
360 # for n in range(self.nrows):
345 # if self.colormaps is not None:
361 # if self.colormaps is not None:
346 # cmap = plt.get_cmap(self.colormaps[n])
362 # cmap = plt.get_cmap(self.colormaps[n])
347 # else:
363 # else:
348 # cmap = plt.get_cmap(self.colormap)
364 # cmap = plt.get_cmap(self.colormap)
349 # cmap.set_bad(self.bgcolor, 1.)
365 # cmap.set_bad(self.bgcolor, 1.)
350 # self.cmaps.append(cmap)
366 # self.cmaps.append(cmap)
351
367
352 def __add_axes(self, ax, size='30%', pad='8%'):
368 def __add_axes(self, ax, size='30%', pad='8%'):
353 '''
369 '''
354 Add new axes to the given figure
370 Add new axes to the given figure
355 '''
371 '''
356 divider = make_axes_locatable(ax)
372 divider = make_axes_locatable(ax)
357 nax = divider.new_horizontal(size=size, pad=pad)
373 nax = divider.new_horizontal(size=size, pad=pad)
358 ax.figure.add_axes(nax)
374 ax.figure.add_axes(nax)
359 return nax
375 return nax
360
376
361 def fill_gaps(self, x_buffer, y_buffer, z_buffer):
377 def fill_gaps(self, x_buffer, y_buffer, z_buffer):
362 '''
378 '''
363 Create a masked array for missing data
379 Create a masked array for missing data
364 '''
380 '''
365 if x_buffer.shape[0] < 2:
381 if x_buffer.shape[0] < 2:
366 return x_buffer, y_buffer, z_buffer
382 return x_buffer, y_buffer, z_buffer
367
383
368 deltas = x_buffer[1:] - x_buffer[0:-1]
384 deltas = x_buffer[1:] - x_buffer[0:-1]
369 x_median = numpy.median(deltas)
385 x_median = numpy.median(deltas)
370
386
371 index = numpy.where(deltas > 5 * x_median)
387 index = numpy.where(deltas > 5 * x_median)
372
388
373 if len(index[0]) != 0:
389 if len(index[0]) != 0:
374 z_buffer[::, index[0], ::] = self.__missing
390 z_buffer[::, index[0], ::] = self.__missing
375 z_buffer = numpy.ma.masked_inside(z_buffer,
391 z_buffer = numpy.ma.masked_inside(z_buffer,
376 0.99 * self.__missing,
392 0.99 * self.__missing,
377 1.01 * self.__missing)
393 1.01 * self.__missing)
378
394
379 return x_buffer, y_buffer, z_buffer
395 return x_buffer, y_buffer, z_buffer
380
396
381 def decimate(self):
397 def decimate(self):
382
398
383 # dx = int(len(self.x)/self.__MAXNUMX) + 1
399 # dx = int(len(self.x)/self.__MAXNUMX) + 1
384 dy = int(len(self.y) / self.decimation) + 1
400 dy = int(len(self.y) / self.decimation) + 1
385
401
386 # x = self.x[::dx]
402 # x = self.x[::dx]
387 x = self.x
403 x = self.x
388 y = self.y[::dy]
404 y = self.y[::dy]
389 z = self.z[::, ::, ::dy]
405 z = self.z[::, ::, ::dy]
390
406
391 return x, y, z
407 return x, y, z
392
408
393 def format(self):
409 def format(self):
394 '''
410 '''
395 Set min and max values, labels, ticks and titles
411 Set min and max values, labels, ticks and titles
396 '''
412 '''
397
413
398 for n, ax in enumerate(self.axes[self.mode]):
414 for n, ax in enumerate(self.axes[self.mode]):
399 if ax.firsttime:
415 if ax.firsttime:
400 if self.xaxis != 'time':
416 if self.xaxis != 'time':
401 xmin = self.xmin
417 xmin = self.xmin
402 xmax = self.xmax
418 xmax = self.xmax
403 else:
419 else:
404 xmin = self.tmin
420 xmin = self.tmin
405 xmax = self.tmin + self.xrange*60*60
421 xmax = self.tmin + self.xrange*60*60
406 ax.xaxis.set_major_formatter(FuncFormatter(self.__fmtTime))
422 ax.xaxis.set_major_formatter(FuncFormatter(self.__fmtTime))
407 ax.xaxis.set_major_locator(LinearLocator(9))
423 ax.xaxis.set_major_locator(LinearLocator(9))
408 ymin = self.ymin if self.ymin is not None else numpy.nanmin(self.y[numpy.isfinite(self.y)])
424 ymin = self.ymin if self.ymin is not None else numpy.nanmin(self.y[numpy.isfinite(self.y)])
409 ymax = self.ymax if self.ymax is not None else numpy.nanmax(self.y[numpy.isfinite(self.y)])
425 ymax = self.ymax if self.ymax is not None else numpy.nanmax(self.y[numpy.isfinite(self.y)])
410
426
411 ax.set_facecolor(self.bgcolor)
427 ax.set_facecolor(self.bgcolor)
412
428
413 if self.xscale:
429 if self.xscale:
414 ax.xaxis.set_major_formatter(FuncFormatter(
430 ax.xaxis.set_major_formatter(FuncFormatter(
415 lambda x, pos: '{0:g}'.format(x*self.xscale)))
431 lambda x, pos: '{0:g}'.format(x*self.xscale)))
416 if self.yscale:
432 if self.yscale:
417 ax.yaxis.set_major_formatter(FuncFormatter(
433 ax.yaxis.set_major_formatter(FuncFormatter(
418 lambda x, pos: '{0:g}'.format(x*self.yscale)))
434 lambda x, pos: '{0:g}'.format(x*self.yscale)))
419 if self.xlabel is not None:
435 if self.xlabel is not None:
420 ax.set_xlabel(self.xlabel)
436 ax.set_xlabel(self.xlabel)
421 if self.ylabel is not None:
437 if self.ylabel is not None:
422 ax.set_ylabel(self.ylabel)
438 ax.set_ylabel(self.ylabel)
423 if self.showprofile:
439 if self.showprofile:
424 self.pf_axes[n].set_ylim(ymin, ymax)
440 self.pf_axes[n].set_ylim(ymin, ymax)
425 self.pf_axes[n].set_xlim(self.zmin, self.zmax)
441 self.pf_axes[n].set_xlim(self.zmin, self.zmax)
426 self.pf_axes[n].set_xlabel('dB')
442 self.pf_axes[n].set_xlabel('dB')
427 self.pf_axes[n].grid(b=True, axis='x')
443 self.pf_axes[n].grid(b=True, axis='x')
428 [tick.set_visible(False)
444 [tick.set_visible(False)
429 for tick in self.pf_axes[n].get_yticklabels()]
445 for tick in self.pf_axes[n].get_yticklabels()]
430 if self.colorbar:
446 if self.colorbar:
431 ax.cbar = plt.colorbar(
447 ax.cbar = plt.colorbar(
432 ax.plt, ax=ax, fraction=0.05, pad=0.06, aspect=10)
448 ax.plt, ax=ax, fraction=0.05, pad=0.06, aspect=10)
433 if self.colormap=='sophy_r':
449 if self.colormap=='sophy_r':
434 ax.cbar.set_ticks([0.2, 0.73, 0.83, 0.93, 0.96, 0.99, 1.02, 1.05])
450 ax.cbar.set_ticks([0.2, 0.73, 0.83, 0.93, 0.96, 0.99, 1.02, 1.05])
435 elif self.colormap=='sophy_d':
451 elif self.colormap=='sophy_d':
436 ax.cbar.set_ticks([-9, -6, -3, 0, 3, 6, 9, 12])
452 ax.cbar.set_ticks([-9, -6, -3, 0, 3, 6, 9, 12])
437 ax.cbar.ax.tick_params(labelsize=8)
453 ax.cbar.ax.tick_params(labelsize=8)
438 ax.cbar.ax.press = None
454 ax.cbar.ax.press = None
439 if self.cb_label:
455 if self.cb_label:
440 ax.cbar.set_label(self.cb_label, size=8)
456 ax.cbar.set_label(self.cb_label, size=8)
441 elif self.cb_labels:
457 elif self.cb_labels:
442 ax.cbar.set_label(self.cb_labels[n], size=8)
458 ax.cbar.set_label(self.cb_labels[n], size=8)
443 else:
459 else:
444 ax.cbar = None
460 ax.cbar = None
445 if self.mode == 'RHI':
461 #if self.mode == 'RHI':
446 ax.set_xlim(xmin, xmax)
462 ax.set_xlim(xmin, xmax)
447 ax.set_ylim(ymin, ymax)
463 ax.set_ylim(ymin, ymax)
464
448 ax.firsttime = False
465 ax.firsttime = False
449 if self.grid:
466 if self.grid:
450 ax.grid(True)
467 ax.grid(True)
451 if not self.polar:
468 if not self.polar:
452 ax.set_title('{} {} {}'.format(
469 ax.set_title('{} {} {}'.format(
453 self.titles[n],
470 self.titles[n],
454 self.getDateTime(self.data.max_time).strftime(
471 self.getDateTime(self.data.max_time).strftime(
455 '%Y-%m-%d %H:%M:%S'),
472 '%Y-%m-%d %H:%M:%S'),
456 self.time_label),
473 self.time_label),
457 size=8)
474 size=8)
458 else:
475 else:
459 #ax.set_title('{}'.format(self.titles[n]), size=8)
476 #ax.set_title('{}'.format(self.titles[n]), size=8)
460 ax.set_title('{} {} {}'.format(
477 ax.set_title('{} {} {}'.format(
461 self.titles[n],
478 self.titles[n],
462 self.getDateTime(self.data.max_time).strftime(
479 self.getDateTime(self.data.max_time).strftime(
463 '%Y-%m-%d %H:%M:%S'),
480 '%Y-%m-%d %H:%M:%S'),
464 self.time_label),
481 self.time_label),
465 size=8)
482 size=8)
466 ax.set_ylim(0, self.ymax)
467 if self.mode == 'PPI':
483 if self.mode == 'PPI':
468 ax.set_yticks(ax.get_yticks(), labels=ax.get_yticks(), color='white')
484 ax.set_yticks(ax.get_yticks(), labels=ax.get_yticks(), color='white')
469 ax.yaxis.labelpad = 28
485 ax.yaxis.labelpad = 28
470 elif self.mode == 'RHI':
486 elif self.mode == 'RHI':
471 ax.xaxis.labelpad = 16
487 ax.xaxis.labelpad = 16
472
488
473 if self.firsttime:
489 if self.firsttime:
474 for fig in self.figures['PPI'] + self.figures['RHI']:
490 for fig in self.figures['PPI'] + self.figures['RHI']:
475 fig.subplots_adjust(**self.plots_adjust)
491 fig.subplots_adjust(**self.plots_adjust)
476 self.firsttime = False
492 self.firsttime = False
477
493
478 def clear_figures(self):
494 def clear_figures(self):
479 '''
495 '''
480 Reset axes for redraw plots
496 Reset axes for redraw plots
481 '''
497 '''
482
498
483 axes = self.pf_axes + self.cb_axes + self.axes[self.mode]
499 axes = self.pf_axes + self.cb_axes + self.axes[self.mode]
484
500
485 for ax in axes:
501 for ax in axes:
486 ax.clear()
502 ax.clear()
487 ax.firsttime = True
503 ax.firsttime = True
488 if hasattr(ax, 'cbar') and ax.cbar:
504 if hasattr(ax, 'cbar') and ax.cbar:
489 ax.cbar.remove()
505 ax.cbar.remove()
490
506
491 def __plot(self):
507 def __plot(self):
492 '''
508 '''
493 Main function to plot, format and save figures
509 Main function to plot, format and save figures
494 '''
510 '''
495
511
496 self.plot()
512 self.plot()
497 self.format()
513 self.format()
498 figures = self.figures[self.mode]
514 figures = self.figures[self.mode]
499 for n, fig in enumerate(figures):
515 for n, fig in enumerate(figures):
500 if self.nrows == 0 or self.nplots == 0:
516 if self.nrows == 0 or self.nplots == 0:
501 log.warning('No data', self.name)
517 log.warning('No data', self.name)
502 fig.text(0.5, 0.5, 'No Data', fontsize='large', ha='center')
518 fig.text(0.5, 0.5, 'No Data', fontsize='large', ha='center')
503 fig.canvas.manager.set_window_title(self.CODE)
519 fig.canvas.manager.set_window_title(self.CODE)
504 continue
520 continue
505
521
506 fig.canvas.manager.set_window_title('{} - {}'.format(self.title,
522 fig.canvas.manager.set_window_title('{} - {}'.format(self.title,
507 self.getDateTime(self.data.max_time).strftime('%Y/%m/%d')))
523 self.getDateTime(self.data.max_time).strftime('%Y/%m/%d')))
508 fig.canvas.draw()
524 fig.canvas.draw()
509 if self.show:
525 if self.show:
510 fig.show()
526 fig.show()
511 figpause(0.01)
527 figpause(0.01)
512
528
513 if self.save:
529 if self.save:
514 self.save_figure(n)
530 self.save_figure(n)
515
531
516 if self.server:
532 if self.server:
517 if self.mode and self.mode == 'RHI':
533 if self.mode and self.mode == 'RHI':
518 return
534 return
519 self.send_to_server()
535 self.send_to_server()
520
536
521 def __update(self, dataOut, timestamp):
537 def __update(self, dataOut, timestamp):
522 '''
538 '''
523 '''
539 '''
524
540
525 metadata = {
541 metadata = {
526 'yrange': dataOut.heightList,
542 'yrange': dataOut.heightList,
527 'interval': dataOut.timeInterval,
543 'interval': dataOut.timeInterval,
528 'channels': dataOut.channelList
544 'channels': dataOut.channelList
529 }
545 }
530
546
531 data, meta = self.update(dataOut)
547 data, meta = self.update(dataOut)
532 metadata.update(meta)
548 metadata.update(meta)
533 self.data.update(data, timestamp, metadata)
549 self.data.update(data, timestamp, metadata)
534
550
535 def save_figure(self, n):
551 def save_figure(self, n):
536 '''
552 '''
537 '''
553 '''
538 if self.mode is not None:
554 if self.mode is not None:
539 ang = 'AZ' if self.mode == 'RHI' else 'EL'
555 ang = 'AZ' if self.mode == 'RHI' else 'EL'
540 folder = '_{}_{}_{}'.format(self.mode, ang, self.mode_value)
556 folder = '_{}_{}_{}'.format(self.mode, ang, self.mode_value)
541 label = '{}{}_{}'.format(ang[0], self.mode_value, self.save_code)
557 label = '{}{}_{}'.format(ang[0], self.mode_value, self.save_code)
542 else:
558 else:
543 folder = ''
559 folder = ''
544 label = ''
560 label = ''
545
561
546 if self.oneFigure:
562 if self.oneFigure:
547 if (self.data.max_time - self.save_time) <= self.save_period:
563 if (self.data.max_time - self.save_time) <= self.save_period:
548 return
564 return
549
565
550 self.save_time = self.data.max_time
566 self.save_time = self.data.max_time
551
567
552 fig = self.figures[self.mode][n]
568 fig = self.figures[self.mode][n]
553
569
554 if self.throttle == 0:
570 if self.throttle == 0:
555 if self.oneFigure:
571 if self.oneFigure:
556 figname = os.path.join(
572 figname = os.path.join(
557 self.save,
573 self.save,
558 self.save_code + folder,
574 self.save_code + folder,
559 '{}_{}_{}.png'.format(
575 '{}_{}_{}.png'.format(
560 'SOPHY',
576 'SOPHY',
561 self.getDateTime(self.data.max_time).strftime(
577 self.getDateTime(self.data.max_time).strftime(
562 '%Y%m%d_%H%M%S'
578 '%Y%m%d_%H%M%S'
563 ),
579 ),
564 label
580 label
565 )
581 )
566 )
582 )
567 else:
583 else:
568 figname = os.path.join(
584 figname = os.path.join(
569 self.save,
585 self.save,
570 self.save_code,
586 self.save_code,
571 '{}_ch{}_{}.png'.format(
587 '{}_ch{}_{}.png'.format(
572 self.save_code, n,
588 self.save_code, n,
573 self.getDateTime(self.data.max_time).strftime(
589 self.getDateTime(self.data.max_time).strftime(
574 '%Y%m%d_%H%M%S'
590 '%Y%m%d_%H%M%S'
575 ),
591 ),
576 )
592 )
577 )
593 )
578 log.log('Saving figure: {}'.format(figname), self.name)
594 log.log('Saving figure: {}'.format(figname), self.name)
579 if not os.path.isdir(os.path.dirname(figname)):
595 if not os.path.isdir(os.path.dirname(figname)):
580 os.makedirs(os.path.dirname(figname))
596 os.makedirs(os.path.dirname(figname))
581 fig.savefig(figname)
597 fig.savefig(figname)
582
598
583 figname = os.path.join(
599 figname = os.path.join(
584 self.save,
600 self.save,
585 '{}_{}.png'.format(
601 '{}_{}.png'.format(
586 self.save_code,
602 self.save_code,
587 self.getDateTime(self.data.min_time).strftime(
603 self.getDateTime(self.data.min_time).strftime(
588 '%Y%m%d'
604 '%Y%m%d'
589 ),
605 ),
590 )
606 )
591 )
607 )
592
608
593 log.log('Saving figure: {}'.format(figname), self.name)
609 log.log('Saving figure: {}'.format(figname), self.name)
594 if not os.path.isdir(os.path.dirname(figname)):
610 if not os.path.isdir(os.path.dirname(figname)):
595 os.makedirs(os.path.dirname(figname))
611 os.makedirs(os.path.dirname(figname))
596 fig.savefig(figname)
612 fig.savefig(figname)
597
613
598 def send_to_server(self):
614 def send_to_server(self):
599 '''
615 '''
600 '''
616 '''
601
617
602 if self.exp_code == None:
618 if self.exp_code == None:
603 log.warning('Missing `exp_code` skipping sending to server...')
619 log.warning('Missing `exp_code` skipping sending to server...')
604
620
605 last_time = self.data.max_time
621 last_time = self.data.max_time
606 interval = last_time - self.sender_time
622 interval = last_time - self.sender_time
607 if interval < self.sender_period:
623 if interval < self.sender_period:
608 return
624 return
609
625
610 self.sender_time = last_time
626 self.sender_time = last_time
611
627
612 attrs = ['titles', 'zmin', 'zmax', 'tag', 'ymin', 'ymax']
628 attrs = ['titles', 'zmin', 'zmax', 'tag', 'ymin', 'ymax']
613 for attr in attrs:
629 for attr in attrs:
614 value = getattr(self, attr)
630 value = getattr(self, attr)
615 if value:
631 if value:
616 if isinstance(value, (numpy.float32, numpy.float64)):
632 if isinstance(value, (numpy.float32, numpy.float64)):
617 value = round(float(value), 2)
633 value = round(float(value), 2)
618 self.data.meta[attr] = value
634 self.data.meta[attr] = value
619 if self.colormap == 'jet' or self.colormap == 'sophy_w':
635 if self.colormap == 'jet' or self.colormap == 'sophy_w':
620 self.data.meta['colormap'] = 'Jet'
636 self.data.meta['colormap'] = 'Jet'
621 elif 'sophy_v' in self.colormap:
637 elif 'sophy_v' in self.colormap:
622 self.data.meta['colormap'] = 'RdBu'
638 self.data.meta['colormap'] = 'RdBu'
623 else:
639 else:
624 self.data.meta['colormap'] = 'Viridis'
640 self.data.meta['colormap'] = 'Viridis'
625 self.data.meta['interval'] = int(interval)
641 self.data.meta['interval'] = int(interval)
626
642
627 self.sender_queue.append(last_time)
643 self.sender_queue.append(last_time)
628
644
629 while True:
645 while True:
630 try:
646 try:
631 tm = self.sender_queue.popleft()
647 tm = self.sender_queue.popleft()
632 except IndexError:
648 except IndexError:
633 break
649 break
634 msg = self.data.jsonify(tm, self.save_code, self.plot_type, key='var')
650 msg = self.data.jsonify(tm, self.save_code, self.plot_type, key='var')
635 self.socket.send_string(msg)
651 self.socket.send_string(msg)
636 socks = dict(self.poll.poll(2000))
652 socks = dict(self.poll.poll(2000))
637 if socks.get(self.socket) == zmq.POLLIN:
653 if socks.get(self.socket) == zmq.POLLIN:
638 reply = self.socket.recv_string()
654 reply = self.socket.recv_string()
639 if reply == 'ok':
655 if reply == 'ok':
640 log.log("Response from server ok", self.name)
656 log.log("Response from server ok", self.name)
641 time.sleep(0.1)
657 time.sleep(0.1)
642 continue
658 continue
643 else:
659 else:
644 log.warning(
660 log.warning(
645 "Malformed reply from server: {}".format(reply), self.name)
661 "Malformed reply from server: {}".format(reply), self.name)
646 else:
662 else:
647 log.warning(
663 log.warning(
648 "No response from server, retrying...", self.name)
664 "No response from server, retrying...", self.name)
649 self.sender_queue.appendleft(tm)
665 self.sender_queue.appendleft(tm)
650 self.socket.setsockopt(zmq.LINGER, 0)
666 self.socket.setsockopt(zmq.LINGER, 0)
651 self.socket.close()
667 self.socket.close()
652 self.poll.unregister(self.socket)
668 self.poll.unregister(self.socket)
653 self.socket = self.context.socket(zmq.REQ)
669 self.socket = self.context.socket(zmq.REQ)
654 self.socket.connect(self.server)
670 self.socket.connect(self.server)
655 self.poll.register(self.socket, zmq.POLLIN)
671 self.poll.register(self.socket, zmq.POLLIN)
656 break
672 break
657
673
658 def setup(self):
674 def setup(self):
659 '''
675 '''
660 This method should be implemented in the child class, the following
676 This method should be implemented in the child class, the following
661 attributes should be set:
677 attributes should be set:
662
678
663 self.nrows: number of rows
679 self.nrows: number of rows
664 self.ncols: number of cols
680 self.ncols: number of cols
665 self.nplots: number of plots (channels or pairs)
681 self.nplots: number of plots (channels or pairs)
666 self.ylabel: label for Y axes
682 self.ylabel: label for Y axes
667 self.titles: list of axes title
683 self.titles: list of axes title
668
684
669 '''
685 '''
670 raise NotImplementedError
686 raise NotImplementedError
671
687
672 def plot(self):
688 def plot(self):
673 '''
689 '''
674 Must be defined in the child class, the actual plotting method
690 Must be defined in the child class, the actual plotting method
675 '''
691 '''
676 raise NotImplementedError
692 raise NotImplementedError
677
693
678 def update(self, dataOut):
694 def update(self, dataOut):
679 '''
695 '''
680 Must be defined in the child class, update self.data with new data
696 Must be defined in the child class, update self.data with new data
681 '''
697 '''
682
698
683 data = {
699 data = {
684 self.CODE: getattr(dataOut, 'data_{}'.format(self.CODE))
700 self.CODE: getattr(dataOut, 'data_{}'.format(self.CODE))
685 }
701 }
686 meta = {}
702 meta = {}
687
703
688 return data, meta
704 return data, meta
689
705
690 def run(self, dataOut, **kwargs):
706 def run(self, dataOut, **kwargs):
691 '''
707 '''
692 Main plotting routine
708 Main plotting routine
693 '''
709 '''
694
710
695 if self.isConfig is False:
711 if self.isConfig is False:
696 self.__setup(**kwargs)
712 self.__setup(**kwargs)
697
713
698 if self.localtime:
714 if self.localtime:
699 self.getDateTime = datetime.datetime.fromtimestamp
715 self.getDateTime = datetime.datetime.fromtimestamp
700 else:
716 else:
701 self.getDateTime = datetime.datetime.utcfromtimestamp
717 self.getDateTime = datetime.datetime.utcfromtimestamp
702
718
703 self.data.setup()
719 self.data.setup()
704 self.isConfig = True
720 self.isConfig = True
705 if self.server:
721 if self.server:
706 self.context = zmq.Context()
722 self.context = zmq.Context()
707 self.socket = self.context.socket(zmq.REQ)
723 self.socket = self.context.socket(zmq.REQ)
708 self.socket.connect(self.server)
724 self.socket.connect(self.server)
709 self.poll = zmq.Poller()
725 self.poll = zmq.Poller()
710 self.poll.register(self.socket, zmq.POLLIN)
726 self.poll.register(self.socket, zmq.POLLIN)
711
727
712 tm = getattr(dataOut, self.attr_time)
728 tm = getattr(dataOut, self.attr_time)
713
729
714 if self.data and 'time' in self.xaxis and (tm - self.tmin) >= self.xrange*60*60:
730 if self.data and 'time' in self.xaxis and (tm - self.tmin) >= self.xrange*60*60:
715 self.save_time = tm
731 self.save_time = tm
716 self.__plot()
732 self.__plot()
717 self.tmin += self.xrange*60*60
733 self.tmin += self.xrange*60*60
718 self.data.setup()
734 self.data.setup()
719 self.clear_figures()
735 self.clear_figures()
720
736
721 self.__update(dataOut, tm)
737 self.__update(dataOut, tm)
722
738
723 if self.isPlotConfig is False:
739 if self.isPlotConfig is False:
724 self.__setup_plot()
740 self.__setup_plot()
725 self.isPlotConfig = True
741 self.isPlotConfig = True
726 if self.xaxis == 'time':
742 if self.xaxis == 'time':
727 dt = self.getDateTime(tm)
743 dt = self.getDateTime(tm)
728 if self.xmin is None:
744 if self.xmin is None:
729 self.tmin = tm
745 self.tmin = tm
730 self.xmin = dt.hour
746 self.xmin = dt.hour
731 minutes = (self.xmin-int(self.xmin)) * 60
747 minutes = (self.xmin-int(self.xmin)) * 60
732 seconds = (minutes - int(minutes)) * 60
748 seconds = (minutes - int(minutes)) * 60
733 self.tmin = (dt.replace(hour=int(self.xmin), minute=int(minutes), second=int(seconds)) -
749 self.tmin = (dt.replace(hour=int(self.xmin), minute=int(minutes), second=int(seconds)) -
734 datetime.datetime(1970, 1, 1)).total_seconds()
750 datetime.datetime(1970, 1, 1)).total_seconds()
735 if self.localtime:
751 if self.localtime:
736 self.tmin += time.timezone
752 self.tmin += time.timezone
737
753
738 if self.xmin is not None and self.xmax is not None:
754 if self.xmin is not None and self.xmax is not None:
739 self.xrange = self.xmax - self.xmin
755 self.xrange = self.xmax - self.xmin
740
756
741 if self.throttle == 0:
757 if self.throttle == 0:
742 self.__plot()
758 self.__plot()
743 else:
759 else:
744 self.__throttle_plot(self.__plot)#, coerce=coerce)
760 self.__throttle_plot(self.__plot)#, coerce=coerce)
745
761
746 def close(self):
762 def close(self):
747
763
748 if self.data and not self.data.flagNoData:
764 if self.data and not self.data.flagNoData:
749 self.save_time = 0
765 self.save_time = 0
750 self.__plot()
766 self.__plot()
751 if self.data and not self.data.flagNoData and self.pause:
767 if self.data and not self.data.flagNoData and self.pause:
752 figpause(10)
768 figpause(10)
@@ -1,736 +1,757
1 import os
1 import os
2 import datetime
2 import datetime
3 import warnings
3 import warnings
4 import numpy
4 import numpy
5 from mpl_toolkits.axisartist.grid_finder import FixedLocator, DictFormatter
5 from mpl_toolkits.axisartist.grid_finder import FixedLocator, DictFormatter
6 from matplotlib.patches import Circle
6 from matplotlib.patches import Circle
7 import cartopy.crs as ccrs
8 from cartopy.feature import ShapelyFeature
7 from cartopy.feature import ShapelyFeature
9 import cartopy.io.shapereader as shpreader
8 import cartopy.io.shapereader as shpreader
10
9
11 from schainpy.model.graphics.jroplot_base import Plot, plt
10 from schainpy.model.graphics.jroplot_base import Plot, plt, ccrs
12 from schainpy.model.graphics.jroplot_spectra import SpectraPlot, RTIPlot, CoherencePlot, SpectraCutPlot
11 from schainpy.model.graphics.jroplot_spectra import SpectraPlot, RTIPlot, CoherencePlot, SpectraCutPlot
13 from schainpy.utils import log
12 from schainpy.utils import log
14 from schainpy.model.graphics.plotting_codes import cb_tables
13 from schainpy.model.graphics.plotting_codes import cb_tables
15
14
16
15
17 EARTH_RADIUS = 6.3710e3
16 EARTH_RADIUS = 6.3710e3
18
17
19
18
20 def antenna_to_cartesian(ranges, azimuths, elevations):
19 def antenna_to_cartesian(ranges, azimuths, elevations):
21 """
20 """
22 Return Cartesian coordinates from antenna coordinates.
21 Return Cartesian coordinates from antenna coordinates.
23
22
24 Parameters
23 Parameters
25 ----------
24 ----------
26 ranges : array
25 ranges : array
27 Distances to the center of the radar gates (bins) in kilometers.
26 Distances to the center of the radar gates (bins) in kilometers.
28 azimuths : array
27 azimuths : array
29 Azimuth angle of the radar in degrees.
28 Azimuth angle of the radar in degrees.
30 elevations : array
29 elevations : array
31 Elevation angle of the radar in degrees.
30 Elevation angle of the radar in degrees.
32
31
33 Returns
32 Returns
34 -------
33 -------
35 x, y, z : array
34 x, y, z : array
36 Cartesian coordinates in meters from the radar.
35 Cartesian coordinates in meters from the radar.
37
36
38 Notes
37 Notes
39 -----
38 -----
40 The calculation for Cartesian coordinate is adapted from equations
39 The calculation for Cartesian coordinate is adapted from equations
41 2.28(b) and 2.28(c) of Doviak and Zrnic [1]_ assuming a
40 2.28(b) and 2.28(c) of Doviak and Zrnic [1]_ assuming a
42 standard atmosphere (4/3 Earth's radius model).
41 standard atmosphere (4/3 Earth's radius model).
43
42
44 .. math::
43 .. math::
45
44
46 z = \\sqrt{r^2+R^2+2*r*R*sin(\\theta_e)} - R
45 z = \\sqrt{r^2+R^2+2*r*R*sin(\\theta_e)} - R
47
46
48 s = R * arcsin(\\frac{r*cos(\\theta_e)}{R+z})
47 s = R * arcsin(\\frac{r*cos(\\theta_e)}{R+z})
49
48
50 x = s * sin(\\theta_a)
49 x = s * sin(\\theta_a)
51
50
52 y = s * cos(\\theta_a)
51 y = s * cos(\\theta_a)
53
52
54 Where r is the distance from the radar to the center of the gate,
53 Where r is the distance from the radar to the center of the gate,
55 :math:`\\theta_a` is the azimuth angle, :math:`\\theta_e` is the
54 :math:`\\theta_a` is the azimuth angle, :math:`\\theta_e` is the
56 elevation angle, s is the arc length, and R is the effective radius
55 elevation angle, s is the arc length, and R is the effective radius
57 of the earth, taken to be 4/3 the mean radius of earth (6371 km).
56 of the earth, taken to be 4/3 the mean radius of earth (6371 km).
58
57
59 References
58 References
60 ----------
59 ----------
61 .. [1] Doviak and Zrnic, Doppler Radar and Weather Observations, Second
60 .. [1] Doviak and Zrnic, Doppler Radar and Weather Observations, Second
62 Edition, 1993, p. 21.
61 Edition, 1993, p. 21.
63
62
64 """
63 """
65 theta_e = numpy.deg2rad(elevations) # elevation angle in radians.
64 theta_e = numpy.deg2rad(elevations) # elevation angle in radians.
66 theta_a = numpy.deg2rad(azimuths) # azimuth angle in radians.
65 theta_a = numpy.deg2rad(azimuths) # azimuth angle in radians.
67 R = 6371.0 * 1000.0 * 4.0 / 3.0 # effective radius of earth in meters.
66 R = 6371.0 * 1000.0 * 4.0 / 3.0 # effective radius of earth in meters.
68 r = ranges * 1000.0 # distances to gates in meters.
67 r = ranges * 1000.0 # distances to gates in meters.
69
68
70 z = (r ** 2 + R ** 2 + 2.0 * r * R * numpy.sin(theta_e)) ** 0.5 - R
69 z = (r ** 2 + R ** 2 + 2.0 * r * R * numpy.sin(theta_e)) ** 0.5 - R
71 s = R * numpy.arcsin(r * numpy.cos(theta_e) / (R + z)) # arc length in m.
70 s = R * numpy.arcsin(r * numpy.cos(theta_e) / (R + z)) # arc length in m.
72 x = s * numpy.sin(theta_a)
71 x = s * numpy.sin(theta_a)
73 y = s * numpy.cos(theta_a)
72 y = s * numpy.cos(theta_a)
74 return x, y, z
73 return x, y, z
75
74
76 def cartesian_to_geographic_aeqd(x, y, lon_0, lat_0, R=EARTH_RADIUS):
75 def cartesian_to_geographic_aeqd(x, y, lon_0, lat_0, R=EARTH_RADIUS):
77 """
76 """
78 Azimuthal equidistant Cartesian to geographic coordinate transform.
77 Azimuthal equidistant Cartesian to geographic coordinate transform.
79
78
80 Transform a set of Cartesian/Cartographic coordinates (x, y) to
79 Transform a set of Cartesian/Cartographic coordinates (x, y) to
81 geographic coordinate system (lat, lon) using a azimuthal equidistant
80 geographic coordinate system (lat, lon) using a azimuthal equidistant
82 map projection [1]_.
81 map projection [1]_.
83
82
84 .. math::
83 .. math::
85
84
86 lat = \\arcsin(\\cos(c) * \\sin(lat_0) +
85 lat = \\arcsin(\\cos(c) * \\sin(lat_0) +
87 (y * \\sin(c) * \\cos(lat_0) / \\rho))
86 (y * \\sin(c) * \\cos(lat_0) / \\rho))
88
87
89 lon = lon_0 + \\arctan2(
88 lon = lon_0 + \\arctan2(
90 x * \\sin(c),
89 x * \\sin(c),
91 \\rho * \\cos(lat_0) * \\cos(c) - y * \\sin(lat_0) * \\sin(c))
90 \\rho * \\cos(lat_0) * \\cos(c) - y * \\sin(lat_0) * \\sin(c))
92
91
93 \\rho = \\sqrt(x^2 + y^2)
92 \\rho = \\sqrt(x^2 + y^2)
94
93
95 c = \\rho / R
94 c = \\rho / R
96
95
97 Where x, y are the Cartesian position from the center of projection;
96 Where x, y are the Cartesian position from the center of projection;
98 lat, lon the corresponding latitude and longitude; lat_0, lon_0 are the
97 lat, lon the corresponding latitude and longitude; lat_0, lon_0 are the
99 latitude and longitude of the center of the projection; R is the radius of
98 latitude and longitude of the center of the projection; R is the radius of
100 the earth (defaults to ~6371 km). lon is adjusted to be between -180 and
99 the earth (defaults to ~6371 km). lon is adjusted to be between -180 and
101 180.
100 180.
102
101
103 Parameters
102 Parameters
104 ----------
103 ----------
105 x, y : array-like
104 x, y : array-like
106 Cartesian coordinates in the same units as R, typically meters.
105 Cartesian coordinates in the same units as R, typically meters.
107 lon_0, lat_0 : float
106 lon_0, lat_0 : float
108 Longitude and latitude, in degrees, of the center of the projection.
107 Longitude and latitude, in degrees, of the center of the projection.
109 R : float, optional
108 R : float, optional
110 Earth radius in the same units as x and y. The default value is in
109 Earth radius in the same units as x and y. The default value is in
111 units of meters.
110 units of meters.
112
111
113 Returns
112 Returns
114 -------
113 -------
115 lon, lat : array
114 lon, lat : array
116 Longitude and latitude of Cartesian coordinates in degrees.
115 Longitude and latitude of Cartesian coordinates in degrees.
117
116
118 References
117 References
119 ----------
118 ----------
120 .. [1] Snyder, J. P. Map Projections--A Working Manual. U. S. Geological
119 .. [1] Snyder, J. P. Map Projections--A Working Manual. U. S. Geological
121 Survey Professional Paper 1395, 1987, pp. 191-202.
120 Survey Professional Paper 1395, 1987, pp. 191-202.
122
121
123 """
122 """
124 x = numpy.atleast_1d(numpy.asarray(x))
123 x = numpy.atleast_1d(numpy.asarray(x))
125 y = numpy.atleast_1d(numpy.asarray(y))
124 y = numpy.atleast_1d(numpy.asarray(y))
126
125
127 lat_0_rad = numpy.deg2rad(lat_0)
126 lat_0_rad = numpy.deg2rad(lat_0)
128 lon_0_rad = numpy.deg2rad(lon_0)
127 lon_0_rad = numpy.deg2rad(lon_0)
129
128
130 rho = numpy.sqrt(x*x + y*y)
129 rho = numpy.sqrt(x*x + y*y)
131 c = rho / R
130 c = rho / R
132
131
133 with warnings.catch_warnings():
132 with warnings.catch_warnings():
134 # division by zero may occur here but is properly addressed below so
133 # division by zero may occur here but is properly addressed below so
135 # the warnings can be ignored
134 # the warnings can be ignored
136 warnings.simplefilter("ignore", RuntimeWarning)
135 warnings.simplefilter("ignore", RuntimeWarning)
137 lat_rad = numpy.arcsin(numpy.cos(c) * numpy.sin(lat_0_rad) +
136 lat_rad = numpy.arcsin(numpy.cos(c) * numpy.sin(lat_0_rad) +
138 y * numpy.sin(c) * numpy.cos(lat_0_rad) / rho)
137 y * numpy.sin(c) * numpy.cos(lat_0_rad) / rho)
139 lat_deg = numpy.rad2deg(lat_rad)
138 lat_deg = numpy.rad2deg(lat_rad)
140 # fix cases where the distance from the center of the projection is zero
139 # fix cases where the distance from the center of the projection is zero
141 lat_deg[rho == 0] = lat_0
140 lat_deg[rho == 0] = lat_0
142
141
143 x1 = x * numpy.sin(c)
142 x1 = x * numpy.sin(c)
144 x2 = rho*numpy.cos(lat_0_rad)*numpy.cos(c) - y*numpy.sin(lat_0_rad)*numpy.sin(c)
143 x2 = rho*numpy.cos(lat_0_rad)*numpy.cos(c) - y*numpy.sin(lat_0_rad)*numpy.sin(c)
145 lon_rad = lon_0_rad + numpy.arctan2(x1, x2)
144 lon_rad = lon_0_rad + numpy.arctan2(x1, x2)
146 lon_deg = numpy.rad2deg(lon_rad)
145 lon_deg = numpy.rad2deg(lon_rad)
147 # Longitudes should be from -180 to 180 degrees
146 # Longitudes should be from -180 to 180 degrees
148 lon_deg[lon_deg > 180] -= 360.
147 lon_deg[lon_deg > 180] -= 360.
149 lon_deg[lon_deg < -180] += 360.
148 lon_deg[lon_deg < -180] += 360.
150
149
151 return lon_deg, lat_deg
150 return lon_deg, lat_deg
152
151
153 def antenna_to_geographic(ranges, azimuths, elevations, site):
152 def antenna_to_geographic(ranges, azimuths, elevations, site):
154
153
155 x, y, z = antenna_to_cartesian(numpy.array(ranges), numpy.array(azimuths), numpy.array(elevations))
154 x, y, z = antenna_to_cartesian(numpy.array(ranges), numpy.array(azimuths), numpy.array(elevations))
156 lon, lat = cartesian_to_geographic_aeqd(x, y, site[0], site[1], R=6370997.)
155 lon, lat = cartesian_to_geographic_aeqd(x, y, site[0], site[1], R=6370997.)
157
156
158 return lon, lat
157 return lon, lat
159
158
160 def ll2xy(lat1, lon1, lat2, lon2):
159 def ll2xy(lat1, lon1, lat2, lon2):
161
160
162 p = 0.017453292519943295
161 p = 0.017453292519943295
163 a = 0.5 - numpy.cos((lat2 - lat1) * p)/2 + numpy.cos(lat1 * p) * \
162 a = 0.5 - numpy.cos((lat2 - lat1) * p)/2 + numpy.cos(lat1 * p) * \
164 numpy.cos(lat2 * p) * (1 - numpy.cos((lon2 - lon1) * p)) / 2
163 numpy.cos(lat2 * p) * (1 - numpy.cos((lon2 - lon1) * p)) / 2
165 r = 12742 * numpy.arcsin(numpy.sqrt(a))
164 r = 12742 * numpy.arcsin(numpy.sqrt(a))
166 theta = numpy.arctan2(numpy.sin((lon2-lon1)*p)*numpy.cos(lat2*p), numpy.cos(lat1*p)
165 theta = numpy.arctan2(numpy.sin((lon2-lon1)*p)*numpy.cos(lat2*p), numpy.cos(lat1*p)
167 * numpy.sin(lat2*p)-numpy.sin(lat1*p)*numpy.cos(lat2*p)*numpy.cos((lon2-lon1)*p))
166 * numpy.sin(lat2*p)-numpy.sin(lat1*p)*numpy.cos(lat2*p)*numpy.cos((lon2-lon1)*p))
168 theta = -theta + numpy.pi/2
167 theta = -theta + numpy.pi/2
169 return r*numpy.cos(theta), r*numpy.sin(theta)
168 return r*numpy.cos(theta), r*numpy.sin(theta)
170
169
171
170
172 def km2deg(km):
171 def km2deg(km):
173 '''
172 '''
174 Convert distance in km to degrees
173 Convert distance in km to degrees
175 '''
174 '''
176
175
177 return numpy.rad2deg(km/EARTH_RADIUS)
176 return numpy.rad2deg(km/EARTH_RADIUS)
178
177
179
178
180
179
181 class SpectralMomentsPlot(SpectraPlot):
180 class SpectralMomentsPlot(SpectraPlot):
182 '''
181 '''
183 Plot for Spectral Moments
182 Plot for Spectral Moments
184 '''
183 '''
185 CODE = 'spc_moments'
184 CODE = 'spc_moments'
186 # colormap = 'jet'
185 # colormap = 'jet'
187 # plot_type = 'pcolor'
186 # plot_type = 'pcolor'
188
187
189 class DobleGaussianPlot(SpectraPlot):
188 class DobleGaussianPlot(SpectraPlot):
190 '''
189 '''
191 Plot for Double Gaussian Plot
190 Plot for Double Gaussian Plot
192 '''
191 '''
193 CODE = 'gaussian_fit'
192 CODE = 'gaussian_fit'
194 # colormap = 'jet'
193 # colormap = 'jet'
195 # plot_type = 'pcolor'
194 # plot_type = 'pcolor'
196
195
197 class DoubleGaussianSpectraCutPlot(SpectraCutPlot):
196 class DoubleGaussianSpectraCutPlot(SpectraCutPlot):
198 '''
197 '''
199 Plot SpectraCut with Double Gaussian Fit
198 Plot SpectraCut with Double Gaussian Fit
200 '''
199 '''
201 CODE = 'cut_gaussian_fit'
200 CODE = 'cut_gaussian_fit'
202
201
203 class SnrPlot(RTIPlot):
202 class SnrPlot(RTIPlot):
204 '''
203 '''
205 Plot for SNR Data
204 Plot for SNR Data
206 '''
205 '''
207
206
208 CODE = 'snr'
207 CODE = 'snr'
209 colormap = 'jet'
208 colormap = 'jet'
210
209
211 def update(self, dataOut):
210 def update(self, dataOut):
212
211
213 data = {
212 data = {
214 'snr': 10*numpy.log10(dataOut.data_snr)
213 'snr': 10*numpy.log10(dataOut.data_snr)
215 }
214 }
216
215
217 return data, {}
216 return data, {}
218
217
219 class DopplerPlot(RTIPlot):
218 class DopplerPlot(RTIPlot):
220 '''
219 '''
221 Plot for DOPPLER Data (1st moment)
220 Plot for DOPPLER Data (1st moment)
222 '''
221 '''
223
222
224 CODE = 'dop'
223 CODE = 'dop'
225 colormap = 'jet'
224 colormap = 'jet'
226
225
227 def update(self, dataOut):
226 def update(self, dataOut):
228
227
229 data = {
228 data = {
230 'dop': 10*numpy.log10(dataOut.data_dop)
229 'dop': 10*numpy.log10(dataOut.data_dop)
231 }
230 }
232
231
233 return data, {}
232 return data, {}
234
233
235 class PowerPlot(RTIPlot):
234 class PowerPlot(RTIPlot):
236 '''
235 '''
237 Plot for Power Data (0 moment)
236 Plot for Power Data (0 moment)
238 '''
237 '''
239
238
240 CODE = 'pow'
239 CODE = 'pow'
241 colormap = 'jet'
240 colormap = 'jet'
242
241
243 def update(self, dataOut):
242 def update(self, dataOut):
244 data = {
243 data = {
245 'pow': 10*numpy.log10(dataOut.data_pow/dataOut.normFactor)
244 'pow': 10*numpy.log10(dataOut.data_pow/dataOut.normFactor)
246 }
245 }
247 return data, {}
246 return data, {}
248
247
249 class SpectralWidthPlot(RTIPlot):
248 class SpectralWidthPlot(RTIPlot):
250 '''
249 '''
251 Plot for Spectral Width Data (2nd moment)
250 Plot for Spectral Width Data (2nd moment)
252 '''
251 '''
253
252
254 CODE = 'width'
253 CODE = 'width'
255 colormap = 'jet'
254 colormap = 'jet'
256
255
257 def update(self, dataOut):
256 def update(self, dataOut):
258
257
259 data = {
258 data = {
260 'width': dataOut.data_width
259 'width': dataOut.data_width
261 }
260 }
262
261
263 return data, {}
262 return data, {}
264
263
265 class SkyMapPlot(Plot):
264 class SkyMapPlot(Plot):
266 '''
265 '''
267 Plot for meteors detection data
266 Plot for meteors detection data
268 '''
267 '''
269
268
270 CODE = 'param'
269 CODE = 'param'
271
270
272 def setup(self):
271 def setup(self):
273
272
274 self.ncols = 1
273 self.ncols = 1
275 self.nrows = 1
274 self.nrows = 1
276 self.width = 7.2
275 self.width = 7.2
277 self.height = 7.2
276 self.height = 7.2
278 self.nplots = 1
277 self.nplots = 1
279 self.xlabel = 'Zonal Zenith Angle (deg)'
278 self.xlabel = 'Zonal Zenith Angle (deg)'
280 self.ylabel = 'Meridional Zenith Angle (deg)'
279 self.ylabel = 'Meridional Zenith Angle (deg)'
281 self.polar = True
280 self.polar = True
282 self.ymin = -180
281 self.ymin = -180
283 self.ymax = 180
282 self.ymax = 180
284 self.colorbar = False
283 self.colorbar = False
285
284
286 def plot(self):
285 def plot(self):
287
286
288 arrayParameters = numpy.concatenate(self.data['param'])
287 arrayParameters = numpy.concatenate(self.data['param'])
289 error = arrayParameters[:, -1]
288 error = arrayParameters[:, -1]
290 indValid = numpy.where(error == 0)[0]
289 indValid = numpy.where(error == 0)[0]
291 finalMeteor = arrayParameters[indValid, :]
290 finalMeteor = arrayParameters[indValid, :]
292 finalAzimuth = finalMeteor[:, 3]
291 finalAzimuth = finalMeteor[:, 3]
293 finalZenith = finalMeteor[:, 4]
292 finalZenith = finalMeteor[:, 4]
294
293
295 x = finalAzimuth * numpy.pi / 180
294 x = finalAzimuth * numpy.pi / 180
296 y = finalZenith
295 y = finalZenith
297
296
298 ax = self.axes[0]
297 ax = self.axes[0]
299
298
300 if ax.firsttime:
299 if ax.firsttime:
301 ax.plot = ax.plot(x, y, 'bo', markersize=5)[0]
300 ax.plot = ax.plot(x, y, 'bo', markersize=5)[0]
302 else:
301 else:
303 ax.plot.set_data(x, y)
302 ax.plot.set_data(x, y)
304
303
305 dt1 = self.getDateTime(self.data.min_time).strftime('%y/%m/%d %H:%M:%S')
304 dt1 = self.getDateTime(self.data.min_time).strftime('%y/%m/%d %H:%M:%S')
306 dt2 = self.getDateTime(self.data.max_time).strftime('%y/%m/%d %H:%M:%S')
305 dt2 = self.getDateTime(self.data.max_time).strftime('%y/%m/%d %H:%M:%S')
307 title = 'Meteor Detection Sky Map\n %s - %s \n Number of events: %5.0f\n' % (dt1,
306 title = 'Meteor Detection Sky Map\n %s - %s \n Number of events: %5.0f\n' % (dt1,
308 dt2,
307 dt2,
309 len(x))
308 len(x))
310 self.titles[0] = title
309 self.titles[0] = title
311
310
312
311
313 class GenericRTIPlot(Plot):
312 class GenericRTIPlot(Plot):
314 '''
313 '''
315 Plot for data_xxxx object
314 Plot for data_xxxx object
316 '''
315 '''
317
316
318 CODE = 'param'
317 CODE = 'param'
319 colormap = 'viridis'
318 colormap = 'viridis'
320 plot_type = 'pcolorbuffer'
319 plot_type = 'pcolorbuffer'
321
320
322 def setup(self):
321 def setup(self):
323 self.xaxis = 'time'
322 self.xaxis = 'time'
324 self.ncols = 1
323 self.ncols = 1
325 self.nrows = self.data.shape('param')[0]
324 self.nrows = self.data.shape('param')[0]
326 self.nplots = self.nrows
325 self.nplots = self.nrows
327 self.plots_adjust.update({'hspace':0.8, 'left': 0.1, 'bottom': 0.08, 'right':0.95, 'top': 0.95})
326 self.plots_adjust.update({'hspace':0.8, 'left': 0.1, 'bottom': 0.08, 'right':0.95, 'top': 0.95})
328
327
329 if not self.xlabel:
328 if not self.xlabel:
330 self.xlabel = 'Time'
329 self.xlabel = 'Time'
331
330
332 self.ylabel = 'Range [km]'
331 self.ylabel = 'Range [km]'
333 if not self.titles:
332 if not self.titles:
334 self.titles = ['Param {}'.format(x) for x in range(self.nrows)]
333 self.titles = ['Param {}'.format(x) for x in range(self.nrows)]
335
334
336 def update(self, dataOut):
335 def update(self, dataOut):
337
336
338 data = {
337 data = {
339 'param' : numpy.concatenate([getattr(dataOut, attr) for attr in self.attr_data], axis=0)
338 'param' : numpy.concatenate([getattr(dataOut, attr) for attr in self.attr_data], axis=0)
340 }
339 }
341
340
342 meta = {}
341 meta = {}
343
342
344 return data, meta
343 return data, meta
345
344
346 def plot(self):
345 def plot(self):
347 # self.data.normalize_heights()
346 # self.data.normalize_heights()
348 self.x = self.data.times
347 self.x = self.data.times
349 self.y = self.data.yrange
348 self.y = self.data.yrange
350 self.z = self.data['param']
349 self.z = self.data['param']
351 self.z = 10*numpy.log10(self.z)
350 self.z = 10*numpy.log10(self.z)
352 self.z = numpy.ma.masked_invalid(self.z)
351 self.z = numpy.ma.masked_invalid(self.z)
353
352
354 if self.decimation is None:
353 if self.decimation is None:
355 x, y, z = self.fill_gaps(self.x, self.y, self.z)
354 x, y, z = self.fill_gaps(self.x, self.y, self.z)
356 else:
355 else:
357 x, y, z = self.fill_gaps(*self.decimate())
356 x, y, z = self.fill_gaps(*self.decimate())
358
357
359 for n, ax in enumerate(self.axes):
358 for n, ax in enumerate(self.axes):
360
359
361 self.zmax = self.zmax if self.zmax is not None else numpy.max(
360 self.zmax = self.zmax if self.zmax is not None else numpy.max(
362 self.z[n])
361 self.z[n])
363 self.zmin = self.zmin if self.zmin is not None else numpy.min(
362 self.zmin = self.zmin if self.zmin is not None else numpy.min(
364 self.z[n])
363 self.z[n])
365
364
366 if ax.firsttime:
365 if ax.firsttime:
367 if self.zlimits is not None:
366 if self.zlimits is not None:
368 self.zmin, self.zmax = self.zlimits[n]
367 self.zmin, self.zmax = self.zlimits[n]
369
368
370 ax.plt = ax.pcolormesh(x, y, z[n].T * self.factors[n],
369 ax.plt = ax.pcolormesh(x, y, z[n].T * self.factors[n],
371 vmin=self.zmin,
370 vmin=self.zmin,
372 vmax=self.zmax,
371 vmax=self.zmax,
373 cmap=self.cmaps[n]
372 cmap=self.cmaps[n]
374 )
373 )
375 else:
374 else:
376 if self.zlimits is not None:
375 if self.zlimits is not None:
377 self.zmin, self.zmax = self.zlimits[n]
376 self.zmin, self.zmax = self.zlimits[n]
378 ax.collections.remove(ax.collections[0])
377 ax.collections.remove(ax.collections[0])
379 ax.plt = ax.pcolormesh(x, y, z[n].T * self.factors[n],
378 ax.plt = ax.pcolormesh(x, y, z[n].T * self.factors[n],
380 vmin=self.zmin,
379 vmin=self.zmin,
381 vmax=self.zmax,
380 vmax=self.zmax,
382 cmap=self.cmaps[n]
381 cmap=self.cmaps[n]
383 )
382 )
384
383
385
384
386 class PolarMapPlot(Plot):
385 class PolarMapPlot(Plot):
387 '''
386 '''
388 Plot for weather radar
387 Plot for weather radar
389 '''
388 '''
390
389
391 CODE = 'param'
390 CODE = 'param'
392 colormap = 'seismic'
391 colormap = 'seismic'
393
392
394 def setup(self):
393 def setup(self):
395 self.ncols = 1
394 self.ncols = 1
396 self.nrows = 1
395 self.nrows = 1
397 self.width = 9
396 self.width = 9
398 self.height = 8
397 self.height = 8
399 self.mode = self.data.meta['mode']
398 self.mode = self.data.meta['mode']
400 if self.channels is not None:
399 if self.channels is not None:
401 self.nplots = len(self.channels)
400 self.nplots = len(self.channels)
402 self.nrows = len(self.channels)
401 self.nrows = len(self.channels)
403 else:
402 else:
404 self.nplots = self.data.shape(self.CODE)[0]
403 self.nplots = self.data.shape(self.CODE)[0]
405 self.nrows = self.nplots
404 self.nrows = self.nplots
406 self.channels = list(range(self.nplots))
405 self.channels = list(range(self.nplots))
407 if self.mode == 'E':
406 if self.mode == 'E':
408 self.xlabel = 'Longitude'
407 self.xlabel = 'Longitude'
409 self.ylabel = 'Latitude'
408 self.ylabel = 'Latitude'
410 else:
409 else:
411 self.xlabel = 'Range (km)'
410 self.xlabel = 'Range (km)'
412 self.ylabel = 'Height (km)'
411 self.ylabel = 'Height (km)'
413 self.bgcolor = 'white'
412 self.bgcolor = 'white'
414 self.cb_labels = self.data.meta['units']
413 self.cb_labels = self.data.meta['units']
415 self.lat = self.data.meta['latitude']
414 self.lat = self.data.meta['latitude']
416 self.lon = self.data.meta['longitude']
415 self.lon = self.data.meta['longitude']
417 self.xmin, self.xmax = float(
416 self.xmin, self.xmax = float(
418 km2deg(self.xmin) + self.lon), float(km2deg(self.xmax) + self.lon)
417 km2deg(self.xmin) + self.lon), float(km2deg(self.xmax) + self.lon)
419 self.ymin, self.ymax = float(
418 self.ymin, self.ymax = float(
420 km2deg(self.ymin) + self.lat), float(km2deg(self.ymax) + self.lat)
419 km2deg(self.ymin) + self.lat), float(km2deg(self.ymax) + self.lat)
421 # self.polar = True
420 # self.polar = True
422
421
423 def plot(self):
422 def plot(self):
424
423
425 for n, ax in enumerate(self.axes):
424 for n, ax in enumerate(self.axes):
426 data = self.data['param'][self.channels[n]]
425 data = self.data['param'][self.channels[n]]
427
426
428 zeniths = numpy.linspace(
427 zeniths = numpy.linspace(
429 0, self.data.meta['max_range'], data.shape[1])
428 0, self.data.meta['max_range'], data.shape[1])
430 if self.mode == 'E':
429 if self.mode == 'E':
431 azimuths = -numpy.radians(self.data.yrange)+numpy.pi/2
430 azimuths = -numpy.radians(self.data.yrange)+numpy.pi/2
432 r, theta = numpy.meshgrid(zeniths, azimuths)
431 r, theta = numpy.meshgrid(zeniths, azimuths)
433 x, y = r*numpy.cos(theta)*numpy.cos(numpy.radians(self.data.meta['elevation'])), r*numpy.sin(
432 x, y = r*numpy.cos(theta)*numpy.cos(numpy.radians(self.data.meta['elevation'])), r*numpy.sin(
434 theta)*numpy.cos(numpy.radians(self.data.meta['elevation']))
433 theta)*numpy.cos(numpy.radians(self.data.meta['elevation']))
435 x = km2deg(x) + self.lon
434 x = km2deg(x) + self.lon
436 y = km2deg(y) + self.lat
435 y = km2deg(y) + self.lat
437 else:
436 else:
438 azimuths = numpy.radians(self.data.yrange)
437 azimuths = numpy.radians(self.data.yrange)
439 r, theta = numpy.meshgrid(zeniths, azimuths)
438 r, theta = numpy.meshgrid(zeniths, azimuths)
440 x, y = r*numpy.cos(theta), r*numpy.sin(theta)
439 x, y = r*numpy.cos(theta), r*numpy.sin(theta)
441 self.y = zeniths
440 self.y = zeniths
442
441
443 if ax.firsttime:
442 if ax.firsttime:
444 if self.zlimits is not None:
443 if self.zlimits is not None:
445 self.zmin, self.zmax = self.zlimits[n]
444 self.zmin, self.zmax = self.zlimits[n]
446 ax.plt = ax.pcolormesh( # r, theta, numpy.ma.array(data, mask=numpy.isnan(data)),
445 ax.plt = ax.pcolormesh( # r, theta, numpy.ma.array(data, mask=numpy.isnan(data)),
447 x, y, numpy.ma.array(data, mask=numpy.isnan(data)),
446 x, y, numpy.ma.array(data, mask=numpy.isnan(data)),
448 vmin=self.zmin,
447 vmin=self.zmin,
449 vmax=self.zmax,
448 vmax=self.zmax,
450 cmap=self.cmaps[n])
449 cmap=self.cmaps[n])
451 else:
450 else:
452 if self.zlimits is not None:
451 if self.zlimits is not None:
453 self.zmin, self.zmax = self.zlimits[n]
452 self.zmin, self.zmax = self.zlimits[n]
454 ax.collections.remove(ax.collections[0])
453 ax.collections.remove(ax.collections[0])
455 ax.plt = ax.pcolormesh( # r, theta, numpy.ma.array(data, mask=numpy.isnan(data)),
454 ax.plt = ax.pcolormesh( # r, theta, numpy.ma.array(data, mask=numpy.isnan(data)),
456 x, y, numpy.ma.array(data, mask=numpy.isnan(data)),
455 x, y, numpy.ma.array(data, mask=numpy.isnan(data)),
457 vmin=self.zmin,
456 vmin=self.zmin,
458 vmax=self.zmax,
457 vmax=self.zmax,
459 cmap=self.cmaps[n])
458 cmap=self.cmaps[n])
460
459
461 if self.mode == 'A':
460 if self.mode == 'A':
462 continue
461 continue
463
462
464 # plot district names
463 # plot district names
465 f = open('/data/workspace/schain_scripts/distrito.csv')
464 f = open('/data/workspace/schain_scripts/distrito.csv')
466 for line in f:
465 for line in f:
467 label, lon, lat = [s.strip() for s in line.split(',') if s]
466 label, lon, lat = [s.strip() for s in line.split(',') if s]
468 lat = float(lat)
467 lat = float(lat)
469 lon = float(lon)
468 lon = float(lon)
470 # ax.plot(lon, lat, '.b', ms=2)
469 # ax.plot(lon, lat, '.b', ms=2)
471 ax.text(lon, lat, label.decode('utf8'), ha='center',
470 ax.text(lon, lat, label.decode('utf8'), ha='center',
472 va='bottom', size='8', color='black')
471 va='bottom', size='8', color='black')
473
472
474 # plot limites
473 # plot limites
475 limites = []
474 limites = []
476 tmp = []
475 tmp = []
477 for line in open('/data/workspace/schain_scripts/lima.csv'):
476 for line in open('/data/workspace/schain_scripts/lima.csv'):
478 if '#' in line:
477 if '#' in line:
479 if tmp:
478 if tmp:
480 limites.append(tmp)
479 limites.append(tmp)
481 tmp = []
480 tmp = []
482 continue
481 continue
483 values = line.strip().split(',')
482 values = line.strip().split(',')
484 tmp.append((float(values[0]), float(values[1])))
483 tmp.append((float(values[0]), float(values[1])))
485 for points in limites:
484 for points in limites:
486 ax.add_patch(
485 ax.add_patch(
487 Polygon(points, ec='k', fc='none', ls='--', lw=0.5))
486 Polygon(points, ec='k', fc='none', ls='--', lw=0.5))
488
487
489 # plot Cuencas
488 # plot Cuencas
490 for cuenca in ('rimac', 'lurin', 'mala', 'chillon', 'chilca', 'chancay-huaral'):
489 for cuenca in ('rimac', 'lurin', 'mala', 'chillon', 'chilca', 'chancay-huaral'):
491 f = open('/data/workspace/schain_scripts/{}.csv'.format(cuenca))
490 f = open('/data/workspace/schain_scripts/{}.csv'.format(cuenca))
492 values = [line.strip().split(',') for line in f]
491 values = [line.strip().split(',') for line in f]
493 points = [(float(s[0]), float(s[1])) for s in values]
492 points = [(float(s[0]), float(s[1])) for s in values]
494 ax.add_patch(Polygon(points, ec='b', fc='none'))
493 ax.add_patch(Polygon(points, ec='b', fc='none'))
495
494
496 # plot grid
495 # plot grid
497 for r in (15, 30, 45, 60):
496 for r in (15, 30, 45, 60):
498 ax.add_artist(plt.Circle((self.lon, self.lat),
497 ax.add_artist(plt.Circle((self.lon, self.lat),
499 km2deg(r), color='0.6', fill=False, lw=0.2))
498 km2deg(r), color='0.6', fill=False, lw=0.2))
500 ax.text(
499 ax.text(
501 self.lon + (km2deg(r))*numpy.cos(60*numpy.pi/180),
500 self.lon + (km2deg(r))*numpy.cos(60*numpy.pi/180),
502 self.lat + (km2deg(r))*numpy.sin(60*numpy.pi/180),
501 self.lat + (km2deg(r))*numpy.sin(60*numpy.pi/180),
503 '{}km'.format(r),
502 '{}km'.format(r),
504 ha='center', va='bottom', size='8', color='0.6', weight='heavy')
503 ha='center', va='bottom', size='8', color='0.6', weight='heavy')
505
504
506 if self.mode == 'E':
505 if self.mode == 'E':
507 title = 'El={}$^\circ$'.format(self.data.meta['elevation'])
506 title = 'El={}$^\circ$'.format(self.data.meta['elevation'])
508 label = 'E{:02d}'.format(int(self.data.meta['elevation']))
507 label = 'E{:02d}'.format(int(self.data.meta['elevation']))
509 else:
508 else:
510 title = 'Az={}$^\circ$'.format(self.data.meta['azimuth'])
509 title = 'Az={}$^\circ$'.format(self.data.meta['azimuth'])
511 label = 'A{:02d}'.format(int(self.data.meta['azimuth']))
510 label = 'A{:02d}'.format(int(self.data.meta['azimuth']))
512
511
513 self.save_labels = ['{}-{}'.format(lbl, label) for lbl in self.labels]
512 self.save_labels = ['{}-{}'.format(lbl, label) for lbl in self.labels]
514 self.titles = ['{} {}'.format(
513 self.titles = ['{} {}'.format(
515 self.data.parameters[x], title) for x in self.channels]
514 self.data.parameters[x], title) for x in self.channels]
516
515
517 class WeatherParamsPlot(Plot):
516 class WeatherParamsPlot(Plot):
518 #CODE = 'RHI'
517
519 #plot_name = 'RHI'
520 plot_type = 'scattermap'
518 plot_type = 'scattermap'
521 buffering = False
519 buffering = False
522 projection = ccrs.PlateCarree()
523
520
524 def setup(self):
521 def setup(self):
525
522
526 self.ncols = 1
523 self.ncols = 1
527 self.nrows = 1
524 self.nrows = 1
528 self.nplots= 1
525 self.nplots= 1
529 self.ylabel= 'Height [km]'
530 self.xlabel= 'Distance from radar [km]'
531
526
532 if self.channels is not None:
527 if self.channels is not None:
533 self.nplots = len(self.channels)
528 self.nplots = len(self.channels)
534 self.ncols = len(self.channels)
529 self.ncols = len(self.channels)
535 else:
530 else:
536 self.nplots = self.data.shape(self.CODE)[0]
531 self.nplots = self.data.shape(self.CODE)[0]
537 self.ncols = self.nplots
532 self.ncols = self.nplots
538 self.channels = list(range(self.nplots))
533 self.channels = list(range(self.nplots))
539
534
540 self.colorbar=True
535 self.colorbar=True
541 if len(self.channels)>1:
536 if len(self.channels)>1:
542 self.width = 12
537 self.width = 12
543 else:
538 else:
544 self.width =8
539 self.width =8
545 self.height =7
540 self.height =7
546 self.ini =0
541 self.ini =0
547 self.len_azi =0
542 self.len_azi =0
548 self.buffer_ini = None
543 self.buffer_ini = None
549 self.buffer_ele = None
544 self.buffer_ele = None
550 self.plots_adjust.update({'wspace': 0.4, 'hspace':0.4, 'left': 0.1, 'right': 0.9, 'bottom': 0.1})
545 self.plots_adjust.update({'wspace': 0.4, 'hspace':0.4, 'left': 0.1, 'right': 0.9, 'bottom': 0.1})
551 self.flag =0
546 self.flag =0
552 self.indicador= 0
547 self.indicador= 0
553 self.last_data_ele = None
548 self.last_data_ele = None
554 self.val_mean = None
549 self.val_mean = None
555
550
556 def update(self, dataOut):
551 def update(self, dataOut):
557
552
558 vars = {
553 vars = {
559 'S' : 0,
554 'S' : 0,
560 'V' : 1,
555 'V' : 1,
561 'W' : 2,
556 'W' : 2,
562 'SNR' : 3,
557 'SNR' : 3,
563 'Z' : 4,
558 'Z' : 4,
564 'D' : 5,
559 'D' : 5,
565 'P' : 6,
560 'P' : 6,
566 'R' : 7,
561 'R' : 7,
567 }
562 }
568
563
569 data = {}
564 data = {}
570 meta = {}
565 meta = {}
571
566
572 if hasattr(dataOut, 'nFFTPoints'):
567 if hasattr(dataOut, 'nFFTPoints'):
573 factor = dataOut.normFactor
568 factor = dataOut.normFactor
574 else:
569 else:
575 factor = 1
570 factor = 1
576
571
577 if hasattr(dataOut, 'dparam'):
572 if hasattr(dataOut, 'dparam'):
578 tmp = getattr(dataOut, 'data_param')
573 tmp = getattr(dataOut, 'data_param')
579 else:
574 else:
580 #print("-------------------self.attr_data[0]",self.attr_data[0])
575 #print("-------------------self.attr_data[0]",self.attr_data[0])
581 if 'S' in self.attr_data[0]:
576 if 'S' in self.attr_data[0]:
582 if self.attr_data[0]=='S':
577 if self.attr_data[0]=='S':
583 tmp = 10*numpy.log10(10.0*getattr(dataOut, 'data_param')[:,0,:]/(factor))
578 tmp = 10*numpy.log10(10.0*getattr(dataOut, 'data_param')[:,0,:]/(factor))
584 if self.attr_data[0]=='SNR':
579 if self.attr_data[0]=='SNR':
585 tmp = 10*numpy.log10(getattr(dataOut, 'data_param')[:,3,:])
580 tmp = 10*numpy.log10(getattr(dataOut, 'data_param')[:,3,:])
586 else:
581 else:
587 tmp = getattr(dataOut, 'data_param')[:,vars[self.attr_data[0]],:]
582 tmp = getattr(dataOut, 'data_param')[:,vars[self.attr_data[0]],:]
588
583
589 if self.mask:
584 if self.mask:
590 mask = dataOut.data_param[:,3,:] < self.mask
585 mask = dataOut.data_param[:,3,:] < self.mask
591 tmp = numpy.ma.masked_array(tmp, mask=mask)
586 tmp = numpy.ma.masked_array(tmp, mask=mask)
592
587
593 r = dataOut.heightList
588 r = dataOut.heightList
594 delta_height = r[1]-r[0]
589 delta_height = r[1]-r[0]
595 valid = numpy.where(r>=0)[0]
590 valid = numpy.where(r>=0)[0]
596 data['r'] = numpy.arange(len(valid))*delta_height
591 data['r'] = numpy.arange(len(valid))*delta_height
597
592
598 data['data'] = [0, 0]
593 data['data'] = [0, 0]
599
594
600 try:
595 try:
601 data['data'][0] = tmp[0][:,valid]
596 data['data'][0] = tmp[0][:,valid]
602 data['data'][1] = tmp[1][:,valid]
597 data['data'][1] = tmp[1][:,valid]
603 except:
598 except:
604 data['data'][0] = tmp[0][:,valid]
599 data['data'][0] = tmp[0][:,valid]
605 data['data'][1] = tmp[0][:,valid]
600 data['data'][1] = tmp[0][:,valid]
606
601
607 if dataOut.mode_op == 'PPI':
602 if dataOut.mode_op == 'PPI':
608 self.CODE = 'PPI'
603 self.CODE = 'PPI'
609 self.title = self.CODE
604 self.title = self.CODE
610 elif dataOut.mode_op == 'RHI':
605 elif dataOut.mode_op == 'RHI':
611 self.CODE = 'RHI'
606 self.CODE = 'RHI'
612 self.title = self.CODE
607 self.title = self.CODE
613
608
614 data['azi'] = dataOut.data_azi
609 data['azi'] = dataOut.data_azi
615 data['ele'] = dataOut.data_ele
610 data['ele'] = dataOut.data_ele
616
611
617 if isinstance(dataOut.mode_op, bytes):
612 if isinstance(dataOut.mode_op, bytes):
618 try:
613 try:
619 dataOut.mode_op = dataOut.mode_op.decode()
614 dataOut.mode_op = dataOut.mode_op.decode()
620 except:
615 except:
621 dataOut.mode_op = str(dataOut.mode_op, 'utf-8')
616 dataOut.mode_op = str(dataOut.mode_op, 'utf-8')
622 data['mode_op'] = dataOut.mode_op
617 data['mode_op'] = dataOut.mode_op
623 self.mode = dataOut.mode_op
618 self.mode = dataOut.mode_op
624
619
625 return data, meta
620 return data, meta
626
621
627 def plot(self):
622 def plot(self):
628 data = self.data[-1]
623 data = self.data[-1]
629 z = data['data']
624 z = data['data']
630 r = data['r']
625 r = data['r']
631 self.titles = []
626 self.titles = []
632
627
633 self.ymax = self.ymax if self.ymax else numpy.nanmax(r)
634 self.ymin = self.ymin if self.ymin else numpy.nanmin(r)
635 self.zmax = self.zmax if self.zmax else numpy.nanmax(z)
628 self.zmax = self.zmax if self.zmax else numpy.nanmax(z)
636 self.zmin = self.zmin if self.zmin is not None else numpy.nanmin(z)
629 self.zmin = self.zmin if self.zmin is not None else numpy.nanmin(z)
637
630
638 if isinstance(data['mode_op'], bytes):
631 if isinstance(data['mode_op'], bytes):
639 data['mode_op'] = data['mode_op'].decode()
632 data['mode_op'] = data['mode_op'].decode()
640
633
641 if data['mode_op'] == 'RHI':
634 if data['mode_op'] == 'RHI':
642 r, theta = numpy.meshgrid(r, numpy.radians(data['ele']))
635 r, theta = numpy.meshgrid(r, numpy.radians(data['ele']))
643 len_aux = int(data['azi'].shape[0]/4)
636 len_aux = int(data['azi'].shape[0]/4)
644 mean = numpy.mean(data['azi'][len_aux:-len_aux])
637 mean = numpy.mean(data['azi'][len_aux:-len_aux])
645 x, y = r*numpy.cos(theta), r*numpy.sin(theta)
638 x, y = r*numpy.cos(theta), r*numpy.sin(theta)
639 if self.yrange:
640 self.ylabel= 'Height [km]'
641 self.xlabel= 'Distance from radar [km]'
642 self.ymax = self.yrange
643 self.ymin = 0
644 self.xmax = self.xrange if self.xrange else numpy.nanmax(r)
645 self.xmin = -self.xrange if self.xrange else -numpy.nanmax(r)
646 self.setrhilimits = False
647 else:
648 self.ymin = 0
649 self.ymax = numpy.nanmax(r)
650 self.xmin = -numpy.nanmax(r)
651 self.xmax = numpy.nanmax(r)
652
646 elif data['mode_op'] == 'PPI':
653 elif data['mode_op'] == 'PPI':
647 r, theta = numpy.meshgrid(r, -numpy.radians(data['azi'])+numpy.pi/2)
654 r, theta = numpy.meshgrid(r, -numpy.radians(data['azi'])+numpy.pi/2)
648 len_aux = int(data['ele'].shape[0]/4)
655 len_aux = int(data['ele'].shape[0]/4)
649 mean = numpy.mean(data['ele'][len_aux:-len_aux])
656 mean = numpy.mean(data['ele'][len_aux:-len_aux])
650 x, y = r*numpy.cos(theta)*numpy.cos(numpy.radians(mean)), r*numpy.sin(
657 x, y = r*numpy.cos(theta)*numpy.cos(numpy.radians(mean)), r*numpy.sin(
651 theta)*numpy.cos(numpy.radians(mean))
658 theta)*numpy.cos(numpy.radians(mean))
652 x = km2deg(x) + -75.295893
659 x = km2deg(x) + self.longitude
653 y = km2deg(y) + -12.040436
660 y = km2deg(y) + self.latitude
661 if self.xrange:
662 self.ylabel= 'Latitude'
663 self.xlabel= 'Longitude'
664
665 self.xmin = km2deg(-self.xrange) + self.longitude
666 self.xmax = km2deg(self.xrange) + self.longitude
667
668 self.ymin = km2deg(-self.xrange) + self.latitude
669 self.ymax = km2deg(self.xrange) + self.latitude
670 else:
671 self.xmin = km2deg(-numpy.nanmax(r)) + self.longitude
672 self.xmax = km2deg(numpy.nanmax(r)) + self.longitude
673
674 self.ymin = km2deg(-numpy.nanmax(r)) + self.latitude
675 self.ymax = km2deg(numpy.nanmax(r)) + self.latitude
654
676
655 self.clear_figures()
677 self.clear_figures()
656
678
657 if data['mode_op'] == 'PPI':
679 if data['mode_op'] == 'PPI':
658 axes = self.axes['PPI']
680 axes = self.axes['PPI']
659 else:
681 else:
660 axes = self.axes['RHI']
682 axes = self.axes['RHI']
661
683
662 if self.colormap in cb_tables:
684 if self.colormap in cb_tables:
663 norm = cb_tables[self.colormap]['norm']
685 norm = cb_tables[self.colormap]['norm']
664 else:
686 else:
665 norm = None
687 norm = None
666
688
667 for i, ax in enumerate(axes):
689 for i, ax in enumerate(axes):
668 if data['mode_op'] == 'PPI':
669 ax.set_extent([-75.745893, -74.845893, -12.490436, -11.590436])
670
690
671 if norm is None:
691 if norm is None:
672 ax.plt = ax.pcolormesh(x, y, z[i], cmap=self.colormap, vmin=self.zmin, vmax=self.zmax)
692 ax.plt = ax.pcolormesh(x, y, z[i], cmap=self.colormap, vmin=self.zmin, vmax=self.zmax)
673 else:
693 else:
674 ax.plt = ax.pcolormesh(x, y, z[i], cmap=self.colormap, norm=norm)
694 ax.plt = ax.pcolormesh(x, y, z[i], cmap=self.colormap, norm=norm)
675
695
676 if data['mode_op'] == 'RHI':
696 if data['mode_op'] == 'RHI':
677 len_aux = int(data['azi'].shape[0]/4)
697 len_aux = int(data['azi'].shape[0]/4)
678 mean = numpy.mean(data['azi'][len_aux:-len_aux])
698 mean = numpy.mean(data['azi'][len_aux:-len_aux])
679 if len(self.channels) !=1:
699 if len(self.channels) !=1:
680 self.titles = ['RHI {} at AZ: {} CH {}'.format(self.labels[x], str(round(mean,1)), x) for x in self.channels]
700 self.titles = ['RHI {} at AZ: {} CH {}'.format(self.labels[x], str(round(mean,1)), x) for x in self.channels]
681 else:
701 else:
682 self.titles = ['RHI {} at AZ: {} CH {}'.format(self.labels[0], str(round(mean,1)), self.channels[0])]
702 self.titles = ['RHI {} at AZ: {} CH {}'.format(self.labels[0], str(round(mean,1)), self.channels[0])]
683 elif data['mode_op'] == 'PPI':
703 elif data['mode_op'] == 'PPI':
684 len_aux = int(data['ele'].shape[0]/4)
704 len_aux = int(data['ele'].shape[0]/4)
685 mean = numpy.mean(data['ele'][len_aux:-len_aux])
705 mean = numpy.mean(data['ele'][len_aux:-len_aux])
686 if len(self.channels) !=1:
706 if len(self.channels) !=1:
687 self.titles = ['PPI {} at EL: {} CH {}'.format(self.labels[x], str(round(mean,1)), x) for x in self.channels]
707 self.titles = ['PPI {} at EL: {} CH {}'.format(self.labels[x], str(round(mean,1)), x) for x in self.channels]
688 else:
708 else:
689 self.titles = ['PPI {} at EL: {} CH {}'.format(self.labels[0], str(round(mean,1)), self.channels[0])]
709 self.titles = ['PPI {} at EL: {} CH {}'.format(self.labels[0], str(round(mean,1)), self.channels[0])]
690 self.mode_value = round(mean,1)
710 self.mode_value = round(mean,1)
691
711
692 if data['mode_op'] == 'PPI':
712 if data['mode_op'] == 'PPI':
713 if self.map:
693 gl = ax.gridlines(crs=ccrs.PlateCarree(), draw_labels=True,
714 gl = ax.gridlines(crs=ccrs.PlateCarree(), draw_labels=True,
694 linewidth=1, color='gray', alpha=0.5, linestyle='--')
715 linewidth=1, color='gray', alpha=0.5, linestyle='--')
695 gl.xlabel_style = {'size': 8}
716 gl.xlabel_style = {'size': 8}
696 gl.ylabel_style = {'size': 8}
717 gl.ylabel_style = {'size': 8}
697 gl.xlabels_top = False
718 gl.xlabels_top = False
698 gl.ylabels_right = False
719 gl.ylabels_right = False
699 #self.shapes="/home/soporte/workspace/sirm/volumes/schain/shapes/"
700 #print("self.shapes",self.shapes)
701 shape_p = os.path.join(self.shapes,'PER_ADM2/PER_ADM2.shp')
720 shape_p = os.path.join(self.shapes,'PER_ADM2/PER_ADM2.shp')
702 shape_d = os.path.join(self.shapes,'PER_ADM1/PER_ADM1.shp')
721 shape_d = os.path.join(self.shapes,'PER_ADM1/PER_ADM1.shp')
703 capitales = os.path.join(self.shapes,'CAPITALES/cap_provincia.shp')
722 capitales = os.path.join(self.shapes,'CAPITALES/cap_provincia.shp')
704 vias = os.path.join(self.shapes,'Carreteras/VIAS_NACIONAL_250000.shp')
723 vias = os.path.join(self.shapes,'Carreteras/VIAS_NACIONAL_250000.shp')
705 reader_d = shpreader.BasicReader(shape_p, encoding='latin1')
724 reader_d = shpreader.BasicReader(shape_p, encoding='latin1')
706 reader_p = shpreader.BasicReader(shape_d, encoding='latin1')
725 reader_p = shpreader.BasicReader(shape_d, encoding='latin1')
707 reader_c = shpreader.BasicReader(capitales, encoding='latin1')
726 reader_c = shpreader.BasicReader(capitales, encoding='latin1')
708 reader_v = shpreader.BasicReader(vias, encoding='latin1')
727 reader_v = shpreader.BasicReader(vias, encoding='latin1')
709 caps = [x for x in reader_c.records() if x.attributes["Departa"] in ("JUNIN", "LIMA", "AYACUCHO", "HUANCAVELICA")]
728 caps = [x for x in reader_c.records() ]#if x.attributes["Departa"] in ("JUNIN", "LIMA", "ICA", "PIURA")]
710 districts = [x for x in reader_d.records() if x.attributes["Name"] in ("JUNÍN", "CHANCHAMAYO", "CHUPACA", "CONCEPCIÓN", "HUANCAYO", "JAUJA", "SATIPO", "TARMA", "YAUYOS", "HUAROCHIRÍ", "CANTA", "HUANTA", "TAYACAJA")]
729 districts = [x for x in reader_d.records() ]# if x.attributes["Name"] in ("JUNÍN", "CHANCHAMAYO", "CHUPACA", "CONCEPCIÓN", "HUANCAYO", "JAUJA", "SATIPO", "TARMA", "YAUYOS", "HUAROCHIRÍ", "CANTA", "HUANTA", "TAYACAJA")]
711 provs = [x for x in reader_p.records() if x.attributes["NAME"] in ("Junín", "Lima")]
730 provs = [x for x in reader_p.records()]# if x.attributes["NAME"] in ("Junín", "Lima")]
712 vias = [x for x in reader_v.records() if x.attributes["DEP"] in ("JUNIN", "LIMA")]
731 vias = [x for x in reader_v.records()]# if x.attributes["DEP"] in ("JUNIN", "LIMA")]
713
732
714 # Display limits and streets
733 # Display limits and streets
715 shape_feature = ShapelyFeature([x.geometry for x in districts], ccrs.PlateCarree(), facecolor="none", edgecolor='grey', lw=0.5)
734 shape_feature = ShapelyFeature([x.geometry for x in districts], ccrs.PlateCarree(), facecolor="none", edgecolor='grey', lw=0.5)
716 ax.add_feature(shape_feature)
735 ax.add_feature(shape_feature)
717 shape_feature = ShapelyFeature([x.geometry for x in provs], ccrs.PlateCarree(), facecolor="none", edgecolor='white', lw=1)
736 shape_feature = ShapelyFeature([x.geometry for x in provs], ccrs.PlateCarree(), facecolor="none", edgecolor='white', lw=1)
718 ax.add_feature(shape_feature)
737 ax.add_feature(shape_feature)
719 shape_feature = ShapelyFeature([x.geometry for x in vias], ccrs.PlateCarree(), facecolor="none", edgecolor='yellow', lw=1)
738 shape_feature = ShapelyFeature([x.geometry for x in vias], ccrs.PlateCarree(), facecolor="none", edgecolor='yellow', lw=1)
720 ax.add_feature(shape_feature)
739 ax.add_feature(shape_feature)
721
740
722 for cap in caps:
741 for cap in caps:
723 if cap.attributes['Nombre'] in ("LA OROYA", "CONCEPCIÓN", "HUANCAYO", "JAUJA", "CHUPACA", "YAUYOS", "HUANTA", "PAMPAS"):
742 #if cap.attributes['Nombre'] in ("LA OROYA", "CONCEPCIÓN", "HUANCAYO", "JAUJA", "CHUPACA", "YAUYOS", "HUANTA", "PAMPAS"):
724 ax.text(cap.attributes['X'], cap.attributes['Y'], cap.attributes['Nombre'].title(), size=7, color='white')
743 ax.text(cap.attributes['X'], cap.attributes['Y'], cap.attributes['Nombre'].title(), size=7, color='white')
725 ax.text(-75.052003, -11.915552, 'Huaytapallana', size=7, color='cyan')
744 #ax.text(-75.052003, -11.915552, 'Huaytapallana', size=7, color='cyan')
726 ax.plot(-75.052003, -11.915552, '*')
745 #ax.plot(-75.052003, -11.915552, '*')
727
746 else:
747 ax.grid(color='grey', alpha=0.5, linestyle='--', linewidth=1)
728 for R in (10, 20, 30 , 40, 50):
748 for R in (10, 20, 30 , 40, 50):
729 circle = Circle((-75.295893, -12.040436), km2deg(R), facecolor='none',
749 if R <= self.xrange:
750 circle = Circle((self.longitude, self.latitude), km2deg(R), facecolor='none',
730 edgecolor='skyblue', linewidth=1, alpha=0.5)
751 edgecolor='skyblue', linewidth=1, alpha=0.5)
731 ax.add_patch(circle)
752 ax.add_patch(circle)
732 ax.text(km2deg(R)*numpy.cos(numpy.radians(45))-75.295893,
753 ax.text(km2deg(R)*numpy.cos(numpy.radians(45))+self.longitude,
733 km2deg(R)*numpy.sin(numpy.radians(45))-12.040436,
754 km2deg(R)*numpy.sin(numpy.radians(45))+self.latitude,
734 '{}km'.format(R), color='skyblue', size=7)
755 '{}km'.format(R), color='skyblue', size=7)
735 elif data['mode_op'] == 'RHI':
756 elif data['mode_op'] == 'RHI':
736 ax.grid(color='grey', alpha=0.5, linestyle='--', linewidth=1)
757 ax.grid(color='grey', alpha=0.5, linestyle='--', linewidth=1)
General Comments 0
You need to be logged in to leave comments. Login now