Code Example - Weather Forecast

The following code example is similar to the previous weather example, except rather than just getting the historical values and populating the asset library, it uses Facebook’s Prophet Python library to use the incoming historical data to make a prediction on the future temperatures, creating some charts in the process.

Dockerfile

By default, Akumen does not include the fbprophet Python package. Simply running the code below will return an error. We can create a file called Dockerfile. A template is created inside Akumen - simply add the line

RUN pip3 install fbprophet

to the Dockerfile. When the model runs, it will download and install fbprophet into the container your model runs in, and allows you to use that package.

The model

Create a new Python model, and copy and paste the code below over the top of main.py.

import akumen_api
from akumen_api import progress
import requests
import pandas as pd
from datetime import datetime
from datetime import timedelta

from fbprophet import Prophet

from matplotlib import pyplot

import matplotlib
matplotlib.use('Agg')

def akumen(**kwargs):
    """
    !! This akumen() function must exist in the execution file!

    Parameters:
        !! These lines define parameters, and a line must exist per input (or output).

        - Output: forecast [tabular]
    """
    progress('Running Akumen model...')

    response = requests.get(f"{akumen_api.AKUMEN_API_URL}assets/template/Weather Station", headers={ 'Authorization': akumen_api.API_KEY })
    response.raise_for_status()
    assets = response.json()
    progress('Fetched weather stations from asset library')
    
    weather = None
    
    for asset in assets:
        id = next((attribute['value'] for attribute in asset['attributes'] if attribute['name'] == 'BOM_Id'), None)
        wmo = next((attribute['value'] for attribute in asset['attributes'] if attribute['name'] == 'WMO'), None)
        if id is None or wmo is None:
            # We don't have all the data for the weather station, so ignore
            continue
        
        response = requests.get(f"http://bom.gov.au/fwo/{id}/{id}.{wmo}.json")
        response.raise_for_status()
        
        # Return a dataframe of the observation data
        df = pd.DataFrame(response.json()['observations']['data'])

        # Configure the data frame for forecasting
        pr = pd.DataFrame(df, columns=['local_date_time_full', 'air_temp'])
        pr.columns = ['ds', 'y']
        pr['ds'] = pd.to_datetime(pr['ds'], format='%Y%m%d%H%M%S')

        # define the model
        model = Prophet()
        # fit the model
        model.fit(pr)

        future = []
        # get the last date
        last_date = pr['ds'].max().to_pydatetime()
        for i in range(0, 30):
            last_date = last_date + timedelta(hours=1/2)
            future.append(last_date)

        future = pd.DataFrame(future)
        future.columns = ['ds']
        forecast = model.predict(future)
        # Add in some columns so we can see the forecasts for all of the stations
        forecast['history_product'] = id
        forecast['wmo'] = wmo

        # Plot and save the image into outputs, this allows Akumen to render the output chart
        model.plot(forecast)
        pyplot.savefig(f"outputs/{asset['name']}.png")
        
        if weather is None:
            weather = forecast
        else:
            # We've already populated from one weather station, so merge in
            weather = weather.append(forecast, ignore_index=True)
            
    # Cleanup the column names
    weather.rename(columns={'ds': 'date', 'y': 'air_temp'}, inplace=True)
        
    # The akumen() function must return a dictionary including keys relating to outputs.
    return {
        'forecast': weather
    }


if __name__ == '__main__':
    """
    Any local test code can be used in an import guard
    when developing on a local machine, you can put code here that won't
    get run by Akumen.
    """
    print('Running local tests...')
    assert (akumen(1, 2)['first_result'] == 3)
    assert (akumen(3, 4)['second_result'] == -1)
    print('Tests completed!')

Once the model has been run successfully, click the images button to see the generated images from the model, including the forecast trend and range of the forecast.