{
"cells": [
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"# Managing time series and Pastas models with a database\n",
"\n",
"This notebook shows how [Pastas](https://pastas.readthedocs.io/en/latest/) time series and models can be managed and stored on disk.\n",
"\n",
"## Content\n",
"1. [The Connector object](#1)\n",
" 1. [PasConnector](#1.1)\n",
" 2. [Database structure](#1.1)\n",
"2. [Initializing a PastaStore](#2)\n",
"3. [Managing time series](#3)\n",
" 1. [Adding oseries and stresses](#3.1)\n",
" 2. [Accessing time series and metadata](#3.2)\n",
" 3. [Deleting oseries and stresses](#3.3)\n",
" 4. [Overview of oseries and stresses](#3.4)\n",
"4. [Managing Pastas models](#4)\n",
" 1. [Creating a model](#4.1)\n",
" 2. [Storing a model](#4.2)\n",
" 3. [Loading a model](#4.3)\n",
" 4. [Overview of models](#4.4)\n",
" 5. [Deleting models](#4.5)\n",
"5. [Bulk operations](#5)\n",
"6. [Deleting databases](#6)\n",
"\n",
"
"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"## [1. The Connector object](#top)\n",
"This sections shows how to initialize a connection to a new database\n",
"(connecting to an existing database works the same way).\n",
"\n",
"Import `pastastore` and some other modules:"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Pastastore version : 1.12.0\n",
"\n",
"Python version : 3.13.11\n",
"Pandas version : 2.3.3\n",
"Matplotlib version : 3.10.8\n",
"Pastas version : 1.12.0\n",
"PyYAML version : 6.0.3\n",
"\n"
]
}
],
"source": [
"from pathlib import Path\n",
"\n",
"import pandas as pd\n",
"import pastas as ps\n",
"\n",
"import pastastore as pst\n",
"\n",
"pst.show_versions()"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"### [1.1 PasConnector](#top)\n",
"\n",
"The PasConnector requires the path to a directory and a name for the connector. Data is stored in JSON files in the given directory."
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"path = \"./pas\"\n",
"name = \"my_first_connector\""
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Initialize the `PasConnector` object:"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\u001b[32mPasConnector: library 'oseries' created in '/home/david/github/pastastore/examples/notebooks/pas/my_first_connector/oseries'\u001b[0m\n",
"\u001b[32mPasConnector: library 'stresses' created in '/home/david/github/pastastore/examples/notebooks/pas/my_first_connector/stresses'\u001b[0m\n",
"\u001b[32mPasConnector: library 'models' created in '/home/david/github/pastastore/examples/notebooks/pas/my_first_connector/models'\u001b[0m\n",
"\u001b[32mPasConnector: library 'oseries_models' created in '/home/david/github/pastastore/examples/notebooks/pas/my_first_connector/oseries_models'\u001b[0m\n",
"\u001b[32mPasConnector: library 'stresses_models' created in '/home/david/github/pastastore/examples/notebooks/pas/my_first_connector/stresses_models'\u001b[0m\n"
]
}
],
"source": [
"conn = pst.PasConnector(name, path)"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"Let's take a look at `conn`. This shows us how many oseries, stresses and models are contained in the store:"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
" 'my_first_connector': 0 oseries, 0 stresses, 0 models"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"conn"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"### [1.2 Database structure](#top)\n",
"\n",
"The database/store contains 4 libraries or collections. Each of these contains specific data related to the project. The four libraries are:\n",
"- oseries\n",
"- stresses\n",
"- models\n",
"- oseries_models\n",
"\n",
"These libraries are usually not meant to be accessed directly, but they can be accessed through the internal method `conn._get_library()`:"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"PosixPath('/home/david/github/pastastore/examples/notebooks/pas/my_first_connector/stresses')"
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# using the PasConnector\n",
"conn._get_library(\"stresses\")"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"The library handles are not generally used directly but internally they manage the reading, writing and deleting of data from the database/store. In the case of the `PasConnector`, the library is just a path to a directory."
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"
\n",
"\n",
"## [2. Initializing a PastaStore object](#top)\n",
"\n",
"The `PastaStore` object is used process and use the data in the database. The\n",
"connector objects only manage the reading/writing/deleting of data. The\n",
"`PastaStore` contains all kinds of methods to actually _do_ other stuff with\n",
"that data.\n",
"\n",
"In order to access the data the `PastaStore` object must be initialized with a\n",
"Connector object."
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [],
"source": [
"pstore = pst.PastaStore(conn, name=\"my_first_project\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Let's take a look at the object:"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
" my_first_project: \n",
" - 'my_first_connector': 0 oseries, 0 stresses, 0 models"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"pstore"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The connector object is accessible through `store.conn`, so all of the methods defined in the connector objects can be accessed through e.g. `store.conn.`. The most common methods are also registered under the `store` object for easier access. The following statements are equivalent."
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
" 'my_first_connector': 0 oseries, 0 stresses, 0 models>"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"pstore.conn.get_oseries"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
" 'my_first_connector': 0 oseries, 0 stresses, 0 models>"
]
},
"execution_count": 9,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"pstore.get_oseries"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"
\n",
"\n",
"## [3. Managing time series](#top)\n",
"\n",
"This section explains how time series can be added, retrieved or deleted from the database. We'll be using the `PastaStore` instance we created before."
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"### [3.1 Adding oseries and stresses](#top)\n",
"\n",
"Let's read some data to put into the database as an oseries. The data we are using is in the `tests/data` directory."
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" head | \n",
"
\n",
" \n",
" | date | \n",
" | \n",
"
\n",
" \n",
" \n",
" \n",
" | 1985-11-14 | \n",
" 27.61 | \n",
"
\n",
" \n",
" | 1985-11-28 | \n",
" 27.73 | \n",
"
\n",
" \n",
" | 1985-12-14 | \n",
" 27.91 | \n",
"
\n",
" \n",
" | 1985-12-28 | \n",
" 28.13 | \n",
"
\n",
" \n",
" | 1986-01-13 | \n",
" 28.32 | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" head\n",
"date \n",
"1985-11-14 27.61\n",
"1985-11-28 27.73\n",
"1985-12-14 27.91\n",
"1985-12-28 28.13\n",
"1986-01-13 28.32"
]
},
"execution_count": 10,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"datadir = Path(\"../../tests/data/\") # relative path to data directory\n",
"oseries1 = pd.read_csv(datadir / \"head_nb1.csv\", index_col=0, parse_dates=True)\n",
"oseries1.head()"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"Add the time series to the oseries library using `store.add_oseries`. Metadata can be optionally be provided as a dictionary. In this example a dictionary x and y coordinates is passed as metadata which is convenient later for automatically creating Pastas models. "
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [],
"source": [
"pstore.add_oseries(oseries1, \"oseries1\", metadata={\"x\": 100300, \"y\": 400400})"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The series was added to the oseries library. Let's confirm by looking at the `store` object:"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
" my_first_project: \n",
" - 'my_first_connector': 1 oseries, 0 stresses, 0 models"
]
},
"execution_count": 12,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"pstore"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"Stresses can be added similarly using `pstore.add_stress`. The only thing to keep in mind when adding stresses is to pass the `kind` argument so that different types of stresses (i.e. precipitation or evaporation) can be distinguished. The code below reads the precipitation and evaporation csv-files and adds them to our project:"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {},
"outputs": [],
"source": [
"# prec\n",
"s = pd.read_csv(datadir / \"rain_nb1.csv\", index_col=0, parse_dates=True)\n",
"pstore.add_stress(s, \"prec1\", kind=\"prec\", metadata={\"x\": 100300, \"y\": 400400})\n",
"\n",
"# evap\n",
"s = pd.read_csv(datadir / \"evap_nb1.csv\", index_col=0, parse_dates=True)\n",
"pstore.add_stress(s, \"evap1\", kind=\"evap\", metadata={\"x\": 100300, \"y\": 400400})"
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
" my_first_project: \n",
" - 'my_first_connector': 1 oseries, 2 stresses, 0 models"
]
},
"execution_count": 14,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"pstore"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"### [3.2 Accessing time series and metadata](#top)\n",
"\n",
"Time series can be accessed through `pstore.get_oseries()` or `pstore.get_stresses()`. These methods accept just a name or a list of names. In the latter case a dictionary of dataframes is returned."
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"1985-11-14 27.61\n",
"1985-11-28 27.73\n",
"1985-12-14 27.91\n",
"1985-12-28 28.13\n",
"1986-01-13 28.32\n",
"Name: oseries1, dtype: float64"
]
},
"execution_count": 15,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"ts = pstore.get_oseries(\"oseries1\")\n",
"ts.head()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Using a list of names:"
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{'prec1': 1980-01-01 0.0033\n",
" 1980-01-02 0.0025\n",
" 1980-01-03 0.0003\n",
" 1980-01-04 0.0075\n",
" 1980-01-05 0.0080\n",
" ... \n",
" 2016-10-27 0.0000\n",
" 2016-10-28 0.0000\n",
" 2016-10-29 0.0003\n",
" 2016-10-30 0.0000\n",
" 2016-10-31 0.0000\n",
" Name: prec1, Length: 13454, dtype: float64,\n",
" 'evap1': 1980-01-01 0.0002\n",
" 1980-01-02 0.0003\n",
" 1980-01-03 0.0002\n",
" 1980-01-04 0.0001\n",
" 1980-01-05 0.0001\n",
" ... \n",
" 2016-11-18 0.0004\n",
" 2016-11-19 0.0003\n",
" 2016-11-20 0.0005\n",
" 2016-11-21 0.0003\n",
" 2016-11-22 0.0005\n",
" Name: evap1, Length: 13476, dtype: float64}"
]
},
"execution_count": 16,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"stresses = pstore.get_stresses([\"prec1\", \"evap1\"])\n",
"stresses"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"The metadata of a time series can be accessed through `pstore.get_metadata()`. Provide the library and the name to load the metadata for an oseries..."
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" x | \n",
" y | \n",
"
\n",
" \n",
" | name | \n",
" | \n",
" | \n",
"
\n",
" \n",
" \n",
" \n",
" | oseries1 | \n",
" 100300 | \n",
" 400400 | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" x y\n",
"name \n",
"oseries1 100300 400400"
]
},
"execution_count": 17,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"meta = pstore.get_metadata(\"oseries\", \"oseries1\")\n",
"meta"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"or for multiple stresses:"
]
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" x | \n",
" y | \n",
" kind | \n",
"
\n",
" \n",
" | name | \n",
" | \n",
" | \n",
" | \n",
"
\n",
" \n",
" \n",
" \n",
" | prec1 | \n",
" 100300.0 | \n",
" 400400.0 | \n",
" prec | \n",
"
\n",
" \n",
" | evap1 | \n",
" 100300.0 | \n",
" 400400.0 | \n",
" evap | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" x y kind\n",
"name \n",
"prec1 100300.0 400400.0 prec\n",
"evap1 100300.0 400400.0 evap"
]
},
"execution_count": 18,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"meta = pstore.get_metadata(\"stresses\", [\"prec1\", \"evap1\"])\n",
"meta"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"### [4.3 Deleting oseries and stresses](#top)\n",
"\n",
"Deleting time series can be done using `pstore.del_oseries` or `pstore.del_stress`. These functions accept a single name or list of names of time series to delete."
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"### [4.4 Overview of oseries and stresses](#top)\n",
"\n",
"An overview of the oseries and stresses is available through `pstore.oseries` and `pstore.stresses`. These are dataframes containing the metadata of all the time series. These dataframes are cached for performance. The cache is cleared when a time series is added or modified in the database. "
]
},