Exogenous model input from a file

In this notebook we’ll demonstrate using an external data source to feed values into a model. We’ll use the carbon emissions dataset, and feed total emissions into a stock of excess atmospheric carbon:

We’ll begin as usual by importing PySD and the machinery we need in order to deal with data manipulation and plotting.

%pylab inline
import pysd
import pandas as pd
Populating the interactive namespace from numpy and matplotlib

We use Pandas library to import emissions data from a .csv file. In this command, we both rename the columns of the dataset, and set the index to the ‘Year’ column.

emissions = pd.read_csv('../../data/Climate/global_emissions.csv',
                        skiprows=2, index_col='Year',
                        names=['Year', 'Total Emissions',
                               'Gas Emissions', 'Liquid Emissions',
                               'Solid Emissions', 'Cement Emissions',
                               'Flare Emissions', 'Per Capita Emissions'])
emissions.head()
Total Emissions Gas Emissions Liquid Emissions Solid Emissions Cement Emissions Flare Emissions Per Capita Emissions
Year
1751 3 0 0 3 0 0 NaN
1752 3 0 0 3 0 0 NaN
1753 3 0 0 3 0 0 NaN
1754 3 0 0 3 0 0 NaN
1755 3 0 0 3 0 0 NaN
model = pysd.read_vensim('../../models/Climate/Atmospheric_Bathtub.mdl')

In our vensim model file, the value of the inflow to the carbon bathtub, the Emissions parameter, is set to zero. We want to instead have this track our exogenous data.

Emissions=
    0

Excess Atmospheric Carbon= INTEG (
    Emissions - Natural Removal,
    0)

Natural Removal=
    Excess Atmospheric Carbon * Removal Constant

Removal Constant=
    0.01

Aligning the model time bounds with that of the dataset

Before we can substitute in our exogenous data, however, we need to ensure that the model will execute over the proper timeseries. The initial and final times of the simulation are specified in the model file as:

print('initial:', model.components.initial_time())
print('final:', model.components.final_time())
initial: 0
final: 100

However, the time frame of the dataset runs:

print('initial:', emissions.index[0])
print('final:', emissions.index[-1])
initial: 1751
final: 2011

In order to run the model over a time series equal to that of the data set, we need to specify the appropriate initial conditions, and ask the run function to return to us timestamps equal to that of our dataset:

res = model.run(initial_condition=(emissions.index[0],
                                   {'Excess Atmospheric Carbon': 0}),
                return_timestamps=emissions.index.values,
                return_columns=['Emissions', 'Excess Atmospheric Carbon'])
res.head()
Emissions Excess Atmospheric Carbon
1751 0 0.0
1752 0 0.0
1753 0 0.0
1754 0 0.0
1755 0 0.0

Pass in our timeseries data

In place of the constant value of emissions, we want to substitute our dataset. We can do this in a very straightforward way by passing the Pandas Series corresponding to the dataset in a dictionary to the params argument of the run function.

res = model.run(initial_condition=(emissions.index[0],
                                   {'Excess Atmospheric Carbon': 0}),
                return_timestamps=emissions.index.values,
                return_columns=['Emissions', 'Excess Atmospheric Carbon'],
                params={'Emissions': emissions['Total Emissions']})
res.plot();
../../_images/exogenous_timeseries_15_0.png