Skip to content

Belchertown Charts Documentation

Pat O'Brien edited this page Mar 8, 2020 · 86 revisions

Belchertown Charts

Introduction

A new methodology for defining and displaying charts has been implemented starting with Version 1.0 of the Belchertown WeeWX skin. This capability provides significantly increased flexibility in decided what graphs to display and to customized them. To achieve this flexibility and still allow settings to be retained across version upgrades, a new file is being used to define the graphs displayed on the web pages output by the Belchertown skin.

This file, graphs.conf, is located in the skins/Belchertown directory and can be modified to define the graphs and charts displayed on the main web page as well as the Today, Week, Month and Year "Graphs" pages.

Although specifying and defining the graphs and charts displayed can seem complex at first, the good news is that even if graphs.conf does not exist, a default set of graphs will be displayed. Editing graphs.conf, though, will allow you to define the charts shown, their order, and their appearance. The following sections of this document will describe:

Quick Start

The Belchertown skin charting system is extremely powerful and flexible. However it is set up so that upon installation of the skin, a set of standard graphs will automatically be generated. If you don't want any graphs generated (not sure why you'd want to do that 😕), just add highcharts_enabled = 0 in the [[Belchertown]] [[[Extras]]] stanza of weewx.conf.

To enable changing the specific observations graphed, their order or details such as type of plot or color of the lines on the charts shown, first make a copy of graphs.conf.example and name it graphs.conf. This can be done by typing sudo cp graphs.conf.example graphs.conf while in the skins/Belchertown directory.

The graphs.conf.example (and graphs.conf copy of it) have a number of comments at the beginning of the file describing the layout and structure of the file, as well as some of the options you can specify within it.

If you make a mistake changing items in the graphs.conf file, you may end up with no graphs being generated. In this case, if you can't locate the error causing the issue, you can always just delete the file and make a fresh copy of it from graphs.conf.example.

Capabilities

  1. Define the timeframe for the graph so it will begin either a specific number of seconds prior to current time, or to start at the beginning of the current day, week, month or year.
  2. Choose the order of the graphs displayed.
  3. Define the name of the graph.
  4. Choose the observation to be plotted (any observation stored in the weewx archive database).
  5. Plot multiple observations on a single graph.
  6. Specify the type of plot that is graphed (line, spline, area, areaspline, scatter, column, etc.).
  7. Specify the color of the plotted observation.
  8. Specify which y-axis (left or right) is associated with the plotted observation.
  9. Display a special radial wind rose plot that shows the percentage of time wind was blowing from each of sixteen directions over the plot's duration.
  10. Other specifications such as determining how much of a gap in data will show as a gap in the plotted line, determining which line is on top of others when multiple observations are plotted on a single graph and y-axis minimum and maximum values.

Key Files

There are 2 new files related to the new graphing capabilities of the Belchertown skin that users need to be aware of. They are graphs.conf.example and graphs.conf. Both are located in the Belchertown skins directory. This is typically /etc/weewx/skins/Belchertown in Linux systems where WeeWX was installed using a package via DEB or RPM. For implementations of WeeWX that used setup.py, the files are located in /home/weewx/skins/Belchertown.

Upon installation, graphs.conf.example is placed in the skins/Belchertown directory. graphs.conf does not exist until the user creates it in order to specify changes to the default graphs which are displayed. It is easiest to make a copy of graphs.conf.example and name it graphs.conf (e.g. by typing sudo cp graphs.conf.example graphs.conf) while in the skins/Belchertown directory. Note: If the graphs.conf file is not present in the skins/Belchertown directory, the default graphs defined in graphs.conf.example are displayed on the Belchertown web pages.

File Structure

The file structure of both graphs.conf.example and graphs.conf are the same and straight-forward. Comment lines are preceded by the # symbol.

At the beginning of the file are detailed comments outlining the chart types and options, a description of the rainTotal observation, some tips and tricks, and a description of the Settings options available.

Next come the observations and their settings for each of the graphs to be plotted on the four "Graphs" pages: "Today" (including graphs plotted on the main web page); "Week"; "Month"; and "Year". The observations and settings for each page are located under their corresponding section stanza ([day], [week], [month] and [year]).

That's it - pretty clear-cut! Just note that the syntax of the settings must be carefully followed. That syntax is described in the next section of this document.

Syntax within graphs.conf

  • First are some global default settings including the aggregate_type. Aggregate_type determines if the observation data is averaged (avg), listed as the maximum value (max), minimum value (min) or summed (sum) over the aggregate_interval. Next are the default plot line colors - 10 of them. Note, the colors are chosen so that they show well whether the skin is in light mode or dark mode. So if you choose to set a particular color for a plot line on a graph (instead of letting Highcharts choose it for you), you should consider using one of the 10 defaults listed.

  • Next are each of the four Chart group stanzas listed below [day], [week], [month] and [year]. These must be present and cannot be renamed. Under each of the four Chart group stanzas is a series of lower level stanzas defining the graphs to be plotted and their settings. The syntax of the file is described below:

  • Chart group: as noted above, these stanzas [day], [week], [month], [year] must be present. They are actually the names of the json files generated to plot the graphs.

  • Chart group level options : if a chart within the group does not specify an option, it’ll inherit this option. As described above, the default options generally will include the time_length covered by the graph and the gapsize which determines how long a period of missing observation data results in a gap in the plotted line.

  • Chart ID Name (contained within a double bracket stanza[[xxx]]): this is used by highcharts and can be anything we want. I recommend choosing a name that signifies the graph to plotted. In the infographic below, the names "temmplt" and "humplt" are used for denote "temperature plot" and "humidity plot". But any names could have been used.

  • Chart-level options: Under the Chart ID Name are the chart-level options that define things such as the graph's title, yAxis parameters, etc.

  • Observations to be plotted (contained within a triple bracket stanza[[[xxx]]]): these are the observations to graph in the chart. The names are case-sensitive and must match the name of the observation in the archive schema. For example outTemp or inTemp or barometer.

  • Observation specific options: Under the Observations to be plotted are specific overrides, such as color, zIndex (which determines which plotted line appears plotted on top of other lines on a multi-line graph) and name of the observation in the legend. If name is omitted, the default weewx name will be applied. For example instead of default “Outside Temperature”, you can specify just “Temperature” with the name option.

