How to build a model using the Python API?

The objective of this notebook is to build a model from scratch in Python. The model corresponds to the Selle and Morvillers test case.

Here we build the model entirely through the Python API without relying on a toml file. Then, we load the same model by using the toml configuration file.

We test if the models are the same and if they deliver the same metrics after an optimization procedure.

import datetime

import pandas as pd

import rameau as rm

Build the model

Inputs

# First create inputs from files
inputs = rm.inputs.InputCollection.from_files(
    rainfall = 'rainfall.csv',
    pet='pet.csv',
    riverobs='riverflow.csv',
    groundwaterobs='groundwaterlevel.csv'
)

# Rainfall is of type Input
rainfall = inputs.rainfall
type(rainfall)
rameau.core.inputs.input.Input
# Print the data
print(rainfall.data)
[[ 0.  ]
 [ 0.  ]
 [ 0.  ]
 ...
 [13.87]
 [ 0.46]
 [ 0.15]]
# Print the associated dates
print(rainfall.dates)
DatetimeIndex(['1985-01-01', '1985-01-02', '1985-01-03', '1985-01-04',
               '1985-01-05', '1985-01-06', '1985-01-07', '1985-01-08',
               '1985-01-09', '1985-01-10',
               ...
               '2003-07-22', '2003-07-23', '2003-07-24', '2003-07-25',
               '2003-07-26', '2003-07-27', '2003-07-28', '2003-07-29',
               '2003-07-30', '2003-07-31'],
              dtype='datetime64[us]', length=6786, freq=None)
# Second way
def read_mycsv(path):
    return pd.read_csv(
        path,
        parse_dates=True,
        date_format='%Y/%m/%d',
        dayfirst=True,
        index_col=0,
        sep=r'\s+'
    )
rainfall = read_mycsv("rainfall.csv")
pet = read_mycsv("pet.csv")
riverobs = read_mycsv("riverflow.csv")
groundwaterobs = read_mycsv("groundwaterlevel.csv")

# convert rainfall to 
inputs2 = rm.inputs.InputCollection(
    rainfall=rainfall,
    pet=pet,
    riverobs=riverobs,
    groundwaterobs=groundwaterobs
)

assert((inputs.rainfall.data == inputs2.rainfall.data).all())

Watershed

# Create parameters for a watershed from scratch
# We can use the already provided object in rameau.core 
# or directly use dictionary
river = rm.RiverParameters(
    area=rm.Parameter(value=524, opti=False),
    weight=5
)
progressive = rm.ProgressiveReservoir(
    capacity=rm.Parameter(value=180, opti=True, lower=0, upper=650)
)
transfer = rm.TransferReservoir(
    runsee=dict(value=600, opti=True, lower=5, upper=9999),
    halflife=rm.Parameter(value=5, opti=True, lower=0.15, upper=25)
)
gwres1 = rm.groundwater.GroundwaterReservoir(
    halflife_baseflow=dict(value=20, opti=True, lower=6, upper=70),
)
gw = rm.groundwater.GroundwaterParameters(
    reservoirs=[gwres1], # Only one grounwater reservoir
    storage=rm.groundwater.StorageParameters(
        coefficient=dict(value=1, opti=True, lower=0.02, upper=50),
        regression=True
    ),
    base_level=rm.Parameter(value=125, opti=True),
    observed_reservoir=1, # Already set by default to 1,
    weight=2
)

# Assemble the pieces to create the Watershed
w = rm.Watershed(
    name="Selle à Plachy",
    river=river,
    progressive_reservoir=progressive,
    transfer_reservoir=transfer,
    groundwater=gw
)

# Then constructs the Tree (easy in this case : only 1 watershed)
tree = rm.Tree(
    watersheds=[w]
)

Settings

# Simulation settings
sim_sets = rm.settings.SimulationSettings(
    spinup_settings=rm.settings.SpinupSettings(
        cycles=3,
        ending_date=datetime.datetime(1988, 12, 31)
    ),
    starting_date=datetime.datetime(1989, 1, 1)
)

# Optimization settings
opt_sets = rm.settings.OptimizationSettings(
    maxit=200,
    starting_date=datetime.datetime(1989, 1, 1),
    river_objective_function='nse'
)

Compare the models

# Create the model from scratch
model = rm.Model(
    tree=tree,
    inputs=inputs,
    simulation_settings=sim_sets,
    optimization_settings=opt_sets
)
# Just load the model from toml for comparing results
model2 = rm.Model.from_toml("model.toml")
# Run the optimization for the two models and compare the results !
sim1 = model.run_optimization()
sim2 = model2.run_optimization()

assert((sim1.get_opti_metrics().values == sim2.get_opti_metrics().values).all())