
{
"cell_type": "code",
"execution_count": 19,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" x | \n",
" y | \n",
"
\n",
" \n",
" | name | \n",
" | \n",
" | \n",
"
\n",
" \n",
" \n",
" \n",
" | oseries1 | \n",
" 100300 | \n",
" 400400 | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" x y\n",
"name \n",
"oseries1 100300 400400"
]
},
"execution_count": 19,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"pstore.oseries"
]
},
{
"cell_type": "code",
"execution_count": 20,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" x | \n",
" y | \n",
" kind | \n",
"
\n",
" \n",
" | name | \n",
" | \n",
" | \n",
" | \n",
"
\n",
" \n",
" \n",
" \n",
" | prec1 | \n",
" 100300.0 | \n",
" 400400.0 | \n",
" prec | \n",
"
\n",
" \n",
" | evap1 | \n",
" 100300.0 | \n",
" 400400.0 | \n",
" evap | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" x y kind\n",
"name \n",
"prec1 100300.0 400400.0 prec\n",
"evap1 100300.0 400400.0 evap"
]
},
"execution_count": 20,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"pstore.stresses"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"
\n",
"\n",
"## [4. Managing Pastas models](#top)\n",
"\n",
"This section shows how Pastas models can be created, stored, and loaded from the database."
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"### [4.1 Creating a model](#top)\n",
"\n",
"Creating a new model is straightforward using `pstore.create_model()`. The\n",
"`add_recharge` keyword argument allows the user to choose (default is True)\n",
"whether recharge is automatically added to the model using the nearest\n",
"precipitation and evaporation stations in the stresses library. Note that the\n",
"x,y-coordinates of the stresses and oseries must be set in the metadata for\n",
"each time series in order for this to work."
]
},