Infographic

The syntax of the stanzas within graphs.conf file must be carefully followed. If the graphs fail to load, check the syntax for errors and revert any errors. If worse comes to worst, delete graphs.conf, ensure that the graphs display with only graphs.conf.example. If so, create a fresh version of graphs.conf by copying graphs.conf.example and try again.

Default Color Palette

The Belchertown default color palette for the charts has been based on the need for light and dark themes. These colors show good contrast and visibility when the light or dark theme is enabled. Below you can see the reference table used when comparing the Belchertown Default to the Highcharts Default. For example, black cannot be used because it will not show up in dark mode. Colors have been moved up and substituted for a slight alternative that works better between the light and dark modes.

Series Number Belchertown Default Preview Highcharts Default Preview
#1 Blue Blue
#2 Green Black
#3 Orange Green
#4 Purple Orange
#5 Pink Purple
#6 Yellow Pink
#7 Dark Blue Yellow
#8 Red Teal Green
#9 Dark Purple Red
#10 Dark Green Sky Blue

There have been multiple sources used to create this hybrid color palette and this list has been a great help.

The rainTotal observation

The built in "rain" observation is really "bucket tips". The chart will show when the bucket tipped and that's it. Using the special built in "rainTotal" observation - unique to Belchertown - will increment those bucket tips across the timespan, showing you the total rain for that timespan.

The weatherRange observation

As of 1.1, another observation which is unique to the Belchertown skin is the weatherRange. Inspired by this post, the weather range will show you a columnrange of the observation's min and max for the timespan selected. If you're using outTemp as your range observation, the columns will be colored based on the average outTemp.

Why can't you just use columnrange as a chart type? Highcharts requires the column range output to be in a specific way. The y axis has to have a min and max within the series data. Standard Belchertown aggregation methods do not do this by default. So I created weatherRange as a way to aggregate the min/max of the observation you want to chart. This allows you more control over which observations you want to see min and max for (or the range).

As a result, this requires you to specify the observation to be charted by using the range_type option. This must match one of the archive schema observation names.

For detailed configuration please refer to the documentation sections below, but here is a brief overview. To add a weather range which shows outTemp ranges for the current year, just use the configuration below.

[weatherRadialGraphGroup]
    title = Temperature Range Radial
    show_button = true
    button_text = Weather Radial
    time_length = year

    [[radialChartName]]
        title = This Year
        css_class = "weatherRadial"
        [[[weatherRange]]]
            range_type = outTemp

image

If you want to have a weather radial for another year or time, just change the time_length option. For example, here's the output for my temperature from 2018:

[weatherRadialGraphGroup]
    title = Temperature Range Radial
    show_button = true
    button_text = Weather Radial
    time_length = year_specific
    year_specific = 2018

    [[radialChartName]]
        title = 2018
        css_class = "weatherRadial"
        [[[weatherRange]]]
            range_type = outTemp

image

Detailed Configuration Settings Overview

data_binding

  • Example config: data_binding = lightning_binding

This allows you to show observations from a separate database than your primary archive database. Helpful if you have multiple sources of data (like lightning, an additional SDR, etc). See example below on how to use this option.

credits

  • Example config: credits = "Your Website Name"

The credits can be customized as a global option. This option would change the default Highcharts credits to your custom credit. Available as of 1.1

credits_url

  • Example config: credits_url = "http://yoursite"

This changes the link if you were to click on the chart credit line. Available as of 1.1

credits_position

  • Example config: credits_position = '{"align": "left", "x": "15"}'

This will change the position of the credits. In the example config, this moves the credit to the left of the chart. You can modify align, x and y positions. Available as of 1.1

title

The title value directly beneath the graph group name (like [day] or [week]) will be the title of the graph group on the graphs page. This will also be useful for the All Graphs page so you can give each section their own individual title.

page_content

As of version 1.1 you can specify a graphs page content or description using full HTML with the page_content setting. This area shows up under the page's title and above the graphs. The setting can be on 1 single line, or you can expand it onto multiple lines if you use 3 " which denote a multi-line string in Python. A multi line string only has an advantage on the readability of the content. Otherwise they act exactly the same.

Full HTML is accepted (div, center, bold, underline, etc.).

Here's an example on each way to use it:

Single Line: page_content = "This graphs page shows all the observation readings from <b>this week</b>

Multi Line:

    page_content = """This is the 2019 bomb cyclone which hit the Northeast.
    <br><br>
    <b>To learn more about the bomb cyclone, <a href="https://en.wikipedia.org/wiki/Explosive_cyclogenesis">click here</a>!</b>
    """

time_length

This is the time length the chart will show. There are two ways to define this.

  1. Use a keyword to define the calendar day, week, month or year.
    • (Default) today = calendar day starting at midnight today.
    • week = calendar week starting at midnight. Week start day is defined in weewx.conf Station details.
    • month = calendar month starting on the 1st day of the month.
    • (Default) year = calendar year start on 1st day of the year.
    • days_ago = calendar day starting at midnight the day before, or midnight on the day from time_ago.
    • weeks_ago = calendar week starting last week at midnight, or the week ago from time_ago. Week start day is defined in weewx.conf Station details.
    • months_ago = calendar month starting on the 1st day of last month, or the month ago from time_ago.
    • years_ago = calendar year starting on 1st day of last year, or the year ago from time_ago.
    • day_specific = a specific day which you want to chart. Must be used in combination with options: day_specific, month_specific and year_specific
    • month_specific = a specific month which you want to chart. Must be used in combination with options: month_specific and year_specific
    • year_specific = a specific year which you want to chart. Must be used in combination with option: year_specific
    • all = all time within the database
  2. Use seconds to graph a rolling time period. Some examples are:
    • 90000 = Use this for day. This will graph the last 25 hours as a rolling time period.
    • (Default) 604800 = Use this for week. This will graph the last 7 days as a rolling time period.
    • (Default) 2592000 = Use this for month. This will graph the last 30 days as a rolling time period.
    • 31536000 = Use this for year. This will graph the last 365 days as a rolling time period.
  • NOTE: If you do not specify a time_length, the global default will be used and that is set for 90000 seconds (25 hours)

time_ago

