1 |
#!/usr/bin/env python |
---|
2 |
# -*- coding: utf-8 -*- |
---|
3 |
|
---|
4 |
__version__ = '1.4cbc1' |
---|
5 |
__author__ = 'Lionel Roubeyrie' |
---|
6 |
__mail__ = 'lionel.roubeyrie@gmail.com' |
---|
7 |
__license__ = 'CeCILL-B' |
---|
8 |
__modified_by__ = 'Chris Calloway' |
---|
9 |
__modified_email__ = 'cbc@unc.edu' |
---|
10 |
|
---|
11 |
import matplotlib |
---|
12 |
import matplotlib.cm as cm |
---|
13 |
import numpy as np |
---|
14 |
from matplotlib.patches import Rectangle, Polygon |
---|
15 |
from matplotlib.ticker import ScalarFormatter, AutoLocator |
---|
16 |
from matplotlib.text import Text, FontProperties |
---|
17 |
from matplotlib.projections.polar import PolarAxes |
---|
18 |
from numpy.lib.twodim_base import histogram2d |
---|
19 |
import matplotlib.pyplot as plt |
---|
20 |
from pylab import poly_between |
---|
21 |
|
---|
22 |
RESOLUTION = 100 |
---|
23 |
ZBASE = -1000 #The starting zorder for all drawing, negative to have the grid on |
---|
24 |
|
---|
25 |
class WindroseAxes(PolarAxes): |
---|
26 |
""" |
---|
27 |
|
---|
28 |
Create a windrose axes |
---|
29 |
|
---|
30 |
""" |
---|
31 |
|
---|
32 |
def __init__(self, *args, **kwargs): |
---|
33 |
""" |
---|
34 |
See Axes base class for args and kwargs documentation |
---|
35 |
""" |
---|
36 |
|
---|
37 |
#Uncomment to have the possibility to change the resolution directly |
---|
38 |
#when the instance is created |
---|
39 |
#self.RESOLUTION = kwargs.pop('resolution', 100) |
---|
40 |
PolarAxes.__init__(self, *args, **kwargs) |
---|
41 |
self.set_aspect('equal', adjustable='box', anchor='C') |
---|
42 |
self.radii_angle = 67.5 |
---|
43 |
self.cla() |
---|
44 |
|
---|
45 |
|
---|
46 |
def cla(self): |
---|
47 |
""" |
---|
48 |
Clear the current axes |
---|
49 |
""" |
---|
50 |
PolarAxes.cla(self) |
---|
51 |
|
---|
52 |
self.theta_angles = np.arange(0, 360, 45) |
---|
53 |
self.theta_labels = ['E', 'N-E', 'N', 'N-W', 'W', 'S-W', 'S', 'S-E'] |
---|
54 |
self.set_thetagrids(angles=self.theta_angles, labels=self.theta_labels) |
---|
55 |
|
---|
56 |
self._info = {'dir' : list(), |
---|
57 |
'bins' : list(), |
---|
58 |
'table' : list()} |
---|
59 |
|
---|
60 |
self.patches_list = list() |
---|
61 |
|
---|
62 |
|
---|
63 |
def _colors(self, cmap, n): |
---|
64 |
''' |
---|
65 |
Returns a list of n colors based on the colormap cmap |
---|
66 |
|
---|
67 |
''' |
---|
68 |
return [cmap(i) for i in np.linspace(0.0, 1.0, n)] |
---|
69 |
|
---|
70 |
|
---|
71 |
def set_radii_angle(self, **kwargs): |
---|
72 |
""" |
---|
73 |
Set the radii labels angle |
---|
74 |
""" |
---|
75 |
|
---|
76 |
null = kwargs.pop('labels', None) |
---|
77 |
angle = kwargs.pop('angle', None) |
---|
78 |
if angle is None: |
---|
79 |
angle = self.radii_angle |
---|
80 |
self.radii_angle = angle |
---|
81 |
radii = np.linspace(0.1, self.get_rmax(), 6) |
---|
82 |
radii_labels = [ "%.1f" %r for r in radii ] |
---|
83 |
radii_labels[0] = "" #Removing label 0 |
---|
84 |
null = self.set_rgrids(radii=radii, labels=radii_labels, |
---|
85 |
angle=self.radii_angle, **kwargs) |
---|
86 |
|
---|
87 |
|
---|
88 |
def _update(self): |
---|
89 |
self.set_rmax(rmax=np.max(np.sum(self._info['table'], axis=0))) |
---|
90 |
self.set_radii_angle(angle=self.radii_angle) |
---|
91 |
|
---|
92 |
|
---|
93 |
def legend(self, loc='lower left', **kwargs): |
---|
94 |
""" |
---|
95 |
Sets the legend location and her properties. |
---|
96 |
The location codes are |
---|
97 |
|
---|
98 |
'best' : 0, |
---|
99 |
'upper right' : 1, |
---|
100 |
'upper left' : 2, |
---|
101 |
'lower left' : 3, |
---|
102 |
'lower right' : 4, |
---|
103 |
'right' : 5, |
---|
104 |
'center left' : 6, |
---|
105 |
'center right' : 7, |
---|
106 |
'lower center' : 8, |
---|
107 |
'upper center' : 9, |
---|
108 |
'center' : 10, |
---|
109 |
|
---|
110 |
If none of these are suitable, loc can be a 2-tuple giving x,y |
---|
111 |
in axes coords, ie, |
---|
112 |
|
---|
113 |
loc = (0, 1) is left top |
---|
114 |
loc = (0.5, 0.5) is center, center |
---|
115 |
|
---|
116 |
and so on. The following kwargs are supported: |
---|
117 |
|
---|
118 |
isaxes=True # whether this is an axes legend |
---|
119 |
prop = FontProperties(size='smaller') # the font property |
---|
120 |
pad = 0.2 # the fractional whitespace inside the legend border |
---|
121 |
shadow # if True, draw a shadow behind legend |
---|
122 |
labelsep = 0.005 # the vertical space between the legend entries |
---|
123 |
handlelen = 0.05 # the length of the legend lines |
---|
124 |
handletextsep = 0.02 # the space between the legend line and legend text |
---|
125 |
axespad = 0.02 # the border between the axes and legend edge |
---|
126 |
""" |
---|
127 |
|
---|
128 |
def get_handles(): |
---|
129 |
handles = list() |
---|
130 |
for p in self.patches_list: |
---|
131 |
if isinstance(p, matplotlib.patches.Polygon) or \ |
---|
132 |
isinstance(p, matplotlib.patches.Rectangle): |
---|
133 |
color = p.get_facecolor() |
---|
134 |
elif isinstance(p, matplotlib.lines.Line2D): |
---|
135 |
color = p.get_color() |
---|
136 |
else: |
---|
137 |
raise AttributeError("Can't handle patches") |
---|
138 |
handles.append(Rectangle((0, 0), 0.2, 0.2, |
---|
139 |
facecolor=color, edgecolor='black')) |
---|
140 |
return handles |
---|
141 |
|
---|
142 |
def get_labels(): |
---|
143 |
labels = np.copy(self._info['bins']) |
---|
144 |
labels = ["[%.1f : %0.1f]" %(labels[i], labels[i+1]) \ |
---|
145 |
if label[i+1] != float('inf') |
---|
146 |
else "[%.1f : inf]" % labels[i] |
---|
147 |
for i in range(len(labels)-1)] |
---|
148 |
return labels |
---|
149 |
|
---|
150 |
null = kwargs.pop('labels', None) |
---|
151 |
null = kwargs.pop('handles', None) |
---|
152 |
handles = get_handles() |
---|
153 |
labels = get_labels() |
---|
154 |
self.legend_ = matplotlib.legend.Legend(self, handles, labels, |
---|
155 |
loc, **kwargs) |
---|
156 |
return self.legend_ |
---|
157 |
|
---|
158 |
|
---|
159 |
def _init_plot(self, dir, var, **kwargs): |
---|
160 |
""" |
---|
161 |
Internal method used by all plotting commands |
---|
162 |
""" |
---|
163 |
#self.cla() |
---|
164 |
null = kwargs.pop('zorder', None) |
---|
165 |
|
---|
166 |
#Init of the bins array if not set |
---|
167 |
bins = kwargs.pop('bins', None) |
---|
168 |
if bins is None: |
---|
169 |
bins = np.linspace(np.min(var), np.max(var), 6) |
---|
170 |
if isinstance(bins, int): |
---|
171 |
bins = np.linspace(np.min(var), np.max(var), bins) |
---|
172 |
bins = np.asarray(bins) |
---|
173 |
nbins = len(bins) |
---|
174 |
|
---|
175 |
#Number of sectors |
---|
176 |
nsector = kwargs.pop('nsector', None) |
---|
177 |
if nsector is None: |
---|
178 |
nsector = 16 |
---|
179 |
|
---|
180 |
#Sets the colors table based on the colormap or the "colors" argument |
---|
181 |
colors = kwargs.pop('colors', None) |
---|
182 |
cmap = kwargs.pop('cmap', None) |
---|
183 |
if colors is not None: |
---|
184 |
if isinstance(colors, str): |
---|
185 |
colors = [colors]*nbins |
---|
186 |
if isinstance(colors, (tuple, list)): |
---|
187 |
if len(colors) != nbins: |
---|
188 |
raise ValueError("colors and bins must have same length") |
---|
189 |
else: |
---|
190 |
if cmap is None: |
---|
191 |
cmap = cm.jet |
---|
192 |
colors = self._colors(cmap, nbins) |
---|
193 |
|
---|
194 |
#Building the angles list |
---|
195 |
angles = np.arange(0, -2*np.pi, -2*np.pi/nsector) + np.pi/2 |
---|
196 |
|
---|
197 |
normed = kwargs.pop('normed', False) |
---|
198 |
blowto = kwargs.pop('blowto', False) |
---|
199 |
|
---|
200 |
#Set the global information dictionnary |
---|
201 |
self._info['dir'], self._info['bins'], self._info['table'] = histogram(dir, var, bins, nsector, normed, blowto) |
---|
202 |
|
---|
203 |
return bins, nbins, nsector, colors, angles, kwargs |
---|
204 |
|
---|
205 |
|
---|
206 |
def contour(self, dir, var, **kwargs): |
---|
207 |
""" |
---|
208 |
Plot a windrose in linear mode. For each var bins, a line will be |
---|
209 |
draw on the axes, a segment between each sector (center to center). |
---|
210 |
Each line can be formated (color, width, ...) like with standard plot |
---|
211 |
pylab command. |
---|
212 |
|
---|
213 |
Mandatory: |
---|
214 |
* dir : 1D array - directions the wind blows from, North centred |
---|
215 |
* var : 1D array - values of the variable to compute. Typically the wind |
---|
216 |
speeds |
---|
217 |
Optional: |
---|
218 |
* nsector: integer - number of sectors used to compute the windrose |
---|
219 |
table. If not set, nsectors=16, then each sector will be 360/16=22.5°, |
---|
220 |
and the resulting computed table will be aligned with the cardinals |
---|
221 |
points. |
---|
222 |
* bins : 1D array or integer- number of bins, or a sequence of |
---|
223 |
bins variable. If not set, bins=6, then |
---|
224 |
bins=linspace(min(var), max(var), 6) |
---|
225 |
* blowto : bool. If True, the windrose will be pi rotated, |
---|
226 |
to show where the wind blow to (usefull for pollutant rose). |
---|
227 |
* colors : string or tuple - one string color ('k' or 'black'), in this |
---|
228 |
case all bins will be plotted in this color; a tuple of matplotlib |
---|
229 |
color args (string, float, rgb, etc), different levels will be plotted |
---|
230 |
in different colors in the order specified. |
---|
231 |
* cmap : a cm Colormap instance from matplotlib.cm. |
---|
232 |
- if cmap == None and colors == None, a default Colormap is used. |
---|
233 |
|
---|
234 |
others kwargs : see help(pylab.plot) |
---|
235 |
|
---|
236 |
""" |
---|
237 |
|
---|
238 |
bins, nbins, nsector, colors, angles, kwargs = self._init_plot(dir, var, |
---|
239 |
**kwargs) |
---|
240 |
|
---|
241 |
#closing lines |
---|
242 |
angles = np.hstack((angles, angles[-1]-2*np.pi/nsector)) |
---|
243 |
vals = np.hstack((self._info['table'], |
---|
244 |
np.reshape(self._info['table'][:,0], |
---|
245 |
(self._info['table'].shape[0], 1)))) |
---|
246 |
|
---|
247 |
offset = 0 |
---|
248 |
for i in range(nbins): |
---|
249 |
val = vals[i,:] + offset |
---|
250 |
offset += vals[i, :] |
---|
251 |
zorder = ZBASE + nbins - i |
---|
252 |
patch = self.plot(angles, val, color=colors[i], zorder=zorder, |
---|
253 |
**kwargs) |
---|
254 |
self.patches_list.extend(patch) |
---|
255 |
self._update() |
---|
256 |
|
---|
257 |
|
---|
258 |
def contourf(self, dir, var, **kwargs): |
---|
259 |
""" |
---|
260 |
Plot a windrose in filled mode. For each var bins, a line will be |
---|
261 |
draw on the axes, a segment between each sector (center to center). |
---|
262 |
Each line can be formated (color, width, ...) like with standard plot |
---|
263 |
pylab command. |
---|
264 |
|
---|
265 |
Mandatory: |
---|
266 |
* dir : 1D array - directions the wind blows from, North centred |
---|
267 |
* var : 1D array - values of the variable to compute. Typically the wind |
---|
268 |
speeds |
---|
269 |
Optional: |
---|
270 |
* nsector: integer - number of sectors used to compute the windrose |
---|
271 |
table. If not set, nsectors=16, then each sector will be 360/16=22.5°, |
---|
272 |
and the resulting computed table will be aligned with the cardinals |
---|
273 |
points. |
---|
274 |
* bins : 1D array or integer- number of bins, or a sequence of |
---|
275 |
bins variable. If not set, bins=6, then |
---|
276 |
bins=linspace(min(var), max(var), 6) |
---|
277 |
* blowto : bool. If True, the windrose will be pi rotated, |
---|
278 |
to show where the wind blow to (usefull for pollutant rose). |
---|
279 |
* colors : string or tuple - one string color ('k' or 'black'), in this |
---|
280 |
case all bins will be plotted in this color; a tuple of matplotlib |
---|
281 |
color args (string, float, rgb, etc), different levels will be plotted |
---|
282 |
in different colors in the order specified. |
---|
283 |
* cmap : a cm Colormap instance from matplotlib.cm. |
---|
284 |
- if cmap == None and colors == None, a default Colormap is used. |
---|
285 |
|
---|
286 |
others kwargs : see help(pylab.plot) |
---|
287 |
|
---|
288 |
""" |
---|
289 |
|
---|
290 |
bins, nbins, nsector, colors, angles, kwargs = self._init_plot(dir, var, |
---|
291 |
**kwargs) |
---|
292 |
null = kwargs.pop('facecolor', None) |
---|
293 |
null = kwargs.pop('edgecolor', None) |
---|
294 |
|
---|
295 |
#closing lines |
---|
296 |
angles = np.hstack((angles, angles[-1]-2*np.pi/nsector)) |
---|
297 |
vals = np.hstack((self._info['table'], |
---|
298 |
np.reshape(self._info['table'][:,0], |
---|
299 |
(self._info['table'].shape[0], 1)))) |
---|
300 |
offset = 0 |
---|
301 |
for i in range(nbins): |
---|
302 |
val = vals[i,:] + offset |
---|
303 |
offset += vals[i, :] |
---|
304 |
zorder = ZBASE + nbins - i |
---|
305 |
xs, ys = poly_between(angles, 0, val) |
---|
306 |
patch = self.fill(xs, ys, facecolor=colors[i], |
---|
307 |
edgecolor=colors[i], zorder=zorder, **kwargs) |
---|
308 |
self.patches_list.extend(patch) |
---|
309 |
|
---|
310 |
|
---|
311 |
def bar(self, dir, var, **kwargs): |
---|
312 |
""" |
---|
313 |
Plot a windrose in bar mode. For each var bins and for each sector, |
---|
314 |
a colored bar will be draw on the axes. |
---|
315 |
|
---|
316 |
Mandatory: |
---|
317 |
* dir : 1D array - directions the wind blows from, North centred |
---|
318 |
* var : 1D array - values of the variable to compute. Typically the wind |
---|
319 |
speeds |
---|
320 |
Optional: |
---|
321 |
* nsector: integer - number of sectors used to compute the windrose |
---|
322 |
table. If not set, nsectors=16, then each sector will be 360/16=22.5°, |
---|
323 |
and the resulting computed table will be aligned with the cardinals |
---|
324 |
points. |
---|
325 |
* bins : 1D array or integer- number of bins, or a sequence of |
---|
326 |
bins variable. If not set, bins=6 between min(var) and max(var). |
---|
327 |
* blowto : bool. If True, the windrose will be pi rotated, |
---|
328 |
to show where the wind blow to (usefull for pollutant rose). |
---|
329 |
* colors : string or tuple - one string color ('k' or 'black'), in this |
---|
330 |
case all bins will be plotted in this color; a tuple of matplotlib |
---|
331 |
color args (string, float, rgb, etc), different levels will be plotted |
---|
332 |
in different colors in the order specified. |
---|
333 |
* cmap : a cm Colormap instance from matplotlib.cm. |
---|
334 |
- if cmap == None and colors == None, a default Colormap is used. |
---|
335 |
edgecolor : string - The string color each edge bar will be plotted. |
---|
336 |
Default : no edgecolor |
---|
337 |
* opening : float - between 0.0 and 1.0, to control the space between |
---|
338 |
each sector (1.0 for no space) |
---|
339 |
|
---|
340 |
""" |
---|
341 |
|
---|
342 |
bins, nbins, nsector, colors, angles, kwargs = self._init_plot(dir, var, |
---|
343 |
**kwargs) |
---|
344 |
null = kwargs.pop('facecolor', None) |
---|
345 |
edgecolor = kwargs.pop('edgecolor', None) |
---|
346 |
if edgecolor is not None: |
---|
347 |
if not isinstance(edgecolor, str): |
---|
348 |
raise ValueError('edgecolor must be a string color') |
---|
349 |
opening = kwargs.pop('opening', None) |
---|
350 |
if opening is None: |
---|
351 |
opening = 0.8 |
---|
352 |
dtheta = 2*np.pi/nsector |
---|
353 |
opening = dtheta*opening |
---|
354 |
|
---|
355 |
for j in range(nsector): |
---|
356 |
offset = 0 |
---|
357 |
for i in range(nbins): |
---|
358 |
if i > 0: |
---|
359 |
offset += self._info['table'][i-1, j] |
---|
360 |
val = self._info['table'][i, j] |
---|
361 |
zorder = ZBASE + nbins - i |
---|
362 |
patch = Rectangle((angles[j]-opening/2, offset), opening, val, |
---|
363 |
facecolor=colors[i], edgecolor=edgecolor, zorder=zorder, |
---|
364 |
**kwargs) |
---|
365 |
self.add_patch(patch) |
---|
366 |
if j == 0: |
---|
367 |
self.patches_list.append(patch) |
---|
368 |
self._update() |
---|
369 |
|
---|
370 |
|
---|
371 |
def box(self, dir, var, **kwargs): |
---|
372 |
""" |
---|
373 |
Plot a windrose in proportional bar mode. For each var bins and for each |
---|
374 |
sector, a colored bar will be draw on the axes. |
---|
375 |
|
---|
376 |
Mandatory: |
---|
377 |
* dir : 1D array - directions the wind blows from, North centred |
---|
378 |
* var : 1D array - values of the variable to compute. Typically the wind |
---|
379 |
speeds |
---|
380 |
Optional: |
---|
381 |
* nsector: integer - number of sectors used to compute the windrose |
---|
382 |
table. If not set, nsectors=16, then each sector will be 360/16=22.5°, |
---|
383 |
and the resulting computed table will be aligned with the cardinals |
---|
384 |
points. |
---|
385 |
* bins : 1D array or integer- number of bins, or a sequence of |
---|
386 |
bins variable. If not set, bins=6 between min(var) and max(var). |
---|
387 |
* blowto : bool. If True, the windrose will be pi rotated, |
---|
388 |
to show where the wind blow to (usefull for pollutant rose). |
---|
389 |
* colors : string or tuple - one string color ('k' or 'black'), in this |
---|
390 |
case all bins will be plotted in this color; a tuple of matplotlib |
---|
391 |
color args (string, float, rgb, etc), different levels will be plotted |
---|
392 |
in different colors in the order specified. |
---|
393 |
* cmap : a cm Colormap instance from matplotlib.cm. |
---|
394 |
- if cmap == None and colors == None, a default Colormap is used. |
---|
395 |
edgecolor : string - The string color each edge bar will be plotted. |
---|
396 |
Default : no edgecolor |
---|
397 |
|
---|
398 |
""" |
---|
399 |
|
---|
400 |
bins, nbins, nsector, colors, angles, kwargs = self._init_plot(dir, var, |
---|
401 |
**kwargs) |
---|
402 |
null = kwargs.pop('facecolor', None) |
---|
403 |
edgecolor = kwargs.pop('edgecolor', None) |
---|
404 |
if edgecolor is not None: |
---|
405 |
if not isinstance(edgecolor, str): |
---|
406 |
raise ValueError('edgecolor must be a string color') |
---|
407 |
opening = np.linspace(0.0, np.pi/16, nbins) |
---|
408 |
|
---|
409 |
for j in range(nsector): |
---|
410 |
offset = 0 |
---|
411 |
for i in range(nbins): |
---|
412 |
if i > 0: |
---|
413 |
offset += self._info['table'][i-1, j] |
---|
414 |
val = self._info['table'][i, j] |
---|
415 |
zorder = ZBASE + nbins - i |
---|
416 |
patch = Rectangle((angles[j]-opening[i]/2, offset), opening[i], |
---|
417 |
val, facecolor=colors[i], edgecolor=edgecolor, |
---|
418 |
zorder=zorder, **kwargs) |
---|
419 |
self.add_patch(patch) |
---|
420 |
if j == 0: |
---|
421 |
self.patches_list.append(patch) |
---|
422 |
self._update() |
---|
423 |
|
---|
424 |
def histogram(dir, var, bins, nsector, normed=False, blowto=False): |
---|
425 |
""" |
---|
426 |
Returns an array where, for each sector of wind |
---|
427 |
(centred on the north), we have the number of time the wind comes with a |
---|
428 |
particular var (speed, polluant concentration, ...). |
---|
429 |
* dir : 1D array - directions the wind blows from, North centred |
---|
430 |
* var : 1D array - values of the variable to compute. Typically the wind |
---|
431 |
speeds |
---|
432 |
* bins : list - list of var category against we're going to compute the table |
---|
433 |
* nsector : integer - number of sectors |
---|
434 |
* normed : boolean - The resulting table is normed in percent or not. |
---|
435 |
* blowto : boolean - Normaly a windrose is computed with directions |
---|
436 |
as wind blows from. If true, the table will be reversed (usefull for |
---|
437 |
pollutantrose) |
---|
438 |
|
---|
439 |
""" |
---|
440 |
|
---|
441 |
if len(var) != len(dir): |
---|
442 |
raise ValueError, "var and dir must have same length" |
---|
443 |
|
---|
444 |
angle = 360./nsector |
---|
445 |
|
---|
446 |
dir_bins = np.arange(-angle/2 ,360.+angle, angle, dtype=np.float) |
---|
447 |
dir_edges = dir_bins.tolist() |
---|
448 |
dir_edges.pop(-1) |
---|
449 |
dir_edges[0] = dir_edges.pop(-1) |
---|
450 |
dir_bins[0] = 0. |
---|
451 |
|
---|
452 |
var_bins = bins.tolist() |
---|
453 |
var_bins.append(np.inf) |
---|
454 |
|
---|
455 |
if blowto: |
---|
456 |
dir = dir + 180. |
---|
457 |
dir[dir>=360.] = dir[dir>=360.] - 360 |
---|
458 |
|
---|
459 |
table = histogram2d(x=var, y=dir, bins=[var_bins, dir_bins], |
---|
460 |
normed=False)[0] |
---|
461 |
# add the last value to the first to have the table of North winds |
---|
462 |
table[:,0] = table[:,0] + table[:,-1] |
---|
463 |
# and remove the last col |
---|
464 |
table = table[:, :-1] |
---|
465 |
if normed: |
---|
466 |
table = table*100/table.sum() |
---|
467 |
|
---|
468 |
return dir_edges, var_bins, table |
---|
469 |
|
---|
470 |
|
---|
471 |
def wrcontour(dir, var, **kwargs): |
---|
472 |
fig = plt.figure() |
---|
473 |
rect = [0.1, 0.1, 0.8, 0.8] |
---|
474 |
ax = WindroseAxes(fig, rect) |
---|
475 |
fig.add_axes(ax) |
---|
476 |
ax.contour(dir, var, **kwargs) |
---|
477 |
l = ax.legend(axespad=-0.10) |
---|
478 |
plt.setp(l.get_texts(), fontsize=8) |
---|
479 |
plt.draw() |
---|
480 |
plt.show() |
---|
481 |
return ax |
---|
482 |
|
---|
483 |
def wrcontourf(dir, var, **kwargs): |
---|
484 |
fig = plt.figure() |
---|
485 |
rect = [0.1, 0.1, 0.8, 0.8] |
---|
486 |
ax = WindroseAxes(fig, rect) |
---|
487 |
fig.add_axes(ax) |
---|
488 |
ax.contourf(dir, var, **kwargs) |
---|
489 |
l = ax.legend(axespad=-0.10) |
---|
490 |
plt.setp(l.get_texts(), fontsize=8) |
---|
491 |
plt.draw() |
---|
492 |
plt.show() |
---|
493 |
return ax |
---|
494 |
|
---|
495 |
def wrbox(dir, var, **kwargs): |
---|
496 |
fig = plt.figure() |
---|
497 |
rect = [0.1, 0.1, 0.8, 0.8] |
---|
498 |
ax = WindroseAxes(fig, rect) |
---|
499 |
fig.add_axes(ax) |
---|
500 |
ax.box(dir, var, **kwargs) |
---|
501 |
l = ax.legend(axespad=-0.10) |
---|
502 |
plt.setp(l.get_texts(), fontsize=8) |
---|
503 |
plt.draw() |
---|
504 |
plt.show() |
---|
505 |
return ax |
---|
506 |
|
---|
507 |
def wrbar(dir, var, **kwargs): |
---|
508 |
fig = plt.figure() |
---|
509 |
rect = [0.1, 0.1, 0.8, 0.8] |
---|
510 |
ax = WindroseAxes(fig, rect) |
---|
511 |
fig.add_axes(ax) |
---|
512 |
ax.bar(dir, var, **kwargs) |
---|
513 |
l = ax.legend(axespad=-0.10) |
---|
514 |
plt.setp(l.get_texts(), fontsize=8) |
---|
515 |
plt.draw() |
---|
516 |
plt.show() |
---|
517 |
return ax |
---|
518 |
|
---|
519 |
def clean(dir, var): |
---|
520 |
''' |
---|
521 |
Remove masked values in the two arrays, where if a direction data is masked, |
---|
522 |
the var data will also be removed in the cleaning process (and vice-versa) |
---|
523 |
''' |
---|
524 |
dirmask = dir.mask==False |
---|
525 |
varmask = var.mask==False |
---|
526 |
ind = dirmask*varmask |
---|
527 |
return dir[ind], var[ind] |
---|
528 |
|
---|
529 |
if __name__=='__main__': |
---|
530 |
from pylab import figure, show, setp, random, grid, draw |
---|
531 |
vv=random(500)*6 |
---|
532 |
dv=random(500)*360 |
---|
533 |
fig = figure(figsize=(8, 8), dpi=80, facecolor='w', edgecolor='w') |
---|
534 |
rect = [0.1, 0.1, 0.8, 0.8] |
---|
535 |
ax = WindroseAxes(fig, rect, axisbg='w') |
---|
536 |
fig.add_axes(ax) |
---|
537 |
|
---|
538 |
# ax.contourf(dv, vv, bins=np.arange(0,8,1), cmap=cm.hot) |
---|
539 |
# ax.contour(dv, vv, bins=np.arange(0,8,1), colors='k') |
---|
540 |
# ax.bar(dv, vv, normed=True, opening=0.8, edgecolor='white') |
---|
541 |
ax.box(dv, vv, normed=True) |
---|
542 |
l = ax.legend(axespad=-0.10) |
---|
543 |
setp(l.get_texts(), fontsize=8) |
---|
544 |
draw() |
---|
545 |
#print ax._info |
---|
546 |
show() |
---|
547 |
|
---|
548 |
|
---|
549 |
|
---|
550 |
|
---|
551 |
|
---|
552 |
|
---|