
{
"cell_type": "code",
"execution_count": 21,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Model(oseries=oseries1, name=oseries1, constant=True, noisemodel=False)"
]
},
"execution_count": 21,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"ml = pstore.create_model(\"oseries1\", add_recharge=True)\n",
"ml"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"### [4.2 Storing a model](#top)\n",
"\n",
"The model that was created in the previous step is not automatically stored in\n",
"the models library. Use `store.add_model()` to store the model. If the model\n",
"already exists, an Exception is raised warning the user the model is already in\n",
"the library. Use `overwrite=True` to add the model anyway.\n",
"\n",
"\n",
"\n",
"Note: The model is stored without the time series. It is assumed the\n",
"time series are already stored in the oseries or stresses libraries, making it\n",
"redundant to store these again. When adding the model, the stored copy of the \n",
"time series is compared to the version in the model to ensure these are the same.\n",
"If not, an error is raised and the model cannot be stored. These validation\n",
"options can be overridden, but that is only recommended for advanced users.
"
]
},
{
"cell_type": "code",
"execution_count": 22,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Fit report oseries1 Fit Statistics\n",
"==================================================\n",
"nfev 20 EVP 93.19\n",
"nobs 644 R2 0.93\n",
"noise False RMSE 0.11\n",
"tmin 1985-11-14 00:00:00 AICc -2809.63\n",
"tmax 2015-06-28 00:00:00 BIC -2791.83\n",
"freq D Obj 4.05\n",
"freq_obs None ___ \n",
"warmup 3650 days 00:00:00 Interp. No\n",
"solver LeastSquares weights Yes\n",
"\n",
"Parameters (4 optimized)\n",
"==================================================\n",
" optimal initial vary\n",
"recharge_A 631.256911 215.674528 True\n",
"recharge_a 165.320923 10.000000 True\n",
"recharge_f -1.466316 -1.000000 True\n",
"constant_d 28.081353 27.900078 True\n"
]
}
],
"source": [
"ml.solve()"
]
},