If your time_length is one of the _ago options, you can specify how far back in history you want to go with time_ago. For example if you set "year_ago" for time_length, then you can use "time_ago = 2" to get a graph for 2 years ago. Same for day, week and month.

day_specific

This is the integer of the day of the month you want to chart for. Must be used with "time_length = day_specific".

month_specific

This is the integer of the month you want to chart for. Must be used with "time_length = month_specific". Also used in "day_specific".

year_specific

This is the year which you want to chart for. Must be used with "time_length = year_specific". Setting "year_specific = 2016" will create charts for 2016. Also used with "day_specific" and "month_specific".

show_button

  • Example config: show_button = true

Values are "true" or "false". This will show or hide the graph button on the Graphs page.

button_text

  • Example config: button_text = Today

This is the text of the button on the Graphs page. If no text is specified, the graph group name will be used.

color

The colors listed in the Global Chart Defaults are the default color palette. This palette works with both light and dark mode, and they are applied in the order they are listed to the charts. To override a specific observation plot with it's own unique color you can set the color option under the observation type. Colors can be specified using the hex notation in quotes, like color = "#000000" for black. Colors can also be generic as specified in their English name, such as color = "green"

name

If you specify a name for the observation, then we will use that. If you do not specify a name, one will be automatically used.

observation_type

You do not need to specify this configuration item frequently since it is automatically pulled from the chart's "observation to be plotted" section in the above infographic. However, if you want to show the same observation twice on the same chart, then you need to use this. For example, to show outTemp twice - once for min, and once for max, then you would define it similar to the below. Since you cannot have duplicate names within the [bracket] you have to give the observation a unique name, but you define the observation with observation_type

        [[[outTemp]]]
            zIndex = 1
            name = Max Temperature
            color = red
        [[[outTemp_min]]]
            name = Min Temperature
            observation_type = outTemp
            aggregate_type = min
            color = "#7cb5ec"

generate

  • Example config: generate = daily

As of 1.1, By using generate = X, you can delay the chart generation for that time period. Useful for charts that don't need to be updated every archive interval (e.g. 5 minutes). So for example your year chart could be delayed to be updated once a day. This can help save your system from bogging down on chart load.

If the charts JSON file doesn't exist, it will be created on first run.

The timestamp of the file is used as the trigger on when to generate a new chart.

Why does Belchertown use the file timestamp? Because weewx can be restarted, I can't use an in-memory variable or timer to do the time comparison. So we have to use something constant, like the file's timestamp.

Options are:

  • hourly
  • daily
  • weekly
  • monthly
  • yearly
  • or any other time in seconds

Example full config which would only generate new chart data daily (24 hours) after the JSON file's timestamp:

[dayonly]
    generate = daily
    title = Generate only daily
    show_button = true
    button_text = Today Only
    time_length = today
    gapsize = 300000

    [[chart1]]
        title = Temperature
        [[[outTemp]]]
            zIndex = 1
            name = Temperature
        [[[windchill]]]
        [[[heatindex]]]
        [[[dewpoint]]]

aggregate_type

  • Example config: aggregate_type = max

This defines the aggregate of the chart values. Valid options are None, avg, sum, min, max

numberFormat

Example config:

            [[[[numberFormat]]]]
                decimals = 5
                decimalPoint = "."
                thousandsSep = ","

If you want to override the chart's number formatting this is where you can do it. For example if your locale uses spaces for the thousands separated (example: 1 007,3) and you want this to show as 1007,3 you can use the numberFormat option and specify the thousandsSep = "". The same idea applies to the number of digits after the decimal point, the decimal point itself and the thousands separator.

Here's some examples:

Here you can see I'm defining 5 decimals, using . as the decimal point and , as the thousands separator. The tooltip hover, and the y axis labels are updated.

[day]
...graph group options...
    [[chart4]]
        title = Barometer
        [[[barometer]]]
            color = "#BECC00"
            [[[[numberFormat]]]]
                decimals = 5
                decimalPoint = "."
                thousandsSep = ","

In this example, I am letting weewx.conf define how many decimals (since decimals is not explicitly defined here), and will have the . for the decimal point which is non-standard for the German locale (they use ,) and nothing for the thousands separator (nothing means no space and no character).

[day]
...graph group options...
    [[chart4]]
        title = Barometer
        [[[barometer]]]
            color = "#BECC00"
            [[[[numberFormat]]]]
                decimalPoint = "."
                thousandsSep = ""

image

polar

  • Example config: polar = true

Certain chart types support polar, or radials. For example if you're creating a weatherRange chart and you want to show those in a radial fashion, just add polar = true. Here's some example configs.

[weatherRadialGraphGroup]
    title = Temperature Range Radial
    show_button = true
    button_text = Weather Radial
    time_length = year

    [[radialChartName]]
        title = This Year
        css_class = "weatherRadial"
        [[[weatherRange]]]
            range_type = outTemp
            polar = true

image

width

  • Example config: width = 100%
  • Example config: width = 100px

This will override any Belchertown assumptions for chart width to your specified width. A note that 100% will fit the container that is holding the chart container, and not be 100% the width of the screen.

You can use percentage or pixels.

height

  • Example config: height = 60px

This will override any Belchertown assumptions for chart height to your specific height. A note that 100% will fit the container that is holding the chart, and not be 100% the height of the screen.

You can use percentage or pixels.

type

  • Example config: type = spline

This is the Highcharts chart type. Some valid ones are line, spline, columns, area, scatter. There's more which may work (like bar) - check the Highcharts type documentation.

xAxis_groupby

In version 1.0 and 1.0.1 this was xaxis_groupby

  • Example config: xAxis_groupby = year
  • Available options: hour, day, month, year. Defaults to month

If you wish to group database values by a month or by a year you would want to use the xAxis_groupby option. This tells the Graph Generator to take the values received and group them by either month, or by year. Typically this is used in partnership with xAxis_categories

xAxis_categories

In version 1.0 and 1.0.1 this was xaxis_categories

  • Example config: xAxis_categories = 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'

Used with xAxis_groupby, this tells Highcharts the labels of the data to group by. For example, if you're using xAxis_groupby = month then you'll want to list the names of the month for the expected data output.

You will need to give the right labels, and do not expect all output to start with January. For example, if you start a new database in June, then you would use xAxis_categories = 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'. **It is up to you to provide the right labels for the data you're expecting. **

