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.