
{
"cell_type": "code",
"execution_count": 23,
"metadata": {},
"outputs": [],
"source": [
"pstore.add_model(ml)"
]
},
{
"cell_type": "code",
"execution_count": 24,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
" 1 model(s): \n",
"['oseries1']"
]
},
"execution_count": 24,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"pstore.models"
]
},
{
"cell_type": "code",
"execution_count": 25,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"['oseries1']"
]
},
"execution_count": 25,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"pstore.model_names"
]
},
{
"cell_type": "code",
"execution_count": 26,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{'oseries1': ['oseries1']}"
]
},
"execution_count": 26,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"pstore.oseries_models"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"### [4.3 Loading a model](#top)\n",
"\n",
"Loading a stored model is simple using `pstore.get_models(\"\")` or using\n",
"the key-value interface for models: `pstore.models[\"\"]`.\n",
"\n",
"The model is stored as a dictionary (see `ml.to_dict()`) without the time\n",
"series data. The time series in the model are picked up based on the names of\n",
"those series from the respective libraries (oseries or stresses)."
]
},
{
"cell_type": "code",
"execution_count": 27,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Model(oseries=oseries1, name=oseries1, constant=True, noisemodel=False)"
]
},
"execution_count": 27,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"ml2 = pstore.get_models(\"oseries1\")\n",
"ml2"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"### [4.4 Overview of models](#top)\n",
"\n",
"An overview of the models is available through `pstore.models` which lists the names of all the models:"
]
},