### Navigation

- index
- modules |
- pywws 13.03_7f9fc90 documentation »
- Code du module »

# Code source de pywws.WindRose

    #!/usr/bin/env python

    # pywws - Python software for USB Wireless Weather Stations
    # http://github.com/jim-easterbrook/pywws
    # Copyright (C) 2008-13  Jim Easterbrook  jim@jim-easterbrook.me.uk

    # This program is free software; you can redistribute it and/or
    # modify it under the terms of the GNU General Public License
    # as published by the Free Software Foundation; either version 2
    # of the License, or (at your option) any later version.

    # This program is distributed in the hope that it will be useful,
    # but WITHOUT ANY WARRANTY; without even the implied warranty of
    # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    # GNU General Public License for more details.

    # You should have received a copy of the GNU General Public License
    # along with this program; if not, write to the Free Software
    # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.

    """Plot a "wind rose"

    ::

    %s

    """

    __docformat__ = "restructuredtext en"
    __usage__ = """
     usage: python RunModule.py WindRose [options] data_dir temp_dir xml_file output_file
     options are:
      -h or --help    display this help
     data_dir is the root directory of the weather data
     temp_dir is a workspace for temporary files e.g. /tmp
     xml_file is the name of the source file that describes the plot
     output_file is the name of the image file to be created e.g. 24hrs.png
    """
    __doc__ %= __usage__
    __usage__ = __doc__.split('\n')[0] + __usage__

    import codecs
    from datetime import datetime, timedelta
    import getopt
    import math
    import os
    import sys
    import xml.dom.minidom

    from .conversions import (
        illuminance_wm2, pressure_inhg, rain_inch, temp_f,
        winddir_degrees, winddir_text, wind_kmph, wind_mph, wind_kn, wind_bft)
    from . import DataStore
    from . import Localisation
    from .Plot import BasePlotter
    from .TimeZone import Local
    from .WeatherStation import dew_point

    class RosePlotter(BasePlotter):
        def GetPlotList(self):
            return self.GetChildren(self.graph, 'windrose')
        def GetDefaultRows(self):
            return int(math.sqrt(self.plot_count))
        def GetDefaultPlotSize(self):
            return 600 // self.rows, 600 // self.rows
        def GetPreamble(self):
            result = """set polar
    set angles degrees
    set xtics axis nomirror
    set ytics axis nomirror
    set zeroaxis
    set grid polar 22.5
    set size square
    unset border
    """
            lmargin = eval(self.GetValue(self.graph, 'lmargin', '-1'))
            result += 'set lmargin %g\n' % (lmargin)
            lmargin = eval(self.GetValue(self.graph, 'rmargin', '-1'))
            result += 'set rmargin %g\n' % (lmargin)
            lmargin = eval(self.GetValue(self.graph, 'tmargin', '-1'))
            result += 'set tmargin %g\n' % (lmargin)
            lmargin = eval(self.GetValue(self.graph, 'bmargin', '-1'))
            result += 'set bmargin %g\n' % (lmargin)
            return result
        def PlotData(self, plot_no, plot, source):
            _ = Localisation.translation.ugettext
            # get statistics
            thresh = eval(self.GetValue(
                plot, 'threshold', '0.0, 1.54, 3.09, 5.14, 8.23, 10.8, 15.5'))
            thresh = thresh + (1000.0,)
            colour = eval(self.GetValue(plot, 'colour', str(range(len(thresh)))))
            xcalc = self.GetValue(plot, 'xcalc', 'True')
            xcalc = compile(xcalc, '<string>', 'eval')
            ycalc = self.GetValue(plot, 'ycalc', None)
            ycalc = compile(ycalc, '<string>', 'eval')
            histograms = []
            for i in range(len(thresh)):
                hist = []
                for n in range(16):
                    hist.append(0)
                histograms.append(hist)
            # x_lo & x_hi are in local time, data is indexed in UTC
            start = self.x_lo - self.utcoffset
            stop = self.x_hi - self.utcoffset
            stop = stop + timedelta(minutes=1)
            for data in source[start:stop]:
                wind_dir = data['wind_dir']
                if wind_dir == None or wind_dir >= 16:
                    continue
                if not eval(xcalc):
                    continue
                value = eval(ycalc)
                if value is None:
                    continue
                for t in range(len(thresh)):
                    if value <= thresh[t]:
                        histograms[t][wind_dir] += 1
                        break
            # evenly distribute zero speed
            total = 0
            for n in range(16):
                total += histograms[0][n]
            for n in range(16):
                histograms[0][n] = total // 16
            # integrate histograms
            for i in range(1, len(thresh)):
                for n in range(16):
                    histograms[i][n] += histograms[i-1][n]
            total = 0
            for n in range(16):
                total += histograms[-1][n]
            result = ''
            yrange = self.GetValue(plot, 'yrange', '31')
            if yrange == '*':
                # auto-ranging
                if total > 0:
                    max_petal = 100.0 * float(max(histograms[-1])) / float(total)
                else:
                    max_petal = 0.0
                if max_petal > 40.0:
                    yrange = (int(max_petal / 20.0) * 20) + 21
                elif max_petal > 30.0:
                    yrange = 41
                elif max_petal > 20.0:
                    yrange = 31
                else:
                    yrange = 21
            else:
                yrange = eval(yrange)
            result += 'set xrange [-%d:%d]\n' % (yrange, yrange)
            result += 'set yrange [-%d:%d]\n' % (yrange, yrange)
            points = [_('N'), _('S'), _('E'), _('W')]
            points = eval(self.GetValue(plot, 'points', str(points)))
            result += 'set label 1000 "%s" at 0, %d center front\n' % (points[0], yrange)
            result += 'set label 1001 "%s" at 0, -%d center front\n' % (points[1], yrange)
            result += 'set label 1002 "%s" at %d, 0 center front\n' % (points[2], yrange)
            result += 'set label 1003 "%s" at -%d, 0 center front\n' % (points[3], yrange)
            # plot segments for each speed-direction
            result += 'plot '
            for i in reversed(range(len(thresh))):
                dat_file = os.path.join(self.work_dir, 'plot_%d_%d.dat' % (plot_no, i))
                self.tmp_files.append(dat_file)
                dat = open(dat_file, 'w')
                sub_total = 0
                for n in range(16):
                    angle = 90.0 - (n * 22.5)
                    sub_total += histograms[i][n]
                    if i > 0:
                        sub_total -= histograms[i-1][n]
                    if total > 0:
                        value = 100.0 * float(histograms[i][n]) / float(total)
                    else:
                        value = 0.0
                    if i == 0:
                        dat.write('%g %g\n' % (angle - 11.24, value * 0.994))
                    else:
                        dat.write('%g %g\n' % (angle - 8.1, 0))
                    dat.write('%g %g\n' % (angle - 8.0, value * 0.997))
                    dat.write('%g %g\n' % (angle, value))
                    dat.write('%g %g\n' % (angle + 8.0, value * 0.997))
                    if i == 0:
                        dat.write('%g %g\n' % (angle + 11.24, value * 0.994))
                        dat.write('%g %g\n' % (angle + 11.25, 0))
                    else:
                        dat.write('%g %g\n' % (angle + 8.1, 0))
                dat.close()
                # plot data
                if total > 0:
                    value = 100.0 * float(sub_total) / float(total)
                else:
                    value = 0.0
                if i == 0:
                    title = '0 .. %g (%.3g%%)' % (thresh[i], value)
                elif i == len(thresh) - 1:
                    title = '> %g (%.3g%%)' % (thresh[i-1], value)
                else:
                    title = '%g .. %g (%.3g%%)' % (thresh[i-1], thresh[i], value)
                result += '"%s" using 1:2 title "%s" with filledcurve lt %d' % (
                    dat_file, title, colour[i % len(colour)])
                if i > 0:
                    result += ', \\'
                result += '\n'
            return result
    def main(argv=None):
        if argv is None:
            argv = sys.argv
        try:
            opts, args = getopt.getopt(argv[1:], "h", ['help'])
        except getopt.error, msg:
            print >>sys.stderr, 'Error: %s\n' % msg
            print >>sys.stderr, __usage__.strip()
            return 1
        # process options
        for o, a in opts:
            if o == '-h' or o == '--help':
                print __usage__.strip()
                return 0
        # check arguments
        if len(args) != 4:
            print >>sys.stderr, 'Error: 4 arguments required\n'
            print >>sys.stderr, __usage__.strip()
            return 2
        params = DataStore.params(args[0])
        Localisation.SetApplicationLanguage(params)
        return RosePlotter(
            params,
            DataStore.calib_store(args[0]), DataStore.hourly_store(args[0]),
            DataStore.daily_store(args[0]), DataStore.monthly_store(args[0]),
            args[1]
            ).DoPlot(args[2], args[3])
    if __name__ == "__main__":
        sys.exit(main())

### Navigation

- index
- modules |
- pywws 13.03_7f9fc90 documentation »
- Code du module »