|
@@
-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)
|