Index: sodarplot/trunk/sodarplot/scintec/windrose-LICENSE =================================================================== --- (revision ) +++ sodarplot/trunk/sodarplot/scintec/windrose-LICENSE (revision 66) @@ -1,0 +1,515 @@ + +CeCILL-B FREE SOFTWARE LICENSE AGREEMENT + + + Notice + +This Agreement is a Free Software license agreement that is the result +of discussions between its authors in order to ensure compliance with +the two main principles guiding its drafting: + + * firstly, compliance with the principles governing the distribution + of Free Software: access to source code, broad rights granted to + users, + * secondly, the election of a governing law, French law, with which + it is conformant, both as regards the law of torts and + intellectual property law, and the protection that it offers to + both authors and holders of the economic rights over software. + +The authors of the CeCILL-B (for Ce[a] C[nrs] I[nria] L[ogiciel] L[ibre]) +license are: + +Commissariat à l'Energie Atomique - CEA, a public scientific, technical +and industrial research establishment, having its principal place of +business at 25 rue Leblanc, immeuble Le Ponant D, 75015 Paris, France. + +Centre National de la Recherche Scientifique - CNRS, a public scientific +and technological establishment, having its principal place of business +at 3 rue Michel-Ange, 75794 Paris cedex 16, France. + +Institut National de Recherche en Informatique et en Automatique - +INRIA, a public scientific and technological establishment, having its +principal place of business at Domaine de Voluceau, Rocquencourt, BP +105, 78153 Le Chesnay cedex, France. + + + Preamble + +This Agreement is an open source software license intended to give users +significant freedom to modify and redistribute the software licensed +hereunder. + +The exercising of this freedom is conditional upon a strong obligation +of giving credits for everybody that distributes a software +incorporating a software ruled by the current license so as all +contributions to be properly identified and acknowledged. + +In consideration of access to the source code and the rights to copy, +modify and redistribute granted by the license, users are provided only +with a limited warranty and the software's author, the holder of the +economic rights, and the successive licensors only have limited liability. + +In this respect, the risks associated with loading, using, modifying +and/or developing or reproducing the software by the user are brought to +the user's attention, given its Free Software status, which may make it +complicated to use, with the result that its use is reserved for +developers and experienced professionals having in-depth computer +knowledge. Users are therefore encouraged to load and test the +suitability of the software as regards their requirements in conditions +enabling the security of their systems and/or data to be ensured and, +more generally, to use and operate it in the same conditions of +security. This Agreement may be freely reproduced and published, +provided it is not altered, and that no provisions are either added or +removed herefrom. + +This Agreement may apply to any or all software for which the holder of +the economic rights decides to submit the use thereof to its provisions. + + + Article 1 - DEFINITIONS + +For the purpose of this Agreement, when the following expressions +commence with a capital letter, they shall have the following meaning: + +Agreement: means this license agreement, and its possible subsequent +versions and annexes. + +Software: means the software in its Object Code and/or Source Code form +and, where applicable, its documentation, "as is" when the Licensee +accepts the Agreement. + +Initial Software: means the Software in its Source Code and possibly its +Object Code form and, where applicable, its documentation, "as is" when +it is first distributed under the terms and conditions of the Agreement. + +Modified Software: means the Software modified by at least one +Contribution. + +Source Code: means all the Software's instructions and program lines to +which access is required so as to modify the Software. + +Object Code: means the binary files originating from the compilation of +the Source Code. + +Holder: means the holder(s) of the economic rights over the Initial +Software. + +Licensee: means the Software user(s) having accepted the Agreement. + +Contributor: means a Licensee having made at least one Contribution. + +Licensor: means the Holder, or any other individual or legal entity, who +distributes the Software under the Agreement. + +Contribution: means any or all modifications, corrections, translations, +adaptations and/or new functions integrated into the Software by any or +all Contributors, as well as any or all Internal Modules. + +Module: means a set of sources files including their documentation that +enables supplementary functions or services in addition to those offered +by the Software. + +External Module: means any or all Modules, not derived from the +Software, so that this Module and the Software run in separate address +spaces, with one calling the other when they are run. + +Internal Module: means any or all Module, connected to the Software so +that they both execute in the same address space. + +Parties: mean both the Licensee and the Licensor. + +These expressions may be used both in singular and plural form. + + + Article 2 - PURPOSE + +The purpose of the Agreement is the grant by the Licensor to the +Licensee of a non-exclusive, transferable and worldwide license for the +Software as set forth in Article 5 hereinafter for the whole term of the +protection granted by the rights over said Software. + + + Article 3 - ACCEPTANCE + +3.1 The Licensee shall be deemed as having accepted the terms and +conditions of this Agreement upon the occurrence of the first of the +following events: + + * (i) loading the Software by any or all means, notably, by + downloading from a remote server, or by loading from a physical + medium; + * (ii) the first time the Licensee exercises any of the rights + granted hereunder. + +3.2 One copy of the Agreement, containing a notice relating to the +characteristics of the Software, to the limited warranty, and to the +fact that its use is restricted to experienced users has been provided +to the Licensee prior to its acceptance as set forth in Article 3.1 +hereinabove, and the Licensee hereby acknowledges that it has read and +understood it. + + + Article 4 - EFFECTIVE DATE AND TERM + + + 4.1 EFFECTIVE DATE + +The Agreement shall become effective on the date when it is accepted by +the Licensee as set forth in Article 3.1. + + + 4.2 TERM + +The Agreement shall remain in force for the entire legal term of +protection of the economic rights over the Software. + + + Article 5 - SCOPE OF RIGHTS GRANTED + +The Licensor hereby grants to the Licensee, who accepts, the following +rights over the Software for any or all use, and for the term of the +Agreement, on the basis of the terms and conditions set forth hereinafter. + +Besides, if the Licensor owns or comes to own one or more patents +protecting all or part of the functions of the Software or of its +components, the Licensor undertakes not to enforce the rights granted by +these patents against successive Licensees using, exploiting or +modifying the Software. If these patents are transferred, the Licensor +undertakes to have the transferees subscribe to the obligations set +forth in this paragraph. + + + 5.1 RIGHT OF USE + +The Licensee is authorized to use the Software, without any limitation +as to its fields of application, with it being hereinafter specified +that this comprises: + + 1. permanent or temporary reproduction of all or part of the Software + by any or all means and in any or all form. + + 2. loading, displaying, running, or storing the Software on any or + all medium. + + 3. entitlement to observe, study or test its operation so as to + determine the ideas and principles behind any or all constituent + elements of said Software. This shall apply when the Licensee + carries out any or all loading, displaying, running, transmission + or storage operation as regards the Software, that it is entitled + to carry out hereunder. + + + 5.2 ENTITLEMENT TO MAKE CONTRIBUTIONS + +The right to make Contributions includes the right to translate, adapt, +arrange, or make any or all modifications to the Software, and the right +to reproduce the resulting software. + +The Licensee is authorized to make any or all Contributions to the +Software provided that it includes an explicit notice that it is the +author of said Contribution and indicates the date of the creation thereof. + + + 5.3 RIGHT OF DISTRIBUTION + +In particular, the right of distribution includes the right to publish, +transmit and communicate the Software to the general public on any or +all medium, and by any or all means, and the right to market, either in +consideration of a fee, or free of charge, one or more copies of the +Software by any means. + +The Licensee is further authorized to distribute copies of the modified +or unmodified Software to third parties according to the terms and +conditions set forth hereinafter. + + + 5.3.1 DISTRIBUTION OF SOFTWARE WITHOUT MODIFICATION + +The Licensee is authorized to distribute true copies of the Software in +Source Code or Object Code form, provided that said distribution +complies with all the provisions of the Agreement and is accompanied by: + + 1. a copy of the Agreement, + + 2. a notice relating to the limitation of both the Licensor's + warranty and liability as set forth in Articles 8 and 9, + +and that, in the event that only the Object Code of the Software is +redistributed, the Licensee allows effective access to the full Source +Code of the Software at a minimum during the entire period of its +distribution of the Software, it being understood that the additional +cost of acquiring the Source Code shall not exceed the cost of +transferring the data. + + + 5.3.2 DISTRIBUTION OF MODIFIED SOFTWARE + +If the Licensee makes any Contribution to the Software, the resulting +Modified Software may be distributed under a license agreement other +than this Agreement subject to compliance with the provisions of Article +5.3.4. + + + 5.3.3 DISTRIBUTION OF EXTERNAL MODULES + +When the Licensee has developed an External Module, the terms and +conditions of this Agreement do not apply to said External Module, that +may be distributed under a separate license agreement. + + + 5.3.4 CREDITS + +Any Licensee who may distribute a Modified Software hereby expressly +agrees to: + + 1. indicate in the related documentation that it is based on the + Software licensed hereunder, and reproduce the intellectual + property notice for the Software, + + 2. ensure that written indications of the Software intended use, + intellectual property notice and license hereunder are included in + easily accessible format from the Modified Software interface, + + 3. mention, on a freely accessible website describing the Modified + Software, at least throughout the distribution term thereof, that + it is based on the Software licensed hereunder, and reproduce the + Software intellectual property notice, + + 4. where it is distributed to a third party that may distribute a + Modified Software without having to make its source code + available, make its best efforts to ensure that said third party + agrees to comply with the obligations set forth in this Article . + +If the Software, whether or not modified, is distributed with an +External Module designed for use in connection with the Software, the +Licensee shall submit said External Module to the foregoing obligations. + + + 5.3.5 COMPATIBILITY WITH THE CeCILL AND CeCILL-C LICENSES + +Where a Modified Software contains a Contribution subject to the CeCILL +license, the provisions set forth in Article 5.3.4 shall be optional. + +A Modified Software may be distributed under the CeCILL-C license. In +such a case the provisions set forth in Article 5.3.4 shall be optional. + + + Article 6 - INTELLECTUAL PROPERTY + + + 6.1 OVER THE INITIAL SOFTWARE + +The Holder owns the economic rights over the Initial Software. Any or +all use of the Initial Software is subject to compliance with the terms +and conditions under which the Holder has elected to distribute its work +and no one shall be entitled to modify the terms and conditions for the +distribution of said Initial Software. + +The Holder undertakes that the Initial Software will remain ruled at +least by this Agreement, for the duration set forth in Article 4.2. + + + 6.2 OVER THE CONTRIBUTIONS + +The Licensee who develops a Contribution is the owner of the +intellectual property rights over this Contribution as defined by +applicable law. + + + 6.3 OVER THE EXTERNAL MODULES + +The Licensee who develops an External Module is the owner of the +intellectual property rights over this External Module as defined by +applicable law and is free to choose the type of agreement that shall +govern its distribution. + + + 6.4 JOINT PROVISIONS + +The Licensee expressly undertakes: + + 1. not to remove, or modify, in any manner, the intellectual property + notices attached to the Software; + + 2. to reproduce said notices, in an identical manner, in the copies + of the Software modified or not. + +The Licensee undertakes not to directly or indirectly infringe the +intellectual property rights of the Holder and/or Contributors on the +Software and to take, where applicable, vis-à-vis its staff, any and all +measures required to ensure respect of said intellectual property rights +of the Holder and/or Contributors. + + + Article 7 - RELATED SERVICES + +7.1 Under no circumstances shall the Agreement oblige the Licensor to +provide technical assistance or maintenance services for the Software. + +However, the Licensor is entitled to offer this type of services. The +terms and conditions of such technical assistance, and/or such +maintenance, shall be set forth in a separate instrument. Only the +Licensor offering said maintenance and/or technical assistance services +shall incur liability therefor. + +7.2 Similarly, any Licensor is entitled to offer to its licensees, under +its sole responsibility, a warranty, that shall only be binding upon +itself, for the redistribution of the Software and/or the Modified +Software, under terms and conditions that it is free to decide. Said +warranty, and the financial terms and conditions of its application, +shall be subject of a separate instrument executed between the Licensor +and the Licensee. + + + Article 8 - LIABILITY + +8.1 Subject to the provisions of Article 8.2, the Licensee shall be +entitled to claim compensation for any direct loss it may have suffered +from the Software as a result of a fault on the part of the relevant +Licensor, subject to providing evidence thereof. + +8.2 The Licensor's liability is limited to the commitments made under +this Agreement and shall not be incurred as a result of in particular: +(i) loss due the Licensee's total or partial failure to fulfill its +obligations, (ii) direct or consequential loss that is suffered by the +Licensee due to the use or performance of the Software, and (iii) more +generally, any consequential loss. In particular the Parties expressly +agree that any or all pecuniary or business loss (i.e. loss of data, +loss of profits, operating loss, loss of customers or orders, +opportunity cost, any disturbance to business activities) or any or all +legal proceedings instituted against the Licensee by a third party, +shall constitute consequential loss and shall not provide entitlement to +any or all compensation from the Licensor. + + + Article 9 - WARRANTY + +9.1 The Licensee acknowledges that the scientific and technical +state-of-the-art when the Software was distributed did not enable all +possible uses to be tested and verified, nor for the presence of +possible defects to be detected. In this respect, the Licensee's +attention has been drawn to the risks associated with loading, using, +modifying and/or developing and reproducing the Software which are +reserved for experienced users. + +The Licensee shall be responsible for verifying, by any or all means, +the suitability of the product for its requirements, its good working +order, and for ensuring that it shall not cause damage to either persons +or properties. + +9.2 The Licensor hereby represents, in good faith, that it is entitled +to grant all the rights over the Software (including in particular the +rights set forth in Article 5). + +9.3 The Licensee acknowledges that the Software is supplied "as is" by +the Licensor without any other express or tacit warranty, other than +that provided for in Article 9.2 and, in particular, without any warranty +as to its commercial value, its secured, safe, innovative or relevant +nature. + +Specifically, the Licensor does not warrant that the Software is free +from any error, that it will operate without interruption, that it will +be compatible with the Licensee's own equipment and software +configuration, nor that it will meet the Licensee's requirements. + +9.4 The Licensor does not either expressly or tacitly warrant that the +Software does not infringe any third party intellectual property right +relating to a patent, software or any other property right. Therefore, +the Licensor disclaims any and all liability towards the Licensee +arising out of any or all proceedings for infringement that may be +instituted in respect of the use, modification and redistribution of the +Software. Nevertheless, should such proceedings be instituted against +the Licensee, the Licensor shall provide it with technical and legal +assistance for its defense. Such technical and legal assistance shall be +decided on a case-by-case basis between the relevant Licensor and the +Licensee pursuant to a memorandum of understanding. The Licensor +disclaims any and all liability as regards the Licensee's use of the +name of the Software. No warranty is given as regards the existence of +prior rights over the name of the Software or as regards the existence +of a trademark. + + + Article 10 - TERMINATION + +10.1 In the event of a breach by the Licensee of its obligations +hereunder, the Licensor may automatically terminate this Agreement +thirty (30) days after notice has been sent to the Licensee and has +remained ineffective. + +10.2 A Licensee whose Agreement is terminated shall no longer be +authorized to use, modify or distribute the Software. However, any +licenses that it may have granted prior to termination of the Agreement +shall remain valid subject to their having been granted in compliance +with the terms and conditions hereof. + + + Article 11 - MISCELLANEOUS + + + 11.1 EXCUSABLE EVENTS + +Neither Party shall be liable for any or all delay, or failure to +perform the Agreement, that may be attributable to an event of force +majeure, an act of God or an outside cause, such as defective +functioning or interruptions of the electricity or telecommunications +networks, network paralysis following a virus attack, intervention by +government authorities, natural disasters, water damage, earthquakes, +fire, explosions, strikes and labor unrest, war, etc. + +11.2 Any failure by either Party, on one or more occasions, to invoke +one or more of the provisions hereof, shall under no circumstances be +interpreted as being a waiver by the interested Party of its right to +invoke said provision(s) subsequently. + +11.3 The Agreement cancels and replaces any or all previous agreements, +whether written or oral, between the Parties and having the same +purpose, and constitutes the entirety of the agreement between said +Parties concerning said purpose. No supplement or modification to the +terms and conditions hereof shall be effective as between the Parties +unless it is made in writing and signed by their duly authorized +representatives. + +11.4 In the event that one or more of the provisions hereof were to +conflict with a current or future applicable act or legislative text, +said act or legislative text shall prevail, and the Parties shall make +the necessary amendments so as to comply with said act or legislative +text. All other provisions shall remain effective. Similarly, invalidity +of a provision of the Agreement, for any reason whatsoever, shall not +cause the Agreement as a whole to be invalid. + + + 11.5 LANGUAGE + +The Agreement is drafted in both French and English and both versions +are deemed authentic. + + + Article 12 - NEW VERSIONS OF THE AGREEMENT + +12.1 Any person is authorized to duplicate and distribute copies of this +Agreement. + +12.2 So as to ensure coherence, the wording of this Agreement is +protected and may only be modified by the authors of the License, who +reserve the right to periodically publish updates or new versions of the +Agreement, each with a separate number. These subsequent versions may +address new issues encountered by Free Software. + +12.3 Any Software distributed under a given version of the Agreement may +only be subsequently distributed under the same version of the Agreement +or a subsequent version. + + + Article 13 - GOVERNING LAW AND JURISDICTION + +13.1 The Agreement is governed by French law. The Parties agree to +endeavor to seek an amicable solution to any disagreements or disputes +that may arise during the performance of the Agreement. + +13.2 Failing an amicable solution within two (2) months as from their +occurrence, and unless emergency proceedings are necessary, the +disagreements or disputes shall be referred to the Paris Courts having +jurisdiction, by the more diligent Party. + + +Version 1.0 dated 2006-09-05. Index: sodarplot/trunk/sodarplot/scintec/windrose.py =================================================================== --- (revision ) +++ sodarplot/trunk/sodarplot/scintec/windrose.py (revision 66) @@ -1,0 +1,548 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +__version__ = '1.4' +__author__ = 'Lionel Roubeyrie' +__mail__ = 'lionel.roubeyrie@gmail.com' +__license__ = 'CeCILL-B' + +import matplotlib +import matplotlib.cm as cm +import numpy as np +from matplotlib.patches import Rectangle, Polygon +from matplotlib.ticker import ScalarFormatter, AutoLocator +from matplotlib.text import Text, FontProperties +from matplotlib.projections.polar import PolarAxes +from numpy.lib.twodim_base import histogram2d +import matplotlib.pyplot as plt +from pylab import poly_between + +RESOLUTION = 100 +ZBASE = -1000 #The starting zorder for all drawing, negative to have the grid on + +class WindroseAxes(PolarAxes): + """ + + Create a windrose axes + + """ + + def __init__(self, *args, **kwargs): + """ + See Axes base class for args and kwargs documentation + """ + + #Uncomment to have the possibility to change the resolution directly + #when the instance is created + #self.RESOLUTION = kwargs.pop('resolution', 100) + PolarAxes.__init__(self, *args, **kwargs) + self.set_aspect('equal', adjustable='box', anchor='C') + self.radii_angle = 67.5 + self.cla() + + + def cla(self): + """ + Clear the current axes + """ + PolarAxes.cla(self) + + self.theta_angles = np.arange(0, 360, 45) + self.theta_labels = ['E', 'N-E', 'N', 'N-W', 'W', 'S-W', 'S', 'S-E'] + self.set_thetagrids(angles=self.theta_angles, labels=self.theta_labels) + + self._info = {'dir' : list(), + 'bins' : list(), + 'table' : list()} + + self.patches_list = list() + + + def _colors(self, cmap, n): + ''' + Returns a list of n colors based on the colormap cmap + + ''' + return [cmap(i) for i in np.linspace(0.0, 1.0, n)] + + + def set_radii_angle(self, **kwargs): + """ + Set the radii labels angle + """ + + null = kwargs.pop('labels', None) + angle = kwargs.pop('angle', None) + if angle is None: + angle = self.radii_angle + self.radii_angle = angle + radii = np.linspace(0.1, self.get_rmax(), 6) + radii_labels = [ "%.1f" %r for r in radii ] + radii_labels[0] = "" #Removing label 0 + null = self.set_rgrids(radii=radii, labels=radii_labels, + angle=self.radii_angle, **kwargs) + + + def _update(self): + self.set_rmax(rmax=np.max(np.sum(self._info['table'], axis=0))) + self.set_radii_angle(angle=self.radii_angle) + + + def legend(self, loc='lower left', **kwargs): + """ + Sets the legend location and her properties. + The location codes are + + 'best' : 0, + 'upper right' : 1, + 'upper left' : 2, + 'lower left' : 3, + 'lower right' : 4, + 'right' : 5, + 'center left' : 6, + 'center right' : 7, + 'lower center' : 8, + 'upper center' : 9, + 'center' : 10, + + If none of these are suitable, loc can be a 2-tuple giving x,y + in axes coords, ie, + + loc = (0, 1) is left top + loc = (0.5, 0.5) is center, center + + and so on. The following kwargs are supported: + + isaxes=True # whether this is an axes legend + prop = FontProperties(size='smaller') # the font property + pad = 0.2 # the fractional whitespace inside the legend border + shadow # if True, draw a shadow behind legend + labelsep = 0.005 # the vertical space between the legend entries + handlelen = 0.05 # the length of the legend lines + handletextsep = 0.02 # the space between the legend line and legend text + axespad = 0.02 # the border between the axes and legend edge + """ + + def get_handles(): + handles = list() + for p in self.patches_list: + if isinstance(p, matplotlib.patches.Polygon) or \ + isinstance(p, matplotlib.patches.Rectangle): + color = p.get_facecolor() + elif isinstance(p, matplotlib.lines.Line2D): + color = p.get_color() + else: + raise AttributeError("Can't handle patches") + handles.append(Rectangle((0, 0), 0.2, 0.2, + facecolor=color, edgecolor='black')) + return handles + + def get_labels(): + labels = np.copy(self._info['bins']) + labels = ["[%.1f : %0.1f[" %(labels[i], labels[i+1]) \ + for i in range(len(labels)-1)] + return labels + + null = kwargs.pop('labels', None) + null = kwargs.pop('handles', None) + handles = get_handles() + labels = get_labels() + self.legend_ = matplotlib.legend.Legend(self, handles, labels, + loc, **kwargs) + return self.legend_ + + + def _init_plot(self, dir, var, **kwargs): + """ + Internal method used by all plotting commands + """ + #self.cla() + null = kwargs.pop('zorder', None) + + #Init of the bins array if not set + bins = kwargs.pop('bins', None) + if bins is None: + bins = np.linspace(np.min(var), np.max(var), 6) + if isinstance(bins, int): + bins = np.linspace(np.min(var), np.max(var), bins) + bins = np.asarray(bins) + nbins = len(bins) + + #Number of sectors + nsector = kwargs.pop('nsector', None) + if nsector is None: + nsector = 16 + + #Sets the colors table based on the colormap or the "colors" argument + colors = kwargs.pop('colors', None) + cmap = kwargs.pop('cmap', None) + if colors is not None: + if isinstance(colors, str): + colors = [colors]*nbins + if isinstance(colors, (tuple, list)): + if len(colors) != nbins: + raise ValueError("colors and bins must have same length") + else: + if cmap is None: + cmap = cm.jet + colors = self._colors(cmap, nbins) + + #Building the angles list + angles = np.arange(0, -2*np.pi, -2*np.pi/nsector) + np.pi/2 + + normed = kwargs.pop('normed', False) + blowto = kwargs.pop('blowto', False) + + #Set the global information dictionnary + self._info['dir'], self._info['bins'], self._info['table'] = histogram(dir, var, bins, nsector, normed, blowto) + + return bins, nbins, nsector, colors, angles, kwargs + + + def contour(self, dir, var, **kwargs): + """ + Plot a windrose in linear mode. For each var bins, a line will be + draw on the axes, a segment between each sector (center to center). + Each line can be formated (color, width, ...) like with standard plot + pylab command. + + Mandatory: + * dir : 1D array - directions the wind blows from, North centred + * var : 1D array - values of the variable to compute. Typically the wind + speeds + Optional: + * nsector: integer - number of sectors used to compute the windrose + table. If not set, nsectors=16, then each sector will be 360/16=22.5°, + and the resulting computed table will be aligned with the cardinals + points. + * bins : 1D array or integer- number of bins, or a sequence of + bins variable. If not set, bins=6, then + bins=linspace(min(var), max(var), 6) + * blowto : bool. If True, the windrose will be pi rotated, + to show where the wind blow to (usefull for pollutant rose). + * colors : string or tuple - one string color ('k' or 'black'), in this + case all bins will be plotted in this color; a tuple of matplotlib + color args (string, float, rgb, etc), different levels will be plotted + in different colors in the order specified. + * cmap : a cm Colormap instance from matplotlib.cm. + - if cmap == None and colors == None, a default Colormap is used. + + others kwargs : see help(pylab.plot) + + """ + + bins, nbins, nsector, colors, angles, kwargs = self._init_plot(dir, var, + **kwargs) + + #closing lines + angles = np.hstack((angles, angles[-1]-2*np.pi/nsector)) + vals = np.hstack((self._info['table'], + np.reshape(self._info['table'][:,0], + (self._info['table'].shape[0], 1)))) + + offset = 0 + for i in range(nbins): + val = vals[i,:] + offset + offset += vals[i, :] + zorder = ZBASE + nbins - i + patch = self.plot(angles, val, color=colors[i], zorder=zorder, + **kwargs) + self.patches_list.extend(patch) + self._update() + + + def contourf(self, dir, var, **kwargs): + """ + Plot a windrose in filled mode. For each var bins, a line will be + draw on the axes, a segment between each sector (center to center). + Each line can be formated (color, width, ...) like with standard plot + pylab command. + + Mandatory: + * dir : 1D array - directions the wind blows from, North centred + * var : 1D array - values of the variable to compute. Typically the wind + speeds + Optional: + * nsector: integer - number of sectors used to compute the windrose + table. If not set, nsectors=16, then each sector will be 360/16=22.5°, + and the resulting computed table will be aligned with the cardinals + points. + * bins : 1D array or integer- number of bins, or a sequence of + bins variable. If not set, bins=6, then + bins=linspace(min(var), max(var), 6) + * blowto : bool. If True, the windrose will be pi rotated, + to show where the wind blow to (usefull for pollutant rose). + * colors : string or tuple - one string color ('k' or 'black'), in this + case all bins will be plotted in this color; a tuple of matplotlib + color args (string, float, rgb, etc), different levels will be plotted + in different colors in the order specified. + * cmap : a cm Colormap instance from matplotlib.cm. + - if cmap == None and colors == None, a default Colormap is used. + + others kwargs : see help(pylab.plot) + + """ + + bins, nbins, nsector, colors, angles, kwargs = self._init_plot(dir, var, + **kwargs) + null = kwargs.pop('facecolor', None) + null = kwargs.pop('edgecolor', None) + + #closing lines + angles = np.hstack((angles, angles[-1]-2*np.pi/nsector)) + vals = np.hstack((self._info['table'], + np.reshape(self._info['table'][:,0], + (self._info['table'].shape[0], 1)))) + offset = 0 + for i in range(nbins): + val = vals[i,:] + offset + offset += vals[i, :] + zorder = ZBASE + nbins - i + xs, ys = poly_between(angles, 0, val) + patch = self.fill(xs, ys, facecolor=colors[i], + edgecolor=colors[i], zorder=zorder, **kwargs) + self.patches_list.extend(patch) + + + def bar(self, dir, var, **kwargs): + """ + Plot a windrose in bar mode. For each var bins and for each sector, + a colored bar will be draw on the axes. + + Mandatory: + * dir : 1D array - directions the wind blows from, North centred + * var : 1D array - values of the variable to compute. Typically the wind + speeds + Optional: + * nsector: integer - number of sectors used to compute the windrose + table. If not set, nsectors=16, then each sector will be 360/16=22.5°, + and the resulting computed table will be aligned with the cardinals + points. + * bins : 1D array or integer- number of bins, or a sequence of + bins variable. If not set, bins=6 between min(var) and max(var). + * blowto : bool. If True, the windrose will be pi rotated, + to show where the wind blow to (usefull for pollutant rose). + * colors : string or tuple - one string color ('k' or 'black'), in this + case all bins will be plotted in this color; a tuple of matplotlib + color args (string, float, rgb, etc), different levels will be plotted + in different colors in the order specified. + * cmap : a cm Colormap instance from matplotlib.cm. + - if cmap == None and colors == None, a default Colormap is used. + edgecolor : string - The string color each edge bar will be plotted. + Default : no edgecolor + * opening : float - between 0.0 and 1.0, to control the space between + each sector (1.0 for no space) + + """ + + bins, nbins, nsector, colors, angles, kwargs = self._init_plot(dir, var, + **kwargs) + null = kwargs.pop('facecolor', None) + edgecolor = kwargs.pop('edgecolor', None) + if edgecolor is not None: + if not isinstance(edgecolor, str): + raise ValueError('edgecolor must be a string color') + opening = kwargs.pop('opening', None) + if opening is None: + opening = 0.8 + dtheta = 2*np.pi/nsector + opening = dtheta*opening + + for j in range(nsector): + offset = 0 + for i in range(nbins): + if i > 0: + offset += self._info['table'][i-1, j] + val = self._info['table'][i, j] + zorder = ZBASE + nbins - i + patch = Rectangle((angles[j]-opening/2, offset), opening, val, + facecolor=colors[i], edgecolor=edgecolor, zorder=zorder, + **kwargs) + self.add_patch(patch) + if j == 0: + self.patches_list.append(patch) + self._update() + + + def box(self, dir, var, **kwargs): + """ + Plot a windrose in proportional bar mode. For each var bins and for each + sector, a colored bar will be draw on the axes. + + Mandatory: + * dir : 1D array - directions the wind blows from, North centred + * var : 1D array - values of the variable to compute. Typically the wind + speeds + Optional: + * nsector: integer - number of sectors used to compute the windrose + table. If not set, nsectors=16, then each sector will be 360/16=22.5°, + and the resulting computed table will be aligned with the cardinals + points. + * bins : 1D array or integer- number of bins, or a sequence of + bins variable. If not set, bins=6 between min(var) and max(var). + * blowto : bool. If True, the windrose will be pi rotated, + to show where the wind blow to (usefull for pollutant rose). + * colors : string or tuple - one string color ('k' or 'black'), in this + case all bins will be plotted in this color; a tuple of matplotlib + color args (string, float, rgb, etc), different levels will be plotted + in different colors in the order specified. + * cmap : a cm Colormap instance from matplotlib.cm. + - if cmap == None and colors == None, a default Colormap is used. + edgecolor : string - The string color each edge bar will be plotted. + Default : no edgecolor + + """ + + bins, nbins, nsector, colors, angles, kwargs = self._init_plot(dir, var, + **kwargs) + null = kwargs.pop('facecolor', None) + edgecolor = kwargs.pop('edgecolor', None) + if edgecolor is not None: + if not isinstance(edgecolor, str): + raise ValueError('edgecolor must be a string color') + opening = np.linspace(0.0, np.pi/16, nbins) + + for j in range(nsector): + offset = 0 + for i in range(nbins): + if i > 0: + offset += self._info['table'][i-1, j] + val = self._info['table'][i, j] + zorder = ZBASE + nbins - i + patch = Rectangle((angles[j]-opening[i]/2, offset), opening[i], + val, facecolor=colors[i], edgecolor=edgecolor, + zorder=zorder, **kwargs) + self.add_patch(patch) + if j == 0: + self.patches_list.append(patch) + self._update() + +def histogram(dir, var, bins, nsector, normed=False, blowto=False): + """ + Returns an array where, for each sector of wind + (centred on the north), we have the number of time the wind comes with a + particular var (speed, polluant concentration, ...). + * dir : 1D array - directions the wind blows from, North centred + * var : 1D array - values of the variable to compute. Typically the wind + speeds + * bins : list - list of var category against we're going to compute the table + * nsector : integer - number of sectors + * normed : boolean - The resulting table is normed in percent or not. + * blowto : boolean - Normaly a windrose is computed with directions + as wind blows from. If true, the table will be reversed (usefull for + pollutantrose) + + """ + + if len(var) != len(dir): + raise ValueError, "var and dir must have same length" + + angle = 360./nsector + + dir_bins = np.arange(-angle/2 ,360.+angle, angle, dtype=np.float) + dir_edges = dir_bins.tolist() + dir_edges.pop(-1) + dir_edges[0] = dir_edges.pop(-1) + dir_bins[0] = 0. + + var_bins = bins.tolist() + var_bins.append(np.inf) + + if blowto: + dir = dir + 180. + dir[dir>=360.] = dir[dir>=360.] - 360 + + table = histogram2d(x=var, y=dir, bins=[var_bins, dir_bins], + normed=False)[0] + # add the last value to the first to have the table of North winds + table[:,0] = table[:,0] + table[:,-1] + # and remove the last col + table = table[:, :-1] + if normed: + table = table*100/table.sum() + + return dir_edges, var_bins, table + + +def wrcontour(dir, var, **kwargs): + fig = plt.figure() + rect = [0.1, 0.1, 0.8, 0.8] + ax = WindroseAxes(fig, rect) + fig.add_axes(ax) + ax.contour(dir, var, **kwargs) + l = ax.legend(axespad=-0.10) + plt.setp(l.get_texts(), fontsize=8) + plt.draw() + plt.show() + return ax + +def wrcontourf(dir, var, **kwargs): + fig = plt.figure() + rect = [0.1, 0.1, 0.8, 0.8] + ax = WindroseAxes(fig, rect) + fig.add_axes(ax) + ax.contourf(dir, var, **kwargs) + l = ax.legend(axespad=-0.10) + plt.setp(l.get_texts(), fontsize=8) + plt.draw() + plt.show() + return ax + +def wrbox(dir, var, **kwargs): + fig = plt.figure() + rect = [0.1, 0.1, 0.8, 0.8] + ax = WindroseAxes(fig, rect) + fig.add_axes(ax) + ax.box(dir, var, **kwargs) + l = ax.legend(axespad=-0.10) + plt.setp(l.get_texts(), fontsize=8) + plt.draw() + plt.show() + return ax + +def wrbar(dir, var, **kwargs): + fig = plt.figure() + rect = [0.1, 0.1, 0.8, 0.8] + ax = WindroseAxes(fig, rect) + fig.add_axes(ax) + ax.bar(dir, var, **kwargs) + l = ax.legend(axespad=-0.10) + plt.setp(l.get_texts(), fontsize=8) + plt.draw() + plt.show() + return ax + +def clean(dir, var): + ''' + Remove masked values in the two arrays, where if a direction data is masked, + the var data will also be removed in the cleaning process (and vice-versa) + ''' + dirmask = dir.mask==False + varmask = var.mask==False + ind = dirmask*varmask + return dir[ind], var[ind] + +if __name__=='__main__': + from pylab import figure, show, setp, random, grid, draw + vv=random(500)*6 + dv=random(500)*360 + fig = figure(figsize=(8, 8), dpi=80, facecolor='w', edgecolor='w') + rect = [0.1, 0.1, 0.8, 0.8] + ax = WindroseAxes(fig, rect, axisbg='w') + fig.add_axes(ax) + +# ax.contourf(dv, vv, bins=np.arange(0,8,1), cmap=cm.hot) +# ax.contour(dv, vv, bins=np.arange(0,8,1), colors='k') +# ax.bar(dv, vv, normed=True, opening=0.8, edgecolor='white') + ax.box(dv, vv, normed=True) + l = ax.legend(axespad=-0.10) + setp(l.get_texts(), fontsize=8) + draw() + #print ax._info + show() + + + + + +