If you are using xAxis_groupby = year then you don't need to use categories since the database provides the year in it's output.

*If you are not sure what categories to use, then remove xAxis_categories all together, wait for the charts to regenerate, then you'll have the month digits, or the year digits as the group categories on the chart. You can then use that information to provide accurate xAxis_categories

yAxis

  • Example Config: yAxis = 1

By placing yAxis under the observation type, this means you want to associate that data to a different yAxis. There are two you can use. For example, this is typically used to show rain totals on left side of the chart, and rain rate on the right side of the chart.

PLEASE NOTE: For best results, define your yAxis = 1 in the first observation for the chart. See Rain Chart defaults within graphs.conf.example.

  • yAxis = 0 (default): observation will show on the left side of the chart.
  • yAxis = 1: observation will show on the right side of the chart.

yAxis_label

In version 1.0 and 1.0.1 this was yAxisLabel

By setting this will give the yAxis label a full custom override from the built-in default.

yAxis_label_unit

In version 1.0 and 1.0.1 this was yAxisLabel_unit

You can specify a custom unit label for the yAxis label. For example, a value of yAxis_label_unit = "W/m2" will put the "W/m2" inside the yAxis label's parenthesis.

yAxis_min and yAxis_max

In version 1.0 and 1.0.1 this was yaxis_min and yaxis_max

  • Example config:
yAxis_min = 0
yAxis_max = 100

This allows you to define a min and max for the yAxis values. These can be used together or independent of each other.

yAxis_softMin and yAxis_softMax

In version 1.0 and 1.0.1 this was yaxis_softmin and yaxis_softmax

  • Example Config:
yAxis_softMin = 50
yAxis_softMax = 70

Just like with the yAxis_min and yAxis_max this allows you to define the min and max on the yAxis, however (taken right from the Highcharts documentation): if the series data minimum is greater than this, the axis will stay at this minimum, but if the series data minimum is lower, the axis will flex to show all data.

yAxis_tickInterval

In version 1.0 and 1.0.1 this was yaxis_tickinterval

  • Example Config: yAxis_tickInterval = 0.1

The tick interval is the interval of the numbers on the y axis. For example with a tick interval of 0.01, the y axis numbers would show 29.92, 29.91, 29.00 - intervals of 0.01. A tick interval of 5 would show the y axis of 0, 5, 10, 15, etc.

Here is an example of yAxis_tickInterval = 0.01

[homepage]
    [[barometerchartname]]
        [[[barometer]]]
            yAxis_tickInterval = 0.01

tick interval 0.01

And here is an example of yAxis_tickInterval = 0.1

[homepage]
    [[barometerchartname]]
        [[[barometer]]]
            yAxis_tickInterval = 0.1

tick interval 0.1

gapSize

  • Example config: gapSize = 3600000

The gapSize setting is defined in milliseconds and will show a gap if the time between two points is equal to or greater than the value of the gapSize. For example, if your archive_interval from weewx.conf is 300 seconds (5 minutes), then it makes sense to show a gap for any point that is larger than 5 minutes on the day chart since that aggregate is 5 minutes. This indicates that this point in time is missing, and there's no data to graph.

For something like the week charts, that aggregate_interval is 3600 seconds (or 1 day), so the gapSize should be 3600000 to represent 1 day in milliseconds. Which means if the time between two points is greater than 1 day it will show a gap to represent that no data is available.

connectNulls

  • Example config: connectNulls = true

In addition to gapSize, if your sensor purposefully does not send data at the same interval as the rest of the chart plots (for example a solar energy meter that reports in once an hour, but your aggregate_interval is every 5 minutes), you can enable the connectNulls option to connect the line between the two plots if there's a gap from gapSize.

connectNulls

zIndex

  • Example config: zIndex = 1

The zIndex allows you to bring chart points to the front or back of other points.

tooltip_date_format

  • Example config: tooltip_date_format = "dddd LL"

The charts all have a tooltip - which is the hovering box of chart value information. There's defaults for the date and time formatting - mostly it's automatic based on your locale. If you find that you want to change the tooltip date time format, then the tooltip_date_format allows you to do that. The tooltips use moment.js for its formatting. You will need to refer to their documentation on the strings to use to format the text.

In the example above, dddd LL would return Friday May 31 2019 if your locale was United States English. That's because LL is a special locale aware format.

If you used tooltip_date_format = "MM-DD-YY" you would get a date format similar to 05-31-19. Plenty of more information is in the moment.js String + Format documentation.

Almost every Highcharts Series options are accepted!

If you find an option that isn't documented here, but is on the Highcharts documentation for Series data configurations, it'll most likely be accepted to work. For example, if you want to change the line width on hover, you can do this below.

windDir will become the Highcharts series, and anything underneath is series data options. Like this one for the states hover lineWidthPlus option.

        [[[windDir]]]
            [[[[states]]]]
                [[[[[hover]]]]]
                        lineWidthPlus = 0

I encourage you to make as many unique charts as you can then share them with the community!

Example plot definitions

Tooltip date time formatting

Highcharts uses moment.js' string format to convert the time into a display format you like. The formats you can use are at https://momentjs.com/docs/#/parsing/string-format/.

Add tooltip_date_format to the graph group, and define the time format you want. LLL in the example below is locale aware and will adjust the day and months around based on your locale. For example in my locale it will show May 15 2019 9:00 AM as an example. If you do not want locale, and rather specify your own format for day/month, you can use DD/MM which will give you 31/05.

If the locale aware string formats aren't working for you then go long hand with the formatting. For example if you want Wednesday 15 May 20:25 you would use this formatting: dddd DD MMM HH:mm.

Explanation (this comes right from the moment.js documentation):

  • dddd gives you full day name, like Saturday. ddd would give you short day name like Sat
  • DD would give you the day's date as a number with a leading 0, like 05. If you want just 5 it would be D
  • MMM gives you the short name of the month like "Jan". If you want "January" it'd be MMMM
  • HH is the hour in 24 hour format with a leading 0, like 02. If you don't want the leading 0 it would be H.
  • mm is the minute with a leading 0, like 08. If you don't want the leading 0, use m.

image

