##// END OF EJS Templates
desplazamiento del logo al margen superior derecho de la figura
sebastianVP -
r1779:443eddb2c904
parent child
Show More
@@ -1,783 +1,789
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 import matplotlib.cbook as cbook
35 import matplotlib.cbook as cbook
36 import matplotlib.image as image
36 import matplotlib.image as image
37
37
38 import cartopy.crs as ccrs
38 import cartopy.crs as ccrs
39
39
40 from .plotting_codes import register_cmap
40 from .plotting_codes import register_cmap
41
41
42 from schainpy.model.data.jrodata import PlotterData
42 from schainpy.model.data.jrodata import PlotterData
43 from schainpy.model.proc.jroproc_base import ProcessingUnit, Operation, MPDecorator
43 from schainpy.model.proc.jroproc_base import ProcessingUnit, Operation, MPDecorator
44 from schainpy.utils import log
44 from schainpy.utils import log
45
45
46
46
47 path = os.getcwd()
47 path = os.getcwd()
48 global file_logo
48 global file_logo
49 file_logo =os.path.join(path,"LogoIGP.png")
49 file_logo =os.path.join(path,"LogoIGP.png")
50
50
51 EARTH_RADIUS = 6.3710e3
51 EARTH_RADIUS = 6.3710e3
52
52
53 register_cmap()
53 register_cmap()
54
54
55 def ll2xy(lat1, lon1, lat2, lon2):
55 def ll2xy(lat1, lon1, lat2, lon2):
56
56
57 p = 0.017453292519943295
57 p = 0.017453292519943295
58 a = 0.5 - numpy.cos((lat2 - lat1) * p)/2 + numpy.cos(lat1 * p) * \
58 a = 0.5 - numpy.cos((lat2 - lat1) * p)/2 + numpy.cos(lat1 * p) * \
59 numpy.cos(lat2 * p) * (1 - numpy.cos((lon2 - lon1) * p)) / 2
59 numpy.cos(lat2 * p) * (1 - numpy.cos((lon2 - lon1) * p)) / 2
60 r = 12742 * numpy.arcsin(numpy.sqrt(a))
60 r = 12742 * numpy.arcsin(numpy.sqrt(a))
61 theta = numpy.arctan2(numpy.sin((lon2-lon1)*p)*numpy.cos(lat2*p), numpy.cos(lat1*p)
61 theta = numpy.arctan2(numpy.sin((lon2-lon1)*p)*numpy.cos(lat2*p), numpy.cos(lat1*p)
62 * numpy.sin(lat2*p)-numpy.sin(lat1*p)*numpy.cos(lat2*p)*numpy.cos((lon2-lon1)*p))
62 * numpy.sin(lat2*p)-numpy.sin(lat1*p)*numpy.cos(lat2*p)*numpy.cos((lon2-lon1)*p))
63 theta = -theta + numpy.pi/2
63 theta = -theta + numpy.pi/2
64 return r*numpy.cos(theta), r*numpy.sin(theta)
64 return r*numpy.cos(theta), r*numpy.sin(theta)
65
65
66
66
67 def km2deg(km):
67 def km2deg(km):
68 '''
68 '''
69 Convert distance in km to degrees
69 Convert distance in km to degrees
70 '''
70 '''
71
71
72 return numpy.rad2deg(km/EARTH_RADIUS)
72 return numpy.rad2deg(km/EARTH_RADIUS)
73
73
74
74
75 def figpause(interval):
75 def figpause(interval):
76 backend = plt.rcParams['backend']
76 backend = plt.rcParams['backend']
77 if backend in matplotlib.rcsetup.interactive_bk:
77 if backend in matplotlib.rcsetup.interactive_bk:
78 figManager = matplotlib._pylab_helpers.Gcf.get_active()
78 figManager = matplotlib._pylab_helpers.Gcf.get_active()
79 if figManager is not None:
79 if figManager is not None:
80 canvas = figManager.canvas
80 canvas = figManager.canvas
81 if canvas.figure.stale:
81 if canvas.figure.stale:
82 canvas.draw()
82 canvas.draw()
83 try:
83 try:
84 canvas.start_event_loop(interval)
84 canvas.start_event_loop(interval)
85 except:
85 except:
86 pass
86 pass
87 return
87 return
88
88
89 def popup(message):
89 def popup(message):
90 '''
90 '''
91 '''
91 '''
92
92
93 fig = plt.figure(figsize=(12, 8), facecolor='r')
93 fig = plt.figure(figsize=(12, 8), facecolor='r')
94 text = '\n'.join([s.strip() for s in message.split(':')])
94 text = '\n'.join([s.strip() for s in message.split(':')])
95 fig.text(0.01, 0.5, text, ha='left', va='center',
95 fig.text(0.01, 0.5, text, ha='left', va='center',
96 size='20', weight='heavy', color='w')
96 size='20', weight='heavy', color='w')
97 fig.show()
97 fig.show()
98 figpause(1000)
98 figpause(1000)
99
99
100
100
101 class Throttle(object):
101 class Throttle(object):
102 '''
102 '''
103 Decorator that prevents a function from being called more than once every
103 Decorator that prevents a function from being called more than once every
104 time period.
104 time period.
105 To create a function that cannot be called more than once a minute, but
105 To create a function that cannot be called more than once a minute, but
106 will sleep until it can be called:
106 will sleep until it can be called:
107 @Throttle(minutes=1)
107 @Throttle(minutes=1)
108 def foo():
108 def foo():
109 pass
109 pass
110
110
111 for i in range(10):
111 for i in range(10):
112 foo()
112 foo()
113 print "This function has run %s times." % i
113 print "This function has run %s times." % i
114 '''
114 '''
115
115
116 def __init__(self, seconds=0, minutes=0, hours=0):
116 def __init__(self, seconds=0, minutes=0, hours=0):
117 self.throttle_period = datetime.timedelta(
117 self.throttle_period = datetime.timedelta(
118 seconds=seconds, minutes=minutes, hours=hours
118 seconds=seconds, minutes=minutes, hours=hours
119 )
119 )
120
120
121 self.time_of_last_call = datetime.datetime.min
121 self.time_of_last_call = datetime.datetime.min
122
122
123 def __call__(self, fn):
123 def __call__(self, fn):
124 @wraps(fn)
124 @wraps(fn)
125 def wrapper(*args, **kwargs):
125 def wrapper(*args, **kwargs):
126 coerce = kwargs.pop('coerce', None)
126 coerce = kwargs.pop('coerce', None)
127 if coerce:
127 if coerce:
128 self.time_of_last_call = datetime.datetime.now()
128 self.time_of_last_call = datetime.datetime.now()
129 return fn(*args, **kwargs)
129 return fn(*args, **kwargs)
130 else:
130 else:
131 now = datetime.datetime.now()
131 now = datetime.datetime.now()
132 time_since_last_call = now - self.time_of_last_call
132 time_since_last_call = now - self.time_of_last_call
133 time_left = self.throttle_period - time_since_last_call
133 time_left = self.throttle_period - time_since_last_call
134
134
135 if time_left > datetime.timedelta(seconds=0):
135 if time_left > datetime.timedelta(seconds=0):
136 return
136 return
137
137
138 self.time_of_last_call = datetime.datetime.now()
138 self.time_of_last_call = datetime.datetime.now()
139 return fn(*args, **kwargs)
139 return fn(*args, **kwargs)
140
140
141 return wrapper
141 return wrapper
142
142
143 def apply_throttle(value):
143 def apply_throttle(value):
144
144
145 @Throttle(seconds=value)
145 @Throttle(seconds=value)
146 def fnThrottled(fn):
146 def fnThrottled(fn):
147 fn()
147 fn()
148
148
149 return fnThrottled
149 return fnThrottled
150
150
151
151
152 @MPDecorator
152 @MPDecorator
153 class Plot(Operation):
153 class Plot(Operation):
154 """Base class for Schain plotting operations
154 """Base class for Schain plotting operations
155
155
156 This class should never be use directtly you must subclass a new operation,
156 This class should never be use directtly you must subclass a new operation,
157 children classes must be defined as follow:
157 children classes must be defined as follow:
158
158
159 ExamplePlot(Plot):
159 ExamplePlot(Plot):
160
160
161 CODE = 'code'
161 CODE = 'code'
162 colormap = 'jet'
162 colormap = 'jet'
163 plot_type = 'pcolor' # options are ('pcolor', 'pcolorbuffer', 'scatter', 'scatterbuffer')
163 plot_type = 'pcolor' # options are ('pcolor', 'pcolorbuffer', 'scatter', 'scatterbuffer')
164
164
165 def setup(self):
165 def setup(self):
166 pass
166 pass
167
167
168 def plot(self):
168 def plot(self):
169 pass
169 pass
170
170
171 """
171 """
172
172
173 CODE = 'Figure'
173 CODE = 'Figure'
174 colormap = 'jet'
174 colormap = 'jet'
175 bgcolor = 'white'
175 bgcolor = 'white'
176 buffering = True
176 buffering = True
177 __missing = 1E30
177 __missing = 1E30
178 projection = None
178 projection = None
179
179
180 __attrs__ = ['show', 'save', 'ymin', 'ymax', 'zmin', 'zmax', 'title',
180 __attrs__ = ['show', 'save', 'ymin', 'ymax', 'zmin', 'zmax', 'title',
181 'showprofile']
181 'showprofile']
182
182
183 def __init__(self):
183 def __init__(self):
184
184
185 Operation.__init__(self)
185 Operation.__init__(self)
186 self.isConfig = False
186 self.isConfig = False
187 self.isPlotConfig = False
187 self.isPlotConfig = False
188 self.save_time = 0
188 self.save_time = 0
189 self.sender_time = 0
189 self.sender_time = 0
190 self.data = None
190 self.data = None
191 self.firsttime = True
191 self.firsttime = True
192 self.sender_queue = deque(maxlen=10)
192 self.sender_queue = deque(maxlen=10)
193 self.plots_adjust = {'left': 0.125, 'right': 0.9, 'bottom': 0.15, 'top': 0.9, 'wspace': 0.2, 'hspace': 0.2}
193 self.plots_adjust = {'left': 0.125, 'right': 0.9, 'bottom': 0.15, 'top': 0.9, 'wspace': 0.2, 'hspace': 0.2}
194
194
195 def __fmtTime(self, x, pos):
195 def __fmtTime(self, x, pos):
196 '''
196 '''
197 '''
197 '''
198
198
199 return '{}'.format(self.getDateTime(x).strftime('%H:%M'))
199 return '{}'.format(self.getDateTime(x).strftime('%H:%M'))
200
200
201 def __setup(self, **kwargs):
201 def __setup(self, **kwargs):
202 '''
202 '''
203 Initialize variables
203 Initialize variables
204 '''
204 '''
205
205
206 self.figures = []
206 self.figures = []
207 self.axes = []
207 self.axes = []
208 self.cb_axes = []
208 self.cb_axes = []
209 self.localtime = kwargs.pop('localtime', True)
209 self.localtime = kwargs.pop('localtime', True)
210 self.show = kwargs.get('show', True)
210 self.show = kwargs.get('show', True)
211 self.save = kwargs.get('save', False)
211 self.save = kwargs.get('save', False)
212 self.save_period = kwargs.get('save_period', 0)
212 self.save_period = kwargs.get('save_period', 0)
213 self.colormap = kwargs.get('colormap', self.colormap)
213 self.colormap = kwargs.get('colormap', self.colormap)
214 self.colormap_coh = kwargs.get('colormap_coh', 'jet')
214 self.colormap_coh = kwargs.get('colormap_coh', 'jet')
215 self.colormap_phase = kwargs.get('colormap_phase', 'RdBu_r')
215 self.colormap_phase = kwargs.get('colormap_phase', 'RdBu_r')
216 self.colormaps = kwargs.get('colormaps', None)
216 self.colormaps = kwargs.get('colormaps', None)
217 self.bgcolor = kwargs.get('bgcolor', self.bgcolor)
217 self.bgcolor = kwargs.get('bgcolor', self.bgcolor)
218 self.showprofile = kwargs.get('showprofile', False)
218 self.showprofile = kwargs.get('showprofile', False)
219 self.title = kwargs.get('wintitle', self.CODE.upper())
219 self.title = kwargs.get('wintitle', self.CODE.upper())
220 self.cb_label = kwargs.get('cb_label', None)
220 self.cb_label = kwargs.get('cb_label', None)
221 self.cb_labels = kwargs.get('cb_labels', None)
221 self.cb_labels = kwargs.get('cb_labels', None)
222 self.labels = kwargs.get('labels', None)
222 self.labels = kwargs.get('labels', None)
223 self.xaxis = kwargs.get('xaxis', 'frequency')
223 self.xaxis = kwargs.get('xaxis', 'frequency')
224 self.zmin = kwargs.get('zmin', None)
224 self.zmin = kwargs.get('zmin', None)
225 self.zmax = kwargs.get('zmax', None)
225 self.zmax = kwargs.get('zmax', None)
226 self.zlimits = kwargs.get('zlimits', None)
226 self.zlimits = kwargs.get('zlimits', None)
227 self.xmin = kwargs.get('xmin', None)
227 self.xmin = kwargs.get('xmin', None)
228 self.xmax = kwargs.get('xmax', None)
228 self.xmax = kwargs.get('xmax', None)
229 self.yrange = kwargs.get('yrange', None)
229 self.yrange = kwargs.get('yrange', None)
230 self.xrange = kwargs.get('xrange', None)
230 self.xrange = kwargs.get('xrange', None)
231 self.xscale = kwargs.get('xscale', None)
231 self.xscale = kwargs.get('xscale', None)
232 self.ymin = kwargs.get('ymin', None)
232 self.ymin = kwargs.get('ymin', None)
233 self.ymax = kwargs.get('ymax', None)
233 self.ymax = kwargs.get('ymax', None)
234 self.yscale = kwargs.get('yscale', None)
234 self.yscale = kwargs.get('yscale', None)
235 self.xlabel = kwargs.get('xlabel', None)
235 self.xlabel = kwargs.get('xlabel', None)
236 self.attr_time = kwargs.get('attr_time', 'utctime')
236 self.attr_time = kwargs.get('attr_time', 'utctime')
237 self.attr_data = kwargs.get('attr_data', 'data_param')
237 self.attr_data = kwargs.get('attr_data', 'data_param')
238 self.decimation = kwargs.get('decimation', None)
238 self.decimation = kwargs.get('decimation', None)
239 self.oneFigure = kwargs.get('oneFigure', True)
239 self.oneFigure = kwargs.get('oneFigure', True)
240 self.width = kwargs.get('width', None)
240 self.width = kwargs.get('width', None)
241 self.height = kwargs.get('height', None)
241 self.height = kwargs.get('height', None)
242 self.colorbar = kwargs.get('colorbar', True)
242 self.colorbar = kwargs.get('colorbar', True)
243 self.factors = kwargs.get('factors', [1, 1, 1, 1, 1, 1, 1, 1])
243 self.factors = kwargs.get('factors', [1, 1, 1, 1, 1, 1, 1, 1])
244 self.channels = kwargs.get('channels', None)
244 self.channels = kwargs.get('channels', None)
245 self.titles = kwargs.get('titles', [])
245 self.titles = kwargs.get('titles', [])
246 self.polar = False
246 self.polar = False
247 self.type = kwargs.get('type', 'iq')
247 self.type = kwargs.get('type', 'iq')
248 self.grid = kwargs.get('grid', False)
248 self.grid = kwargs.get('grid', False)
249 self.pause = kwargs.get('pause', False)
249 self.pause = kwargs.get('pause', False)
250 self.save_code = kwargs.get('save_code', self.CODE)
250 self.save_code = kwargs.get('save_code', self.CODE)
251 self.throttle = kwargs.get('throttle', 0)
251 self.throttle = kwargs.get('throttle', 0)
252 self.exp_code = kwargs.get('exp_code', None)
252 self.exp_code = kwargs.get('exp_code', None)
253 self.server = kwargs.get('server', False)
253 self.server = kwargs.get('server', False)
254 self.sender_period = kwargs.get('sender_period', 60)
254 self.sender_period = kwargs.get('sender_period', 60)
255 self.tag = kwargs.get('tag', '')
255 self.tag = kwargs.get('tag', '')
256 self.height_index = kwargs.get('height_index', None)
256 self.height_index = kwargs.get('height_index', None)
257 self.__throttle_plot = apply_throttle(self.throttle)
257 self.__throttle_plot = apply_throttle(self.throttle)
258 code = self.attr_data if self.attr_data else self.CODE
258 code = self.attr_data if self.attr_data else self.CODE
259 self.data = PlotterData(self.CODE, self.exp_code, self.localtime)
259 self.data = PlotterData(self.CODE, self.exp_code, self.localtime)
260 self.ang_min = kwargs.get('ang_min', None)
260 self.ang_min = kwargs.get('ang_min', None)
261 self.ang_max = kwargs.get('ang_max', None)
261 self.ang_max = kwargs.get('ang_max', None)
262 self.mode = kwargs.get('mode', None)
262 self.mode = kwargs.get('mode', None)
263 self.mask = kwargs.get('mask', False)
263 self.mask = kwargs.get('mask', False)
264 self.shapes = kwargs.get('shapes', './')
264 self.shapes = kwargs.get('shapes', './')
265 self.map = kwargs.get('map', False)
265 self.map = kwargs.get('map', False)
266 self.latitude = kwargs.get('latitude', -12)
266 self.latitude = kwargs.get('latitude', -12)
267 self.longitude = kwargs.get('longitude', -74)
267 self.longitude = kwargs.get('longitude', -74)
268
268
269 if self.server:
269 if self.server:
270 if not self.server.startswith('tcp://'):
270 if not self.server.startswith('tcp://'):
271 self.server = 'tcp://{}'.format(self.server)
271 self.server = 'tcp://{}'.format(self.server)
272 log.success(
272 log.success(
273 'Sending to server: {}'.format(self.server),
273 'Sending to server: {}'.format(self.server),
274 self.name
274 self.name
275 )
275 )
276
276
277 if isinstance(self.attr_data, str):
277 if isinstance(self.attr_data, str):
278 self.attr_data = [self.attr_data]
278 self.attr_data = [self.attr_data]
279
279
280
280
281 def __setup_plot(self):
281 def __setup_plot(self):
282 '''
282 '''
283 Common setup for all figures, here figures and axes are created
283 Common setup for all figures, here figures and axes are created
284 '''
284 '''
285
285
286 self.setup()
286 self.setup()
287
287
288 self.time_label = 'LT' if self.localtime else 'UTC'
288 self.time_label = 'LT' if self.localtime else 'UTC'
289
289
290 if self.width is None:
290 if self.width is None:
291 self.width = 8
291 self.width = 8
292
292
293 self.figures = {'PPI':[], 'RHI':[]}
293 self.figures = {'PPI':[], 'RHI':[]}
294 self.axes = {'PPI':[], 'RHI':[]}
294 self.axes = {'PPI':[], 'RHI':[]}
295 self.cb_axes = []
295 self.cb_axes = []
296 self.pf_axes = []
296 self.pf_axes = []
297 self.cmaps = []
297 self.cmaps = []
298
298
299 size = '15%' if self.ncols == 1 else '30%'
299 size = '15%' if self.ncols == 1 else '30%'
300 pad = '4%' if self.ncols == 1 else '8%'
300 pad = '4%' if self.ncols == 1 else '8%'
301
301
302 if self.oneFigure:
302 if self.oneFigure:
303 if self.height is None:
303 if self.height is None:
304 self.height = 1.4 * self.nrows + 1
304 self.height = 1.4 * self.nrows + 1
305 fig_p = plt.figure(figsize=(self.width, self.height),
305 fig_p = plt.figure(figsize=(self.width, self.height),
306 edgecolor='k',
306 edgecolor='k',
307 facecolor='w')
307 facecolor='w')
308 fig_r = plt.figure(figsize=(self.width, 4),
308 fig_r = plt.figure(figsize=(self.width, 4),
309 edgecolor='k',
309 edgecolor='k',
310 facecolor='w')
310 facecolor='w')
311 self.figures['PPI'].append(fig_p)
311 self.figures['PPI'].append(fig_p)
312 self.figures['RHI'].append(fig_r)
312 self.figures['RHI'].append(fig_r)
313 for n in range(self.nplots):
313 for n in range(self.nplots):
314 if self.map:
314 if self.map:
315 ax_p = fig_p.add_subplot(self.nrows, self.ncols, n+1, polar=self.polar, projection=ccrs.PlateCarree())
315 ax_p = fig_p.add_subplot(self.nrows, self.ncols, n+1, polar=self.polar, projection=ccrs.PlateCarree())
316 else:
316 else:
317 ax_p = fig_p.add_subplot(self.nrows, self.ncols, n+1, polar=self.polar)
317 ax_p = fig_p.add_subplot(self.nrows, self.ncols, n+1, polar=self.polar)
318 print('sin projection')
318 print('sin projection')
319 ax_r = fig_r.add_subplot(self.nrows, self.ncols, n+1, polar=self.polar)
319 ax_r = fig_r.add_subplot(self.nrows, self.ncols, n+1, polar=self.polar)
320 ax_p.tick_params(labelsize=8)
320 ax_p.tick_params(labelsize=8)
321 ax_p.firsttime = True
321 ax_p.firsttime = True
322 ax_p.index = 0
322 ax_p.index = 0
323 ax_p.press = None
323 ax_p.press = None
324 ax_r.tick_params(labelsize=8)
324 ax_r.tick_params(labelsize=8)
325 ax_r.firsttime = True
325 ax_r.firsttime = True
326 ax_r.index = 0
326 ax_r.index = 0
327 ax_r.press = None
327 ax_r.press = None
328
328
329 self.axes['PPI'].append(ax_p)
329 self.axes['PPI'].append(ax_p)
330 self.axes['RHI'].append(ax_r)
330 self.axes['RHI'].append(ax_r)
331
331
332 if self.showprofile:
332 if self.showprofile:
333 cax = self.__add_axes(ax, size=size, pad=pad)
333 cax = self.__add_axes(ax, size=size, pad=pad)
334 cax.tick_params(labelsize=8)
334 cax.tick_params(labelsize=8)
335 self.pf_axes.append(cax)
335 self.pf_axes.append(cax)
336 else:
336 else:
337 if self.height is None:
337 if self.height is None:
338 self.height = 3
338 self.height = 3
339 for n in range(self.nplots):
339 for n in range(self.nplots):
340 fig = plt.figure(figsize=(self.width, self.height),
340 fig = plt.figure(figsize=(self.width, self.height),
341 edgecolor='k',
341 edgecolor='k',
342 facecolor='w')
342 facecolor='w')
343 if self.map:
343 if self.map:
344 ax_p = fig.add_subplot(1, 1, 1, polar=self.polar, projection=ccrs.PlateCarree())
344 ax_p = fig.add_subplot(1, 1, 1, polar=self.polar, projection=ccrs.PlateCarree())
345 else:
345 else:
346 ax_p = fig.add_subplot(1, 1, 1, polar=self.polar)
346 ax_p = fig.add_subplot(1, 1, 1, polar=self.polar)
347 print('sin projection')
347 print('sin projection')
348
348
349 ax_r = fig.add_subplot(1, 1, 1, polar=self.polar)
349 ax_r = fig.add_subplot(1, 1, 1, polar=self.polar)
350 ax_p.tick_params(labelsize=8)
350 ax_p.tick_params(labelsize=8)
351 ax_p.firsttime = True
351 ax_p.firsttime = True
352 ax_p.index = 0
352 ax_p.index = 0
353 ax_p.press = None
353 ax_p.press = None
354 ax_r.tick_params(labelsize=8)
354 ax_r.tick_params(labelsize=8)
355 ax_r.firsttime = True
355 ax_r.firsttime = True
356 ax_r.index = 0
356 ax_r.index = 0
357 ax_r.press = None
357 ax_r.press = None
358 self.figures.append(fig)
358 self.figures.append(fig)
359 self.axes['PPI'].append(ax_p)
359 self.axes['PPI'].append(ax_p)
360 self.axes['RHI'].append(ax_r)
360 self.axes['RHI'].append(ax_r)
361 if self.showprofile:
361 if self.showprofile:
362 cax = self.__add_axes(ax, size=size, pad=pad)
362 cax = self.__add_axes(ax, size=size, pad=pad)
363 cax.tick_params(labelsize=8)
363 cax.tick_params(labelsize=8)
364 self.pf_axes.append(cax)
364 self.pf_axes.append(cax)
365
365
366 # for n in range(self.nrows):
366 # for n in range(self.nrows):
367 # if self.colormaps is not None:
367 # if self.colormaps is not None:
368 # cmap = plt.get_cmap(self.colormaps[n])
368 # cmap = plt.get_cmap(self.colormaps[n])
369 # else:
369 # else:
370 # cmap = plt.get_cmap(self.colormap)
370 # cmap = plt.get_cmap(self.colormap)
371 # cmap.set_bad(self.bgcolor, 1.)
371 # cmap.set_bad(self.bgcolor, 1.)
372 # self.cmaps.append(cmap)
372 # self.cmaps.append(cmap)
373
373
374 def __add_axes(self, ax, size='30%', pad='8%'):
374 def __add_axes(self, ax, size='30%', pad='8%'):
375 '''
375 '''
376 Add new axes to the given figure
376 Add new axes to the given figure
377 '''
377 '''
378 divider = make_axes_locatable(ax)
378 divider = make_axes_locatable(ax)
379 nax = divider.new_horizontal(size=size, pad=pad)
379 nax = divider.new_horizontal(size=size, pad=pad)
380 ax.figure.add_axes(nax)
380 ax.figure.add_axes(nax)
381 return nax
381 return nax
382
382
383 def fill_gaps(self, x_buffer, y_buffer, z_buffer):
383 def fill_gaps(self, x_buffer, y_buffer, z_buffer):
384 '''
384 '''
385 Create a masked array for missing data
385 Create a masked array for missing data
386 '''
386 '''
387 if x_buffer.shape[0] < 2:
387 if x_buffer.shape[0] < 2:
388 return x_buffer, y_buffer, z_buffer
388 return x_buffer, y_buffer, z_buffer
389
389
390 deltas = x_buffer[1:] - x_buffer[0:-1]
390 deltas = x_buffer[1:] - x_buffer[0:-1]
391 x_median = numpy.median(deltas)
391 x_median = numpy.median(deltas)
392
392
393 index = numpy.where(deltas > 5 * x_median)
393 index = numpy.where(deltas > 5 * x_median)
394
394
395 if len(index[0]) != 0:
395 if len(index[0]) != 0:
396 z_buffer[::, index[0], ::] = self.__missing
396 z_buffer[::, index[0], ::] = self.__missing
397 z_buffer = numpy.ma.masked_inside(z_buffer,
397 z_buffer = numpy.ma.masked_inside(z_buffer,
398 0.99 * self.__missing,
398 0.99 * self.__missing,
399 1.01 * self.__missing)
399 1.01 * self.__missing)
400
400
401 return x_buffer, y_buffer, z_buffer
401 return x_buffer, y_buffer, z_buffer
402
402
403 def decimate(self):
403 def decimate(self):
404
404
405 # dx = int(len(self.x)/self.__MAXNUMX) + 1
405 # dx = int(len(self.x)/self.__MAXNUMX) + 1
406 dy = int(len(self.y) / self.decimation) + 1
406 dy = int(len(self.y) / self.decimation) + 1
407
407
408 # x = self.x[::dx]
408 # x = self.x[::dx]
409 x = self.x
409 x = self.x
410 y = self.y[::dy]
410 y = self.y[::dy]
411 z = self.z[::, ::, ::dy]
411 z = self.z[::, ::, ::dy]
412
412
413 return x, y, z
413 return x, y, z
414
414
415 def format(self):
415 def format(self):
416 '''
416 '''
417 Set min and max values, labels, ticks and titles
417 Set min and max values, labels, ticks and titles
418 '''
418 '''
419
419
420 for n, ax in enumerate(self.axes[self.mode]):
420 for n, ax in enumerate(self.axes[self.mode]):
421 if ax.firsttime:
421 if ax.firsttime:
422 if self.xaxis != 'time':
422 if self.xaxis != 'time':
423 xmin = self.xmin
423 xmin = self.xmin
424 xmax = self.xmax
424 xmax = self.xmax
425 else:
425 else:
426 xmin = self.tmin
426 xmin = self.tmin
427 xmax = self.tmin + self.xrange*60*60
427 xmax = self.tmin + self.xrange*60*60
428 ax.xaxis.set_major_formatter(FuncFormatter(self.__fmtTime))
428 ax.xaxis.set_major_formatter(FuncFormatter(self.__fmtTime))
429 ax.xaxis.set_major_locator(LinearLocator(9))
429 ax.xaxis.set_major_locator(LinearLocator(9))
430 ymin = self.ymin if self.ymin is not None else numpy.nanmin(self.y[numpy.isfinite(self.y)])
430 ymin = self.ymin if self.ymin is not None else numpy.nanmin(self.y[numpy.isfinite(self.y)])
431 ymax = self.ymax if self.ymax is not None else numpy.nanmax(self.y[numpy.isfinite(self.y)])
431 ymax = self.ymax if self.ymax is not None else numpy.nanmax(self.y[numpy.isfinite(self.y)])
432
432
433 ax.set_facecolor(self.bgcolor)
433 ax.set_facecolor(self.bgcolor)
434
434
435 if self.xscale:
435 if self.xscale:
436 ax.xaxis.set_major_formatter(FuncFormatter(
436 ax.xaxis.set_major_formatter(FuncFormatter(
437 lambda x, pos: '{0:g}'.format(x*self.xscale)))
437 lambda x, pos: '{0:g}'.format(x*self.xscale)))
438 if self.yscale:
438 if self.yscale:
439 ax.yaxis.set_major_formatter(FuncFormatter(
439 ax.yaxis.set_major_formatter(FuncFormatter(
440 lambda x, pos: '{0:g}'.format(x*self.yscale)))
440 lambda x, pos: '{0:g}'.format(x*self.yscale)))
441 if self.xlabel is not None:
441 if self.xlabel is not None:
442 ax.set_xlabel(self.xlabel)
442 ax.set_xlabel(self.xlabel)
443 if self.ylabel is not None:
443 if self.ylabel is not None:
444 ax.set_ylabel(self.ylabel)
444 ax.set_ylabel(self.ylabel)
445 if self.showprofile:
445 if self.showprofile:
446 self.pf_axes[n].set_ylim(ymin, ymax)
446 self.pf_axes[n].set_ylim(ymin, ymax)
447 self.pf_axes[n].set_xlim(self.zmin, self.zmax)
447 self.pf_axes[n].set_xlim(self.zmin, self.zmax)
448 self.pf_axes[n].set_xlabel('dB')
448 self.pf_axes[n].set_xlabel('dB')
449 self.pf_axes[n].grid(b=True, axis='x')
449 self.pf_axes[n].grid(b=True, axis='x')
450 [tick.set_visible(False)
450 [tick.set_visible(False)
451 for tick in self.pf_axes[n].get_yticklabels()]
451 for tick in self.pf_axes[n].get_yticklabels()]
452 if self.colorbar:
452 if self.colorbar:
453 ax.cbar = plt.colorbar(
453 ax.cbar = plt.colorbar(
454 ax.plt, ax=ax, fraction=0.05, pad=0.06, aspect=10)
454 ax.plt, ax=ax, fraction=0.05, pad=0.06, aspect=10)
455 if self.colormap=='sophy_r':
455 if self.colormap=='sophy_r':
456 ax.cbar.set_ticks([0.2, 0.73, 0.83, 0.93, 0.96, 0.99, 1.02, 1.05])
456 ax.cbar.set_ticks([0.2, 0.73, 0.83, 0.93, 0.96, 0.99, 1.02, 1.05])
457 elif self.colormap=='sophy_d':
457 elif self.colormap=='sophy_d':
458 ax.cbar.set_ticks([-9, -6, -3, 0, 3, 6, 9, 12])
458 ax.cbar.set_ticks([-9, -6, -3, 0, 3, 6, 9, 12])
459 ax.cbar.ax.tick_params(labelsize=8)
459 ax.cbar.ax.tick_params(labelsize=8)
460 ax.cbar.ax.press = None
460 ax.cbar.ax.press = None
461 if self.cb_label:
461 if self.cb_label:
462 ax.cbar.set_label(self.cb_label, size=8)
462 ax.cbar.set_label(self.cb_label, size=8)
463 elif self.cb_labels:
463 elif self.cb_labels:
464 ax.cbar.set_label(self.cb_labels[n], size=8)
464 ax.cbar.set_label(self.cb_labels[n], size=8)
465 else:
465 else:
466 ax.cbar = None
466 ax.cbar = None
467 #if self.mode == 'RHI':
467 #if self.mode == 'RHI':
468 ax.set_xlim(xmin, xmax)
468 ax.set_xlim(xmin, xmax)
469 ax.set_ylim(ymin, ymax)
469 ax.set_ylim(ymin, ymax)
470
470
471 ax.firsttime = False
471 ax.firsttime = False
472 if self.grid:
472 if self.grid:
473 ax.grid(True)
473 ax.grid(True)
474 if not self.polar:
474 if not self.polar:
475 ax.set_title('{} \n{} {} ({} LT)'.format(
475 ax.set_title('{} \n{} {} ({} LT)'.format(
476 self.titles[n],
476 self.titles[n],
477 self.getDateTime(self.data.max_time).strftime(
477 self.getDateTime(self.data.max_time).strftime(
478 '%Y-%m-%d %H:%M:%S'),
478 '%Y-%m-%d %H:%M:%S'),
479 self.time_label,
479 self.time_label,
480 (self.getDateTime(self.data.max_time)-datetime.timedelta(hours=5)).strftime(
480 (self.getDateTime(self.data.max_time)-datetime.timedelta(hours=5)).strftime(
481 '%Y-%m-%d %H:%M:%S')),
481 '%Y-%m-%d %H:%M:%S')),
482 size=8)
482 size=8)
483 else:
483 else:
484 ax.set_title('{} \n{} {} ({} LT)'.format(
484 ax.set_title('{} \n{} {} ({} LT)'.format(
485 self.titles[n],
485 self.titles[n],
486 self.getDateTime(self.data.max_time).strftime(
486 self.getDateTime(self.data.max_time).strftime(
487 '%Y-%m-%d %H:%M:%S'),
487 '%Y-%m-%d %H:%M:%S'),
488 self.time_label,
488 self.time_label,
489 (self.getDateTime(self.data.max_time)-datetime.timedelta(hours=5)).strftime(
489 (self.getDateTime(self.data.max_time)-datetime.timedelta(hours=5)).strftime(
490 '%Y-%m-%d %H:%M:%S')),
490 '%Y-%m-%d %H:%M:%S')),
491 size=8)
491 size=8)
492 if self.mode == 'PPI':
492 if self.mode == 'PPI':
493 ax.set_yticks(ax.get_yticks(), labels=ax.get_yticks(), color='white')
493 ax.set_yticks(ax.get_yticks(), labels=ax.get_yticks(), color='white')
494 ax.yaxis.labelpad = 28
494 ax.yaxis.labelpad = 28
495 elif self.mode == 'RHI':
495 elif self.mode == 'RHI':
496 ax.xaxis.labelpad = 16
496 ax.xaxis.labelpad = 16
497
497
498 if self.firsttime:
498 if self.firsttime:
499 for fig in self.figures['PPI'] + self.figures['RHI']:
499 for fig in self.figures['PPI'] + self.figures['RHI']:
500 fig.subplots_adjust(**self.plots_adjust)
500 fig.subplots_adjust(**self.plots_adjust)
501 self.firsttime = False
501 self.firsttime = False
502
502
503 def clear_figures(self):
503 def clear_figures(self):
504 '''
504 '''
505 Reset axes for redraw plots
505 Reset axes for redraw plots
506 '''
506 '''
507
507
508 axes = self.pf_axes + self.cb_axes + self.axes[self.mode]
508 axes = self.pf_axes + self.cb_axes + self.axes[self.mode]
509
509
510 for ax in axes:
510 for ax in axes:
511 ax.clear()
511 ax.clear()
512 ax.firsttime = True
512 ax.firsttime = True
513 if hasattr(ax, 'cbar') and ax.cbar:
513 if hasattr(ax, 'cbar') and ax.cbar:
514 ax.cbar.remove()
514 ax.cbar.remove()
515
515
516 def __plot(self):
516 def __plot(self):
517 '''
517 '''
518 Main function to plot, format and save figures
518 Main function to plot, format and save figures
519 '''
519 '''
520
520
521 self.plot()
521 self.plot()
522 self.format()
522 self.format()
523 figures = self.figures[self.mode]
523 figures = self.figures[self.mode]
524 for n, fig in enumerate(figures):
524 for n, fig in enumerate(figures):
525 if self.nrows == 0 or self.nplots == 0:
525 if self.nrows == 0 or self.nplots == 0:
526 log.warning('No data', self.name)
526 log.warning('No data', self.name)
527 fig.text(0.5, 0.5, 'No Data', fontsize='large', ha='center')
527 fig.text(0.5, 0.5, 'No Data', fontsize='large', ha='center')
528 fig.canvas.manager.set_window_title(self.CODE)
528 fig.canvas.manager.set_window_title(self.CODE)
529 continue
529 continue
530
530
531 fig.canvas.manager.set_window_title('{} - {}'.format(self.title,
531 fig.canvas.manager.set_window_title('{} - {}'.format(self.title,
532 self.getDateTime(self.data.max_time).strftime('%Y/%m/%d')))
532 self.getDateTime(self.data.max_time).strftime('%Y/%m/%d')))
533 fig.canvas.draw()
533 fig.canvas.draw()
534 if self.show:
534 if self.show:
535 fig.show()
535 fig.show()
536 figpause(0.01)
536 figpause(0.01)
537
537
538 if self.save:
538 if self.save:
539 self.save_figure(n)
539 self.save_figure(n)
540
540
541 if self.server:
541 if self.server:
542 if self.mode and self.mode == 'RHI':
542 if self.mode and self.mode == 'RHI':
543 return
543 return
544 self.send_to_server()
544 self.send_to_server()
545
545
546 def __update(self, dataOut, timestamp):
546 def __update(self, dataOut, timestamp):
547 '''
547 '''
548 '''
548 '''
549
549
550 metadata = {
550 metadata = {
551 'yrange': dataOut.heightList,
551 'yrange': dataOut.heightList,
552 'interval': dataOut.timeInterval,
552 'interval': dataOut.timeInterval,
553 'channels': dataOut.channelList
553 'channels': dataOut.channelList
554 }
554 }
555
555
556 data, meta = self.update(dataOut)
556 data, meta = self.update(dataOut)
557 metadata.update(meta)
557 metadata.update(meta)
558 self.data.update(data, timestamp, metadata)
558 self.data.update(data, timestamp, metadata)
559
559
560 def save_figure(self, n):
560 def save_figure(self, n):
561 '''
561 '''
562 '''
562 '''
563 if self.mode is not None:
563 if self.mode is not None:
564 ang = 'AZ' if self.mode == 'RHI' else 'EL'
564 ang = 'AZ' if self.mode == 'RHI' else 'EL'
565 folder = '_{}_{}_{}'.format(self.mode, ang, self.mode_value)
565 folder = '_{}_{}_{}'.format(self.mode, ang, self.mode_value)
566 label = '{}{}_{}'.format(ang[0], self.mode_value, self.save_code)
566 label = '{}{}_{}'.format(ang[0], self.mode_value, self.save_code)
567 else:
567 else:
568 folder = ''
568 folder = ''
569 label = ''
569 label = ''
570
570
571 if self.oneFigure:
571 if self.oneFigure:
572 if (self.data.max_time - self.save_time) <= self.save_period:
572 if (self.data.max_time - self.save_time) <= self.save_period:
573 return
573 return
574
574
575 self.save_time = self.data.max_time
575 self.save_time = self.data.max_time
576
576
577 fig = self.figures[self.mode][n]
577 fig = self.figures[self.mode][n]
578
578
579 if self.throttle == 0:
579 if self.throttle == 0:
580 if self.oneFigure:
580 if self.oneFigure:
581 figname = os.path.join(
581 figname = os.path.join(
582 self.save,
582 self.save,
583 self.save_code + folder,
583 self.save_code + folder,
584 '{}_{}_{}.png'.format(
584 '{}_{}_{}.png'.format(
585 'SOPHY',
585 'SOPHY',
586 self.getDateTime(self.data.max_time).strftime(
586 self.getDateTime(self.data.max_time).strftime(
587 '%Y%m%d_%H%M%S'
587 '%Y%m%d_%H%M%S'
588 ),
588 ),
589 label
589 label
590 )
590 )
591 )
591 )
592 with cbook.get_sample_data(file_logo) as file:
592 with cbook.get_sample_data(file_logo) as file:
593 IM_LOGO = image.imread(file)
593 IM_LOGO = image.imread(file)
594 IM_X = 94
594 alto_logo = IM_LOGO.shape[0] # Altura del logo en pΓ­xeles
595 IM_Y = 90
595 ancho_logo= IM_LOGO.shape[1] # ancho del logo en pixeles
596 fig_height = fig.get_figheight() * fig.dpi
597 fig_width = fig.get_figwidth() * fig.dpi
598 # IM_X = 94
599 # IM_Y = 90
600 IM_X = fig_width - ancho_logo - 160 # Pegado al borde derecho
601 IM_Y = fig_height - alto_logo - 95 # Pegado al borde superior
596 logo=fig.figimage(IM_LOGO,IM_X,IM_Y,zorder=3,alpha=0.7)
602 logo=fig.figimage(IM_LOGO,IM_X,IM_Y,zorder=3,alpha=0.7)
597 else:
603 else:
598 figname = os.path.join(
604 figname = os.path.join(
599 self.save,
605 self.save,
600 self.save_code,
606 self.save_code,
601 '{}_ch{}_{}.png'.format(
607 '{}_ch{}_{}.png'.format(
602 self.save_code, n,
608 self.save_code, n,
603 self.getDateTime(self.data.max_time).strftime(
609 self.getDateTime(self.data.max_time).strftime(
604 '%Y%m%d_%H%M%S'
610 '%Y%m%d_%H%M%S'
605 ),
611 ),
606 )
612 )
607 )
613 )
608 log.log('Saving figure: {}'.format(figname), self.name)
614 log.log('Saving figure: {}'.format(figname), self.name)
609 if not os.path.isdir(os.path.dirname(figname)):
615 if not os.path.isdir(os.path.dirname(figname)):
610 os.makedirs(os.path.dirname(figname))
616 os.makedirs(os.path.dirname(figname))
611 fig.savefig(figname)
617 fig.savefig(figname)
612
618
613 figname = os.path.join(
619 figname = os.path.join(
614 self.save,
620 self.save,
615 '{}_{}.png'.format(
621 '{}_{}.png'.format(
616 self.save_code,
622 self.save_code,
617 self.getDateTime(self.data.min_time).strftime(
623 self.getDateTime(self.data.min_time).strftime(
618 '%Y%m%d'
624 '%Y%m%d'
619 ),
625 ),
620 )
626 )
621 )
627 )
622
628
623 log.log('Saving figure: {}'.format(figname), self.name)
629 log.log('Saving figure: {}'.format(figname), self.name)
624 if not os.path.isdir(os.path.dirname(figname)):
630 if not os.path.isdir(os.path.dirname(figname)):
625 os.makedirs(os.path.dirname(figname))
631 os.makedirs(os.path.dirname(figname))
626 fig.savefig(figname)
632 fig.savefig(figname)
627 logo.remove()
633 logo.remove()
628
634
629 def send_to_server(self):
635 def send_to_server(self):
630 '''
636 '''
631 '''
637 '''
632
638
633 if self.exp_code == None:
639 if self.exp_code == None:
634 log.warning('Missing `exp_code` skipping sending to server...')
640 log.warning('Missing `exp_code` skipping sending to server...')
635
641
636 last_time = self.data.max_time
642 last_time = self.data.max_time
637 interval = last_time - self.sender_time
643 interval = last_time - self.sender_time
638 if interval < self.sender_period:
644 if interval < self.sender_period:
639 return
645 return
640
646
641 self.sender_time = last_time
647 self.sender_time = last_time
642
648
643 attrs = ['titles', 'zmin', 'zmax', 'tag', 'ymin', 'ymax']
649 attrs = ['titles', 'zmin', 'zmax', 'tag', 'ymin', 'ymax']
644 for attr in attrs:
650 for attr in attrs:
645 value = getattr(self, attr)
651 value = getattr(self, attr)
646 if value:
652 if value:
647 if isinstance(value, (numpy.float32, numpy.float64)):
653 if isinstance(value, (numpy.float32, numpy.float64)):
648 value = round(float(value), 2)
654 value = round(float(value), 2)
649 self.data.meta[attr] = value
655 self.data.meta[attr] = value
650 if self.colormap == 'jet' or self.colormap == 'sophy_w':
656 if self.colormap == 'jet' or self.colormap == 'sophy_w':
651 self.data.meta['colormap'] = 'Jet'
657 self.data.meta['colormap'] = 'Jet'
652 elif 'sophy_v' in self.colormap:
658 elif 'sophy_v' in self.colormap:
653 self.data.meta['colormap'] = 'RdBu'
659 self.data.meta['colormap'] = 'RdBu'
654 else:
660 else:
655 self.data.meta['colormap'] = 'Viridis'
661 self.data.meta['colormap'] = 'Viridis'
656 self.data.meta['interval'] = int(interval)
662 self.data.meta['interval'] = int(interval)
657
663
658 self.sender_queue.append(last_time)
664 self.sender_queue.append(last_time)
659
665
660 while True:
666 while True:
661 try:
667 try:
662 tm = self.sender_queue.popleft()
668 tm = self.sender_queue.popleft()
663 except IndexError:
669 except IndexError:
664 break
670 break
665 msg = self.data.jsonify(tm, self.save_code, self.plot_type, key='var')
671 msg = self.data.jsonify(tm, self.save_code, self.plot_type, key='var')
666 self.socket.send_string(msg)
672 self.socket.send_string(msg)
667 socks = dict(self.poll.poll(2000))
673 socks = dict(self.poll.poll(2000))
668 if socks.get(self.socket) == zmq.POLLIN:
674 if socks.get(self.socket) == zmq.POLLIN:
669 reply = self.socket.recv_string()
675 reply = self.socket.recv_string()
670 if reply == 'ok':
676 if reply == 'ok':
671 log.log("Response from server ok", self.name)
677 log.log("Response from server ok", self.name)
672 time.sleep(0.1)
678 time.sleep(0.1)
673 continue
679 continue
674 else:
680 else:
675 log.warning(
681 log.warning(
676 "Malformed reply from server: {}".format(reply), self.name)
682 "Malformed reply from server: {}".format(reply), self.name)
677 else:
683 else:
678 log.warning(
684 log.warning(
679 "No response from server, retrying...", self.name)
685 "No response from server, retrying...", self.name)
680 self.sender_queue.appendleft(tm)
686 self.sender_queue.appendleft(tm)
681 self.socket.setsockopt(zmq.LINGER, 0)
687 self.socket.setsockopt(zmq.LINGER, 0)
682 self.socket.close()
688 self.socket.close()
683 self.poll.unregister(self.socket)
689 self.poll.unregister(self.socket)
684 self.socket = self.context.socket(zmq.REQ)
690 self.socket = self.context.socket(zmq.REQ)
685 self.socket.connect(self.server)
691 self.socket.connect(self.server)
686 self.poll.register(self.socket, zmq.POLLIN)
692 self.poll.register(self.socket, zmq.POLLIN)
687 break
693 break
688
694
689 def setup(self):
695 def setup(self):
690 '''
696 '''
691 This method should be implemented in the child class, the following
697 This method should be implemented in the child class, the following
692 attributes should be set:
698 attributes should be set:
693
699
694 self.nrows: number of rows
700 self.nrows: number of rows
695 self.ncols: number of cols
701 self.ncols: number of cols
696 self.nplots: number of plots (channels or pairs)
702 self.nplots: number of plots (channels or pairs)
697 self.ylabel: label for Y axes
703 self.ylabel: label for Y axes
698 self.titles: list of axes title
704 self.titles: list of axes title
699
705
700 '''
706 '''
701 raise NotImplementedError
707 raise NotImplementedError
702
708
703 def plot(self):
709 def plot(self):
704 '''
710 '''
705 Must be defined in the child class, the actual plotting method
711 Must be defined in the child class, the actual plotting method
706 '''
712 '''
707 raise NotImplementedError
713 raise NotImplementedError
708
714
709 def update(self, dataOut):
715 def update(self, dataOut):
710 '''
716 '''
711 Must be defined in the child class, update self.data with new data
717 Must be defined in the child class, update self.data with new data
712 '''
718 '''
713
719
714 data = {
720 data = {
715 self.CODE: getattr(dataOut, 'data_{}'.format(self.CODE))
721 self.CODE: getattr(dataOut, 'data_{}'.format(self.CODE))
716 }
722 }
717 meta = {}
723 meta = {}
718
724
719 return data, meta
725 return data, meta
720
726
721 def run(self, dataOut, **kwargs):
727 def run(self, dataOut, **kwargs):
722 '''
728 '''
723 Main plotting routine
729 Main plotting routine
724 '''
730 '''
725
731
726 if self.isConfig is False:
732 if self.isConfig is False:
727 self.__setup(**kwargs)
733 self.__setup(**kwargs)
728
734
729 if self.localtime:
735 if self.localtime:
730 self.getDateTime = datetime.datetime.fromtimestamp
736 self.getDateTime = datetime.datetime.fromtimestamp
731 else:
737 else:
732 self.getDateTime = datetime.datetime.utcfromtimestamp
738 self.getDateTime = datetime.datetime.utcfromtimestamp
733
739
734 self.data.setup()
740 self.data.setup()
735 self.isConfig = True
741 self.isConfig = True
736 if self.server:
742 if self.server:
737 self.context = zmq.Context()
743 self.context = zmq.Context()
738 self.socket = self.context.socket(zmq.REQ)
744 self.socket = self.context.socket(zmq.REQ)
739 self.socket.connect(self.server)
745 self.socket.connect(self.server)
740 self.poll = zmq.Poller()
746 self.poll = zmq.Poller()
741 self.poll.register(self.socket, zmq.POLLIN)
747 self.poll.register(self.socket, zmq.POLLIN)
742
748
743 tm = getattr(dataOut, self.attr_time)
749 tm = getattr(dataOut, self.attr_time)
744
750
745 if self.data and 'time' in self.xaxis and (tm - self.tmin) >= self.xrange*60*60:
751 if self.data and 'time' in self.xaxis and (tm - self.tmin) >= self.xrange*60*60:
746 self.save_time = tm
752 self.save_time = tm
747 self.__plot()
753 self.__plot()
748 self.tmin += self.xrange*60*60
754 self.tmin += self.xrange*60*60
749 self.data.setup()
755 self.data.setup()
750 self.clear_figures()
756 self.clear_figures()
751
757
752 self.__update(dataOut, tm)
758 self.__update(dataOut, tm)
753
759
754 if self.isPlotConfig is False:
760 if self.isPlotConfig is False:
755 self.__setup_plot()
761 self.__setup_plot()
756 self.isPlotConfig = True
762 self.isPlotConfig = True
757 if self.xaxis == 'time':
763 if self.xaxis == 'time':
758 dt = self.getDateTime(tm)
764 dt = self.getDateTime(tm)
759 if self.xmin is None:
765 if self.xmin is None:
760 self.tmin = tm
766 self.tmin = tm
761 self.xmin = dt.hour
767 self.xmin = dt.hour
762 minutes = (self.xmin-int(self.xmin)) * 60
768 minutes = (self.xmin-int(self.xmin)) * 60
763 seconds = (minutes - int(minutes)) * 60
769 seconds = (minutes - int(minutes)) * 60
764 self.tmin = (dt.replace(hour=int(self.xmin), minute=int(minutes), second=int(seconds)) -
770 self.tmin = (dt.replace(hour=int(self.xmin), minute=int(minutes), second=int(seconds)) -
765 datetime.datetime(1970, 1, 1)).total_seconds()
771 datetime.datetime(1970, 1, 1)).total_seconds()
766 if self.localtime:
772 if self.localtime:
767 self.tmin += time.timezone
773 self.tmin += time.timezone
768
774
769 if self.xmin is not None and self.xmax is not None:
775 if self.xmin is not None and self.xmax is not None:
770 self.xrange = self.xmax - self.xmin
776 self.xrange = self.xmax - self.xmin
771
777
772 if self.throttle == 0:
778 if self.throttle == 0:
773 self.__plot()
779 self.__plot()
774 else:
780 else:
775 self.__throttle_plot(self.__plot)#, coerce=coerce)
781 self.__throttle_plot(self.__plot)#, coerce=coerce)
776
782
777 def close(self):
783 def close(self):
778
784
779 if self.data and not self.data.flagNoData:
785 if self.data and not self.data.flagNoData:
780 self.save_time = 0
786 self.save_time = 0
781 self.__plot()
787 self.__plot()
782 if self.data and not self.data.flagNoData and self.pause:
788 if self.data and not self.data.flagNoData and self.pause:
783 figpause(10)
789 figpause(10)
General Comments 0
You need to be logged in to leave comments. Login now