##// END OF EJS Templates
Add angles to Block360 fix plotting codes
Juan C. Espinoza -
r1589:0234d27936fd
parent child
Show More

The requested changes are too big and content was truncated. Show full diff

@@ -1,750 +1,752
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 from .plotting_codes import register_cmap
36 from .plotting_codes import register_cmap
37
37
38 from schainpy.model.data.jrodata import PlotterData
38 from schainpy.model.data.jrodata import PlotterData
39 from schainpy.model.proc.jroproc_base import ProcessingUnit, Operation, MPDecorator
39 from schainpy.model.proc.jroproc_base import ProcessingUnit, Operation, MPDecorator
40 from schainpy.utils import log
40 from schainpy.utils import log
41
41
42
42
43 EARTH_RADIUS = 6.3710e3
43 EARTH_RADIUS = 6.3710e3
44
44
45 register_cmap()
45 register_cmap()
46
46
47 def ll2xy(lat1, lon1, lat2, lon2):
47 def ll2xy(lat1, lon1, lat2, lon2):
48
48
49 p = 0.017453292519943295
49 p = 0.017453292519943295
50 a = 0.5 - numpy.cos((lat2 - lat1) * p)/2 + numpy.cos(lat1 * p) * \
50 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
51 numpy.cos(lat2 * p) * (1 - numpy.cos((lon2 - lon1) * p)) / 2
52 r = 12742 * numpy.arcsin(numpy.sqrt(a))
52 r = 12742 * numpy.arcsin(numpy.sqrt(a))
53 theta = numpy.arctan2(numpy.sin((lon2-lon1)*p)*numpy.cos(lat2*p), numpy.cos(lat1*p)
53 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))
54 * numpy.sin(lat2*p)-numpy.sin(lat1*p)*numpy.cos(lat2*p)*numpy.cos((lon2-lon1)*p))
55 theta = -theta + numpy.pi/2
55 theta = -theta + numpy.pi/2
56 return r*numpy.cos(theta), r*numpy.sin(theta)
56 return r*numpy.cos(theta), r*numpy.sin(theta)
57
57
58
58
59 def km2deg(km):
59 def km2deg(km):
60 '''
60 '''
61 Convert distance in km to degrees
61 Convert distance in km to degrees
62 '''
62 '''
63
63
64 return numpy.rad2deg(km/EARTH_RADIUS)
64 return numpy.rad2deg(km/EARTH_RADIUS)
65
65
66
66
67 def figpause(interval):
67 def figpause(interval):
68 backend = plt.rcParams['backend']
68 backend = plt.rcParams['backend']
69 if backend in matplotlib.rcsetup.interactive_bk:
69 if backend in matplotlib.rcsetup.interactive_bk:
70 figManager = matplotlib._pylab_helpers.Gcf.get_active()
70 figManager = matplotlib._pylab_helpers.Gcf.get_active()
71 if figManager is not None:
71 if figManager is not None:
72 canvas = figManager.canvas
72 canvas = figManager.canvas
73 if canvas.figure.stale:
73 if canvas.figure.stale:
74 canvas.draw()
74 canvas.draw()
75 try:
75 try:
76 canvas.start_event_loop(interval)
76 canvas.start_event_loop(interval)
77 except:
77 except:
78 pass
78 pass
79 return
79 return
80
80
81 def popup(message):
81 def popup(message):
82 '''
82 '''
83 '''
83 '''
84
84
85 fig = plt.figure(figsize=(12, 8), facecolor='r')
85 fig = plt.figure(figsize=(12, 8), facecolor='r')
86 text = '\n'.join([s.strip() for s in message.split(':')])
86 text = '\n'.join([s.strip() for s in message.split(':')])
87 fig.text(0.01, 0.5, text, ha='left', va='center',
87 fig.text(0.01, 0.5, text, ha='left', va='center',
88 size='20', weight='heavy', color='w')
88 size='20', weight='heavy', color='w')
89 fig.show()
89 fig.show()
90 figpause(1000)
90 figpause(1000)
91
91
92
92
93 class Throttle(object):
93 class Throttle(object):
94 '''
94 '''
95 Decorator that prevents a function from being called more than once every
95 Decorator that prevents a function from being called more than once every
96 time period.
96 time period.
97 To create a function that cannot be called more than once a minute, but
97 To create a function that cannot be called more than once a minute, but
98 will sleep until it can be called:
98 will sleep until it can be called:
99 @Throttle(minutes=1)
99 @Throttle(minutes=1)
100 def foo():
100 def foo():
101 pass
101 pass
102
102
103 for i in range(10):
103 for i in range(10):
104 foo()
104 foo()
105 print "This function has run %s times." % i
105 print "This function has run %s times." % i
106 '''
106 '''
107
107
108 def __init__(self, seconds=0, minutes=0, hours=0):
108 def __init__(self, seconds=0, minutes=0, hours=0):
109 self.throttle_period = datetime.timedelta(
109 self.throttle_period = datetime.timedelta(
110 seconds=seconds, minutes=minutes, hours=hours
110 seconds=seconds, minutes=minutes, hours=hours
111 )
111 )
112
112
113 self.time_of_last_call = datetime.datetime.min
113 self.time_of_last_call = datetime.datetime.min
114
114
115 def __call__(self, fn):
115 def __call__(self, fn):
116 @wraps(fn)
116 @wraps(fn)
117 def wrapper(*args, **kwargs):
117 def wrapper(*args, **kwargs):
118 coerce = kwargs.pop('coerce', None)
118 coerce = kwargs.pop('coerce', None)
119 if coerce:
119 if coerce:
120 self.time_of_last_call = datetime.datetime.now()
120 self.time_of_last_call = datetime.datetime.now()
121 return fn(*args, **kwargs)
121 return fn(*args, **kwargs)
122 else:
122 else:
123 now = datetime.datetime.now()
123 now = datetime.datetime.now()
124 time_since_last_call = now - self.time_of_last_call
124 time_since_last_call = now - self.time_of_last_call
125 time_left = self.throttle_period - time_since_last_call
125 time_left = self.throttle_period - time_since_last_call
126
126
127 if time_left > datetime.timedelta(seconds=0):
127 if time_left > datetime.timedelta(seconds=0):
128 return
128 return
129
129
130 self.time_of_last_call = datetime.datetime.now()
130 self.time_of_last_call = datetime.datetime.now()
131 return fn(*args, **kwargs)
131 return fn(*args, **kwargs)
132
132
133 return wrapper
133 return wrapper
134
134
135 def apply_throttle(value):
135 def apply_throttle(value):
136
136
137 @Throttle(seconds=value)
137 @Throttle(seconds=value)
138 def fnThrottled(fn):
138 def fnThrottled(fn):
139 fn()
139 fn()
140
140
141 return fnThrottled
141 return fnThrottled
142
142
143
143
144 @MPDecorator
144 @MPDecorator
145 class Plot(Operation):
145 class Plot(Operation):
146 """Base class for Schain plotting operations
146 """Base class for Schain plotting operations
147
147
148 This class should never be use directtly you must subclass a new operation,
148 This class should never be use directtly you must subclass a new operation,
149 children classes must be defined as follow:
149 children classes must be defined as follow:
150
150
151 ExamplePlot(Plot):
151 ExamplePlot(Plot):
152
152
153 CODE = 'code'
153 CODE = 'code'
154 colormap = 'jet'
154 colormap = 'jet'
155 plot_type = 'pcolor' # options are ('pcolor', 'pcolorbuffer', 'scatter', 'scatterbuffer')
155 plot_type = 'pcolor' # options are ('pcolor', 'pcolorbuffer', 'scatter', 'scatterbuffer')
156
156
157 def setup(self):
157 def setup(self):
158 pass
158 pass
159
159
160 def plot(self):
160 def plot(self):
161 pass
161 pass
162
162
163 """
163 """
164
164
165 CODE = 'Figure'
165 CODE = 'Figure'
166 colormap = 'jet'
166 colormap = 'jet'
167 bgcolor = 'white'
167 bgcolor = 'white'
168 buffering = True
168 buffering = True
169 __missing = 1E30
169 __missing = 1E30
170 projection = None
170 projection = None
171
171
172 __attrs__ = ['show', 'save', 'ymin', 'ymax', 'zmin', 'zmax', 'title',
172 __attrs__ = ['show', 'save', 'ymin', 'ymax', 'zmin', 'zmax', 'title',
173 'showprofile']
173 'showprofile']
174
174
175 def __init__(self):
175 def __init__(self):
176
176
177 Operation.__init__(self)
177 Operation.__init__(self)
178 self.isConfig = False
178 self.isConfig = False
179 self.isPlotConfig = False
179 self.isPlotConfig = False
180 self.save_time = 0
180 self.save_time = 0
181 self.sender_time = 0
181 self.sender_time = 0
182 self.data = None
182 self.data = None
183 self.firsttime = True
183 self.firsttime = True
184 self.sender_queue = deque(maxlen=10)
184 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}
185 self.plots_adjust = {'left': 0.125, 'right': 0.9, 'bottom': 0.15, 'top': 0.9, 'wspace': 0.2, 'hspace': 0.2}
186
186
187 def __fmtTime(self, x, pos):
187 def __fmtTime(self, x, pos):
188 '''
188 '''
189 '''
189 '''
190
190
191 return '{}'.format(self.getDateTime(x).strftime('%H:%M'))
191 return '{}'.format(self.getDateTime(x).strftime('%H:%M'))
192
192
193 def __setup(self, **kwargs):
193 def __setup(self, **kwargs):
194 '''
194 '''
195 Initialize variables
195 Initialize variables
196 '''
196 '''
197
197
198 self.figures = []
198 self.figures = []
199 self.axes = []
199 self.axes = []
200 self.cb_axes = []
200 self.cb_axes = []
201 self.localtime = kwargs.pop('localtime', True)
201 self.localtime = kwargs.pop('localtime', True)
202 self.show = kwargs.get('show', True)
202 self.show = kwargs.get('show', True)
203 self.save = kwargs.get('save', False)
203 self.save = kwargs.get('save', False)
204 self.save_period = kwargs.get('save_period', 0)
204 self.save_period = kwargs.get('save_period', 0)
205 self.colormap = kwargs.get('colormap', self.colormap)
205 self.colormap = kwargs.get('colormap', self.colormap)
206 self.colormap_coh = kwargs.get('colormap_coh', 'jet')
206 self.colormap_coh = kwargs.get('colormap_coh', 'jet')
207 self.colormap_phase = kwargs.get('colormap_phase', 'RdBu_r')
207 self.colormap_phase = kwargs.get('colormap_phase', 'RdBu_r')
208 self.colormaps = kwargs.get('colormaps', None)
208 self.colormaps = kwargs.get('colormaps', None)
209 self.bgcolor = kwargs.get('bgcolor', self.bgcolor)
209 self.bgcolor = kwargs.get('bgcolor', self.bgcolor)
210 self.showprofile = kwargs.get('showprofile', False)
210 self.showprofile = kwargs.get('showprofile', False)
211 self.title = kwargs.get('wintitle', self.CODE.upper())
211 self.title = kwargs.get('wintitle', self.CODE.upper())
212 self.cb_label = kwargs.get('cb_label', None)
212 self.cb_label = kwargs.get('cb_label', None)
213 self.cb_labels = kwargs.get('cb_labels', None)
213 self.cb_labels = kwargs.get('cb_labels', None)
214 self.labels = kwargs.get('labels', None)
214 self.labels = kwargs.get('labels', None)
215 self.xaxis = kwargs.get('xaxis', 'frequency')
215 self.xaxis = kwargs.get('xaxis', 'frequency')
216 self.zmin = kwargs.get('zmin', None)
216 self.zmin = kwargs.get('zmin', None)
217 self.zmax = kwargs.get('zmax', None)
217 self.zmax = kwargs.get('zmax', None)
218 self.zlimits = kwargs.get('zlimits', None)
218 self.zlimits = kwargs.get('zlimits', None)
219 self.xmin = kwargs.get('xmin', None)
219 self.xmin = kwargs.get('xmin', None)
220 self.xmax = kwargs.get('xmax', None)
220 self.xmax = kwargs.get('xmax', None)
221 self.xrange = kwargs.get('xrange', 12)
221 self.xrange = kwargs.get('xrange', 12)
222 self.xscale = kwargs.get('xscale', None)
222 self.xscale = kwargs.get('xscale', None)
223 self.ymin = kwargs.get('ymin', None)
223 self.ymin = kwargs.get('ymin', None)
224 self.ymax = kwargs.get('ymax', None)
224 self.ymax = kwargs.get('ymax', None)
225 self.yscale = kwargs.get('yscale', None)
225 self.yscale = kwargs.get('yscale', None)
226 self.xlabel = kwargs.get('xlabel', None)
226 self.xlabel = kwargs.get('xlabel', None)
227 self.attr_time = kwargs.get('attr_time', 'utctime')
227 self.attr_time = kwargs.get('attr_time', 'utctime')
228 self.attr_data = kwargs.get('attr_data', 'data_param')
228 self.attr_data = kwargs.get('attr_data', 'data_param')
229 self.decimation = kwargs.get('decimation', None)
229 self.decimation = kwargs.get('decimation', None)
230 self.oneFigure = kwargs.get('oneFigure', True)
230 self.oneFigure = kwargs.get('oneFigure', True)
231 self.width = kwargs.get('width', None)
231 self.width = kwargs.get('width', None)
232 self.height = kwargs.get('height', None)
232 self.height = kwargs.get('height', None)
233 self.colorbar = kwargs.get('colorbar', True)
233 self.colorbar = kwargs.get('colorbar', True)
234 self.factors = kwargs.get('factors', [1, 1, 1, 1, 1, 1, 1, 1])
234 self.factors = kwargs.get('factors', [1, 1, 1, 1, 1, 1, 1, 1])
235 self.channels = kwargs.get('channels', None)
235 self.channels = kwargs.get('channels', None)
236 self.titles = kwargs.get('titles', [])
236 self.titles = kwargs.get('titles', [])
237 self.polar = False
237 self.polar = False
238 self.type = kwargs.get('type', 'iq')
238 self.type = kwargs.get('type', 'iq')
239 self.grid = kwargs.get('grid', False)
239 self.grid = kwargs.get('grid', False)
240 self.pause = kwargs.get('pause', False)
240 self.pause = kwargs.get('pause', False)
241 self.save_code = kwargs.get('save_code', self.CODE)
241 self.save_code = kwargs.get('save_code', self.CODE)
242 self.throttle = kwargs.get('throttle', 0)
242 self.throttle = kwargs.get('throttle', 0)
243 self.exp_code = kwargs.get('exp_code', None)
243 self.exp_code = kwargs.get('exp_code', None)
244 self.server = kwargs.get('server', False)
244 self.server = kwargs.get('server', False)
245 self.sender_period = kwargs.get('sender_period', 60)
245 self.sender_period = kwargs.get('sender_period', 60)
246 self.tag = kwargs.get('tag', '')
246 self.tag = kwargs.get('tag', '')
247 self.height_index = kwargs.get('height_index', None)
247 self.height_index = kwargs.get('height_index', None)
248 self.__throttle_plot = apply_throttle(self.throttle)
248 self.__throttle_plot = apply_throttle(self.throttle)
249 code = self.attr_data if self.attr_data else self.CODE
249 code = self.attr_data if self.attr_data else self.CODE
250 self.data = PlotterData(self.CODE, self.exp_code, self.localtime)
250 self.data = PlotterData(self.CODE, self.exp_code, self.localtime)
251 self.ang_min = kwargs.get('ang_min', None)
251 self.ang_min = kwargs.get('ang_min', None)
252 self.ang_max = kwargs.get('ang_max', None)
252 self.ang_max = kwargs.get('ang_max', None)
253 self.mode = kwargs.get('mode', None)
253 self.mode = kwargs.get('mode', None)
254 self.mask = kwargs.get('mask', False)
254 self.mask = kwargs.get('mask', False)
255 self.shapes = kwargs.get('shapes', './')
255 self.shapes = kwargs.get('shapes', './')
256
256
257 if self.server:
257 if self.server:
258 if not self.server.startswith('tcp://'):
258 if not self.server.startswith('tcp://'):
259 self.server = 'tcp://{}'.format(self.server)
259 self.server = 'tcp://{}'.format(self.server)
260 log.success(
260 log.success(
261 'Sending to server: {}'.format(self.server),
261 'Sending to server: {}'.format(self.server),
262 self.name
262 self.name
263 )
263 )
264
264
265 if isinstance(self.attr_data, str):
265 if isinstance(self.attr_data, str):
266 self.attr_data = [self.attr_data]
266 self.attr_data = [self.attr_data]
267
267
268 def __setup_plot(self):
268 def __setup_plot(self):
269 '''
269 '''
270 Common setup for all figures, here figures and axes are created
270 Common setup for all figures, here figures and axes are created
271 '''
271 '''
272
272
273 self.setup()
273 self.setup()
274
274
275 self.time_label = 'LT' if self.localtime else 'UTC'
275 self.time_label = 'LT' if self.localtime else 'UTC'
276
276
277 if self.width is None:
277 if self.width is None:
278 self.width = 8
278 self.width = 8
279
279
280 self.figures = {'PPI':[], 'RHI':[]}
280 self.figures = {'PPI':[], 'RHI':[]}
281 self.axes = {'PPI':[], 'RHI':[]}
281 self.axes = {'PPI':[], 'RHI':[]}
282 self.cb_axes = []
282 self.cb_axes = []
283 self.pf_axes = []
283 self.pf_axes = []
284 self.cmaps = []
284 self.cmaps = []
285
285
286 size = '15%' if self.ncols == 1 else '30%'
286 size = '15%' if self.ncols == 1 else '30%'
287 pad = '4%' if self.ncols == 1 else '8%'
287 pad = '4%' if self.ncols == 1 else '8%'
288
288
289 if self.oneFigure:
289 if self.oneFigure:
290 if self.height is None:
290 if self.height is None:
291 self.height = 1.4 * self.nrows + 1
291 self.height = 1.4 * self.nrows + 1
292 fig_p = plt.figure(figsize=(self.width, self.height),
292 fig_p = plt.figure(figsize=(self.width, self.height),
293 edgecolor='k',
293 edgecolor='k',
294 facecolor='w')
294 facecolor='w')
295 fig_r = plt.figure(figsize=(self.width, 4),
295 fig_r = plt.figure(figsize=(self.width, 4),
296 edgecolor='k',
296 edgecolor='k',
297 facecolor='w')
297 facecolor='w')
298 self.figures['PPI'].append(fig_p)
298 self.figures['PPI'].append(fig_p)
299 self.figures['RHI'].append(fig_r)
299 self.figures['RHI'].append(fig_r)
300 for n in range(self.nplots):
300 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)
301 ax_p = fig_p.add_subplot(self.nrows, self.ncols, n+1, polar=self.polar, projection=self.projection)
302 ax_r = fig_r.add_subplot(self.nrows, self.ncols, n+1, polar=self.polar)
302 ax_r = fig_r.add_subplot(self.nrows, self.ncols, n+1, polar=self.polar)
303 ax_p.tick_params(labelsize=8)
303 ax_p.tick_params(labelsize=8)
304 ax_p.firsttime = True
304 ax_p.firsttime = True
305 ax_p.index = 0
305 ax_p.index = 0
306 ax_p.press = None
306 ax_p.press = None
307 ax_r.tick_params(labelsize=8)
307 ax_r.tick_params(labelsize=8)
308 ax_r.firsttime = True
308 ax_r.firsttime = True
309 ax_r.index = 0
309 ax_r.index = 0
310 ax_r.press = None
310 ax_r.press = None
311
311
312 self.axes['PPI'].append(ax_p)
312 self.axes['PPI'].append(ax_p)
313 self.axes['RHI'].append(ax_r)
313 self.axes['RHI'].append(ax_r)
314
314
315 if self.showprofile:
315 if self.showprofile:
316 cax = self.__add_axes(ax, size=size, pad=pad)
316 cax = self.__add_axes(ax, size=size, pad=pad)
317 cax.tick_params(labelsize=8)
317 cax.tick_params(labelsize=8)
318 self.pf_axes.append(cax)
318 self.pf_axes.append(cax)
319 else:
319 else:
320 if self.height is None:
320 if self.height is None:
321 self.height = 3
321 self.height = 3
322 for n in range(self.nplots):
322 for n in range(self.nplots):
323 fig = plt.figure(figsize=(self.width, self.height),
323 fig = plt.figure(figsize=(self.width, self.height),
324 edgecolor='k',
324 edgecolor='k',
325 facecolor='w')
325 facecolor='w')
326 ax_p = fig.add_subplot(1, 1, 1, polar=self.polar, projection=self.projection)
326 ax_p = fig.add_subplot(1, 1, 1, polar=self.polar, projection=self.projection)
327 ax_r = fig.add_subplot(1, 1, 1, polar=self.polar)
327 ax_r = fig.add_subplot(1, 1, 1, polar=self.polar)
328 ax_p.tick_params(labelsize=8)
328 ax_p.tick_params(labelsize=8)
329 ax_p.firsttime = True
329 ax_p.firsttime = True
330 ax_p.index = 0
330 ax_p.index = 0
331 ax_p.press = None
331 ax_p.press = None
332 ax_r.tick_params(labelsize=8)
332 ax_r.tick_params(labelsize=8)
333 ax_r.firsttime = True
333 ax_r.firsttime = True
334 ax_r.index = 0
334 ax_r.index = 0
335 ax_r.press = None
335 ax_r.press = None
336 self.figures.append(fig)
336 self.figures.append(fig)
337 self.axes['PPI'].append(ax_p)
337 self.axes['PPI'].append(ax_p)
338 self.axes['RHI'].append(ax_r)
338 self.axes['RHI'].append(ax_r)
339 if self.showprofile:
339 if self.showprofile:
340 cax = self.__add_axes(ax, size=size, pad=pad)
340 cax = self.__add_axes(ax, size=size, pad=pad)
341 cax.tick_params(labelsize=8)
341 cax.tick_params(labelsize=8)
342 self.pf_axes.append(cax)
342 self.pf_axes.append(cax)
343
343
344 # for n in range(self.nrows):
344 # for n in range(self.nrows):
345 # if self.colormaps is not None:
345 # if self.colormaps is not None:
346 # cmap = plt.get_cmap(self.colormaps[n])
346 # cmap = plt.get_cmap(self.colormaps[n])
347 # else:
347 # else:
348 # cmap = plt.get_cmap(self.colormap)
348 # cmap = plt.get_cmap(self.colormap)
349 # cmap.set_bad(self.bgcolor, 1.)
349 # cmap.set_bad(self.bgcolor, 1.)
350 # self.cmaps.append(cmap)
350 # self.cmaps.append(cmap)
351
351
352 def __add_axes(self, ax, size='30%', pad='8%'):
352 def __add_axes(self, ax, size='30%', pad='8%'):
353 '''
353 '''
354 Add new axes to the given figure
354 Add new axes to the given figure
355 '''
355 '''
356 divider = make_axes_locatable(ax)
356 divider = make_axes_locatable(ax)
357 nax = divider.new_horizontal(size=size, pad=pad)
357 nax = divider.new_horizontal(size=size, pad=pad)
358 ax.figure.add_axes(nax)
358 ax.figure.add_axes(nax)
359 return nax
359 return nax
360
360
361 def fill_gaps(self, x_buffer, y_buffer, z_buffer):
361 def fill_gaps(self, x_buffer, y_buffer, z_buffer):
362 '''
362 '''
363 Create a masked array for missing data
363 Create a masked array for missing data
364 '''
364 '''
365 if x_buffer.shape[0] < 2:
365 if x_buffer.shape[0] < 2:
366 return x_buffer, y_buffer, z_buffer
366 return x_buffer, y_buffer, z_buffer
367
367
368 deltas = x_buffer[1:] - x_buffer[0:-1]
368 deltas = x_buffer[1:] - x_buffer[0:-1]
369 x_median = numpy.median(deltas)
369 x_median = numpy.median(deltas)
370
370
371 index = numpy.where(deltas > 5 * x_median)
371 index = numpy.where(deltas > 5 * x_median)
372
372
373 if len(index[0]) != 0:
373 if len(index[0]) != 0:
374 z_buffer[::, index[0], ::] = self.__missing
374 z_buffer[::, index[0], ::] = self.__missing
375 z_buffer = numpy.ma.masked_inside(z_buffer,
375 z_buffer = numpy.ma.masked_inside(z_buffer,
376 0.99 * self.__missing,
376 0.99 * self.__missing,
377 1.01 * self.__missing)
377 1.01 * self.__missing)
378
378
379 return x_buffer, y_buffer, z_buffer
379 return x_buffer, y_buffer, z_buffer
380
380
381 def decimate(self):
381 def decimate(self):
382
382
383 # dx = int(len(self.x)/self.__MAXNUMX) + 1
383 # dx = int(len(self.x)/self.__MAXNUMX) + 1
384 dy = int(len(self.y) / self.decimation) + 1
384 dy = int(len(self.y) / self.decimation) + 1
385
385
386 # x = self.x[::dx]
386 # x = self.x[::dx]
387 x = self.x
387 x = self.x
388 y = self.y[::dy]
388 y = self.y[::dy]
389 z = self.z[::, ::, ::dy]
389 z = self.z[::, ::, ::dy]
390
390
391 return x, y, z
391 return x, y, z
392
392
393 def format(self):
393 def format(self):
394 '''
394 '''
395 Set min and max values, labels, ticks and titles
395 Set min and max values, labels, ticks and titles
396 '''
396 '''
397
397
398 for n, ax in enumerate(self.axes[self.mode]):
398 for n, ax in enumerate(self.axes[self.mode]):
399 if ax.firsttime:
399 if ax.firsttime:
400 if self.xaxis != 'time':
400 if self.xaxis != 'time':
401 xmin = self.xmin
401 xmin = self.xmin
402 xmax = self.xmax
402 xmax = self.xmax
403 else:
403 else:
404 xmin = self.tmin
404 xmin = self.tmin
405 xmax = self.tmin + self.xrange*60*60
405 xmax = self.tmin + self.xrange*60*60
406 ax.xaxis.set_major_formatter(FuncFormatter(self.__fmtTime))
406 ax.xaxis.set_major_formatter(FuncFormatter(self.__fmtTime))
407 ax.xaxis.set_major_locator(LinearLocator(9))
407 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)])
408 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)])
409 ymax = self.ymax if self.ymax is not None else numpy.nanmax(self.y[numpy.isfinite(self.y)])
410
410
411 ax.set_facecolor(self.bgcolor)
411 ax.set_facecolor(self.bgcolor)
412
412
413 if self.xscale:
413 if self.xscale:
414 ax.xaxis.set_major_formatter(FuncFormatter(
414 ax.xaxis.set_major_formatter(FuncFormatter(
415 lambda x, pos: '{0:g}'.format(x*self.xscale)))
415 lambda x, pos: '{0:g}'.format(x*self.xscale)))
416 if self.yscale:
416 if self.yscale:
417 ax.yaxis.set_major_formatter(FuncFormatter(
417 ax.yaxis.set_major_formatter(FuncFormatter(
418 lambda x, pos: '{0:g}'.format(x*self.yscale)))
418 lambda x, pos: '{0:g}'.format(x*self.yscale)))
419 if self.xlabel is not None:
419 if self.xlabel is not None:
420 ax.set_xlabel(self.xlabel)
420 ax.set_xlabel(self.xlabel)
421 if self.ylabel is not None:
421 if self.ylabel is not None:
422 ax.set_ylabel(self.ylabel)
422 ax.set_ylabel(self.ylabel)
423 if self.showprofile:
423 if self.showprofile:
424 self.pf_axes[n].set_ylim(ymin, ymax)
424 self.pf_axes[n].set_ylim(ymin, ymax)
425 self.pf_axes[n].set_xlim(self.zmin, self.zmax)
425 self.pf_axes[n].set_xlim(self.zmin, self.zmax)
426 self.pf_axes[n].set_xlabel('dB')
426 self.pf_axes[n].set_xlabel('dB')
427 self.pf_axes[n].grid(b=True, axis='x')
427 self.pf_axes[n].grid(b=True, axis='x')
428 [tick.set_visible(False)
428 [tick.set_visible(False)
429 for tick in self.pf_axes[n].get_yticklabels()]
429 for tick in self.pf_axes[n].get_yticklabels()]
430 if self.colorbar:
430 if self.colorbar:
431 ax.cbar = plt.colorbar(
431 ax.cbar = plt.colorbar(
432 ax.plt, ax=ax, fraction=0.05, pad=0.06, aspect=10)
432 ax.plt, ax=ax, fraction=0.05, pad=0.06, aspect=10)
433 if self.colormap=='sophy_r':
433 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])
434 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':
436 ax.cbar.set_ticks([-9, -6, -3, 0, 3, 6, 9, 12])
435 ax.cbar.ax.tick_params(labelsize=8)
437 ax.cbar.ax.tick_params(labelsize=8)
436 ax.cbar.ax.press = None
438 ax.cbar.ax.press = None
437 if self.cb_label:
439 if self.cb_label:
438 ax.cbar.set_label(self.cb_label, size=8)
440 ax.cbar.set_label(self.cb_label, size=8)
439 elif self.cb_labels:
441 elif self.cb_labels:
440 ax.cbar.set_label(self.cb_labels[n], size=8)
442 ax.cbar.set_label(self.cb_labels[n], size=8)
441 else:
443 else:
442 ax.cbar = None
444 ax.cbar = None
443 if self.mode == 'RHI':
445 if self.mode == 'RHI':
444 ax.set_xlim(xmin, xmax)
446 ax.set_xlim(xmin, xmax)
445 ax.set_ylim(ymin, ymax)
447 ax.set_ylim(ymin, ymax)
446 ax.firsttime = False
448 ax.firsttime = False
447 if self.grid:
449 if self.grid:
448 ax.grid(True)
450 ax.grid(True)
449 if not self.polar:
451 if not self.polar:
450 ax.set_title('{} {} {}'.format(
452 ax.set_title('{} {} {}'.format(
451 self.titles[n],
453 self.titles[n],
452 self.getDateTime(self.data.max_time).strftime(
454 self.getDateTime(self.data.max_time).strftime(
453 '%Y-%m-%d %H:%M:%S'),
455 '%Y-%m-%d %H:%M:%S'),
454 self.time_label),
456 self.time_label),
455 size=8)
457 size=8)
456 else:
458 else:
457 #ax.set_title('{}'.format(self.titles[n]), size=8)
459 #ax.set_title('{}'.format(self.titles[n]), size=8)
458 ax.set_title('{} {} {}'.format(
460 ax.set_title('{} {} {}'.format(
459 self.titles[n],
461 self.titles[n],
460 self.getDateTime(self.data.max_time).strftime(
462 self.getDateTime(self.data.max_time).strftime(
461 '%Y-%m-%d %H:%M:%S'),
463 '%Y-%m-%d %H:%M:%S'),
462 self.time_label),
464 self.time_label),
463 size=8)
465 size=8)
464 ax.set_ylim(0, self.ymax)
466 ax.set_ylim(0, self.ymax)
465 if self.mode == 'PPI':
467 if self.mode == 'PPI':
466 ax.set_yticks(ax.get_yticks(), labels=ax.get_yticks(), color='white')
468 ax.set_yticks(ax.get_yticks(), labels=ax.get_yticks(), color='white')
467 ax.yaxis.labelpad = 28
469 ax.yaxis.labelpad = 28
468 elif self.mode == 'RHI':
470 elif self.mode == 'RHI':
469 ax.xaxis.labelpad = 16
471 ax.xaxis.labelpad = 16
470
472
471 if self.firsttime:
473 if self.firsttime:
472 for fig in self.figures['PPI'] + self.figures['RHI']:
474 for fig in self.figures['PPI'] + self.figures['RHI']:
473 fig.subplots_adjust(**self.plots_adjust)
475 fig.subplots_adjust(**self.plots_adjust)
474 self.firsttime = False
476 self.firsttime = False
475
477
476 def clear_figures(self):
478 def clear_figures(self):
477 '''
479 '''
478 Reset axes for redraw plots
480 Reset axes for redraw plots
479 '''
481 '''
480
482
481 axes = self.pf_axes + self.cb_axes + self.axes[self.mode]
483 axes = self.pf_axes + self.cb_axes + self.axes[self.mode]
482
484
483 for ax in axes:
485 for ax in axes:
484 ax.clear()
486 ax.clear()
485 ax.firsttime = True
487 ax.firsttime = True
486 if hasattr(ax, 'cbar') and ax.cbar:
488 if hasattr(ax, 'cbar') and ax.cbar:
487 ax.cbar.remove()
489 ax.cbar.remove()
488
490
489 def __plot(self):
491 def __plot(self):
490 '''
492 '''
491 Main function to plot, format and save figures
493 Main function to plot, format and save figures
492 '''
494 '''
493
495
494 self.plot()
496 self.plot()
495 self.format()
497 self.format()
496 figures = self.figures[self.mode]
498 figures = self.figures[self.mode]
497 for n, fig in enumerate(figures):
499 for n, fig in enumerate(figures):
498 if self.nrows == 0 or self.nplots == 0:
500 if self.nrows == 0 or self.nplots == 0:
499 log.warning('No data', self.name)
501 log.warning('No data', self.name)
500 fig.text(0.5, 0.5, 'No Data', fontsize='large', ha='center')
502 fig.text(0.5, 0.5, 'No Data', fontsize='large', ha='center')
501 fig.canvas.manager.set_window_title(self.CODE)
503 fig.canvas.manager.set_window_title(self.CODE)
502 continue
504 continue
503
505
504 fig.canvas.manager.set_window_title('{} - {}'.format(self.title,
506 fig.canvas.manager.set_window_title('{} - {}'.format(self.title,
505 self.getDateTime(self.data.max_time).strftime('%Y/%m/%d')))
507 self.getDateTime(self.data.max_time).strftime('%Y/%m/%d')))
506 fig.canvas.draw()
508 fig.canvas.draw()
507 if self.show:
509 if self.show:
508 fig.show()
510 fig.show()
509 figpause(0.01)
511 figpause(0.01)
510
512
511 if self.save:
513 if self.save:
512 self.save_figure(n)
514 self.save_figure(n)
513
515
514 if self.server:
516 if self.server:
515 if self.mode and self.mode == 'RHI':
517 if self.mode and self.mode == 'RHI':
516 return
518 return
517 self.send_to_server()
519 self.send_to_server()
518
520
519 def __update(self, dataOut, timestamp):
521 def __update(self, dataOut, timestamp):
520 '''
522 '''
521 '''
523 '''
522
524
523 metadata = {
525 metadata = {
524 'yrange': dataOut.heightList,
526 'yrange': dataOut.heightList,
525 'interval': dataOut.timeInterval,
527 'interval': dataOut.timeInterval,
526 'channels': dataOut.channelList
528 'channels': dataOut.channelList
527 }
529 }
528
530
529 data, meta = self.update(dataOut)
531 data, meta = self.update(dataOut)
530 metadata.update(meta)
532 metadata.update(meta)
531 self.data.update(data, timestamp, metadata)
533 self.data.update(data, timestamp, metadata)
532
534
533 def save_figure(self, n):
535 def save_figure(self, n):
534 '''
536 '''
535 '''
537 '''
536 if self.mode is not None:
538 if self.mode is not None:
537 ang = 'AZ' if self.mode == 'RHI' else 'EL'
539 ang = 'AZ' if self.mode == 'RHI' else 'EL'
538 folder = '_{}_{}_{}'.format(self.mode, ang, self.mode_value)
540 folder = '_{}_{}_{}'.format(self.mode, ang, self.mode_value)
539 label = '{}{}_{}'.format(ang[0], self.mode_value, self.save_code)
541 label = '{}{}_{}'.format(ang[0], self.mode_value, self.save_code)
540 else:
542 else:
541 folder = ''
543 folder = ''
542 label = ''
544 label = ''
543
545
544 if self.oneFigure:
546 if self.oneFigure:
545 if (self.data.max_time - self.save_time) <= self.save_period:
547 if (self.data.max_time - self.save_time) <= self.save_period:
546 return
548 return
547
549
548 self.save_time = self.data.max_time
550 self.save_time = self.data.max_time
549
551
550 fig = self.figures[self.mode][n]
552 fig = self.figures[self.mode][n]
551
553
552 if self.throttle == 0:
554 if self.throttle == 0:
553 if self.oneFigure:
555 if self.oneFigure:
554 figname = os.path.join(
556 figname = os.path.join(
555 self.save,
557 self.save,
556 self.save_code + folder,
558 self.save_code + folder,
557 '{}_{}_{}.png'.format(
559 '{}_{}_{}.png'.format(
558 'SOPHY',
560 'SOPHY',
559 self.getDateTime(self.data.max_time).strftime(
561 self.getDateTime(self.data.max_time).strftime(
560 '%Y%m%d_%H%M%S'
562 '%Y%m%d_%H%M%S'
561 ),
563 ),
562 label
564 label
563 )
565 )
564 )
566 )
565 else:
567 else:
566 figname = os.path.join(
568 figname = os.path.join(
567 self.save,
569 self.save,
568 self.save_code,
570 self.save_code,
569 '{}_ch{}_{}.png'.format(
571 '{}_ch{}_{}.png'.format(
570 self.save_code, n,
572 self.save_code, n,
571 self.getDateTime(self.data.max_time).strftime(
573 self.getDateTime(self.data.max_time).strftime(
572 '%Y%m%d_%H%M%S'
574 '%Y%m%d_%H%M%S'
573 ),
575 ),
574 )
576 )
575 )
577 )
576 log.log('Saving figure: {}'.format(figname), self.name)
578 log.log('Saving figure: {}'.format(figname), self.name)
577 if not os.path.isdir(os.path.dirname(figname)):
579 if not os.path.isdir(os.path.dirname(figname)):
578 os.makedirs(os.path.dirname(figname))
580 os.makedirs(os.path.dirname(figname))
579 fig.savefig(figname)
581 fig.savefig(figname)
580
582
581 figname = os.path.join(
583 figname = os.path.join(
582 self.save,
584 self.save,
583 '{}_{}.png'.format(
585 '{}_{}.png'.format(
584 self.save_code,
586 self.save_code,
585 self.getDateTime(self.data.min_time).strftime(
587 self.getDateTime(self.data.min_time).strftime(
586 '%Y%m%d'
588 '%Y%m%d'
587 ),
589 ),
588 )
590 )
589 )
591 )
590
592
591 log.log('Saving figure: {}'.format(figname), self.name)
593 log.log('Saving figure: {}'.format(figname), self.name)
592 if not os.path.isdir(os.path.dirname(figname)):
594 if not os.path.isdir(os.path.dirname(figname)):
593 os.makedirs(os.path.dirname(figname))
595 os.makedirs(os.path.dirname(figname))
594 fig.savefig(figname)
596 fig.savefig(figname)
595
597
596 def send_to_server(self):
598 def send_to_server(self):
597 '''
599 '''
598 '''
600 '''
599
601
600 if self.exp_code == None:
602 if self.exp_code == None:
601 log.warning('Missing `exp_code` skipping sending to server...')
603 log.warning('Missing `exp_code` skipping sending to server...')
602
604
603 last_time = self.data.max_time
605 last_time = self.data.max_time
604 interval = last_time - self.sender_time
606 interval = last_time - self.sender_time
605 if interval < self.sender_period:
607 if interval < self.sender_period:
606 return
608 return
607
609
608 self.sender_time = last_time
610 self.sender_time = last_time
609
611
610 attrs = ['titles', 'zmin', 'zmax', 'tag', 'ymin', 'ymax']
612 attrs = ['titles', 'zmin', 'zmax', 'tag', 'ymin', 'ymax']
611 for attr in attrs:
613 for attr in attrs:
612 value = getattr(self, attr)
614 value = getattr(self, attr)
613 if value:
615 if value:
614 if isinstance(value, (numpy.float32, numpy.float64)):
616 if isinstance(value, (numpy.float32, numpy.float64)):
615 value = round(float(value), 2)
617 value = round(float(value), 2)
616 self.data.meta[attr] = value
618 self.data.meta[attr] = value
617 if self.colormap == 'jet' or self.colormap == 'sophy_w':
619 if self.colormap == 'jet' or self.colormap == 'sophy_w':
618 self.data.meta['colormap'] = 'Jet'
620 self.data.meta['colormap'] = 'Jet'
619 elif 'sophy_v' in self.colormap:
621 elif 'sophy_v' in self.colormap:
620 self.data.meta['colormap'] = 'RdBu'
622 self.data.meta['colormap'] = 'RdBu'
621 else:
623 else:
622 self.data.meta['colormap'] = 'Viridis'
624 self.data.meta['colormap'] = 'Viridis'
623 self.data.meta['interval'] = int(interval)
625 self.data.meta['interval'] = int(interval)
624
626
625 self.sender_queue.append(last_time)
627 self.sender_queue.append(last_time)
626
628
627 while True:
629 while True:
628 try:
630 try:
629 tm = self.sender_queue.popleft()
631 tm = self.sender_queue.popleft()
630 except IndexError:
632 except IndexError:
631 break
633 break
632 msg = self.data.jsonify(tm, self.save_code, self.plot_type, key='var')
634 msg = self.data.jsonify(tm, self.save_code, self.plot_type, key='var')
633 self.socket.send_string(msg)
635 self.socket.send_string(msg)
634 socks = dict(self.poll.poll(2000))
636 socks = dict(self.poll.poll(2000))
635 if socks.get(self.socket) == zmq.POLLIN:
637 if socks.get(self.socket) == zmq.POLLIN:
636 reply = self.socket.recv_string()
638 reply = self.socket.recv_string()
637 if reply == 'ok':
639 if reply == 'ok':
638 log.log("Response from server ok", self.name)
640 log.log("Response from server ok", self.name)
639 time.sleep(0.1)
641 time.sleep(0.1)
640 continue
642 continue
641 else:
643 else:
642 log.warning(
644 log.warning(
643 "Malformed reply from server: {}".format(reply), self.name)
645 "Malformed reply from server: {}".format(reply), self.name)
644 else:
646 else:
645 log.warning(
647 log.warning(
646 "No response from server, retrying...", self.name)
648 "No response from server, retrying...", self.name)
647 self.sender_queue.appendleft(tm)
649 self.sender_queue.appendleft(tm)
648 self.socket.setsockopt(zmq.LINGER, 0)
650 self.socket.setsockopt(zmq.LINGER, 0)
649 self.socket.close()
651 self.socket.close()
650 self.poll.unregister(self.socket)
652 self.poll.unregister(self.socket)
651 self.socket = self.context.socket(zmq.REQ)
653 self.socket = self.context.socket(zmq.REQ)
652 self.socket.connect(self.server)
654 self.socket.connect(self.server)
653 self.poll.register(self.socket, zmq.POLLIN)
655 self.poll.register(self.socket, zmq.POLLIN)
654 break
656 break
655
657
656 def setup(self):
658 def setup(self):
657 '''
659 '''
658 This method should be implemented in the child class, the following
660 This method should be implemented in the child class, the following
659 attributes should be set:
661 attributes should be set:
660
662
661 self.nrows: number of rows
663 self.nrows: number of rows
662 self.ncols: number of cols
664 self.ncols: number of cols
663 self.nplots: number of plots (channels or pairs)
665 self.nplots: number of plots (channels or pairs)
664 self.ylabel: label for Y axes
666 self.ylabel: label for Y axes
665 self.titles: list of axes title
667 self.titles: list of axes title
666
668
667 '''
669 '''
668 raise NotImplementedError
670 raise NotImplementedError
669
671
670 def plot(self):
672 def plot(self):
671 '''
673 '''
672 Must be defined in the child class, the actual plotting method
674 Must be defined in the child class, the actual plotting method
673 '''
675 '''
674 raise NotImplementedError
676 raise NotImplementedError
675
677
676 def update(self, dataOut):
678 def update(self, dataOut):
677 '''
679 '''
678 Must be defined in the child class, update self.data with new data
680 Must be defined in the child class, update self.data with new data
679 '''
681 '''
680
682
681 data = {
683 data = {
682 self.CODE: getattr(dataOut, 'data_{}'.format(self.CODE))
684 self.CODE: getattr(dataOut, 'data_{}'.format(self.CODE))
683 }
685 }
684 meta = {}
686 meta = {}
685
687
686 return data, meta
688 return data, meta
687
689
688 def run(self, dataOut, **kwargs):
690 def run(self, dataOut, **kwargs):
689 '''
691 '''
690 Main plotting routine
692 Main plotting routine
691 '''
693 '''
692
694
693 if self.isConfig is False:
695 if self.isConfig is False:
694 self.__setup(**kwargs)
696 self.__setup(**kwargs)
695
697
696 if self.localtime:
698 if self.localtime:
697 self.getDateTime = datetime.datetime.fromtimestamp
699 self.getDateTime = datetime.datetime.fromtimestamp
698 else:
700 else:
699 self.getDateTime = datetime.datetime.utcfromtimestamp
701 self.getDateTime = datetime.datetime.utcfromtimestamp
700
702
701 self.data.setup()
703 self.data.setup()
702 self.isConfig = True
704 self.isConfig = True
703 if self.server:
705 if self.server:
704 self.context = zmq.Context()
706 self.context = zmq.Context()
705 self.socket = self.context.socket(zmq.REQ)
707 self.socket = self.context.socket(zmq.REQ)
706 self.socket.connect(self.server)
708 self.socket.connect(self.server)
707 self.poll = zmq.Poller()
709 self.poll = zmq.Poller()
708 self.poll.register(self.socket, zmq.POLLIN)
710 self.poll.register(self.socket, zmq.POLLIN)
709
711
710 tm = getattr(dataOut, self.attr_time)
712 tm = getattr(dataOut, self.attr_time)
711
713
712 if self.data and 'time' in self.xaxis and (tm - self.tmin) >= self.xrange*60*60:
714 if self.data and 'time' in self.xaxis and (tm - self.tmin) >= self.xrange*60*60:
713 self.save_time = tm
715 self.save_time = tm
714 self.__plot()
716 self.__plot()
715 self.tmin += self.xrange*60*60
717 self.tmin += self.xrange*60*60
716 self.data.setup()
718 self.data.setup()
717 self.clear_figures()
719 self.clear_figures()
718
720
719 self.__update(dataOut, tm)
721 self.__update(dataOut, tm)
720
722
721 if self.isPlotConfig is False:
723 if self.isPlotConfig is False:
722 self.__setup_plot()
724 self.__setup_plot()
723 self.isPlotConfig = True
725 self.isPlotConfig = True
724 if self.xaxis == 'time':
726 if self.xaxis == 'time':
725 dt = self.getDateTime(tm)
727 dt = self.getDateTime(tm)
726 if self.xmin is None:
728 if self.xmin is None:
727 self.tmin = tm
729 self.tmin = tm
728 self.xmin = dt.hour
730 self.xmin = dt.hour
729 minutes = (self.xmin-int(self.xmin)) * 60
731 minutes = (self.xmin-int(self.xmin)) * 60
730 seconds = (minutes - int(minutes)) * 60
732 seconds = (minutes - int(minutes)) * 60
731 self.tmin = (dt.replace(hour=int(self.xmin), minute=int(minutes), second=int(seconds)) -
733 self.tmin = (dt.replace(hour=int(self.xmin), minute=int(minutes), second=int(seconds)) -
732 datetime.datetime(1970, 1, 1)).total_seconds()
734 datetime.datetime(1970, 1, 1)).total_seconds()
733 if self.localtime:
735 if self.localtime:
734 self.tmin += time.timezone
736 self.tmin += time.timezone
735
737
736 if self.xmin is not None and self.xmax is not None:
738 if self.xmin is not None and self.xmax is not None:
737 self.xrange = self.xmax - self.xmin
739 self.xrange = self.xmax - self.xmin
738
740
739 if self.throttle == 0:
741 if self.throttle == 0:
740 self.__plot()
742 self.__plot()
741 else:
743 else:
742 self.__throttle_plot(self.__plot)#, coerce=coerce)
744 self.__throttle_plot(self.__plot)#, coerce=coerce)
743
745
744 def close(self):
746 def close(self):
745
747
746 if self.data and not self.data.flagNoData:
748 if self.data and not self.data.flagNoData:
747 self.save_time = 0
749 self.save_time = 0
748 self.__plot()
750 self.__plot()
749 if self.data and not self.data.flagNoData and self.pause:
751 if self.data and not self.data.flagNoData and self.pause:
750 figpause(10)
752 figpause(10)
@@ -1,113 +1,113
1 '''
1 '''
2 @author: roj-idl71
2 @author: roj-idl71
3 '''
3 '''
4
4
5 import matplotlib
5 import matplotlib
6
6
7 #USED IN jroplot_spectra.py
7 #USED IN jroplot_spectra.py
8 RTI_CODE = 0 #Range time intensity (RTI).
8 RTI_CODE = 0 #Range time intensity (RTI).
9 SPEC_CODE = 1 #Spectra (and Cross-spectra) information.
9 SPEC_CODE = 1 #Spectra (and Cross-spectra) information.
10 CROSS_CODE = 2 #Cross-Correlation information.
10 CROSS_CODE = 2 #Cross-Correlation information.
11 COH_CODE = 3 #Coherence map.
11 COH_CODE = 3 #Coherence map.
12 BASE_CODE = 4 #Base lines graphic.
12 BASE_CODE = 4 #Base lines graphic.
13 ROW_CODE = 5 #Row Spectra.
13 ROW_CODE = 5 #Row Spectra.
14 TOTAL_CODE = 6 #Total Power.
14 TOTAL_CODE = 6 #Total Power.
15 DRIFT_CODE = 7 #Drifts graphics.
15 DRIFT_CODE = 7 #Drifts graphics.
16 HEIGHT_CODE = 8 #Height profile.
16 HEIGHT_CODE = 8 #Height profile.
17 PHASE_CODE = 9 #Signal Phase.
17 PHASE_CODE = 9 #Signal Phase.
18
18
19 POWER_CODE = 16
19 POWER_CODE = 16
20 NOISE_CODE = 17
20 NOISE_CODE = 17
21 BEACON_CODE = 18
21 BEACON_CODE = 18
22
22
23 #USED IN jroplot_parameters.py
23 #USED IN jroplot_parameters.py
24 WIND_CODE = 22
24 WIND_CODE = 22
25 MSKYMAP_CODE = 23
25 MSKYMAP_CODE = 23
26 MPHASE_CODE = 24
26 MPHASE_CODE = 24
27
27
28 MOMENTS_CODE = 25
28 MOMENTS_CODE = 25
29 PARMS_CODE = 26
29 PARMS_CODE = 26
30 SPECFIT_CODE = 27
30 SPECFIT_CODE = 27
31 EWDRIFT_CODE = 28
31 EWDRIFT_CODE = 28
32
32
33
33
34 #COLOR TABLES
34 #COLOR TABLES
35
35
36 refl = [
36 refl = [
37 "#2a323b", "#3f4c59", "#556576", "#6a7f94", "#7f99b2",
37 "#2a323b", "#3f4c59", "#556576", "#6a7f94", "#7f99b2",
38 "#00ffff", "#007fff", "#0000ff", "#00ff00", "#00bf00",
38 "#00ffff", "#007fff", "#0000ff", "#00ff00", "#00bf00",
39 "#007f00", "#ffff00", "#ffbf00", "#ff7f00", "#ff0000",
39 "#007f00", "#ffff00", "#ffbf00", "#ff7f00", "#ff0000",
40 "#bf0000", "#7f0000", "#fe00fe", "#8e59ff", "#f0f0f0",
40 "#bf0000", "#7f0000", "#fe00fe", "#8e59ff", "#f0f0f0",
41 ]
41 ]
42
42
43 refl_bounds = [-20, -15, -10, -5, 0, 5, 10 ,15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80]
43 #refl_bounds = [-25, -20, -15, -10, -5, 0, 5, 10 ,15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80]
44
44
45 doppler = [
45 doppler = [
46 "#003300", "#005500", "#007700", "#009900", "#00bb00", "#24ce24", "#6cd26c", "#b4d6b4",
46 "#003300", "#005500", "#007700", "#009900", "#00bb00", "#24ce24", "#6cd26c", "#b4d6b4",
47 "#d6b4b4", "#d26c6c", "#ce2424", "#bb0000", "#980000", "#760000", "#540000", "#330000",
47 "#d6b4b4", "#d26c6c", "#ce2424", "#bb0000", "#980000", "#760000", "#540000", "#330000",
48 ]
48 ]
49
49
50 width = [
50 width = [
51 "#00ffff", "#00aaf2", "#0055e5", "#0000d8",
51 "#00ffff", "#00aaf2", "#0055e5", "#0000d8",
52 "#007f00", "#00aa00", "#00d400", "#00ff00",
52 "#007f00", "#00aa00", "#00d400", "#00ff00",
53 "#ffff00", "#ffd400", "#ffaa00", "#ff7f00",
53 "#ffff00", "#ffd400", "#ffaa00", "#ff7f00",
54 "#ff0000", "#d40000", "#aa0000", "#7f0000",
54 "#ff0000", "#d40000", "#aa0000", "#7f0000",
55 "#ff00ff", "#d400d4", "#aa00aa", "#7f007f",
55 "#ff00ff", "#d400d4", "#aa00aa", "#7f007f",
56 "#9938ff", "#832ed8", "#6e25b2", "#591c8c",
56 "#9938ff", "#832ed8", "#6e25b2", "#591c8c",
57 ]
57 ]
58
58
59 zdr = [
59 zdr = [
60 "#7333cc", "#7e3cd5", "#8945de", "#944ee7", "#9f57f0", "#aa5ff8",
60 "#7333cc", "#7e3cd5", "#8945de", "#944ee7", "#9f57f0", "#aa5ff8",
61 "#82345c", "#984272", "#ae4f88", "#c55c9f", "#db6ab5", "#db6ab5",
61 "#82345c", "#984272", "#ae4f88", "#c55c9f", "#db6ab5", "#f177cb",
62 "#b5842d", "#c29a4c", "#d0b16b", "#ddc78a", "#ebddaa", "#f8f4c9",
62 "#b5842d", "#c29a4c", "#d0b16b", "#ddc78a", "#ebddaa", "#f8f4c9",
63 "#f0f5ff", "#c4d8ff", "#97bbff", "#6a9eff", "#3e81ff", "#1164ff",
63 "#f0f5ff", "#c4d8ff", "#97bbff", "#6a9eff", "#3e81ff", "#1164ff",
64 "#17f576", "#13df60", "#0ec949", "#0ab233", "#059c1d", "#018606",
64 "#17f576", "#13df60", "#0ec949", "#0ab233", "#059c1d", "#018606",
65 "#fff300", "#ffdd00", "#ffc700", "#ffb000", "#ff9a00", "#ff8400",
65 "#fff300", "#ffdd00", "#ffc700", "#ffb000", "#ff9a00", "#ff8400",
66 "#f10000", "#db0000", "#c40000", "#ae0000", "#980000", "#810000",
66 "#f10000", "#db0000", "#c40000", "#ae0000", "#980000", "#810000",
67 ]
67 ]
68
68
69 phi = [
69 phi = [
70 "#ff3f40", "#ec3b6d", "#bf2f7e", "#92247c", "#7b1f7f", "#732492", "#782fbf", "#6f3bec",
70 "#ff3f40", "#ec3b6d", "#bf2f7e", "#92247c", "#7b1f7f", "#732492", "#782fbf", "#6f3bec",
71 "#513fff", "#3b4bec", "#2f57bf", "#245592", "#1f5a7f", "#247992", "#2fb4bf", "#3bece0",
71 "#513fff", "#3b4bec", "#2f57bf", "#245592", "#1f5a7f", "#247992", "#2fb4bf", "#3bece0",
72 "#3fffd8", "#3becb1", "#2fbf7d", "#249253", "#1f7f3d", "#24923b", "#2fbf3e", "#3bec3b",
72 "#3fffd8", "#3becb1", "#2fbf7d", "#249253", "#1f7f3d", "#24923b", "#2fbf3e", "#3bec3b",
73 "#50ff3f", "#5aec3b", "#55bf2f", "#4a9224", "#487f1f", "#5a9224", "#80bf2f", "#aaec3b",
73 "#50ff3f", "#5aec3b", "#55bf2f", "#4a9224", "#487f1f", "#5a9224", "#80bf2f", "#aaec3b",
74 "#c4ff3f", "#c0ec3b", "#a4bf2f", "#839224", "#777f1f", "#8e9224", "#bfbc2f", "#ece03b",
74 "#c4ff3f", "#c0ec3b", "#a4bf2f", "#839224", "#777f1f", "#8e9224", "#bfbc2f", "#ece03b",
75 "#ffea3f", "#ecd13b", "#bfa42f", "#927924", "#7f661f", "#927124", "#bf8f2f", "#ecac3b",
75 "#ffea3f", "#ecd13b", "#bfa42f", "#927924", "#7f661f", "#927124", "#bf8f2f", "#ecac3b",
76 "#ffb43f", "#eca23b", "#bf7f2f", "#925e24", "#7f501f", "#925924", "#bf712f", "#ec883b",
76 "#ffb43f", "#eca23b", "#bf7f2f", "#925e24", "#7f501f", "#925924", "#bf712f", "#ec883b",
77 "#ff8f3f", "#ec813b", "#bf662f", "#924c24", "#7f401f", "#924824", "#bf5c2f", "#ec6f3b",
77 "#ff8f3f", "#ec813b", "#bf662f", "#924c24", "#7f401f", "#924824", "#bf5c2f", "#ec6f3b",
78 ]
78 ]
79
79
80 rho = [
80 rho = [
81 "#2a323b", "#3f4c59", "#556576", "#6a7f94", "#7f99b2",
81 "#2a323b", "#3f4c59", "#556576", "#6a7f94", "#7f99b2",
82 "#00ffff", "#00bff5", "#007feb", "#003fe2", "#0000d8",
82 "#00ffff", "#00bff5", "#007feb", "#003fe2", "#0000d8",
83 "#00ff00", "#00df00", "#00bf00", "#009f00", "#007f00",
83 "#00ff00", "#00df00", "#00bf00", "#009f00", "#007f00",
84 "#ffff00", "#ffdf00", "#ffbf00", "#ff9f00", "#ff7f00",
84 "#ffff00", "#ffdf00", "#ffbf00", "#ff9f00", "#ff7f00",
85 "#ff0000", "#df0000", "#bf0000", "#9f0000", "#7f0000",
85 "#ff0000", "#df0000", "#bf0000", "#9f0000", "#7f0000",
86 "#ff00ff", "#df00df", "#bf00bf", "#9f009f", "#7f007f",
86 "#ff00ff", "#df00df", "#bf00bf", "#9f009f", "#7f007f",
87 "#9938ff", "#8931e2", "#792ac5", "#6923a8", "#591c8c",
87 "#9938ff", "#8931e2", "#792ac5", "#6923a8", "#591c8c",
88 ]
88 ]
89
89
90 rho_bounds = [0.2, 0.306, 0.412, 0.518, 0.624, 0.73,
90 rho_bounds = [0.2, 0.306, 0.412, 0.518, 0.624, 0.73,
91 0.75, 0.77, 0.79, 0.81, 0.83,
91 0.75, 0.77, 0.79, 0.81, 0.83,
92 0.85, 0.87, 0.89, 0.91, 0.93,
92 0.85, 0.87, 0.89, 0.91, 0.93,
93 0.936, 0.942, 0.948, 0.954, 0.96,
93 0.936, 0.942, 0.948, 0.954, 0.96,
94 0.966, 0.972, 0.978, 0.984, 0.99,
94 0.966, 0.972, 0.978, 0.984, 0.99,
95 0.996, 1.002, 1.008, 1.014, 1.02,
95 0.996, 1.002, 1.008, 1.014, 1.02,
96 1.026, 1.032, 1.038, 1.044, 1.05, 1.056]
96 1.026, 1.032, 1.038, 1.044, 1.05, 1.056]
97
97
98 cb_tables = {
98 cb_tables = {
99 'sophy_z': {'colors': refl, 'norm': None },
99 'sophy_z': {'colors': refl, 'norm': None },
100 'sophy_v': {'colors': doppler, 'norm': None },
100 'sophy_v': {'colors': doppler, 'norm': None },
101 'sophy_w': {'colors': width, 'norm': None },
101 'sophy_w': {'colors': width, 'norm': None },
102 'sophy_d': {'colors': zdr, 'norm': None },
102 'sophy_d': {'colors': zdr, 'norm': None},
103 'sophy_p': {'colors': phi, 'norm': None },
103 'sophy_p': {'colors': phi, 'norm': None },
104 'sophy_r': {'colors': rho, 'norm': matplotlib.colors.BoundaryNorm(rho_bounds, 37), 'extremes': ['#15191d', '#333899']},
104 'sophy_r': {'colors': rho, 'norm': matplotlib.colors.BoundaryNorm(rho_bounds, 37), 'extremes': ['#15191d', '#333899']},
105 }
105 }
106
106
107 def register_cmap():
107 def register_cmap():
108
108
109 for colormap in cb_tables:
109 for colormap in cb_tables:
110 cmap = matplotlib.colors.ListedColormap(cb_tables[colormap]['colors'], name=colormap)
110 cmap = matplotlib.colors.ListedColormap(cb_tables[colormap]['colors'], name=colormap)
111 if 'extremes' in cb_tables[colormap]:
111 if 'extremes' in cb_tables[colormap]:
112 cmap = cmap.with_extremes(under=cb_tables[colormap]['extremes'][0], over=cb_tables[colormap]['extremes'][1])
112 cmap = cmap.with_extremes(under=cb_tables[colormap]['extremes'][0], over=cb_tables[colormap]['extremes'][1])
113 matplotlib.pyplot.register_cmap(cmap=cmap)
113 matplotlib.pyplot.register_cmap(cmap=cmap)
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
General Comments 0
You need to be logged in to leave comments. Login now