[day]
    # Chart Timespan Defaults
    title = Today
    show_button = true
    button_text = Today
    time_length = today
    tooltip_date_format = "LLL"
    gapsize = 300000

    [[chart1]]
        title = Temperature
        ..........

Decimal point, thousands grouping and the number of digits after the decimal point - string formatting

The number format (decimals, decimal point and thousands separator) are automatically detected by the skin and defined by the locale on your system. If you want to do an override for a specific graph observation you can use the numberFormat option for that observation.

Here you can see barometer is defined to use 5 decimals using the decimals = 5, the decimal point is . using the decimalPoint = "." and the thousands separator is , with thousandsSep = ",". The tooltip hover and the y axis numbers are also updated with this formatting.

image

[day]
... graph group options ...
    [[chart4]]
        title = Barometer
        [[[barometer]]]
            color = "#BECC00"
            [[[[numberFormat]]]]
                decimals = 5
                decimalPoint = "."
                thousandsSep = ","

In this example below, I am letting weewx define how many decimals from weewx.conf's StringFormats section (since decimals is not explicitly defined here), and will have the , for the decimal point and nothing for the thousands separator (nothing means no space and no character).

image

[day]
... graph group options ...
    [[chart4]]
        title = Barometer
        [[[barometer]]]
            color = "#BECC00"
            [[[[numberFormat]]]]
                decimalPoint = ","
                thousandsSep = ""

Example Chart Types

Wind Graph with scatter, area, and line plots

    [[windplt]]
        # The combined Wind Chart works best in this configuration
        title = Wind Speed and Direction
        yAxis_min = 0
        [[[windDir]]]
            zIndex = 2
            yAxis = 1
            yAxis_max = 360
            lineWidth = 0
            # This plot is to be shown on the Graphs Week page. So here we override the timespan default aggregate type to one specific to this chart
            aggregate_type = avg
            [[[[marker]]]]
                enabled = true
            [[[[states]]]]
                [[[[[hover]]]]]
                    lineWidthPlus = 0
        [[[windGust]]]
            zIndex = 1
        [[[windSpeed]]]
           type = area

This plot definition has three observations on one graph. the Wind Speed (windSpeed) is plotted below the others (no zIndex specified). Wind Gust (windGust) is plotted on top of Wind Speed (zIndex=1) and Wind Direction is plotted on top of both (zIndex=2).

Additionally Wind direction is associated with the right vertical axis (yAxis=1). That axis has a set maximum of 360 degrees (yAxis_max = 360) which translate to N. So wind direction goes from North through all directions and returning to North. The other Wind direction settings are needed because it is a scatter plot without connecting lines.

Wind Gust and Wind Speed are associated with the left vertical axis (no yAxis is specified). Wind speed is rendered as an area plot. Here's an example of how the plot specified by the settings above looks: Wind Plot


Wind Rose

[[roseplt]]
    title = Wind Rose
    [[[windRose]]]

A Wind Rose is a special graph that displays wind speed and direction over the period of time chosen. As you see above it only needs a title and the observation type [[[windRose]]]. A Wind Rose is displayed as a polar chart with wedges designating the wind direction around the compass. The length and color of the wedges represent the percentage of time each range of the wind speeds was blowing from a specific direction. Hovering the mouse over the Wind Rose will display the data. This is an example Wind Rose with the mouse being hovered over the NNE direction to show the details of wind from that direction. Wind Rose


UV and Solar Radiation

[[solarRadGraph]]
    title = Solar Radiation and  UV Index
    [[[radiation]]]
       name = Solar Radiation
       zIndex = 1
       color = "#ffc83f"
    [[[maxSolarRad]]]
        name = Theoretical Max Solar Radiation
        type = area
        color = "#f7f2b4"
        y_label = "W/m2"
    [[[UV]]]
        yAxis = 1
        yAxis_min = 0
        yAxis_max = 14
        color = "#90ed7d"
        y_label = "UV"
        name = UV Index
        zIndex = 2

This plot combines the UV, Solar Radiation and maxSolarRad observations into 1 chart. Note: The maxSolarRad observation is not a default for weewx. It requires pyephem to be installed and your weewx schema to be extended. The maxSolarRad is displayed here in an area chart, with a background yellow color fill. The UV chart is on the right yAxis with a minimum of 0 and maximum of 14 for that axis. The solar radiation only has a color override, which returns this graph. Thanks to Belchertown user @41south for this great graph combination!

UV and Solar Radiation

Stacked Column Graph

[stackedTest]
    title = Lightning
    time_length = year
    aggregate_type = max
    aggregate_interval = 86400 # 1 day
    gapsize = 86400000
    type = column

    [[chart1]]
        title = Lightning
        [[[lightning_strikes]]]
            name = Lightning
            stacking = normal
        [[[avg_distance]]]
            name = Average Distance
            stacking = normal

image

Mirrored Stacked Column Chart

If you want to show a bar chart that has values on both sides of the 0 xAxis, you can use the example below. This will show positive numbers below the 0, allowing you to show multiple observations in a "mirror". The key is to use the stacking option, and the mirrored_value option.

Note: These observations in this example are not part of weewx. You would have to expand your weewx database to include energy values like this. That process is not covered under the Belchertown skin scope.

[[chart6]]
    title = Energy
    type = column
    [[[totalEnergyConsumption]]]
        stacking = "normal"
        name = Consumed
    [[[totalEnergyImport]]]
        stacking = "normal"
        mirrored_value = true
        name = Imported
        color = '#d33682'
    [[[totalEnergyGenerated]]]
        stacking = "normal"
        name = Generated
        color = '#e4d354'
    [[[totalEnergyExported]]]
        stacking = "normal"
        mirrored_value = true
        name = Exported
        color = '#90ed7d'

image

Average Climate Values Chart

One of the requested charts to have support for was the Average Climate Values chart. This chart utilizes the x axis grouping to aggregate the data and show it as a total for the group. Here's the config for a 2018 chart grouped by month, and the output.

In this example you can also see how to enable markers using the series option [[[[marker]]]] so that they show up on the line graph.

