{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# How to build a model using the Python API?\n", "\n", "The objective of this notebook is to build a model from scratch in Python. The model corresponds to the\n", "{ref}`Selle and Morvillers <_selle_morvillers>` test case. \n", "\n", "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.\n", "\n", "We test if the models are the same and if they deliver the same metrics after an optimization procedure. " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import datetime\n", "\n", "import pandas as pd\n", "\n", "import rameau as rm" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Build the model" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Inputs" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# First create inputs from files\n", "inputs = rm.inputs.InputCollection.from_files(\n", " rainfall = 'rainfall.csv',\n", " pet='pet.csv',\n", " riverobs='riverflow.csv',\n", " groundwaterobs='groundwaterlevel.csv'\n", ")\n", "\n", "# Rainfall is of type Input\n", "rainfall = inputs.rainfall\n", "type(rainfall)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Print the data\n", "print(rainfall.data)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Print the associated dates\n", "print(rainfall.dates)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Second way\n", "def read_mycsv(path):\n", " return pd.read_csv(\n", " path,\n", " parse_dates=True,\n", " date_format='%Y/%m/%d',\n", " dayfirst=True,\n", " index_col=0,\n", " sep=r'\\s+'\n", " )\n", "rainfall = read_mycsv(\"rainfall.csv\")\n", "pet = read_mycsv(\"pet.csv\")\n", "riverobs = read_mycsv(\"riverflow.csv\")\n", "groundwaterobs = read_mycsv(\"groundwaterlevel.csv\")\n", "\n", "# convert rainfall to \n", "inputs2 = rm.inputs.InputCollection(\n", " rainfall=rainfall,\n", " pet=pet,\n", " riverobs=riverobs,\n", " groundwaterobs=groundwaterobs\n", ")\n", "\n", "assert((inputs.rainfall.data == inputs2.rainfall.data).all())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Watershed" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Create parameters for a watershed from scratch\n", "# We can use the already provided object in rameau.core \n", "# or directly use dictionary\n", "river = rm.RiverParameters(\n", " area=rm.Parameter(value=524, opti=False),\n", " weight=5\n", ")\n", "progressive = rm.ProgressiveReservoir(\n", " capacity=rm.Parameter(value=180, opti=True, lower=0, upper=650)\n", ")\n", "transfer = rm.TransferReservoir(\n", " runsee=dict(value=600, opti=True, lower=5, upper=9999),\n", " halflife=rm.Parameter(value=5, opti=True, lower=0.15, upper=25)\n", ")\n", "gwres1 = rm.groundwater.GroundwaterReservoir(\n", " halflife_baseflow=dict(value=20, opti=True, lower=6, upper=70),\n", ")\n", "gw = rm.groundwater.GroundwaterParameters(\n", " reservoirs=[gwres1], # Only one grounwater reservoir\n", " storage=rm.groundwater.StorageParameters(\n", " coefficient=dict(value=1, opti=True, lower=0.02, upper=50),\n", " regression=True\n", " ),\n", " base_level=rm.Parameter(value=125, opti=True),\n", " observed_reservoir=1, # Already set by default to 1,\n", " weight=2\n", ")\n", "\n", "# Assemble the pieces to create the Watershed\n", "w = rm.Watershed(\n", " name=\"Selle à Plachy\",\n", " river=river,\n", " progressive_reservoir=progressive,\n", " transfer_reservoir=transfer,\n", " groundwater=gw\n", ")\n", "\n", "# Then constructs the Tree (easy in this case : only 1 watershed)\n", "tree = rm.Tree(\n", " watersheds=[w]\n", ")\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Settings" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Simulation settings\n", "sim_sets = rm.settings.SimulationSettings(\n", " spinup_settings=rm.settings.SpinupSettings(\n", " cycles=3,\n", " ending_date=datetime.datetime(1988, 12, 31)\n", " ),\n", " starting_date=datetime.datetime(1989, 1, 1)\n", ")\n", "\n", "# Optimization settings\n", "opt_sets = rm.settings.OptimizationSettings(\n", " maxit=200,\n", " starting_date=datetime.datetime(1989, 1, 1),\n", " river_objective_function='nse'\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Compare the models" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Create the model from scratch\n", "model = rm.Model(\n", " tree=tree,\n", " inputs=inputs,\n", " simulation_settings=sim_sets,\n", " optimization_settings=opt_sets\n", ")" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Just load the model from toml for comparing results\n", "model2 = rm.Model.from_toml(\"model.toml\")" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Run the optimization for the two models and compare the results !\n", "sim1 = model.run_optimization()\n", "sim2 = model2.run_optimization()\n", "\n", "assert((sim1.get_opti_metrics().values == sim2.get_opti_metrics().values).all())" ] } ], "metadata": { "kernelspec": { "display_name": "dev", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.12.3" } }, "nbformat": 4, "nbformat_minor": 2 }