
{
"cell_type": "code",
"execution_count": 28,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
" 1 model(s): \n",
"['oseries1']"
]
},
"execution_count": 28,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"pstore.models"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"### [4.5 Deleting models](#top)\n",
"\n",
"Deleting the model is done with `pstore.del_models`:"
]
},
{
"cell_type": "code",
"execution_count": 29,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\u001b[32mDeleted 1 model(s) from database.\u001b[0m\n"
]
}
],
"source": [
"pstore.del_models(\"oseries1\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Checking to see if it was indeed deleted:"
]
},
{
"cell_type": "code",
"execution_count": 30,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
" my_first_project: \n",
" - 'my_first_connector': 1 oseries, 2 stresses, 0 models"
]
},
"execution_count": 30,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"pstore"
]
},
{
"cell_type": "code",
"execution_count": 31,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
" 0 model(s): \n",
"[]"
]
},
"execution_count": 31,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"pstore.models"
]
},
{
"cell_type": "code",
"execution_count": 32,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[]"
]
},
"execution_count": 32,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"pstore.model_names"
]
},
{
"cell_type": "code",
"execution_count": 33,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{}"
]
},
"execution_count": 33,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"pstore.oseries_models"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"
\n",
"\n",
"## [5. Bulk operations](#top)\n",
"\n",
"The following bulk operations are available:\n",
"- `create_models`: create models for all or a selection of oseries in database\n",
"- `solve_models`: solve all or selection of models in database\n",
"- `model_results`: get results for all or selection of models in database. Requires the `art_tools` module!\n",
"\n",
"Let's add some more data to the pastastore to show how the bulk operations work."
]
},
{
"cell_type": "code",
"execution_count": 34,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"The Time Series 'oseries2' has nan-values. Pastas will use the fill_nan settings to fill up the nan-values.\n",
"The Time Series 'oseries2' has nan-values. Pastas will use the fill_nan settings to fill up the nan-values.\n"
]
}
],
"source": [
"# oseries 2\n",
"o = pd.read_csv(datadir / \"obs.csv\", index_col=0, parse_dates=True)\n",
"pstore.add_oseries(o, \"oseries2\", metadata={\"x\": 100000, \"y\": 400000})\n",
"\n",
"# prec 2\n",
"s = pd.read_csv(datadir / \"rain.csv\", index_col=0, parse_dates=True)\n",
"pstore.add_stress(s, \"prec2\", kind=\"prec\", metadata={\"x\": 100000, \"y\": 400000})\n",
"\n",
"# evap 2\n",
"s = pd.read_csv(datadir / \"evap.csv\", index_col=0, parse_dates=True)\n",
"pstore.add_stress(s, \"evap2\", kind=\"evap\", metadata={\"x\": 100000, \"y\": 400000})"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Let's take a look at our `PastaStore`:"
]
},
{
"cell_type": "code",
"execution_count": 35,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
" my_first_project: \n",
" - 'my_first_connector': 2 oseries, 4 stresses, 0 models"
]
},
"execution_count": 35,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"pstore"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"\n",
"Let's try using the bulk methods on our database. The `pstore.create_models_bulk()`\n",
"method allows the user to get models for all or a selection of oseries in the\n",
"database. Options include:\n",
"- selecting specific oseries to create models for\n",
"- automatically adding recharge based on nearest precipitation and evaporation stresses\n",
"- solving the models\n",
"- storing the models in the models library\n",
"\n",
"**Note**: when using the progressbar, for a prettier result the pastas log\n",
"level can be set to ERROR using: `ps.set_log_level(\"ERROR\")` or\n",
"`ps.logger.setLevel(\"ERROR\")`."
]
},
{
"cell_type": "code",
"execution_count": 36,
"metadata": {},
"outputs": [],
"source": [
"# to suppress most of the log messages\n",
"ps.logger.setLevel(\"ERROR\")"
]
},
{
"cell_type": "code",
"execution_count": 37,
"metadata": {},
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "ef8128d45d2b4836bd1f1f5f702f5c2e",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"Bulk creation models: 0%| | 0/2 [00:00, ?it/s]"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"errors = pstore.create_models_bulk()"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"To solve all or a selection of models use `pstore.solve_models()`. Options for this method include:\n",
"- selecting models to solve\n",
"- store results in models library\n",
"- raise error (or not) when solving fails\n",
"- print solve reports"
]
},
{
"cell_type": "code",
"execution_count": 38,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
" my_first_project: \n",
" - 'my_first_connector': 2 oseries, 4 stresses, 2 models"
]
},
"execution_count": 38,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"pstore"
]
},
{
"cell_type": "code",
"execution_count": 39,
"metadata": {},
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "18bc6340b27e4b1ab9d5fb138ffe8b0c",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"Solving models: 0%| | 0/2 [00:00, ?it/s]"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"pstore.solve_models(report=False)"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"Obtaining the model parameters and statistics is easy with\n",
"`pstore.get_parameters()` and `pstore.get_statistics()`. Results can be\n",
"obtained for all or a selection of models. The results are returned as\n",
"DataFrames."
]
},
{
"cell_type": "code",
"execution_count": 40,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" recharge_A | \n",
" recharge_a | \n",
" recharge_f | \n",
" constant_d | \n",
"
\n",
" \n",
" \n",
" \n",
" | oseries2 | \n",
" 429.424496 | \n",
" 147.226264 | \n",
" -1.913980 | \n",
" 28.383626 | \n",
"
\n",
" \n",
" | oseries1 | \n",
" 631.256911 | \n",
" 165.320923 | \n",
" -1.466316 | \n",
" 28.081353 | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" recharge_A recharge_a recharge_f constant_d\n",
"oseries2 429.424496 147.226264 -1.913980 28.383626\n",
"oseries1 631.256911 165.320923 -1.466316 28.081353"
]
},
"execution_count": 40,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"params = pstore.get_parameters()\n",
"params"
]
},
{
"cell_type": "code",
"execution_count": 41,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" evp | \n",
" rmse | \n",
"
\n",
" \n",
" \n",
" \n",
" | oseries2 | \n",
" 90.448729 | \n",
" 0.114373 | \n",
"
\n",
" \n",
" | oseries1 | \n",
" 93.188297 | \n",
" 0.112180 | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" evp rmse\n",
"oseries2 90.448729 0.114373\n",
"oseries1 93.188297 0.112180"
]
},
"execution_count": 41,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"stats = pstore.get_statistics([\"evp\", \"rmse\"])\n",
"stats"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"tags": []
},
"source": [
"## [6. Deleting databases](#top)\n",
"\n",
"The `pastastore.util` submodule contains functions for deleting database contents:"
]
},
{
"cell_type": "code",
"execution_count": 42,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\u001b[32mDeleting PasConnector database: 'my_first_connector' ... \u001b[0m\n",
"\u001b[32mDone!\u001b[0m\n"
]
}
],
"source": [
"pst.util.delete_pastastore(pstore)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "pastastore (3.13.11)",
"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.13.11"
},
"toc-showtags": false
},
"nbformat": 4,
"nbformat_minor": 4
}