[2018climate]
    title = "Average Climatological Values for 2018"
    show_button = true
    button_text = 2018 Climate
    type = spline
    time_length = year_specific
    year_specific = 2018
    aggregate_type = max
    aggregate_interval = 86400 # 1 day
    gapsize = 86400000
    xAxis_groupby = month
    xAxis_categories = 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'

    [[chart1]]
        title = "Average Climatological Values for 2018"
        [[[outTemp]]]
            zIndex = 2
            name = Max Temperature
            color = "#fc0404"
            [[[[marker]]]]
                enabled = true
                radius = 4
        [[[outTemp_min]]]
            name = Min Temperature
            observation_type = outTemp
            aggregate_type = min
            zIndex = 2
            color = "#173c6a"
            [[[[marker]]]]
                enabled = true
                radius = 4
        [[[rainTotal]]]
            name = Rain Total
            type = column
            yAxis = 1
            zIndex = 0
            color = "#438bd6"

image

If you want Average Climatological Values for the current year use this config. Note See how I am able to combine the day timescale inside the [day] group, but override that with the chart options itself under the [[avgclimatethisyear]]? This is how you can mix and match charts and their timespans!

[day]
    # Chart Timespan Defaults
    title = Today since Midnight
    show_button = true
    button_text = Today
    time_length = today
    gapsize = 300000
    
    [[avgclimatethisyear]]
        title = "Average Climatological Values for This Year"
        type = spline
        time_length = year
        aggregate_type = max
        aggregate_interval = 86400 # 1 day
        gapsize = 86400000
        xAxis_groupby = month
        xAxis_categories = 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'
        [[[outTemp]]]
            zIndex = 2
            name = Max Temperature
            color = red
        [[[outTemp_min]]]
            name = Min Temperature
            observation_type = outTemp
            aggregate_type = min
            zIndex = 2
        [[[rainTotal]]]
            name = Rain Total
            type = column
            yAxis = 1
            zIndex = 0
            color = "#268bd2"

image

Grouping rain totals

To use the same x axis grouping but this time to get all rain data from your database for all time, you can use a config like this.

The first chart in this group will show all rain totals from your database for all times grouped by month. This is a good way to find out which month is your rainiest month.

The second chart will give you the rain totals for all years in your database.

The third chart shows you all the rain for 2018 grouped by month. This way you can chart and find which month was the rainiest month.

[raintotals]
    title = Rain Totals by Month
    show_button = true
    button_text = Rain Totals
    type = column
    time_length = all
    aggregate_type = max
    aggregate_interval = 86400 # 1 day

    [[rainmonthtotals]]
        title = Historical Rain Totals By Month
        subtitle = Rain Totals for All Months for All Time
        xAxis_groupby = month
        xAxis_categories = 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'
        [[[rainTotal]]]
            name = Rain Total

    [[rainyeartotals]]
        title = Historical Rain Totals By Year
        xAxis_groupby = year
        [[[rainTotal]]]
            name = Rain Total

    [[rain2018totals]]
        title = Rain Totals for 2018
        xAxis_groupby = month
        xAxis_categories = 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'
        time_length = year_specific
        year_specific = 2018
        [[[rainTotal]]]
            name = Rain Total

image

Using data_binding

If you have data in another database than the primary weewx database, then you can use the data_binding option to retrieve that data to visualize it in a chart. For example if you have a lightning sensor, or an SDR Receiver and it's logging to a separate database you can use a config similar to this one.

Things to notice, data_binding is below the 2 bracket section, and the words in the 3 brackets must match the column name in your custom database.

[homepage]
    [[lightning_binding_test]]
    title = Lightning  Binding
    data_binding = lightning_binding  
    yAxisLabel =  ""
    time_length = year  
    xAxis_groupby = day
    [[[distance_km]]]
        name = Lightning  Distance KM  
        type = column  
        yAxisLabel =  Lightning  Count  
    [[[distance_mi]]]
        name = Lightning  Distance  (mi)
        type = column

This would produce a chart similar to this one:

lightning_binding_chart

Your chart!

Have you made a pretty sweet chart that should be featured here? Let me know!

Time Scales for Charts

To graph days ago

  • Example config: time_length = days_ago

You can also use time_length = days_ago with supporting option of time_ago = 1 which will graph a single graph of plots for 1 day ago. Use time_ago = 7 to graph a single day plots from the 7th day ago.

[yesterday]
    # Chart Timespan Defaults
    title = Yesterday
    show_button = true
    button_text = Yesterday
    time_length = days_ago
    time_ago = 1
    gapsize = 300000

    [[chart1]]
        title = Temperature
        [[[outTemp]]]
            zIndex = 1
            name = Temperature
        [[[windchill]]]
        [[[heatindex]]]
        [[[dewpoint]]]
            color = "#91e8e1"

To graph weeks ago

  • Example config: time_length = weeks_ago

You can also use time_length = weeks_ago with supporting option of time_ago = 1 which will graph a single graph of plots for 1 week ago for the full week. Use time_ago = 7 to graph a single week plots from the 7th week ago for that full week.

To graph months ago

  • Example config: time_length = months_ago

You can also use time_length = months_ago with supporting option of time_ago = 1 which will graph a single graph of plots for 1 month ago for the full month. Use time_ago = 7 to graph a single month plots from the 7th month ago for that full month.

To graph years ago

  • Example config: time_length = years_ago

You can also use time_length = years_ago with supporting option of time_ago = 1 which will graph the plots for 1 year ago for the full year. Use time_ago = 3 to graph a single year plots from the 3rd year ago for that full year.

[lastyear]
    # Chart Timespan Defaults
    title = Last Year
    show_button = true
    button_text = Last Year
    type = spline
    time_length = years_ago
    time_ago = 1
    aggregate_type = max
    aggregate_interval = 86400 # 1 day
    gapsize = 86400000

    [[chart1]]
        title = Temperature
        [[[outTemp]]]
            zIndex = 1
            name = Max Temperature
            color = red
        [[[outTemp_min]]]
            name = Min Temperature
            observation_type = outTemp
            aggregate_type = min
            color = "#7cb5ec"

To graph a specific day

  • Example config: time_length = day_specific
[halloween2017]
    button_text = "October 31, 2017"
    time_length = day_specific
    month_specific = 10
    day_specific = 31
    year_specific = 2017
    gapsize = 300000
    title = "Halloween 2017"

    [[chart1]]
        title = Temperature
        [[[outTemp]]]
            name = Temperature
            zIndex = 1
        [[[windchill]]]
        [[[heatindex]]]
        [[[dewpoint]]]

