What's new in the Forecastwrapper

  • Solar Irradiance on a tilted plane
  • Wind on an oriented building face
  • No more "include this", "include that". Everything is included. (I implemented these flags to speed to speed up some things (which you cannot notice), but it complicates the code so much that it is not worth it)
  • Daytime aggregates have been deprecated (we don't need this anymore since we have irradiance from dark sky. But if anyone incists, i can perhaps re-implement it)
  • No more special timezone stuff, you get the data in a timezone-aware format, localized to the location of the request. If you want another timezone, use tz_convert

Demo of the forecast.io wrapper to get past and future weather data

Important: you need to register for an apikey here: https://developer.forecast.io/ Put the key you obtain in the opengrid.cfg file as follows:

[Forecast.io]
apikey: your_key

In [ ]:
import os
import sys
import inspect
import pandas as pd
import charts

Import API wrapper module


In [ ]:
from opengrid.library import forecastwrapper

Get weather data in daily and hourly resolution

To get started, create a Weather object for a certain location and a period


In [ ]:
start = pd.Timestamp('20150813')
end = pd.Timestamp('20150816')

In [ ]:
Weather_Ukkel = forecastwrapper.Weather(location='Ukkel', start=start, end=end)

You can use the methods days() and hours() to get a dataframe in daily or hourly resolution


In [ ]:
Weather_Ukkel.days()

In [ ]:
Weather_Ukkel.hours().info()

Degree Days

Daily resolution has the option of adding degree days. By default, the temperature equivalent and heating degree days with a base temperature of 16.5°C are added.

Heating degree days are calculated as follows:

$$heatingDegreeDays = max(0 , baseTemp - 0.6 * T_{today} + 0.3 * T_{today-1} + 0.1 * T_{today-2} )$$

Cooling degree days are calculated in an analog way:

$$coolingDegreeDays = max(0, 0.6 * T_{today} + 0.3 * T_{today-1} + 0.1 * T_{today-2} - baseTemp )$$

Add degree days by supplying heating_base_temperatures and/or cooling_base_temperatures as a list (you can add multiple base temperatures, or just a list of 1 element)

Get some more degree days


In [ ]:
Weather_Ukkel.days(heating_base_temperatures = [15,18],
                   cooling_base_temperatures = [18,24]).filter(like='DegreeDays')

In [ ]:
Weather_Ukkel.days()

Hourly resolution example

Location can also be coördinates


In [ ]:
start = pd.Timestamp('20150916')
end = pd.Timestamp('20150918')
Weather_Brussel = forecastwrapper.Weather(location=[50.8503396, 4.3517103], start=start, end=end)
Weather_Boutersem = forecastwrapper.Weather(location='Kapelstraat 1, 3370 Boutersem', start=start, end=end)

In [ ]:
df_combined = pd.merge(Weather_Brussel.hours(), Weather_Boutersem.hours(), suffixes=('_Brussel', '_Boutersem'), 
                       left_index=True, right_index=True)

In [ ]:
charts.plot(df_combined.filter(like='cloud'), stock=True, show='inline')

Built-In Caching

Caching is turned on by default, so when you try and get dataframes the first time it takes a long time...


In [ ]:
start = pd.Timestamp('20170131', tz='Europe/Brussels')
end = pd.Timestamp('20170201', tz='Europe/Brussels')

In [ ]:
Weather_Ukkel = forecastwrapper.Weather(location='Ukkel', start=start, end=end)
Weather_Ukkel.days().head(1)

... but now try that again and it goes very fast


In [ ]:
Weather_Ukkel = forecastwrapper.Weather(location='Ukkel', start=start, end=end)
Weather_Ukkel.days().head(1)

You can turn of the behaviour by setting the cache flag to false:


In [ ]:
Weather_Ukkel = forecastwrapper.Weather(location='Ukkel', start=start, end=end, cache=False)

Solar Irradiance!

Dark Sky has added Solar Irradiance data as a beta.

Note:

  • The values are calculated, not measured. Dark Sky uses the position of the sun in combination with cloud cover.
  • Western Europe is not in Dark Sky's "primary region", therefore the data is not super-accurate.
  • Since it is a beta, the algorithms and therefore the values may change
  • I (JrtPec) have done a qualitative analysis that compared these values with those measured by KNMI (Netherlands). The differences were significant (27% lower). I have notified Dark Sky and they will investigate and possibly update their algorithms.
  • You need to delete your cached files in order to include these new values (everything will have to be re-downloaded)
  • If Dark Sky were to update their values, the cache needs to be deleted again.

In [ ]:
Weather_Ukkel = forecastwrapper.Weather(location='Ukkel', start=start, end=end)

Hourly data


In [ ]:
Weather_Ukkel.hours()[[
        'GlobalHorizontalIrradiance',
        'DirectNormalIrradiance',
        'DiffuseHorizontalIrradiance',
        'ExtraTerrestrialRadiation',
        'SolarAltitude',
        'SolarAzimuth']].dropna().head()
  • Global Horizontal Irradiance is the amount of Solar Irradiance that shines on a horizontal surface, direct and diffuse, in Wh/m2. It is calculated by transforming the Direct Normal Irradiance (DNI) to the horizontal plane and adding the Diffuse Horizontal Irradiance (DHI):
$$GHI = DNI * cos(90° - Altitude) + DHI$$
  • The GHI is what you would use to benchmark PV-panels

  • Direct Normal Irradiance is the amount of solar irradiance that shines directly on a plane tilted towards the sun. In Wh/m2.

  • Diffuse Horizontal Irradiance is the amount of solar irradiance that is scattered in the atmosphere and by clouds. In Wh/m2.

  • Extra-Terrestrial Radiation is the GHI a point would receive if there was no atmosphere.

  • Altitude of the Sun is measured in degrees above the horizon.

  • Azimuth is the direction of the Sun in degrees, measured from the true north going clockwise.

At night, all values will be NaN

Daily data

The daily sum of the GHI is included in the day dataframe. Values are in Wh/m2

If you need other daily aggregates, give me a shout!


In [ ]:
Weather_Ukkel.days()

Add Global Irradiance on a tilted surface!

Create a list with all the different irradiances you want

A surface is specified by the orientation and tilt

  • Orientation in degrees from the north: 0 = North, 90 = East, 180 = South, 270 = West
  • Tilt in de degrees from the horizontal plane: 0 = Horizontal, 90 = Vertical

In [ ]:
# Lets get the vertical faces of a house
irradiances=[
    (0, 90), # north vertical
    (90, 90), # east vertical
    (180, 90), # south vertical
    (270, 90), # west vertical
]

In [ ]:
Weather_Ukkel.hours(irradiances=irradiances).filter(like='GlobalIrradiance').dropna().head()

The names of the columns reflect the orientation and the tilt


In [ ]:
Weather_Ukkel.days(irradiances=irradiances).filter(like='GlobalIrradiance')

Wind on an oriented building face

The hourly wind speed and bearing is projected on an oriented building face.

We call this the windComponent for a given orientation. This value is also squared and called windComponentSquared. This can be equated with the force or pressure of the wind on a static surface, like a building face. The value is also cubed and called windComponentCubed. This can be correlated with the power output of a windturbine.

First, define some orientations you want the wind calculated for. Orientation in degrees starting from the north and going clockwise


In [ ]:
orientations = [0, 90, 180, 270]

In [ ]:
Weather_Ukkel.hours(wind_orients=orientations).filter(like='wind').head()

In [ ]:
Weather_Ukkel.days(wind_orients=orientations).filter(like='wind').head()

In [ ]: