Python software for USB Wireless WeatherStations

Plot.py -- plots graph using an XML template

Like Template.py this is one of the more difficult to use modules in the weather station software collection. It plots a graph (or set of graphs) of weather data. Almost everything about the graph is controlled by an XML file. I refer to these files as templates, but they aren't templates in the same sense as Template.py uses to create text files.

Before writing your own graph template files, it might be useful to look at some of the examples in the example_graph_templates directory. If (like I was) you are unfamiliar with XML, I suggest reading the W3 Schools XML tutorial.

XML graph file syntax

Here is the simplest useful graph template. It plots the external temperature for the last 24 hours.

<?xml version="1.0" encoding="ISO-8859-1"?>
<graph>
  <plot>
    <subplot>
      <title>Temperature (°C)</title>
      <ycalc>data['temp_out']</ycalc>
    </subplot>
  </plot>
</graph>

In this example, the root element graph has one plot element, which has one subplot element. The subplot element contains a title element and a ycalc element. To plot more data on the same set of axes (for example dew point and temperature), we can add more subplot elements. To plot more than one set of axes (for example wind speed is measured in different units from temperature) in the same file we can add more plot elements.

The complete element hierarchy is shown below. Each element name links to a full description of that element.

graph

This is the root element of the graph XML file. It does not have to be called "graph", but there must be exactly one root element.

plot

Every graph element should contain at least one plot element. A separate graph is drawn for each plot element, but all share the same X axis.

start

This element sets the date & time of the start of the X axis. It is used in the constructor of a Python datetime object. For example, to start the graph at noon (local time) on Christmas day: <start>year=2008, month=12, day=25, hour=12</start>. The default value is (stop - duration).

stop

This element sets the date & time of the end of the X axis. It is used in the constructor of a Python datetime object. For example, to end the graph at 10 am (local time) on new year's day: <stop>year=2009, month=1, day=1, hour=10</stop>. The default value is (start + duration), unless start is not defined in which case the timestamp of the latest weather station hourly reading is used.

duration

This element sets the extent of the X axis of the graph, unless both start and stop are defined. It is used in the constructor of a Python timedelta object. For example, to plot one week: <duration>weeks=1</duration>. The default value is hours=24.

layout

Controls the layout of the plots. Default is a single column. The layout element specifies rows and columns. For example: <layout>4, 2</layout> will use a grid of 4 rows and 2 columns.

size

Sets the overall dimensions of the image file containing the graph. Default (in a single column layout) is a width of 600 pixels and height of 200 pixels for each plot, so a graph with four plot elements would be 600 x 800 pixels. Any size element must include both width and height. For example: <size>800, 600</size> will produce an image 800 pixels wide and 600 pixels high.

fileformat

Sets the image format of the file containing the graph. Default is png. Any string recognised by your installation of gnuplot should do. For example: <fileformat>gif</fileformat> will produce a GIF image.

terminal

Allows complete control of gnuplot's 'terminal' settings. You may want to use this if you are plotting to an unusual image format. Any string recognised by your installation of gnuplot's 'set terminal' command should do. For example: <terminal>svg enhanced font "arial,9" size 600,800 dynamic rounded</terminal>. This setting overwrites both size and fileformat.

lmargin

Sets the left margin of the plots, i.e. the distance from the left hand axis to the left hand edge of the image area. According to the gnuplot documentation the units of lmargin are character widths. The default value is 5, which should look OK in most circumstances.

rmargin

Sets the right margin of the plots, i.e. the distance from the right hand axis to the right hand edge of the image area. According to the gnuplot documentation the units of rmargin are character widths. The default value is -1, which sets automatic adjustment.

xformat

Sets the format of the time / date xtic labels. The value is a strftime style format string. Default depends on the graph duration: 24 hours or less is "%H%M", 24 hours to 7 days is "%a %d" and 7 days or more is "%Y/%m/%d".

xlabel

Sets the X axis label. The value is a strftime style format string. Default depends on the graph duration: 24 hours or less is "Time (%Z)", 24 hours to 7 days is "Day" and 7 days or more is "Date". The datetime used to compute this is start, which may produce unexpected results when a graph spans DST start or end.

dateformat

Sets the format of the date labels at each end of X axis. The value is a strftime style format string. Default is "%Y/%m/%d". The right hand label is only drawn if it differs from the left. To have no labels, set an empty format: <dateformat></dateformat>

xtics

Sets the spacing of the "tic" marks on the X axis. The value is an integer number of hours. The default is to allow gnuplot to set an appropriate interval.

title

Sets the title of the graph. A single line of text, for example: <title>Today's weather</title>. This title appears at the very top of the graph, outside any plot area.

subplot

Every plot element should contain at least one subplot element. A separate trace is drawn for each subplot element, but all share the same X and Y axes.

bmargin

Sets the bottom margin, i.e. the spacing between the lower X axis and the edge of the graph (or the next plot). The default is to let gnuplot adjust this automatically, which works OK most of the time but you may wish to fine tune the value to suit your installation.