This configuration uses time_length = day_specific which has supporting options of month_specific which specifies the month, day_specific which specifies the day of the month and year_specific which specifies the year. All 3 combined will chart the temperature plots from October 31, 2017 from your database.

To graph a specific month

  • Example config: time_length = month_specific
[august2016]
    # Chart Timespan Defaults
    title = August 2016
    button_text = August 2016
    time_length = month_specific
    month_specific = 8
    year_specific = 2016
    type = spline
    aggregate_type = max
    aggregate_interval = 86400 # 1 day
    gapsize = 86400000

    [[chart1]]
        title = Temperature
        [[[outTemp]]]
            zIndex = 1
            name = Max Temperature
            color = red
        [[[outTemp_min]]]
            name = Min Temperature
            observation_type = outTemp
            aggregate_type = min
            color = "#7cb5ec"

This configuration uses time_length = month_specific which has supporting options of month_specific which specifies the month and year_specific which specifies the year. All 2 combined will chart the temperature plots from August 1 through August 31, 2016 from your database.

To graph a specific year

  • Example config: year_specific = 2018
[2018]
    # Chart Timespan Defaults
    title = 2018
    button_text = 2018
    type = spline
    time_length = year_specific
    year_specific = 2018
    aggregate_type = max
    aggregate_interval = 86400 # 1 day
    gapsize = 86400000

    [[chart1]]
        title = Temperature
        [[[outTemp]]]
            zIndex = 1
            name = Max Temperature
            color = red
        [[[outTemp_min]]]
            name = Min Temperature
            observation_type = outTemp
            aggregate_type = min
            color = "#7cb5ec"

This configuration uses time_length = year_specific which has supporting options of year_specific which specifies the year. This will chart the temperature plots from 2018 from your database.

To graph a specific time span

  • Example config:
    time_length = timespan_specific
    timespan_start = START_TIMESTAMP
    timespan_stop = STOP_TIMESTAMP

As of version 1.1, you can specify a specific timespan to graph. You need to provide the start timestamp and the end timestamp in the Unix Epoch format. The easiest way to get these epoch timestamps is to use a converter like epochconverter.com. Simply fill their form out for the time you need and it will return a timestamp.

For example, I want to graph the "bomb cyclone" we had in New England on October 16 and October 17, 2019. So I find out that October 16, 2019 at 12:00:00 AM in the Eastern timezone is 1571198400. That's my start time. My end time is October 17, 2019 at 11:59:59 AM, so my timestamp is 1571371199

With that I can make my graphs.conf configuration look like this:

[2019bombcyclone]
    button_text = "2019 Bomb Cyclone"
    show_button = true
    time_length = timespan_specific
    timespan_start = 1571198400
    timespan_stop = 1571371199
    gapsize = 300000
    title = "2019 Bomb Cyclone"

    [[barometerchart]]
        title = Barometer
        type = spline
        [[[barometer]]]
            color = "#BECC00"

This returns a chart which spans across the 2 days, it looks like this:

image

To graph all times in your database

Using time_length = all will create a chart from the first record in your database to the last.

yAxis Labels

yAxis label is defined top down. Meaning the last observation in the group will override the others.

No yAxisLabel override defined

In this example there are no yAxisLabel overrides defined, so the yAxis label is taken from the last observation in the group which is dewpoint.

[homepage]
    # Chart Timespan Defaults
    show_button = false
    button_text = Homepage
    time_length = today
    gapsize = 300000
    title = Today Since Midnight.

    [[chart1]]
        title = Temperature
        [[[outTemp]]]
            name = Temperature
            zIndex = 1
        [[[windchill]]]
        [[[heatindex]]]
        [[[dewpoint]]]
            color = gray

image

yAxis Label Override at the top of the observation group

Since we have defined a yAxisLabel at the top of the observation chart group, it will be used instead of any of the observation labels.

[homepage]
    # Chart Timespan Defaults
    show_button = false
    button_text = Homepage
    time_length = today
    gapsize = 300000
    title = Today Since Midnight.

    [[chart1]]
        title = Temperature
        yAxisLabel = "Example Label At The Top (°F)" 
        [[[outTemp]]]
            name = Temperature
            zIndex = 1
        [[[windchill]]]
        [[[heatindex]]]
        [[[dewpoint]]]
            color = gray

image

Multiple yAxis Labels defined but not for the last observation

If you have multiple yAxisLabels defined, the bottom one in the group will win - even if that bottom observation does not have a yAxisLabel defined. Because it's top down, the last observation will win the label. Take this example which has 3 defined, yet the output is for Dew Point. That's because Dew Point's default label is applied.

To fix this, specify a yAxisLabel for dewpoint that would be what you want for the yAxis label.

[homepage]
    # Chart Timespan Defaults
    show_button = false
    button_text = Homepage
    time_length = today
    gapsize = 300000
    title = Today Since Midnight.
    
    [[chart1]]
        title = Temperature
        [[[outTemp]]]
            name = Temperature
            zIndex = 1
            yAxisLabel = "yAxisLabel inside temperature"
        [[[windchill]]]
            yAxisLabel = "yAxisLabel inside windchill"
        [[[heatindex]]]
            yAxisLabel = "yAxisLabel inside heatindex"
        [[[dewpoint]]]
            color = gray

image

Multiple yAxis Labels defined for all observations

As with the example above, we add the yAxisLabel to the last observation and now that label is what becomes the label for the yAxis.

[homepage]
    # Chart Timespan Defaults
    show_button = false
    button_text = Homepage
    time_length = today
    gapsize = 300000
    title = Today Since Midnight.
    
    [[chart1]]
        title = Temperature
        [[[outTemp]]]
            name = Temperature
            zIndex = 1
            yAxisLabel = "yAxisLabel inside temperature"
        [[[windchill]]]
            yAxisLabel = "yAxisLabel inside windchill"
        [[[heatindex]]]
            yAxisLabel = "yAxisLabel inside heatindex"
        [[[dewpoint]]]
            yAxisLabel = "yAxisLabel inside dewpoint"
            color = gray

image

Removing a yAxis label

If you want to remove the yAxis label all together, you can set the yAxisLabel to "" and define it at the top of the observation group that you want to be blank. Take this example below:

