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