The permitted value is any non-negative real number. On my setup 0.9 is a good value, set as follows: <bmargin>0.9</bmargin>.

yrange

Sets the lower and upper limits of the (left hand) Y axis. The value is anything understood by gnuplot, typically a pair of numbers. The default is to allow gnuplot to set appropriate values, which is unlikely to be what you want. For example, to plot typical UK temperatures with no value going off the graph: <yrange>-10, 30</yrange>. Note that commas are converted to colons, so <yrange>-10:30</yrange> would be equivalent.

You can use an asterisk to have gnuplot choose a suitable value. For example, to have the upper value auto scale whilst fixing the lower value at zero, use <yrange>0:*</yrange>.

y2range

Sets the lower and upper limits of the right hand Y axis. Default is for the right hand Y axis to be the same as the left, but setting a different range is useful in dual axis plotting.

ylabel

Adds a label to the (left hand) Y axis. For example, when plotting temperature: <ylabel>°C</ylabel>. If you use ylabel you will probably want to adjust lmargin.

ylabelangle

Adjust the angle of the (left hand) Y axis label, if your version of gnuplot supports it. For example, to write the label horizontally: <ylabelangle>90</ylabelangle>.

y2label

Adds a label to the right hand Y axis. For example, when plotting humidity: <y2label>%</y2label>. This is mostly used when plotting dual axis graphs. If you use y2label you will probably want to adjust rmargin.

y2labelangle

Adjust the angle of the right hand Y axis label, if your version of gnuplot supports it. For example, to write the label horizontally: <y2labelangle>90</y2labelangle>.

grid

Adds a grid to the plot. In most situations gnuplot's default grid is suitable, so no value is needed: <grid></grid>. More control is possible using any of the options understood by gnuplot's set grid command. For example, to have horizontal grid lines only: <grid>ytics</grid>.

source

Select the weather data to be plotted. Permitted values are <source>raw</source>, <source>hourly</source>, <source>daily</source> and <source>monthly</source>. Default is raw. Note that the different sources have different data dictionaries, so this choice affects ycalc.

boxwidth

Sets the width of the "boxes" used when drawing bar graphs. The value is an integer expression yielding a number of seconds. Default depends on source: raw is 240, hourly is 2800 and daily is 2800 * 24.

title

Sets the title of the plot. A single line of text, for example: <title>Temperature (°C)</title>. This title appears within the plot area, above any subplot titles.

command

Execute any gnuplot command, just before the main "plot" command. This option allows advanced users to have greater control over the graph appearance. The value is any valid gnuplot command, typically beginning with the word set. For example: <command>set key tmargin center horizontal width 1 noreverse enhanced autotitles box linetype -1 linewidth 1</command>. (Don't ask me what this example does — I'm not an advanced user).

xcalc

Controls the X axis positioning of plotted data values. The default value of data['idx'] is correct for most data, but there are some exceptions. For example, when plotting bar charts of hourly rainfall, it's nice to centre the bars on 30 minutes past the hour: <xcalc>data['idx'].replace(minute=30, second=0)</xcalc>.

ycalc

Selects the data to be plotted. Any one line Python expression that returns a single float value can be used. At its simplest this just selects one value from the "data" dictionary, for example: <ycalc>data['temp_out']</ycalc> plots the external temperature. More complex expressions are possible, and some helper functions are provided. For example: <ycalc>dew_point(data['temp_out'], data['hum_out'])</ycalc> plots the external dew point, and <ycalc>data['wind_ave'] * 3.6 / 1.609344</ycalc> plots the average wind speed in miles per hour.

Cumulative plots are also possible. The result of each ycalc computation is stored and made available to the next computation in the variable last_ycalc. This can be used with any data, but is most useful with rainfall: <ycalc>data['rain'] + last_ycalc</ycalc>.

axes

Selects which Y axis the data is plotted against. Default is the left hand axis, but the right hand axis can be chosen with: <axes>x1y2</axes>. This can be used in conjunction with y2range to plot two unrelated quantities on one graph, for example temperature and humidity.

style

Sets the line style for the graph. Default is a smooth continuous line, thickness 1. To select a bar graph use: <style>box</style>. To select points without a connecting line use: <style>+</style> or <style>x</style>. To select a line thickness 3 (for example) use: <style>line 3</style>. The thickness of points can be set in a similar fashion. For complete control (advanced users only) a full gnuplot style can be set: <style>smooth unique lc 5 lw 3</style>.

colour

Sets the colour of the subplot line or boxes. Any integer value is accepted. The mapping of colours to numbers is set by gnuplot. Default value is the previous colour plus one.

title

Sets the title of the subplot. A single line of text, for example: <title>Temperature (°C)</title>. This title appears within the plot area, next to a short segment of the line colour used for the subplot.


Python software for USB Wireless WeatherStations © Jim Easterbrook.