[homepage]
    # Chart Timespan Defaults
    show_button = false
    button_text = Homepage
    time_length = today
    gapsize = 300000
    title = Today Since Midnight.

    [[chart1]]
        title = Temperature
        yAxisLabel = ""
        [[[outTemp]]]
            name = Temperature
            zIndex = 1
        [[[windchill]]]
        [[[heatindex]]]
        [[[dewpoint]]]
            color = gray

image

An unknown observation and it's label

This will have NO yAxis label since lightning_strikes and avg_distance are not a known built-in weewx observation - so there's no label or unit label.

Setting the yAxis label is easy! Just see one of the examples above.

    [[lightninggroupby]]
        title = Lightning Strikes This Year
        time_length = year
        xAxis_groupby = month
        xAxis_categories = 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'

        [[[lightning_strikes]]]
            name = Lightning
            type = column
            stacking = normal
        [[[avg_distance]]]
            name = Average Distance
            type = column
            stacking = normal

image

Tips

  • Caution! The more charts you have, the slower things can become. This is especially true for graphs defined beneath the [year] Chart Group (graphs which are displayed on the Graphs YEAR page). Charts are interactive and have to be generated from the database on every archive interval. This could result in large file sizes that are generated, and that your website visitors have to download. You're welcome to customize as many charts as you want, but be warned things could slow down if you do too much! The defaults in this skin have proven to be a good baseline for the number of charts and options without overwhelming your system.

  • A line plot (like windSpeed) and a scatter plot (like windDir) cannot exist on the same chart and have working tooltips (the bubble that pops up). But according to this post, you can "trick" highcharts into doing almost the same thing. https://stackoverflow.com/a/43992380/1177153. However the graph which has windSpeed and windDir inside graphs.conf.example utilize line charts. The line chart for windDir has the line width removed, so it appears as a scatter chart. I have been referring to this trick as a line-as-scatter.

  • When you specify a color for an observation, try choosing a color from this list first. They tend to look good both in light mode and in dark mode. They are the default colors if you allow the skin to choose the colors. Note: Color names are mine and not official.

    • #268bd2 - blue
    • #90ed7d - light green
    • #f7a35c - tan-brown
    • #d33682 - magenta
    • #8085e9 - light purple
    • #e4d354 - yellow-green
    • #f15c80 - pink
    • #8085e8 - purple-blue
    • #8d4653 - brick
    • #91e8e1 - aqua
  • Special rainTotal Observation Type: The weewx archive type "rain" actually counts "bucket tips". That is, when the rain fills your rain collector and the bucket tips to count that rain measurement. The chart generated for rain will only show when the bucket tipped. It is not an aggregated total. Using the special built in "rainTotal" observation - unique to Belchertown - will increment those bucket tips across the graph's time period, showing you the total rain calculation for that time period. This means that any calculated rain total which precedes the beginning of the graph time period will not be added to the rain total plotted on the graph.

  • A missing Y Axis label. If your yAxis label is missing, it may mean that the observation doesn't have a label that weewx has built-in. You can do 1 of two things. First, re-order the items in the chart so the last observation is different since this is the label typically used. If that doesn't solve it, then you can add a custom yAxis label using y_label. Within your chart group, add y_label = Your Label Here and the chart will display this text. For example in this chart configuration maxSolarRad is the last observation, so that will be what's used for the yAxis label. Since weewx doesn't have a label for maxSolarRad built-in, it'll be an empty () on the chart. So in this example you can see I'm adding my own custom label for that observation.

    [[solarRadGraph]]
        title = Solar Radiation
        [[[radiation]]]
            name = Solar Radiation
        [[[maxSolarRad]]]
            y_label = "W/m²"
            name = Theoretical Max Solar Radiation
  • It is possible to specify different plots (and/or plot definitions) on the Belchertown home page than those on the Today Graphs page. For instance the front page can show plots since midnight of the current day, while the Today Graphs page can show those same (or different) plots with data from the past 24 hours. To do this, just change the entries under the Chart Group section in graphs.conf called [homepage]. Under this section add the graphs you want plotted on the home page with their associated options. If you want to mirror an existing Chart Group (e.g. [week]) and don't want to copy all of the entries from that Chart Group to the [homepage] Chart Group, you can just add highcharts_frontpage_graphgroup = week to the Belchertown [Extras] stanza in the weewx.conf file. (The variable highcharts_frontpage_graphgroup is set to homepage by default in skin.conf). Be sure to reload WeeWX or restart it if you make a change in weewx.conf and then run a wee_reports (or wait for an archive interval).

  • Additionally, a plot can be added to any Belchertown page that supports .inc files (e.g. Records page, About page and the home page index_hooks)! For example let's work on the About page. To do this, add a new Chart Group section in graphs.conf called [about] and add one or more plot definitions there. Then open your about.inc file and at the top enter this: <script type='text/javascript'>showChart("about");</script>. Then within the content of your About page, you would place a line like this where you want the chart to appear: <div id="**YOUR-CHART-ID**"></div>. Replace YOUR-CHART-ID with the Chart ID name (or names) that you gave the chart under the [about] section in graphs.conf. Repeat this <div> for each custom chart you wish to display, changing the id= with your chart ID. An example can be seen at https://belchertownweather.com/about/

What to do if you need help

If your charts aren't rendering properly, enable the belchertown_debug setting in your skin.conf and restart weewx. Then run a wee_reports (or wait for an archive interval). Using your browsers Developer Tools (Chrome, Firefox, Edge) open the JavaScript console and refresh your page. This console will have a lot of information which can help you determine what may have went wrong. Such as a malformed graphs.conf, a graph group missing, etc. Check these debug messages first to see if it can clue you in to what may have went wrong.

The best place to find help if you encounter problems is the Google weewx-users group (https://groups.google.com/forum/#!forum/weewx-user). This is the official WeeWX place to post questions and request help. The developer of the Belchertown skin is active there as are other WeeWX developers and many knowledgeable users. All are helpful to those who encounter issues with WeeWX implementations. If your issue is caused by a bug you find in the Belchertown skin, or you have a feature request, you can open an Issue on the poblabs/weewx-belchertown GitHub repository (https://github.com/poblabs/weewx-belchertown/issues). If you are testing release candidates of the Belchertown skin, this is probably the best place to note any problems or bugs you encounter.