##// END OF EJS Templates
Add NCDFReader for PX1000 radar, new PlotPolarMap, bugs in jroplot_data
jespinoza -
r1137:124e67b869ed
parent child
Show More
@@ -0,0 +1,351
1 '''
2 Created on Dec 27, 2017
3
4 @author: Juan C. Espinoza
5 '''
6
7 import os
8 import sys
9 import time
10 import json
11 import glob
12 import datetime
13 import tarfile
14
15 import numpy
16 from netCDF4 import Dataset
17
18 from schainpy.model.io.jroIO_base import JRODataReader
19 from schainpy.model.proc.jroproc_base import ProcessingUnit, Operation
20 from schainpy.model.data.jrodata import Parameters
21 from schainpy.utils import log
22
23 UT1970 = datetime.datetime(1970, 1, 1) - datetime.timedelta(seconds=time.timezone)
24
25 def load_json(obj):
26 '''
27 Parse json as string instead of unicode
28 '''
29
30 if isinstance(obj, str):
31 iterable = json.loads(obj)
32 else:
33 iterable = obj
34
35 if isinstance(iterable, dict):
36 return {str(k): load_json(v) if isinstance(v, dict) else str(v) if isinstance(v, unicode) else v
37 for k, v in iterable.items()}
38 elif isinstance(iterable, (list, tuple)):
39 return [str(v) if isinstance(v, unicode) else v for v in iterable]
40
41 return iterable
42
43
44 class NCDFReader(JRODataReader, ProcessingUnit):
45
46 def __init__(self, **kwargs):
47
48 ProcessingUnit.__init__(self, **kwargs)
49
50 self.dataOut = Parameters()
51 self.counter_records = 0
52 self.nrecords = None
53 self.flagNoMoreFiles = 0
54 self.isConfig = False
55 self.filename = None
56 self.intervals = set()
57 self.ext = ('.nc', '.tgz')
58 self.online_mode = False
59
60 def setup(self,
61 path=None,
62 startDate=None,
63 endDate=None,
64 format=None,
65 startTime=datetime.time(0, 0, 0),
66 endTime=datetime.time(23, 59, 59),
67 walk=False,
68 **kwargs):
69
70 self.path = path
71 self.startDate = startDate
72 self.endDate = endDate
73 self.startTime = startTime
74 self.endTime = endTime
75 self.datatime = datetime.datetime(1900,1,1)
76 self.walk = walk
77 self.nTries = kwargs.get('nTries', 3)
78 self.online = kwargs.get('online', False)
79 self.delay = kwargs.get('delay', 30)
80
81 if self.path is None:
82 raise ValueError, 'The path is not valid'
83
84 self.search_files(path, startDate, endDate, startTime, endTime, walk)
85 self.cursor = 0
86 self.counter_records = 0
87
88 if not self.files:
89 raise Warning, 'There is no files matching these date in the folder: {}. \n Check startDate and endDate'.format(path)
90
91 def search_files(self, path, startDate, endDate, startTime, endTime, walk):
92 '''
93 Searching for NCDF files in path
94 Creating a list of files to procces included in [startDate,endDate]
95
96 Input:
97 path - Path to find files
98 '''
99
100 log.log('Searching files {} in {} '.format(self.ext, path), 'NCDFReader')
101 if walk:
102 paths = [os.path.join(path, p) for p in os.listdir(path) if os.path.isdir(os.path.join(path, p))]
103 paths.sort()
104 else:
105 paths = [path]
106
107 fileList0 = []
108
109 for subpath in paths:
110 fileList0 += [os.path.join(subpath, s) for s in glob.glob1(subpath, '*') if os.path.splitext(s)[-1] in self.ext]
111
112 fileList0.sort()
113
114 self.files = {}
115
116 startDate = startDate - datetime.timedelta(1)
117 endDate = endDate + datetime.timedelta(1)
118
119 for fullname in fileList0:
120 thisFile = fullname.split('/')[-1]
121 year = thisFile[3:7]
122 if not year.isdigit():
123 continue
124
125 month = thisFile[7:9]
126 if not month.isdigit():
127 continue
128
129 day = thisFile[9:11]
130 if not day.isdigit():
131 continue
132
133 year, month, day = int(year), int(month), int(day)
134 dateFile = datetime.date(year, month, day)
135 timeFile = datetime.time(int(thisFile[12:14]), int(thisFile[14:16]), int(thisFile[16:18]))
136
137 if (startDate > dateFile) or (endDate < dateFile):
138 continue
139
140 dt = datetime.datetime.combine(dateFile, timeFile)
141 if dt not in self.files:
142 self.files[dt] = []
143 self.files[dt].append(fullname)
144
145 self.dates = self.files.keys()
146 self.dates.sort()
147
148 return
149
150 def search_files_online(self):
151 '''
152 Searching for NCDF files in online mode path
153 Creating a list of files to procces included in [startDate,endDate]
154
155 Input:
156 path - Path to find files
157 '''
158
159 old_files = self.files[self.dt]
160 self.files = {}
161
162 for n in range(self.nTries):
163
164 if self.walk:
165 paths = [os.path.join(self.path, p) for p in os.listdir(self.path) if os.path.isdir(os.path.join(self.path, p))]
166 paths = paths[-2:]
167 else:
168 paths = [self.path]
169
170 new_files = []
171
172 for path in paths:
173 new_files += [os.path.join(path, s) for s in glob.glob1(path, '*') if os.path.splitext(s)[-1] in self.ext and os.path.join(path, s not in old_files)]
174
175 new_files.sort()
176
177 if new_files:
178 break
179 else:
180 log.warning('Waiting {} seconds for the next file, try {} ...'.format(self.delay, n + 1), 'NCDFReader')
181 time.sleep(self.delay)
182
183 if not new_files:
184 log.error('No more files found', 'NCDFReader')
185 return 0
186
187 startDate = self.dt - datetime.timedelta(seconds=1)
188
189 for fullname in new_files:
190 thisFile = fullname.split('/')[-1]
191 year = thisFile[3:7]
192 if not year.isdigit():
193 continue
194
195 month = thisFile[7:9]
196 if not month.isdigit():
197 continue
198
199 day = thisFile[9:11]
200 if not day.isdigit():
201 continue
202
203 year, month, day = int(year), int(month), int(day)
204 dateFile = datetime.date(year, month, day)
205 timeFile = datetime.time(int(thisFile[12:14]), int(thisFile[14:16]), int(thisFile[16:18]))
206
207 if (startDate > dateFile):
208 continue
209
210 dt = datetime.datetime.combine(dateFile, timeFile)
211 if dt not in self.files:
212 self.files[dt] = []
213
214 self.files[dt].append(fullname)
215
216 self.dates = self.files.keys()
217 self.dates.sort()
218 self.cursor = 0
219
220 return 1
221
222 def parseFile(self):
223 '''
224 '''
225
226 self.header = {}
227
228 for attr in self.fp.ncattrs():
229 self.header[str(attr)] = getattr(self.fp, attr)
230
231 self.data[self.header['TypeName']] = numpy.array(self.fp.variables[self.header['TypeName']])
232
233 if 'Azimuth' not in self.data:
234 self.data['Azimuth'] = numpy.array(self.fp.variables['Azimuth'])
235
236
237 def setNextFile(self):
238 '''
239 Open next files for the current datetime
240 '''
241
242 cursor = self.cursor
243
244 if not self.online_mode:
245 self.dt = self.dates[cursor]
246 if cursor == len(self.dates):
247 if self.online:
248 self.online_mode = True
249 else:
250 log.success('No more files', 'NCDFReader')
251 self.flagNoMoreFiles = 1
252 return 0
253 else:
254 if not self.search_files_online():
255 return 0
256
257 log.log(
258 'Opening: {}\'s files'.format(self.dates[cursor]),
259 'NCDFReader'
260 )
261
262 self.data = {}
263
264 for fullname in self.files[self.dates[cursor]]:
265
266 if os.path.splitext(fullname)[-1] == '.tgz':
267 tar = tarfile.open(fullname, 'r:gz')
268 tar.extractall('/tmp')
269 files = [os.path.join('/tmp', member.name) for member in tar.getmembers()]
270 else:
271 files = [fullname]
272
273 for filename in files:
274 if self.filename is not None:
275 self.fp.close()
276
277 self.filename = filename
278 self.filedate = self.dates[cursor]
279 self.fp = Dataset(self.filename, 'r')
280 self.parseFile()
281
282 self.counter_records += 1
283 self.cursor += 1
284 return 1
285
286 def readNextFile(self):
287
288 while True:
289 self.flagDiscontinuousBlock = 0
290 if not self.setNextFile():
291 return 0
292
293 self.datatime = datetime.datetime.utcfromtimestamp(self.header['Time'])
294
295 if (self.datatime < datetime.datetime.combine(self.startDate, self.startTime)) or \
296 (self.datatime > datetime.datetime.combine(self.endDate, self.endTime)):
297 log.warning(
298 'Reading Record No. {}/{} -> {} [Skipping]'.format(
299 self.counter_records,
300 self.nrecords,
301 self.datatime.ctime()),
302 'NCDFReader')
303 continue
304 break
305
306 log.log(
307 'Reading Record No. {}/{} -> {}'.format(
308 self.counter_records,
309 self.nrecords,
310 self.datatime.ctime()),
311 'NCDFReader')
312
313 return 1
314
315
316 def set_output(self):
317 '''
318 Storing data from buffer to dataOut object
319 '''
320
321 self.dataOut.heightList = self.data.pop('Azimuth')
322
323 log.log('Parameters found: {}'.format(','.join(self.data.keys())),
324 'PXReader')
325
326 self.dataOut.data_param = numpy.array(self.data.values())
327 self.dataOut.data_param[self.dataOut.data_param == -99900.] = numpy.nan
328 self.dataOut.parameters = self.data.keys()
329 self.dataOut.utctime = self.header['Time']
330 self.dataOut.utctimeInit = self.dataOut.utctime
331 self.dataOut.useLocalTime = False
332 self.dataOut.flagNoData = False
333 self.dataOut.flagDiscontinuousBlock = self.flagDiscontinuousBlock
334
335 def getData(self):
336 '''
337 Storing data from databuffer to dataOut object
338 '''
339 if self.flagNoMoreFiles:
340 self.dataOut.flagNoData = True
341 log.error('No file left to process', 'NCDFReader')
342 return 0
343
344 if not self.readNextFile():
345 self.dataOut.flagNoData = True
346 return 0
347
348 self.set_output()
349
350 return 1
351
@@ -1,965 +1,1042
1
1
2 import os
2 import os
3 import time
3 import time
4 import glob
4 import glob
5 import datetime
5 import datetime
6 from multiprocessing import Process
6 from multiprocessing import Process
7
7
8 import zmq
8 import zmq
9 import numpy
9 import numpy
10 import matplotlib
10 import matplotlib
11 import matplotlib.pyplot as plt
11 import matplotlib.pyplot as plt
12 from mpl_toolkits.axes_grid1 import make_axes_locatable
12 from mpl_toolkits.axes_grid1 import make_axes_locatable
13 from matplotlib.ticker import FuncFormatter, LinearLocator, MultipleLocator
13 from matplotlib.ticker import FuncFormatter, LinearLocator, MultipleLocator
14
14
15 from schainpy.model.proc.jroproc_base import Operation
15 from schainpy.model.proc.jroproc_base import Operation
16 from schainpy.utils import log
16 from schainpy.utils import log
17
17
18 jet_values = matplotlib.pyplot.get_cmap('jet', 100)(numpy.arange(100))[10:90]
18 jet_values = matplotlib.pyplot.get_cmap('jet', 100)(numpy.arange(100))[10:90]
19 blu_values = matplotlib.pyplot.get_cmap(
19 blu_values = matplotlib.pyplot.get_cmap(
20 'seismic_r', 20)(numpy.arange(20))[10:15]
20 'seismic_r', 20)(numpy.arange(20))[10:15]
21 ncmap = matplotlib.colors.LinearSegmentedColormap.from_list(
21 ncmap = matplotlib.colors.LinearSegmentedColormap.from_list(
22 'jro', numpy.vstack((blu_values, jet_values)))
22 'jro', numpy.vstack((blu_values, jet_values)))
23 matplotlib.pyplot.register_cmap(cmap=ncmap)
23 matplotlib.pyplot.register_cmap(cmap=ncmap)
24
24
25 CMAPS = [plt.get_cmap(s) for s in ('jro', 'jet', 'viridis', 'plasma', 'inferno', 'Greys', 'seismic', 'bwr', 'coolwarm')]
25 CMAPS = [plt.get_cmap(s) for s in ('jro', 'jet', 'viridis', 'plasma', 'inferno', 'Greys', 'seismic', 'bwr', 'coolwarm', 'spectral')]
26
26
27
27
28 def figpause(interval):
28 def figpause(interval):
29 backend = plt.rcParams['backend']
29 backend = plt.rcParams['backend']
30 if backend in matplotlib.rcsetup.interactive_bk:
30 if backend in matplotlib.rcsetup.interactive_bk:
31 figManager = matplotlib._pylab_helpers.Gcf.get_active()
31 figManager = matplotlib._pylab_helpers.Gcf.get_active()
32 if figManager is not None:
32 if figManager is not None:
33 canvas = figManager.canvas
33 canvas = figManager.canvas
34 if canvas.figure.stale:
34 if canvas.figure.stale:
35 canvas.draw()
35 canvas.draw()
36 canvas.start_event_loop(interval)
36 canvas.start_event_loop(interval)
37 return
37 return
38
38
39
39
40 class PlotData(Operation, Process):
40 class PlotData(Operation, Process):
41 '''
41 '''
42 Base class for Schain plotting operations
42 Base class for Schain plotting operations
43 '''
43 '''
44
44
45 CODE = 'Figure'
45 CODE = 'Figure'
46 colormap = 'jro'
46 colormap = 'jro'
47 bgcolor = 'white'
47 bgcolor = 'white'
48 CONFLATE = False
48 CONFLATE = False
49 __missing = 1E30
49 __missing = 1E30
50
50
51 __attrs__ = ['show', 'save', 'xmin', 'xmax', 'ymin', 'ymax', 'zmin', 'zmax',
51 __attrs__ = ['show', 'save', 'xmin', 'xmax', 'ymin', 'ymax', 'zmin', 'zmax',
52 'zlimits', 'xlabel', 'ylabel', 'xaxis','cb_label', 'title',
52 'zlimits', 'xlabel', 'ylabel', 'xaxis','cb_label', 'title',
53 'colorbar', 'bgcolor', 'width', 'height', 'localtime', 'oneFigure',
53 'colorbar', 'bgcolor', 'width', 'height', 'localtime', 'oneFigure',
54 'showprofile', 'decimation']
54 'showprofile', 'decimation', 'ftp']
55
55
56 def __init__(self, **kwargs):
56 def __init__(self, **kwargs):
57
57
58 Operation.__init__(self, plot=True, **kwargs)
58 Operation.__init__(self, plot=True, **kwargs)
59 Process.__init__(self)
59 Process.__init__(self)
60
60
61 self.kwargs['code'] = self.CODE
61 self.kwargs['code'] = self.CODE
62 self.mp = False
62 self.mp = False
63 self.data = None
63 self.data = None
64 self.isConfig = False
64 self.isConfig = False
65 self.figures = []
65 self.figures = []
66 self.axes = []
66 self.axes = []
67 self.cb_axes = []
67 self.cb_axes = []
68 self.localtime = kwargs.pop('localtime', True)
68 self.localtime = kwargs.pop('localtime', True)
69 self.show = kwargs.get('show', True)
69 self.show = kwargs.get('show', True)
70 self.save = kwargs.get('save', False)
70 self.save = kwargs.get('save', False)
71 self.ftp = kwargs.get('ftp', False)
71 self.colormap = kwargs.get('colormap', self.colormap)
72 self.colormap = kwargs.get('colormap', self.colormap)
72 self.colormap_coh = kwargs.get('colormap_coh', 'jet')
73 self.colormap_coh = kwargs.get('colormap_coh', 'jet')
73 self.colormap_phase = kwargs.get('colormap_phase', 'RdBu_r')
74 self.colormap_phase = kwargs.get('colormap_phase', 'RdBu_r')
74 self.colormaps = kwargs.get('colormaps', None)
75 self.colormaps = kwargs.get('colormaps', None)
75 self.bgcolor = kwargs.get('bgcolor', self.bgcolor)
76 self.bgcolor = kwargs.get('bgcolor', self.bgcolor)
76 self.showprofile = kwargs.get('showprofile', False)
77 self.showprofile = kwargs.get('showprofile', False)
77 self.title = kwargs.get('wintitle', self.CODE.upper())
78 self.title = kwargs.get('wintitle', self.CODE.upper())
78 self.cb_label = kwargs.get('cb_label', None)
79 self.cb_label = kwargs.get('cb_label', None)
79 self.cb_labels = kwargs.get('cb_labels', None)
80 self.cb_labels = kwargs.get('cb_labels', None)
81 self.labels = kwargs.get('labels', None)
80 self.xaxis = kwargs.get('xaxis', 'frequency')
82 self.xaxis = kwargs.get('xaxis', 'frequency')
81 self.zmin = kwargs.get('zmin', None)
83 self.zmin = kwargs.get('zmin', None)
82 self.zmax = kwargs.get('zmax', None)
84 self.zmax = kwargs.get('zmax', None)
83 self.zlimits = kwargs.get('zlimits', None)
85 self.zlimits = kwargs.get('zlimits', None)
84 self.xmin = kwargs.get('xmin', None)
86 self.xmin = kwargs.get('xmin', None)
85 self.xmax = kwargs.get('xmax', None)
87 self.xmax = kwargs.get('xmax', None)
86 self.xrange = kwargs.get('xrange', 24)
88 self.xrange = kwargs.get('xrange', 24)
89 self.xscale = kwargs.get('xscale', None)
87 self.ymin = kwargs.get('ymin', None)
90 self.ymin = kwargs.get('ymin', None)
88 self.ymax = kwargs.get('ymax', None)
91 self.ymax = kwargs.get('ymax', None)
92 self.yscale = kwargs.get('yscale', None)
89 self.xlabel = kwargs.get('xlabel', None)
93 self.xlabel = kwargs.get('xlabel', None)
90 self.decimation = kwargs.get('decimation', None)
94 self.decimation = kwargs.get('decimation', None)
91 self.showSNR = kwargs.get('showSNR', False)
95 self.showSNR = kwargs.get('showSNR', False)
92 self.oneFigure = kwargs.get('oneFigure', True)
96 self.oneFigure = kwargs.get('oneFigure', True)
93 self.width = kwargs.get('width', None)
97 self.width = kwargs.get('width', None)
94 self.height = kwargs.get('height', None)
98 self.height = kwargs.get('height', None)
95 self.colorbar = kwargs.get('colorbar', True)
99 self.colorbar = kwargs.get('colorbar', True)
96 self.factors = kwargs.get('factors', [1, 1, 1, 1, 1, 1, 1, 1])
100 self.factors = kwargs.get('factors', [1, 1, 1, 1, 1, 1, 1, 1])
101 self.channels = kwargs.get('channels', None)
97 self.titles = kwargs.get('titles', [])
102 self.titles = kwargs.get('titles', [])
98 self.polar = False
103 self.polar = False
99
104
100 def __fmtTime(self, x, pos):
105 def __fmtTime(self, x, pos):
101 '''
106 '''
102 '''
107 '''
103
108
104 return '{}'.format(self.getDateTime(x).strftime('%H:%M'))
109 return '{}'.format(self.getDateTime(x).strftime('%H:%M'))
105
110
106 def __setup(self):
111 def __setup(self):
107 '''
112 '''
108 Common setup for all figures, here figures and axes are created
113 Common setup for all figures, here figures and axes are created
109 '''
114 '''
110
115
111 if self.CODE not in self.data:
116 if self.CODE not in self.data:
112 raise ValueError(log.error('Missing data for {}'.format(self.CODE),
117 raise ValueError(log.error('Missing data for {}'.format(self.CODE),
113 self.name))
118 self.name))
114
119
115 self.setup()
120 self.setup()
116
121
117 self.time_label = 'LT' if self.localtime else 'UTC'
122 self.time_label = 'LT' if self.localtime else 'UTC'
118 if self.data.localtime:
123 if self.data.localtime:
119 self.getDateTime = datetime.datetime.fromtimestamp
124 self.getDateTime = datetime.datetime.fromtimestamp
120 else:
125 else:
121 self.getDateTime = datetime.datetime.utcfromtimestamp
126 self.getDateTime = datetime.datetime.utcfromtimestamp
122
127
123 if self.width is None:
128 if self.width is None:
124 self.width = 8
129 self.width = 8
125
130
126 self.figures = []
131 self.figures = []
127 self.axes = []
132 self.axes = []
128 self.cb_axes = []
133 self.cb_axes = []
129 self.pf_axes = []
134 self.pf_axes = []
130 self.cmaps = []
135 self.cmaps = []
131
136
132 size = '15%' if self.ncols == 1 else '30%'
137 size = '15%' if self.ncols == 1 else '30%'
133 pad = '4%' if self.ncols == 1 else '8%'
138 pad = '4%' if self.ncols == 1 else '8%'
134
139
135 if self.oneFigure:
140 if self.oneFigure:
136 if self.height is None:
141 if self.height is None:
137 self.height = 1.4 * self.nrows + 1
142 self.height = 1.4 * self.nrows + 1
138 fig = plt.figure(figsize=(self.width, self.height),
143 fig = plt.figure(figsize=(self.width, self.height),
139 edgecolor='k',
144 edgecolor='k',
140 facecolor='w')
145 facecolor='w')
141 self.figures.append(fig)
146 self.figures.append(fig)
142 for n in range(self.nplots):
147 for n in range(self.nplots):
143 ax = fig.add_subplot(self.nrows, self.ncols,
148 ax = fig.add_subplot(self.nrows, self.ncols,
144 n + 1, polar=self.polar)
149 n + 1, polar=self.polar)
145 ax.tick_params(labelsize=8)
150 ax.tick_params(labelsize=8)
146 ax.firsttime = True
151 ax.firsttime = True
147 ax.index = 0
152 ax.index = 0
148 ax.press = None
153 ax.press = None
149 self.axes.append(ax)
154 self.axes.append(ax)
150 if self.showprofile:
155 if self.showprofile:
151 cax = self.__add_axes(ax, size=size, pad=pad)
156 cax = self.__add_axes(ax, size=size, pad=pad)
152 cax.tick_params(labelsize=8)
157 cax.tick_params(labelsize=8)
153 self.pf_axes.append(cax)
158 self.pf_axes.append(cax)
154 else:
159 else:
155 if self.height is None:
160 if self.height is None:
156 self.height = 3
161 self.height = 3
157 for n in range(self.nplots):
162 for n in range(self.nplots):
158 fig = plt.figure(figsize=(self.width, self.height),
163 fig = plt.figure(figsize=(self.width, self.height),
159 edgecolor='k',
164 edgecolor='k',
160 facecolor='w')
165 facecolor='w')
161 ax = fig.add_subplot(1, 1, 1, polar=self.polar)
166 ax = fig.add_subplot(1, 1, 1, polar=self.polar)
162 ax.tick_params(labelsize=8)
167 ax.tick_params(labelsize=8)
163 ax.firsttime = True
168 ax.firsttime = True
164 ax.index = 0
169 ax.index = 0
165 ax.press = None
170 ax.press = None
166 self.figures.append(fig)
171 self.figures.append(fig)
167 self.axes.append(ax)
172 self.axes.append(ax)
168 if self.showprofile:
173 if self.showprofile:
169 cax = self.__add_axes(ax, size=size, pad=pad)
174 cax = self.__add_axes(ax, size=size, pad=pad)
170 cax.tick_params(labelsize=8)
175 cax.tick_params(labelsize=8)
171 self.pf_axes.append(cax)
176 self.pf_axes.append(cax)
172
177
173 for n in range(self.nrows):
178 for n in range(self.nrows):
174 if self.colormaps is not None:
179 if self.colormaps is not None:
175 cmap = plt.get_cmap(self.colormaps[n])
180 cmap = plt.get_cmap(self.colormaps[n])
176 else:
181 else:
177 cmap = plt.get_cmap(self.colormap)
182 cmap = plt.get_cmap(self.colormap)
178 cmap.set_bad(self.bgcolor, 1.)
183 cmap.set_bad(self.bgcolor, 1.)
179 self.cmaps.append(cmap)
184 self.cmaps.append(cmap)
180
185
181 for fig in self.figures:
186 for fig in self.figures:
182 fig.canvas.mpl_connect('key_press_event', self.OnKeyPress)
187 fig.canvas.mpl_connect('key_press_event', self.OnKeyPress)
183 fig.canvas.mpl_connect('scroll_event', self.OnBtnScroll)
188 fig.canvas.mpl_connect('scroll_event', self.OnBtnScroll)
184 fig.canvas.mpl_connect('button_press_event', self.onBtnPress)
189 fig.canvas.mpl_connect('button_press_event', self.onBtnPress)
185 fig.canvas.mpl_connect('motion_notify_event', self.onMotion)
190 fig.canvas.mpl_connect('motion_notify_event', self.onMotion)
186 fig.canvas.mpl_connect('button_release_event', self.onBtnRelease)
191 fig.canvas.mpl_connect('button_release_event', self.onBtnRelease)
187 if self.show:
192 if self.show:
188 fig.show()
193 fig.show()
189
194
190 def OnKeyPress(self, event):
195 def OnKeyPress(self, event):
191 '''
196 '''
192 Event for pressing keys (up, down) change colormap
197 Event for pressing keys (up, down) change colormap
193 '''
198 '''
194 ax = event.inaxes
199 ax = event.inaxes
195 if ax in self.axes:
200 if ax in self.axes:
196 if event.key == 'down':
201 if event.key == 'down':
197 ax.index += 1
202 ax.index += 1
198 elif event.key == 'up':
203 elif event.key == 'up':
199 ax.index -= 1
204 ax.index -= 1
200 if ax.index < 0:
205 if ax.index < 0:
201 ax.index = len(CMAPS) - 1
206 ax.index = len(CMAPS) - 1
202 elif ax.index == len(CMAPS):
207 elif ax.index == len(CMAPS):
203 ax.index = 0
208 ax.index = 0
204 cmap = CMAPS[ax.index]
209 cmap = CMAPS[ax.index]
205 ax.cbar.set_cmap(cmap)
210 ax.cbar.set_cmap(cmap)
206 ax.cbar.draw_all()
211 ax.cbar.draw_all()
207 ax.plt.set_cmap(cmap)
212 ax.plt.set_cmap(cmap)
208 ax.cbar.patch.figure.canvas.draw()
213 ax.cbar.patch.figure.canvas.draw()
209 self.colormap = cmap.name
214 self.colormap = cmap.name
210
215
211 def OnBtnScroll(self, event):
216 def OnBtnScroll(self, event):
212 '''
217 '''
213 Event for scrolling, scale figure
218 Event for scrolling, scale figure
214 '''
219 '''
215 cb_ax = event.inaxes
220 cb_ax = event.inaxes
216 if cb_ax in [ax.cbar.ax for ax in self.axes if ax.cbar]:
221 if cb_ax in [ax.cbar.ax for ax in self.axes if ax.cbar]:
217 ax = [ax for ax in self.axes if cb_ax == ax.cbar.ax][0]
222 ax = [ax for ax in self.axes if cb_ax == ax.cbar.ax][0]
218 pt = ax.cbar.ax.bbox.get_points()[:, 1]
223 pt = ax.cbar.ax.bbox.get_points()[:, 1]
219 nrm = ax.cbar.norm
224 nrm = ax.cbar.norm
220 vmin, vmax, p0, p1, pS = (
225 vmin, vmax, p0, p1, pS = (
221 nrm.vmin, nrm.vmax, pt[0], pt[1], event.y)
226 nrm.vmin, nrm.vmax, pt[0], pt[1], event.y)
222 scale = 2 if event.step == 1 else 0.5
227 scale = 2 if event.step == 1 else 0.5
223 point = vmin + (vmax - vmin) / (p1 - p0) * (pS - p0)
228 point = vmin + (vmax - vmin) / (p1 - p0) * (pS - p0)
224 ax.cbar.norm.vmin = point - scale * (point - vmin)
229 ax.cbar.norm.vmin = point - scale * (point - vmin)
225 ax.cbar.norm.vmax = point - scale * (point - vmax)
230 ax.cbar.norm.vmax = point - scale * (point - vmax)
226 ax.plt.set_norm(ax.cbar.norm)
231 ax.plt.set_norm(ax.cbar.norm)
227 ax.cbar.draw_all()
232 ax.cbar.draw_all()
228 ax.cbar.patch.figure.canvas.draw()
233 ax.cbar.patch.figure.canvas.draw()
229
234
230 def onBtnPress(self, event):
235 def onBtnPress(self, event):
231 '''
236 '''
232 Event for mouse button press
237 Event for mouse button press
233 '''
238 '''
234 cb_ax = event.inaxes
239 cb_ax = event.inaxes
235 if cb_ax is None:
240 if cb_ax is None:
236 return
241 return
237
242
238 if cb_ax in [ax.cbar.ax for ax in self.axes if ax.cbar]:
243 if cb_ax in [ax.cbar.ax for ax in self.axes if ax.cbar]:
239 cb_ax.press = event.x, event.y
244 cb_ax.press = event.x, event.y
240 else:
245 else:
241 cb_ax.press = None
246 cb_ax.press = None
242
247
243 def onMotion(self, event):
248 def onMotion(self, event):
244 '''
249 '''
245 Event for move inside colorbar
250 Event for move inside colorbar
246 '''
251 '''
247 cb_ax = event.inaxes
252 cb_ax = event.inaxes
248 if cb_ax is None:
253 if cb_ax is None:
249 return
254 return
250 if cb_ax not in [ax.cbar.ax for ax in self.axes if ax.cbar]:
255 if cb_ax not in [ax.cbar.ax for ax in self.axes if ax.cbar]:
251 return
256 return
252 if cb_ax.press is None:
257 if cb_ax.press is None:
253 return
258 return
254
259
255 ax = [ax for ax in self.axes if cb_ax == ax.cbar.ax][0]
260 ax = [ax for ax in self.axes if cb_ax == ax.cbar.ax][0]
256 xprev, yprev = cb_ax.press
261 xprev, yprev = cb_ax.press
257 dx = event.x - xprev
262 dx = event.x - xprev
258 dy = event.y - yprev
263 dy = event.y - yprev
259 cb_ax.press = event.x, event.y
264 cb_ax.press = event.x, event.y
260 scale = ax.cbar.norm.vmax - ax.cbar.norm.vmin
265 scale = ax.cbar.norm.vmax - ax.cbar.norm.vmin
261 perc = 0.03
266 perc = 0.03
262
267
263 if event.button == 1:
268 if event.button == 1:
264 ax.cbar.norm.vmin -= (perc * scale) * numpy.sign(dy)
269 ax.cbar.norm.vmin -= (perc * scale) * numpy.sign(dy)
265 ax.cbar.norm.vmax -= (perc * scale) * numpy.sign(dy)
270 ax.cbar.norm.vmax -= (perc * scale) * numpy.sign(dy)
266 elif event.button == 3:
271 elif event.button == 3:
267 ax.cbar.norm.vmin -= (perc * scale) * numpy.sign(dy)
272 ax.cbar.norm.vmin -= (perc * scale) * numpy.sign(dy)
268 ax.cbar.norm.vmax += (perc * scale) * numpy.sign(dy)
273 ax.cbar.norm.vmax += (perc * scale) * numpy.sign(dy)
269
274
270 ax.cbar.draw_all()
275 ax.cbar.draw_all()
271 ax.plt.set_norm(ax.cbar.norm)
276 ax.plt.set_norm(ax.cbar.norm)
272 ax.cbar.patch.figure.canvas.draw()
277 ax.cbar.patch.figure.canvas.draw()
273
278
274 def onBtnRelease(self, event):
279 def onBtnRelease(self, event):
275 '''
280 '''
276 Event for mouse button release
281 Event for mouse button release
277 '''
282 '''
278 cb_ax = event.inaxes
283 cb_ax = event.inaxes
279 if cb_ax is not None:
284 if cb_ax is not None:
280 cb_ax.press = None
285 cb_ax.press = None
281
286
282 def __add_axes(self, ax, size='30%', pad='8%'):
287 def __add_axes(self, ax, size='30%', pad='8%'):
283 '''
288 '''
284 Add new axes to the given figure
289 Add new axes to the given figure
285 '''
290 '''
286 divider = make_axes_locatable(ax)
291 divider = make_axes_locatable(ax)
287 nax = divider.new_horizontal(size=size, pad=pad)
292 nax = divider.new_horizontal(size=size, pad=pad)
288 ax.figure.add_axes(nax)
293 ax.figure.add_axes(nax)
289 return nax
294 return nax
290
295
291 self.setup()
296 self.setup()
292
297
293 def setup(self):
298 def setup(self):
294 '''
299 '''
295 This method should be implemented in the child class, the following
300 This method should be implemented in the child class, the following
296 attributes should be set:
301 attributes should be set:
297
302
298 self.nrows: number of rows
303 self.nrows: number of rows
299 self.ncols: number of cols
304 self.ncols: number of cols
300 self.nplots: number of plots (channels or pairs)
305 self.nplots: number of plots (channels or pairs)
301 self.ylabel: label for Y axes
306 self.ylabel: label for Y axes
302 self.titles: list of axes title
307 self.titles: list of axes title
303
308
304 '''
309 '''
305 raise(NotImplementedError, 'Implement this method in child class')
310 raise(NotImplementedError, 'Implement this method in child class')
306
311
307 def fill_gaps(self, x_buffer, y_buffer, z_buffer):
312 def fill_gaps(self, x_buffer, y_buffer, z_buffer):
308 '''
313 '''
309 Create a masked array for missing data
314 Create a masked array for missing data
310 '''
315 '''
311 if x_buffer.shape[0] < 2:
316 if x_buffer.shape[0] < 2:
312 return x_buffer, y_buffer, z_buffer
317 return x_buffer, y_buffer, z_buffer
313
318
314 deltas = x_buffer[1:] - x_buffer[0:-1]
319 deltas = x_buffer[1:] - x_buffer[0:-1]
315 x_median = numpy.median(deltas)
320 x_median = numpy.median(deltas)
316
321
317 index = numpy.where(deltas > 5 * x_median)
322 index = numpy.where(deltas > 5 * x_median)
318
323
319 if len(index[0]) != 0:
324 if len(index[0]) != 0:
320 z_buffer[::, index[0], ::] = self.__missing
325 z_buffer[::, index[0], ::] = self.__missing
321 z_buffer = numpy.ma.masked_inside(z_buffer,
326 z_buffer = numpy.ma.masked_inside(z_buffer,
322 0.99 * self.__missing,
327 0.99 * self.__missing,
323 1.01 * self.__missing)
328 1.01 * self.__missing)
324
329
325 return x_buffer, y_buffer, z_buffer
330 return x_buffer, y_buffer, z_buffer
326
331
327 def decimate(self):
332 def decimate(self):
328
333
329 # dx = int(len(self.x)/self.__MAXNUMX) + 1
334 # dx = int(len(self.x)/self.__MAXNUMX) + 1
330 dy = int(len(self.y) / self.decimation) + 1
335 dy = int(len(self.y) / self.decimation) + 1
331
336
332 # x = self.x[::dx]
337 # x = self.x[::dx]
333 x = self.x
338 x = self.x
334 y = self.y[::dy]
339 y = self.y[::dy]
335 z = self.z[::, ::, ::dy]
340 z = self.z[::, ::, ::dy]
336
341
337 return x, y, z
342 return x, y, z
338
343
339 def format(self):
344 def format(self):
340 '''
345 '''
341 Set min and max values, labels, ticks and titles
346 Set min and max values, labels, ticks and titles
342 '''
347 '''
343
348
344 if self.xmin is None:
349 if self.xmin is None:
345 xmin = self.min_time
350 xmin = self.min_time
346 else:
351 else:
347 if self.xaxis is 'time':
352 if self.xaxis is 'time':
348 dt = self.getDateTime(self.min_time)
353 dt = self.getDateTime(self.min_time)
349 xmin = (dt.replace(hour=int(self.xmin), minute=0, second=0) -
354 xmin = (dt.replace(hour=int(self.xmin), minute=0, second=0) -
350 datetime.datetime(1970, 1, 1)).total_seconds()
355 datetime.datetime(1970, 1, 1)).total_seconds()
351 if self.data.localtime:
356 if self.data.localtime:
352 xmin += time.timezone
357 xmin += time.timezone
353 else:
358 else:
354 xmin = self.xmin
359 xmin = self.xmin
355
360
356 if self.xmax is None:
361 if self.xmax is None:
357 xmax = xmin + self.xrange * 60 * 60
362 xmax = xmin + self.xrange * 60 * 60
358 else:
363 else:
359 if self.xaxis is 'time':
364 if self.xaxis is 'time':
360 dt = self.getDateTime(self.max_time)
365 dt = self.getDateTime(self.max_time)
361 xmax = (dt.replace(hour=int(self.xmax), minute=59, second=59) -
366 xmax = (dt.replace(hour=int(self.xmax), minute=59, second=59) -
362 datetime.datetime(1970, 1, 1) + datetime.timedelta(seconds=1)).total_seconds()
367 datetime.datetime(1970, 1, 1) + datetime.timedelta(seconds=1)).total_seconds()
363 if self.data.localtime:
368 if self.data.localtime:
364 xmax += time.timezone
369 xmax += time.timezone
365 else:
370 else:
366 xmax = self.xmax
371 xmax = self.xmax
367
372
368 ymin = self.ymin if self.ymin else numpy.nanmin(self.y)
373 ymin = self.ymin if self.ymin else numpy.nanmin(self.y)
369 ymax = self.ymax if self.ymax else numpy.nanmax(self.y)
374 ymax = self.ymax if self.ymax else numpy.nanmax(self.y)
370
375
371 Y = numpy.array([5, 10, 20, 50, 100, 200, 500, 1000, 2000])
376 Y = numpy.array([5, 10, 20, 50, 100, 200, 500, 1000, 2000, 5000])
372 i = 1 if numpy.where(ymax-ymin < Y)[0][0] < 0 else numpy.where(ymax-ymin < Y)[0][0]
377 i = 1 if numpy.where(abs(ymax-ymin) <= Y)[0][0] < 0 else numpy.where(abs(ymax-ymin) <= Y)[0][0]
373 ystep = Y[i] / 5
378 ystep = Y[i] / 5.
374
379
375 for n, ax in enumerate(self.axes):
380 for n, ax in enumerate(self.axes):
376 if ax.firsttime:
381 if ax.firsttime:
377 ax.set_facecolor(self.bgcolor)
382 ax.set_facecolor(self.bgcolor)
378 ax.yaxis.set_major_locator(MultipleLocator(ystep))
383 ax.yaxis.set_major_locator(MultipleLocator(ystep))
384 ax.xaxis.set_major_locator(MultipleLocator(ystep))
385 if self.xscale:
386 ax.xaxis.set_major_formatter(FuncFormatter(lambda x, pos: '{0:g}'.format(x*self.xscale)))
387 if self.xscale:
388 ax.yaxis.set_major_formatter(FuncFormatter(lambda x, pos: '{0:g}'.format(x*self.yscale)))
379 if self.xaxis is 'time':
389 if self.xaxis is 'time':
380 ax.xaxis.set_major_formatter(FuncFormatter(self.__fmtTime))
390 ax.xaxis.set_major_formatter(FuncFormatter(self.__fmtTime))
381 ax.xaxis.set_major_locator(LinearLocator(9))
391 ax.xaxis.set_major_locator(LinearLocator(9))
382 if self.xlabel is not None:
392 if self.xlabel is not None:
383 ax.set_xlabel(self.xlabel)
393 ax.set_xlabel(self.xlabel)
384 ax.set_ylabel(self.ylabel)
394 ax.set_ylabel(self.ylabel)
385 ax.firsttime = False
395 ax.firsttime = False
386 if self.showprofile:
396 if self.showprofile:
387 self.pf_axes[n].set_ylim(ymin, ymax)
397 self.pf_axes[n].set_ylim(ymin, ymax)
388 self.pf_axes[n].set_xlim(self.zmin, self.zmax)
398 self.pf_axes[n].set_xlim(self.zmin, self.zmax)
389 self.pf_axes[n].set_xlabel('dB')
399 self.pf_axes[n].set_xlabel('dB')
390 self.pf_axes[n].grid(b=True, axis='x')
400 self.pf_axes[n].grid(b=True, axis='x')
391 [tick.set_visible(False)
401 [tick.set_visible(False)
392 for tick in self.pf_axes[n].get_yticklabels()]
402 for tick in self.pf_axes[n].get_yticklabels()]
393 if self.colorbar:
403 if self.colorbar:
394 ax.cbar = plt.colorbar(
404 ax.cbar = plt.colorbar(
395 ax.plt, ax=ax, fraction=0.05, pad=0.02, aspect=10)
405 ax.plt, ax=ax, fraction=0.05, pad=0.02, aspect=10)
396 ax.cbar.ax.tick_params(labelsize=8)
406 ax.cbar.ax.tick_params(labelsize=8)
397 ax.cbar.ax.press = None
407 ax.cbar.ax.press = None
398 if self.cb_label:
408 if self.cb_label:
399 ax.cbar.set_label(self.cb_label, size=8)
409 ax.cbar.set_label(self.cb_label, size=8)
400 elif self.cb_labels:
410 elif self.cb_labels:
401 ax.cbar.set_label(self.cb_labels[n], size=8)
411 ax.cbar.set_label(self.cb_labels[n], size=8)
402 else:
412 else:
403 ax.cbar = None
413 ax.cbar = None
404
414
405 if not self.polar:
415 if not self.polar:
406 ax.set_xlim(xmin, xmax)
416 ax.set_xlim(xmin, xmax)
407 ax.set_ylim(ymin, ymax)
417 ax.set_ylim(ymin, ymax)
408 ax.set_title('{} - {} {}'.format(
418 ax.set_title('{} - {} {}'.format(
409 self.titles[n],
419 self.titles[n],
410 self.getDateTime(self.max_time).strftime('%H:%M:%S'),
420 self.getDateTime(self.max_time).strftime('%H:%M:%S'),
411 self.time_label),
421 self.time_label),
412 size=8)
422 size=8)
413 else:
423 else:
414 ax.set_title('{}'.format(self.titles[n]), size=8)
424 ax.set_title('{}'.format(self.titles[n]), size=8)
415 ax.set_ylim(0, 90)
425 ax.set_ylim(0, 90)
416 ax.set_yticks(numpy.arange(0, 90, 20))
426 ax.set_yticks(numpy.arange(0, 90, 20))
417 ax.yaxis.labelpad = 40
427 ax.yaxis.labelpad = 40
418
428
419 def __plot(self):
429 def __plot(self):
420 '''
430 '''
421 '''
431 '''
422 log.success('Plotting', self.name)
432 log.log('Plotting', self.name)
423
433
424 try:
434 try:
425 self.plot()
435 self.plot()
426 self.format()
436 self.format()
427 except:
437 except:
428 log.warning('{} Plot could not be updated... check data'.format(self.CODE), self.name)
438 log.warning('{} Plot could not be updated... check data'.format(self.CODE), self.name)
429
439
430 for n, fig in enumerate(self.figures):
440 for n, fig in enumerate(self.figures):
431 if self.nrows == 0 or self.nplots == 0:
441 if self.nrows == 0 or self.nplots == 0:
432 log.warning('No data', self.name)
442 log.warning('No data', self.name)
433 fig.text(0.5, 0.5, 'No Data', fontsize='large', ha='center')
443 fig.text(0.5, 0.5, 'No Data', fontsize='large', ha='center')
434 fig.canvas.manager.set_window_title(self.CODE)
444 fig.canvas.manager.set_window_title(self.CODE)
435 continue
445 continue
436
446
437 fig.tight_layout()
447 fig.tight_layout()
438 fig.canvas.manager.set_window_title('{} - {}'.format(self.title,
448 fig.canvas.manager.set_window_title('{} - {}'.format(self.title,
439 self.getDateTime(self.max_time).strftime('%Y/%m/%d')))
449 self.getDateTime(self.max_time).strftime('%Y/%m/%d')))
440 fig.canvas.draw()
450 fig.canvas.draw()
441
451
442 if self.save and self.data.ended:
452 if self.save and (self.data.ended or not self.data.buffering):
443 channels = range(self.nrows)
453
454 if self.labels:
455 labels = self.labels
456 else:
457 labels = range(self.nrows)
458
444 if self.oneFigure:
459 if self.oneFigure:
445 label = ''
460 label = ''
446 else:
461 else:
447 label = '_{}'.format(channels[n])
462 label = '-{}'.format(labels[n])
448 figname = os.path.join(
463 figname = os.path.join(
449 self.save,
464 self.save,
465 self.CODE,
450 '{}{}_{}.png'.format(
466 '{}{}_{}.png'.format(
451 self.CODE,
467 self.CODE,
452 label,
468 label,
453 self.getDateTime(self.saveTime).strftime(
469 self.getDateTime(self.saveTime).strftime(
454 '%Y%m%d_%H%M%S'),
470 '%Y%m%d_%H%M%S'),
455 )
471 )
456 )
472 )
457 log.log('Saving figure: {}'.format(figname), self.name)
473 log.log('Saving figure: {}'.format(figname), self.name)
474 if not os.path.isdir(os.path.dirname(figname)):
475 os.makedirs(os.path.dirname(figname))
458 fig.savefig(figname)
476 fig.savefig(figname)
459
477
460 def plot(self):
478 def plot(self):
461 '''
479 '''
462 '''
480 '''
463 raise(NotImplementedError, 'Implement this method in child class')
481 raise(NotImplementedError, 'Implement this method in child class')
464
482
465 def run(self):
483 def run(self):
466
484
467 log.success('Starting', self.name)
485 log.log('Starting', self.name)
468
486
469 context = zmq.Context()
487 context = zmq.Context()
470 receiver = context.socket(zmq.SUB)
488 receiver = context.socket(zmq.SUB)
471 receiver.setsockopt(zmq.SUBSCRIBE, '')
489 receiver.setsockopt(zmq.SUBSCRIBE, '')
472 receiver.setsockopt(zmq.CONFLATE, self.CONFLATE)
490 receiver.setsockopt(zmq.CONFLATE, self.CONFLATE)
473
491
474 if 'server' in self.kwargs['parent']:
492 if 'server' in self.kwargs['parent']:
475 receiver.connect(
493 receiver.connect(
476 'ipc:///tmp/{}.plots'.format(self.kwargs['parent']['server']))
494 'ipc:///tmp/{}.plots'.format(self.kwargs['parent']['server']))
477 else:
495 else:
478 receiver.connect("ipc:///tmp/zmq.plots")
496 receiver.connect("ipc:///tmp/zmq.plots")
479
497
480 while True:
498 while True:
481 try:
499 try:
482 self.data = receiver.recv_pyobj(flags=zmq.NOBLOCK)
500 self.data = receiver.recv_pyobj(flags=zmq.NOBLOCK)
483 if self.data.localtime and self.localtime:
501 if self.data.localtime and self.localtime:
484 self.times = self.data.times
502 self.times = self.data.times
485 elif self.data.localtime and not self.localtime:
503 elif self.data.localtime and not self.localtime:
486 self.times = self.data.times + time.timezone
504 self.times = self.data.times + time.timezone
487 elif not self.data.localtime and self.localtime:
505 elif not self.data.localtime and self.localtime:
488 self.times = self.data.times - time.timezone
506 self.times = self.data.times - time.timezone
489 else:
507 else:
490 self.times = self.data.times
508 self.times = self.data.times
491
509
492 self.min_time = self.times[0]
510 self.min_time = self.times[0]
493 self.max_time = self.times[-1]
511 self.max_time = self.times[-1]
494
512
495 if self.isConfig is False:
513 if self.isConfig is False:
496 self.__setup()
514 self.__setup()
497 self.isConfig = True
515 self.isConfig = True
498
516
499 self.__plot()
517 self.__plot()
500
518
501 except zmq.Again as e:
519 except zmq.Again as e:
502 log.log('Waiting for data...')
520 log.log('.', tag='', nl=False)
503 if self.data:
521 if self.data:
504 figpause(self.data.throttle)
522 figpause(self.data.throttle)
505 else:
523 else:
506 time.sleep(2)
524 time.sleep(2)
507
525
508 def close(self):
526 def close(self):
509 if self.data:
527 if self.data:
510 self.__plot()
528 self.__plot()
511
529
512
530
513 class PlotSpectraData(PlotData):
531 class PlotSpectraData(PlotData):
514 '''
532 '''
515 Plot for Spectra data
533 Plot for Spectra data
516 '''
534 '''
517
535
518 CODE = 'spc'
536 CODE = 'spc'
519 colormap = 'jro'
537 colormap = 'jro'
520
538
521 def setup(self):
539 def setup(self):
522 self.nplots = len(self.data.channels)
540 self.nplots = len(self.data.channels)
523 self.ncols = int(numpy.sqrt(self.nplots) + 0.9)
541 self.ncols = int(numpy.sqrt(self.nplots) + 0.9)
524 self.nrows = int((1.0 * self.nplots / self.ncols) + 0.9)
542 self.nrows = int((1.0 * self.nplots / self.ncols) + 0.9)
525 self.width = 3.4 * self.ncols
543 self.width = 3.4 * self.ncols
526 self.height = 3 * self.nrows
544 self.height = 3 * self.nrows
527 self.cb_label = 'dB'
545 self.cb_label = 'dB'
528 if self.showprofile:
546 if self.showprofile:
529 self.width += 0.8 * self.ncols
547 self.width += 0.8 * self.ncols
530
548
531 self.ylabel = 'Range [km]'
549 self.ylabel = 'Range [km]'
532
550
533 def plot(self):
551 def plot(self):
534 if self.xaxis == "frequency":
552 if self.xaxis == "frequency":
535 x = self.data.xrange[0]
553 x = self.data.xrange[0]
536 self.xlabel = "Frequency (kHz)"
554 self.xlabel = "Frequency (kHz)"
537 elif self.xaxis == "time":
555 elif self.xaxis == "time":
538 x = self.data.xrange[1]
556 x = self.data.xrange[1]
539 self.xlabel = "Time (ms)"
557 self.xlabel = "Time (ms)"
540 else:
558 else:
541 x = self.data.xrange[2]
559 x = self.data.xrange[2]
542 self.xlabel = "Velocity (m/s)"
560 self.xlabel = "Velocity (m/s)"
543
561
544 if self.CODE == 'spc_mean':
562 if self.CODE == 'spc_mean':
545 x = self.data.xrange[2]
563 x = self.data.xrange[2]
546 self.xlabel = "Velocity (m/s)"
564 self.xlabel = "Velocity (m/s)"
547
565
548 self.titles = []
566 self.titles = []
549
567
550 y = self.data.heights
568 y = self.data.heights
551 self.y = y
569 self.y = y
552 z = self.data['spc']
570 z = self.data['spc']
553
571
554 for n, ax in enumerate(self.axes):
572 for n, ax in enumerate(self.axes):
555 noise = self.data['noise'][n][-1]
573 noise = self.data['noise'][n][-1]
556 if self.CODE == 'spc_mean':
574 if self.CODE == 'spc_mean':
557 mean = self.data['mean'][n][-1]
575 mean = self.data['mean'][n][-1]
558 if ax.firsttime:
576 if ax.firsttime:
559 self.xmax = self.xmax if self.xmax else numpy.nanmax(x)
577 self.xmax = self.xmax if self.xmax else numpy.nanmax(x)
560 self.xmin = self.xmin if self.xmin else -self.xmax
578 self.xmin = self.xmin if self.xmin else -self.xmax
561 self.zmin = self.zmin if self.zmin else numpy.nanmin(z)
579 self.zmin = self.zmin if self.zmin else numpy.nanmin(z)
562 self.zmax = self.zmax if self.zmax else numpy.nanmax(z)
580 self.zmax = self.zmax if self.zmax else numpy.nanmax(z)
563 ax.plt = ax.pcolormesh(x, y, z[n].T,
581 ax.plt = ax.pcolormesh(x, y, z[n].T,
564 vmin=self.zmin,
582 vmin=self.zmin,
565 vmax=self.zmax,
583 vmax=self.zmax,
566 cmap=plt.get_cmap(self.colormap)
584 cmap=plt.get_cmap(self.colormap)
567 )
585 )
568
586
569 if self.showprofile:
587 if self.showprofile:
570 ax.plt_profile = self.pf_axes[n].plot(
588 ax.plt_profile = self.pf_axes[n].plot(
571 self.data['rti'][n][-1], y)[0]
589 self.data['rti'][n][-1], y)[0]
572 ax.plt_noise = self.pf_axes[n].plot(numpy.repeat(noise, len(y)), y,
590 ax.plt_noise = self.pf_axes[n].plot(numpy.repeat(noise, len(y)), y,
573 color="k", linestyle="dashed", lw=1)[0]
591 color="k", linestyle="dashed", lw=1)[0]
574 if self.CODE == 'spc_mean':
592 if self.CODE == 'spc_mean':
575 ax.plt_mean = ax.plot(mean, y, color='k')[0]
593 ax.plt_mean = ax.plot(mean, y, color='k')[0]
576 else:
594 else:
577 ax.plt.set_array(z[n].T.ravel())
595 ax.plt.set_array(z[n].T.ravel())
578 if self.showprofile:
596 if self.showprofile:
579 ax.plt_profile.set_data(self.data['rti'][n][-1], y)
597 ax.plt_profile.set_data(self.data['rti'][n][-1], y)
580 ax.plt_noise.set_data(numpy.repeat(noise, len(y)), y)
598 ax.plt_noise.set_data(numpy.repeat(noise, len(y)), y)
581 if self.CODE == 'spc_mean':
599 if self.CODE == 'spc_mean':
582 ax.plt_mean.set_data(mean, y)
600 ax.plt_mean.set_data(mean, y)
583
601
584 self.titles.append('CH {}: {:3.2f}dB'.format(n, noise))
602 self.titles.append('CH {}: {:3.2f}dB'.format(n, noise))
585 self.saveTime = self.max_time
603 self.saveTime = self.max_time
586
604
587
605
588 class PlotCrossSpectraData(PlotData):
606 class PlotCrossSpectraData(PlotData):
589
607
590 CODE = 'cspc'
608 CODE = 'cspc'
591 zmin_coh = None
609 zmin_coh = None
592 zmax_coh = None
610 zmax_coh = None
593 zmin_phase = None
611 zmin_phase = None
594 zmax_phase = None
612 zmax_phase = None
595
613
596 def setup(self):
614 def setup(self):
597
615
598 self.ncols = 4
616 self.ncols = 4
599 self.nrows = len(self.data.pairs)
617 self.nrows = len(self.data.pairs)
600 self.nplots = self.nrows * 4
618 self.nplots = self.nrows * 4
601 self.width = 3.4 * self.ncols
619 self.width = 3.4 * self.ncols
602 self.height = 3 * self.nrows
620 self.height = 3 * self.nrows
603 self.ylabel = 'Range [km]'
621 self.ylabel = 'Range [km]'
604 self.showprofile = False
622 self.showprofile = False
605
623
606 def plot(self):
624 def plot(self):
607
625
608 if self.xaxis == "frequency":
626 if self.xaxis == "frequency":
609 x = self.data.xrange[0]
627 x = self.data.xrange[0]
610 self.xlabel = "Frequency (kHz)"
628 self.xlabel = "Frequency (kHz)"
611 elif self.xaxis == "time":
629 elif self.xaxis == "time":
612 x = self.data.xrange[1]
630 x = self.data.xrange[1]
613 self.xlabel = "Time (ms)"
631 self.xlabel = "Time (ms)"
614 else:
632 else:
615 x = self.data.xrange[2]
633 x = self.data.xrange[2]
616 self.xlabel = "Velocity (m/s)"
634 self.xlabel = "Velocity (m/s)"
617
635
618 self.titles = []
636 self.titles = []
619
637
620 y = self.data.heights
638 y = self.data.heights
621 self.y = y
639 self.y = y
622 spc = self.data['spc']
640 spc = self.data['spc']
623 cspc = self.data['cspc']
641 cspc = self.data['cspc']
624
642
625 for n in range(self.nrows):
643 for n in range(self.nrows):
626 noise = self.data['noise'][n][-1]
644 noise = self.data['noise'][n][-1]
627 pair = self.data.pairs[n]
645 pair = self.data.pairs[n]
628 ax = self.axes[4 * n]
646 ax = self.axes[4 * n]
629 ax3 = self.axes[4 * n + 3]
647 ax3 = self.axes[4 * n + 3]
630 if ax.firsttime:
648 if ax.firsttime:
631 self.xmax = self.xmax if self.xmax else numpy.nanmax(x)
649 self.xmax = self.xmax if self.xmax else numpy.nanmax(x)
632 self.xmin = self.xmin if self.xmin else -self.xmax
650 self.xmin = self.xmin if self.xmin else -self.xmax
633 self.zmin = self.zmin if self.zmin else numpy.nanmin(spc)
651 self.zmin = self.zmin if self.zmin else numpy.nanmin(spc)
634 self.zmax = self.zmax if self.zmax else numpy.nanmax(spc)
652 self.zmax = self.zmax if self.zmax else numpy.nanmax(spc)
635 ax.plt = ax.pcolormesh(x, y, spc[pair[0]].T,
653 ax.plt = ax.pcolormesh(x, y, spc[pair[0]].T,
636 vmin=self.zmin,
654 vmin=self.zmin,
637 vmax=self.zmax,
655 vmax=self.zmax,
638 cmap=plt.get_cmap(self.colormap)
656 cmap=plt.get_cmap(self.colormap)
639 )
657 )
640 else:
658 else:
641 ax.plt.set_array(spc[pair[0]].T.ravel())
659 ax.plt.set_array(spc[pair[0]].T.ravel())
642 self.titles.append('CH {}: {:3.2f}dB'.format(n, noise))
660 self.titles.append('CH {}: {:3.2f}dB'.format(n, noise))
643
661
644 ax = self.axes[4 * n + 1]
662 ax = self.axes[4 * n + 1]
645 if ax.firsttime:
663 if ax.firsttime:
646 ax.plt = ax.pcolormesh(x, y, spc[pair[1]].T,
664 ax.plt = ax.pcolormesh(x, y, spc[pair[1]].T,
647 vmin=self.zmin,
665 vmin=self.zmin,
648 vmax=self.zmax,
666 vmax=self.zmax,
649 cmap=plt.get_cmap(self.colormap)
667 cmap=plt.get_cmap(self.colormap)
650 )
668 )
651 else:
669 else:
652 ax.plt.set_array(spc[pair[1]].T.ravel())
670 ax.plt.set_array(spc[pair[1]].T.ravel())
653 self.titles.append('CH {}: {:3.2f}dB'.format(n, noise))
671 self.titles.append('CH {}: {:3.2f}dB'.format(n, noise))
654
672
655 out = cspc[n] / numpy.sqrt(spc[pair[0]] * spc[pair[1]])
673 out = cspc[n] / numpy.sqrt(spc[pair[0]] * spc[pair[1]])
656 coh = numpy.abs(out)
674 coh = numpy.abs(out)
657 phase = numpy.arctan2(out.imag, out.real) * 180 / numpy.pi
675 phase = numpy.arctan2(out.imag, out.real) * 180 / numpy.pi
658
676
659 ax = self.axes[4 * n + 2]
677 ax = self.axes[4 * n + 2]
660 if ax.firsttime:
678 if ax.firsttime:
661 ax.plt = ax.pcolormesh(x, y, coh.T,
679 ax.plt = ax.pcolormesh(x, y, coh.T,
662 vmin=0,
680 vmin=0,
663 vmax=1,
681 vmax=1,
664 cmap=plt.get_cmap(self.colormap_coh)
682 cmap=plt.get_cmap(self.colormap_coh)
665 )
683 )
666 else:
684 else:
667 ax.plt.set_array(coh.T.ravel())
685 ax.plt.set_array(coh.T.ravel())
668 self.titles.append(
686 self.titles.append(
669 'Coherence Ch{} * Ch{}'.format(pair[0], pair[1]))
687 'Coherence Ch{} * Ch{}'.format(pair[0], pair[1]))
670
688
671 ax = self.axes[4 * n + 3]
689 ax = self.axes[4 * n + 3]
672 if ax.firsttime:
690 if ax.firsttime:
673 ax.plt = ax.pcolormesh(x, y, phase.T,
691 ax.plt = ax.pcolormesh(x, y, phase.T,
674 vmin=-180,
692 vmin=-180,
675 vmax=180,
693 vmax=180,
676 cmap=plt.get_cmap(self.colormap_phase)
694 cmap=plt.get_cmap(self.colormap_phase)
677 )
695 )
678 else:
696 else:
679 ax.plt.set_array(phase.T.ravel())
697 ax.plt.set_array(phase.T.ravel())
680 self.titles.append('Phase CH{} * CH{}'.format(pair[0], pair[1]))
698 self.titles.append('Phase CH{} * CH{}'.format(pair[0], pair[1]))
681
699
682 self.saveTime = self.max_time
700 self.saveTime = self.max_time
683
701
684
702
685 class PlotSpectraMeanData(PlotSpectraData):
703 class PlotSpectraMeanData(PlotSpectraData):
686 '''
704 '''
687 Plot for Spectra and Mean
705 Plot for Spectra and Mean
688 '''
706 '''
689 CODE = 'spc_mean'
707 CODE = 'spc_mean'
690 colormap = 'jro'
708 colormap = 'jro'
691
709
692
710
693 class PlotRTIData(PlotData):
711 class PlotRTIData(PlotData):
694 '''
712 '''
695 Plot for RTI data
713 Plot for RTI data
696 '''
714 '''
697
715
698 CODE = 'rti'
716 CODE = 'rti'
699 colormap = 'jro'
717 colormap = 'jro'
700
718
701 def setup(self):
719 def setup(self):
702 self.xaxis = 'time'
720 self.xaxis = 'time'
703 self.ncols = 1
721 self.ncols = 1
704 self.nrows = len(self.data.channels)
722 self.nrows = len(self.data.channels)
705 self.nplots = len(self.data.channels)
723 self.nplots = len(self.data.channels)
706 self.ylabel = 'Range [km]'
724 self.ylabel = 'Range [km]'
707 self.cb_label = 'dB'
725 self.cb_label = 'dB'
708 self.titles = ['{} Channel {}'.format(
726 self.titles = ['{} Channel {}'.format(
709 self.CODE.upper(), x) for x in range(self.nrows)]
727 self.CODE.upper(), x) for x in range(self.nrows)]
710
728
711 def plot(self):
729 def plot(self):
712 self.x = self.times
730 self.x = self.times
713 self.y = self.data.heights
731 self.y = self.data.heights
714 self.z = self.data[self.CODE]
732 self.z = self.data[self.CODE]
715 self.z = numpy.ma.masked_invalid(self.z)
733 self.z = numpy.ma.masked_invalid(self.z)
716
734
717 if self.decimation is None:
735 if self.decimation is None:
718 x, y, z = self.fill_gaps(self.x, self.y, self.z)
736 x, y, z = self.fill_gaps(self.x, self.y, self.z)
719 else:
737 else:
720 x, y, z = self.fill_gaps(*self.decimate())
738 x, y, z = self.fill_gaps(*self.decimate())
721
739
722 for n, ax in enumerate(self.axes):
740 for n, ax in enumerate(self.axes):
723 self.zmin = self.zmin if self.zmin else numpy.min(self.z)
741 self.zmin = self.zmin if self.zmin else numpy.min(self.z)
724 self.zmax = self.zmax if self.zmax else numpy.max(self.z)
742 self.zmax = self.zmax if self.zmax else numpy.max(self.z)
725 if ax.firsttime:
743 if ax.firsttime:
726 ax.plt = ax.pcolormesh(x, y, z[n].T,
744 ax.plt = ax.pcolormesh(x, y, z[n].T,
727 vmin=self.zmin,
745 vmin=self.zmin,
728 vmax=self.zmax,
746 vmax=self.zmax,
729 cmap=plt.get_cmap(self.colormap)
747 cmap=plt.get_cmap(self.colormap)
730 )
748 )
731 if self.showprofile:
749 if self.showprofile:
732 ax.plot_profile = self.pf_axes[n].plot(
750 ax.plot_profile = self.pf_axes[n].plot(
733 self.data['rti'][n][-1], self.y)[0]
751 self.data['rti'][n][-1], self.y)[0]
734 ax.plot_noise = self.pf_axes[n].plot(numpy.repeat(self.data['noise'][n][-1], len(self.y)), self.y,
752 ax.plot_noise = self.pf_axes[n].plot(numpy.repeat(self.data['noise'][n][-1], len(self.y)), self.y,
735 color="k", linestyle="dashed", lw=1)[0]
753 color="k", linestyle="dashed", lw=1)[0]
736 else:
754 else:
737 ax.collections.remove(ax.collections[0])
755 ax.collections.remove(ax.collections[0])
738 ax.plt = ax.pcolormesh(x, y, z[n].T,
756 ax.plt = ax.pcolormesh(x, y, z[n].T,
739 vmin=self.zmin,
757 vmin=self.zmin,
740 vmax=self.zmax,
758 vmax=self.zmax,
741 cmap=plt.get_cmap(self.colormap)
759 cmap=plt.get_cmap(self.colormap)
742 )
760 )
743 if self.showprofile:
761 if self.showprofile:
744 ax.plot_profile.set_data(self.data['rti'][n][-1], self.y)
762 ax.plot_profile.set_data(self.data['rti'][n][-1], self.y)
745 ax.plot_noise.set_data(numpy.repeat(
763 ax.plot_noise.set_data(numpy.repeat(
746 self.data['noise'][n][-1], len(self.y)), self.y)
764 self.data['noise'][n][-1], len(self.y)), self.y)
747
765
748 self.saveTime = self.min_time
766 self.saveTime = self.min_time
749
767
750
768
751 class PlotCOHData(PlotRTIData):
769 class PlotCOHData(PlotRTIData):
752 '''
770 '''
753 Plot for Coherence data
771 Plot for Coherence data
754 '''
772 '''
755
773
756 CODE = 'coh'
774 CODE = 'coh'
757
775
758 def setup(self):
776 def setup(self):
759 self.xaxis = 'time'
777 self.xaxis = 'time'
760 self.ncols = 1
778 self.ncols = 1
761 self.nrows = len(self.data.pairs)
779 self.nrows = len(self.data.pairs)
762 self.nplots = len(self.data.pairs)
780 self.nplots = len(self.data.pairs)
763 self.ylabel = 'Range [km]'
781 self.ylabel = 'Range [km]'
764 if self.CODE == 'coh':
782 if self.CODE == 'coh':
765 self.cb_label = ''
783 self.cb_label = ''
766 self.titles = [
784 self.titles = [
767 'Coherence Map Ch{} * Ch{}'.format(x[0], x[1]) for x in self.data.pairs]
785 'Coherence Map Ch{} * Ch{}'.format(x[0], x[1]) for x in self.data.pairs]
768 else:
786 else:
769 self.cb_label = 'Degrees'
787 self.cb_label = 'Degrees'
770 self.titles = [
788 self.titles = [
771 'Phase Map Ch{} * Ch{}'.format(x[0], x[1]) for x in self.data.pairs]
789 'Phase Map Ch{} * Ch{}'.format(x[0], x[1]) for x in self.data.pairs]
772
790
773
791
774 class PlotPHASEData(PlotCOHData):
792 class PlotPHASEData(PlotCOHData):
775 '''
793 '''
776 Plot for Phase map data
794 Plot for Phase map data
777 '''
795 '''
778
796
779 CODE = 'phase'
797 CODE = 'phase'
780 colormap = 'seismic'
798 colormap = 'seismic'
781
799
782
800
783 class PlotNoiseData(PlotData):
801 class PlotNoiseData(PlotData):
784 '''
802 '''
785 Plot for noise
803 Plot for noise
786 '''
804 '''
787
805
788 CODE = 'noise'
806 CODE = 'noise'
789
807
790 def setup(self):
808 def setup(self):
791 self.xaxis = 'time'
809 self.xaxis = 'time'
792 self.ncols = 1
810 self.ncols = 1
793 self.nrows = 1
811 self.nrows = 1
794 self.nplots = 1
812 self.nplots = 1
795 self.ylabel = 'Intensity [dB]'
813 self.ylabel = 'Intensity [dB]'
796 self.titles = ['Noise']
814 self.titles = ['Noise']
797 self.colorbar = False
815 self.colorbar = False
798
816
799 def plot(self):
817 def plot(self):
800
818
801 x = self.times
819 x = self.times
802 xmin = self.min_time
820 xmin = self.min_time
803 xmax = xmin + self.xrange * 60 * 60
821 xmax = xmin + self.xrange * 60 * 60
804 Y = self.data[self.CODE]
822 Y = self.data[self.CODE]
805
823
806 if self.axes[0].firsttime:
824 if self.axes[0].firsttime:
807 for ch in self.data.channels:
825 for ch in self.data.channels:
808 y = Y[ch]
826 y = Y[ch]
809 self.axes[0].plot(x, y, lw=1, label='Ch{}'.format(ch))
827 self.axes[0].plot(x, y, lw=1, label='Ch{}'.format(ch))
810 plt.legend()
828 plt.legend()
811 else:
829 else:
812 for ch in self.data.channels:
830 for ch in self.data.channels:
813 y = Y[ch]
831 y = Y[ch]
814 self.axes[0].lines[ch].set_data(x, y)
832 self.axes[0].lines[ch].set_data(x, y)
815
833
816 self.ymin = numpy.nanmin(Y) - 5
834 self.ymin = numpy.nanmin(Y) - 5
817 self.ymax = numpy.nanmax(Y) + 5
835 self.ymax = numpy.nanmax(Y) + 5
818 self.saveTime = self.min_time
836 self.saveTime = self.min_time
819
837
820
838
821 class PlotSNRData(PlotRTIData):
839 class PlotSNRData(PlotRTIData):
822 '''
840 '''
823 Plot for SNR Data
841 Plot for SNR Data
824 '''
842 '''
825
843
826 CODE = 'snr'
844 CODE = 'snr'
827 colormap = 'jet'
845 colormap = 'jet'
828
846
829
847
830 class PlotDOPData(PlotRTIData):
848 class PlotDOPData(PlotRTIData):
831 '''
849 '''
832 Plot for DOPPLER Data
850 Plot for DOPPLER Data
833 '''
851 '''
834
852
835 CODE = 'dop'
853 CODE = 'dop'
836 colormap = 'jet'
854 colormap = 'jet'
837
855
838
856
839 class PlotSkyMapData(PlotData):
857 class PlotSkyMapData(PlotData):
840 '''
858 '''
841 Plot for meteors detection data
859 Plot for meteors detection data
842 '''
860 '''
843
861
844 CODE = 'param'
862 CODE = 'param'
845
863
846 def setup(self):
864 def setup(self):
847
865
848 self.ncols = 1
866 self.ncols = 1
849 self.nrows = 1
867 self.nrows = 1
850 self.width = 7.2
868 self.width = 7.2
851 self.height = 7.2
869 self.height = 7.2
852 self.nplots = 1
870 self.nplots = 1
853 self.xlabel = 'Zonal Zenith Angle (deg)'
871 self.xlabel = 'Zonal Zenith Angle (deg)'
854 self.ylabel = 'Meridional Zenith Angle (deg)'
872 self.ylabel = 'Meridional Zenith Angle (deg)'
855 self.polar = True
873 self.polar = True
856 self.ymin = -180
874 self.ymin = -180
857 self.ymax = 180
875 self.ymax = 180
858 self.colorbar = False
876 self.colorbar = False
859
877
860 def plot(self):
878 def plot(self):
861
879
862 arrayParameters = numpy.concatenate(self.data['param'])
880 arrayParameters = numpy.concatenate(self.data['param'])
863 error = arrayParameters[:, -1]
881 error = arrayParameters[:, -1]
864 indValid = numpy.where(error == 0)[0]
882 indValid = numpy.where(error == 0)[0]
865 finalMeteor = arrayParameters[indValid, :]
883 finalMeteor = arrayParameters[indValid, :]
866 finalAzimuth = finalMeteor[:, 3]
884 finalAzimuth = finalMeteor[:, 3]
867 finalZenith = finalMeteor[:, 4]
885 finalZenith = finalMeteor[:, 4]
868
886
869 x = finalAzimuth * numpy.pi / 180
887 x = finalAzimuth * numpy.pi / 180
870 y = finalZenith
888 y = finalZenith
871
889
872 ax = self.axes[0]
890 ax = self.axes[0]
873
891
874 if ax.firsttime:
892 if ax.firsttime:
875 ax.plot = ax.plot(x, y, 'bo', markersize=5)[0]
893 ax.plot = ax.plot(x, y, 'bo', markersize=5)[0]
876 else:
894 else:
877 ax.plot.set_data(x, y)
895 ax.plot.set_data(x, y)
878
896
879 dt1 = self.getDateTime(self.min_time).strftime('%y/%m/%d %H:%M:%S')
897 dt1 = self.getDateTime(self.min_time).strftime('%y/%m/%d %H:%M:%S')
880 dt2 = self.getDateTime(self.max_time).strftime('%y/%m/%d %H:%M:%S')
898 dt2 = self.getDateTime(self.max_time).strftime('%y/%m/%d %H:%M:%S')
881 title = 'Meteor Detection Sky Map\n %s - %s \n Number of events: %5.0f\n' % (dt1,
899 title = 'Meteor Detection Sky Map\n %s - %s \n Number of events: %5.0f\n' % (dt1,
882 dt2,
900 dt2,
883 len(x))
901 len(x))
884 self.titles[0] = title
902 self.titles[0] = title
885 self.saveTime = self.max_time
903 self.saveTime = self.max_time
886
904
887
905
888 class PlotParamData(PlotRTIData):
906 class PlotParamData(PlotRTIData):
889 '''
907 '''
890 Plot for data_param object
908 Plot for data_param object
891 '''
909 '''
892
910
893 CODE = 'param'
911 CODE = 'param'
894 colormap = 'seismic'
912 colormap = 'seismic'
895
913
896 def setup(self):
914 def setup(self):
897 self.xaxis = 'time'
915 self.xaxis = 'time'
898 self.ncols = 1
916 self.ncols = 1
899 self.nrows = self.data.shape(self.CODE)[0]
917 self.nrows = self.data.shape(self.CODE)[0]
900 self.nplots = self.nrows
918 self.nplots = self.nrows
901 if self.showSNR:
919 if self.showSNR:
902 self.nrows += 1
920 self.nrows += 1
903 self.nplots += 1
921 self.nplots += 1
904
922
905 self.ylabel = 'Height [km]'
923 self.ylabel = 'Height [km]'
906 if not self.titles:
924 if not self.titles:
907 self.titles = self.data.parameters \
925 self.titles = self.data.parameters \
908 if self.data.parameters else ['Param {}'.format(x) for x in xrange(self.nrows)]
926 if self.data.parameters else ['Param {}'.format(x) for x in xrange(self.nrows)]
909 if self.showSNR:
927 if self.showSNR:
910 self.titles.append('SNR')
928 self.titles.append('SNR')
911
929
912 def plot(self):
930 def plot(self):
913 self.data.normalize_heights()
931 self.data.normalize_heights()
914 self.x = self.times
932 self.x = self.times
915 self.y = self.data.heights
933 self.y = self.data.heights
916 if self.showSNR:
934 if self.showSNR:
917 self.z = numpy.concatenate(
935 self.z = numpy.concatenate(
918 (self.data[self.CODE], self.data['snr'])
936 (self.data[self.CODE], self.data['snr'])
919 )
937 )
920 else:
938 else:
921 self.z = self.data[self.CODE]
939 self.z = self.data[self.CODE]
922
940
923 self.z = numpy.ma.masked_invalid(self.z)
941 self.z = numpy.ma.masked_invalid(self.z)
924
942
925 if self.decimation is None:
943 if self.decimation is None:
926 x, y, z = self.fill_gaps(self.x, self.y, self.z)
944 x, y, z = self.fill_gaps(self.x, self.y, self.z)
927 else:
945 else:
928 x, y, z = self.fill_gaps(*self.decimate())
946 x, y, z = self.fill_gaps(*self.decimate())
929
947
930 for n, ax in enumerate(self.axes):
948 for n, ax in enumerate(self.axes):
931
949
932 self.zmax = self.zmax if self.zmax is not None else numpy.max(
950 self.zmax = self.zmax if self.zmax is not None else numpy.max(
933 self.z[n])
951 self.z[n])
934 self.zmin = self.zmin if self.zmin is not None else numpy.min(
952 self.zmin = self.zmin if self.zmin is not None else numpy.min(
935 self.z[n])
953 self.z[n])
936
954
937 if ax.firsttime:
955 if ax.firsttime:
938 if self.zlimits is not None:
956 if self.zlimits is not None:
939 self.zmin, self.zmax = self.zlimits[n]
957 self.zmin, self.zmax = self.zlimits[n]
940
958
941 ax.plt = ax.pcolormesh(x, y, z[n].T * self.factors[n],
959 ax.plt = ax.pcolormesh(x, y, z[n].T * self.factors[n],
942 vmin=self.zmin,
960 vmin=self.zmin,
943 vmax=self.zmax,
961 vmax=self.zmax,
944 cmap=self.cmaps[n]
962 cmap=self.cmaps[n]
945 )
963 )
946 else:
964 else:
947 if self.zlimits is not None:
965 if self.zlimits is not None:
948 self.zmin, self.zmax = self.zlimits[n]
966 self.zmin, self.zmax = self.zlimits[n]
949 ax.collections.remove(ax.collections[0])
967 ax.collections.remove(ax.collections[0])
950 ax.plt = ax.pcolormesh(x, y, z[n].T * self.factors[n],
968 ax.plt = ax.pcolormesh(x, y, z[n].T * self.factors[n],
951 vmin=self.zmin,
969 vmin=self.zmin,
952 vmax=self.zmax,
970 vmax=self.zmax,
953 cmap=self.cmaps[n]
971 cmap=self.cmaps[n]
954 )
972 )
955
973
956 self.saveTime = self.min_time
974 self.saveTime = self.min_time
957
975
958
976
959 class PlotOutputData(PlotParamData):
977 class PlotOutputData(PlotParamData):
960 '''
978 '''
961 Plot data_output object
979 Plot data_output object
962 '''
980 '''
963
981
964 CODE = 'output'
982 CODE = 'output'
965 colormap = 'seismic'
983 colormap = 'seismic'
984
985
986 class PlotPolarMapData(PlotData):
987 '''
988 Plot for meteors detection data
989 '''
990
991 CODE = 'param'
992 colormap = 'seismic'
993
994 def setup(self):
995 self.ncols = 1
996 self.nrows = 1
997 self.width = 9
998 self.height = 8
999 if self.channels is not None:
1000 self.nplots = len(self.channels)
1001 self.nrows = len(self.channels)
1002 else:
1003 self.nplots = self.data.shape(self.CODE)[0]
1004 self.nrows = self.nplots
1005 self.channels = range(self.nplots)
1006 self.xlabel = 'Zonal Distance (km)'
1007 self.ylabel = 'Meridional Distance (km)'
1008 self.bgcolor = 'white'
1009
1010 def plot(self):
1011
1012 for n, ax in enumerate(self.axes):
1013 data = self.data['param'][self.channels[n]]
1014
1015 zeniths = numpy.arange(data.shape[1])
1016 azimuths = -numpy.radians(self.data.heights)+numpy.pi/2
1017 self.y = zeniths
1018
1019 r, theta = numpy.meshgrid(zeniths, azimuths)
1020 x, y = r*numpy.cos(theta), r*numpy.sin(theta)
1021
1022 if ax.firsttime:
1023 if self.zlimits is not None:
1024 self.zmin, self.zmax = self.zlimits[n]
1025 ax.plt = ax.pcolormesh(x, y, numpy.ma.array(data, mask=numpy.isnan(data)),
1026 vmin=self.zmin,
1027 vmax=self.zmax,
1028 cmap=self.cmaps[n])
1029 else:
1030 if self.zlimits is not None:
1031 self.zmin, self.zmax = self.zlimits[n]
1032 ax.collections.remove(ax.collections[0])
1033 ax.plt = ax.pcolormesh(x, y, numpy.ma.array(data, mask=numpy.isnan(data)),
1034 vmin=self.zmin,
1035 vmax=self.zmax,
1036 cmap=self.cmaps[n])
1037
1038
1039 title = ''
1040
1041 self.titles = [self.data.parameters[x] for x in self.channels]
1042 self.saveTime = self.max_time
@@ -1,21 +1,23
1 '''
1 '''
2
2
3 $Author: murco $
3 $Author: murco $
4 $Id: JRODataIO.py 169 2012-11-19 21:57:03Z murco $
4 $Id: JRODataIO.py 169 2012-11-19 21:57:03Z murco $
5 '''
5 '''
6
6
7 from jroIO_voltage import *
7 from jroIO_voltage import *
8 from jroIO_spectra import *
8 from jroIO_spectra import *
9 from jroIO_heispectra import *
9 from jroIO_heispectra import *
10 from jroIO_usrp import *
10 from jroIO_usrp import *
11 from jroIO_digitalRF import *
11 from jroIO_digitalRF import *
12 from jroIO_kamisr import *
12 from jroIO_kamisr import *
13 from jroIO_param import *
13 from jroIO_param import *
14 from jroIO_hf import *
14 from jroIO_hf import *
15
15
16 from jroIO_madrigal import *
16 from jroIO_madrigal import *
17
17
18 from bltrIO_param import *
18 from bltrIO_param import *
19 from jroIO_bltr import *
19 from jroIO_bltr import *
20 from jroIO_mira35c import *
20 from jroIO_mira35c import *
21 from julIO_param import * No newline at end of file
21 from julIO_param import *
22
23 from pxIO_param import * No newline at end of file
General Comments 0
You need to be logged in to leave comments. Login now