├── VERSION.txt
├── hydrobox
├── utils
│ ├── __init__.py
│ ├── typing.py
│ └── decorators.py
├── preprocessing
│ ├── __init__.py
│ ├── union.py
│ └── scale.py
├── discharge
│ ├── __init__.py
│ ├── indices.py
│ └── catchment.py
├── stats
│ ├── __init__.py
│ ├── rolling.py
│ └── regression.py
├── __init__.py
├── data
│ ├── __init__.py
│ ├── sample_sr.csv
│ ├── pan_sample.csv
│ └── sample_lr.csv
├── plotting
│ ├── __init__.py
│ ├── variogram.py
│ ├── _backend.py
│ ├── kriging.py
│ ├── flow_duration_curve.py
│ └── regime.py
├── geostat
│ ├── typing.py
│ ├── __init__.py
│ ├── variogram.py
│ ├── gridsearch.py
│ └── kriging.py
└── tests
│ └── test_geostat.py
├── doc
├── gen_modules
│ ├── backreferences
│ │ ├── hydrobox.geostat.examples
│ │ ├── hydrobox.geostat.simple_kriging.examples
│ │ ├── hydrobox.geostat.ext_drift_kriging.examples
│ │ ├── hydrobox.geostat.universal_kriging.examples
│ │ ├── hydrobox.data.pancake.examples
│ │ ├── hydrobox.plotting_backend.examples
│ │ ├── hydrobox.geostat.variogram.examples
│ │ ├── hydrobox.geostat.gridsearch.examples
│ │ └── hydrobox.geostat.ordinary_kriging.examples
│ ├── hydrobox.geostat.variogram.rst
│ ├── hydrobox.geostat.gridsearch.rst
│ ├── hydrobox.geostat.simple_kriging.rst
│ ├── hydrobox.geostat.ordinary_kriging.rst
│ ├── hydrobox.geostat.ext_drift_kriging.rst
│ └── hydrobox.geostat.universal_kriging.rst
├── auto_examples
│ ├── geostat
│ │ ├── plot_gridsearch.py.md5
│ │ ├── plot_variogram.py.md5
│ │ ├── plot_ordinary_kriging.py.md5
│ │ ├── plot_gridsearch_codeobj.pickle
│ │ ├── plot_variogram_codeobj.pickle
│ │ ├── plot_ordinary_kriging_codeobj.pickle
│ │ ├── images
│ │ │ ├── sphx_glr_plot_variogram_001.png
│ │ │ ├── sphx_glr_plot_variogram_002.png
│ │ │ ├── sphx_glr_plot_gridsearch_001.png
│ │ │ ├── sphx_glr_plot_ordinary_kriging_001.png
│ │ │ ├── thumb
│ │ │ │ ├── sphx_glr_plot_variogram_thumb.png
│ │ │ │ ├── sphx_glr_plot_gridsearch_thumb.png
│ │ │ │ └── sphx_glr_plot_ordinary_kriging_thumb.png
│ │ │ ├── sphx_glr_plot_gridsearch_001.html
│ │ │ └── sphx_glr_plot_variogram_001.html
│ │ ├── sg_execution_times.rst
│ │ ├── plot_ordinary_kriging.py
│ │ ├── plot_variogram.py
│ │ ├── plot_gridsearch.py
│ │ ├── plot_ordinary_kriging.ipynb
│ │ ├── plot_ordinary_kriging.rst
│ │ ├── plot_variogram.ipynb
│ │ ├── plot_gridsearch.ipynb
│ │ ├── plot_gridsearch.rst
│ │ └── plot_variogram.rst
│ ├── auto_examples_python.zip
│ ├── auto_examples_jupyter.zip
│ └── index.rst
├── toolboxes
│ ├── geostat.rst
│ ├── index.rst
│ └── gen_modules
│ │ ├── hydrobox.geostat.variogram.rst
│ │ ├── hydrobox.geostat.gridsearch.rst
│ │ ├── hydrobox.geostat.simple_kriging.rst
│ │ ├── hydrobox.geostat.ordinary_kriging.rst
│ │ ├── hydrobox.geostat.ext_drift_kriging.rst
│ │ └── hydrobox.geostat.universal_kriging.rst
├── Makefile
├── make.bat
├── index.rst
└── conf.py
├── examples
├── README.rst
└── geostat
│ ├── README.rst
│ ├── plot_ordinary_kriging.py
│ ├── plot_variogram.py
│ └── plot_gridsearch.py
├── requirements.txt
├── MANIFEST.in
├── classifiers.txt
├── .coveragerc
├── setup.py
├── LICENSE
├── .github
└── workflows
│ └── main.yaml
├── .gitignore
└── README.md
/VERSION.txt:
--------------------------------------------------------------------------------
1 | 0.2.0
2 |
--------------------------------------------------------------------------------
/hydrobox/utils/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/hydrobox/preprocessing/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/doc/gen_modules/backreferences/hydrobox.geostat.examples:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/doc/gen_modules/backreferences/hydrobox.geostat.simple_kriging.examples:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/doc/gen_modules/backreferences/hydrobox.geostat.ext_drift_kriging.examples:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/doc/gen_modules/backreferences/hydrobox.geostat.universal_kriging.examples:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/doc/auto_examples/geostat/plot_gridsearch.py.md5:
--------------------------------------------------------------------------------
1 | 5afe77ecb8029bad8b45f1b6caeeed19
--------------------------------------------------------------------------------
/doc/auto_examples/geostat/plot_variogram.py.md5:
--------------------------------------------------------------------------------
1 | e865bb35235811251eb818a95e29a994
--------------------------------------------------------------------------------
/doc/auto_examples/geostat/plot_ordinary_kriging.py.md5:
--------------------------------------------------------------------------------
1 | 0edca8dd2db51a6491a99f77651997f7
--------------------------------------------------------------------------------
/hydrobox/discharge/__init__.py:
--------------------------------------------------------------------------------
1 | from .catchment import regime, flow_duration_curve
2 | from . import indices
--------------------------------------------------------------------------------
/hydrobox/stats/__init__.py:
--------------------------------------------------------------------------------
1 | from .rolling import moving_window
2 | from .regression import linear_regression
--------------------------------------------------------------------------------
/doc/toolboxes/geostat.rst:
--------------------------------------------------------------------------------
1 | =============
2 | Geostatistics
3 | =============
4 |
5 | .. automodule:: hydrobox.geostat
--------------------------------------------------------------------------------
/doc/auto_examples/auto_examples_python.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VForWaTer/hydrobox/HEAD/doc/auto_examples/auto_examples_python.zip
--------------------------------------------------------------------------------
/examples/README.rst:
--------------------------------------------------------------------------------
1 | Hydrobox Examples
2 | =================
3 |
4 | This gallery collects example scripts for most functions in hydrobox.
--------------------------------------------------------------------------------
/doc/auto_examples/auto_examples_jupyter.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VForWaTer/hydrobox/HEAD/doc/auto_examples/auto_examples_jupyter.zip
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | numpy
2 | scipy
3 | pandas
4 | matplotlib
5 | plotly
6 | colorcet
7 | scikit-learn
8 | scikit-gstat>=0.5.4
9 | gstools>=1.3.0
--------------------------------------------------------------------------------
/examples/geostat/README.rst:
--------------------------------------------------------------------------------
1 | Geostatistics Toolbox
2 | ---------------------
3 |
4 | The following examples demonstrate the usage of the geostatistics toolbox.
--------------------------------------------------------------------------------
/doc/auto_examples/geostat/plot_gridsearch_codeobj.pickle:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VForWaTer/hydrobox/HEAD/doc/auto_examples/geostat/plot_gridsearch_codeobj.pickle
--------------------------------------------------------------------------------
/doc/auto_examples/geostat/plot_variogram_codeobj.pickle:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VForWaTer/hydrobox/HEAD/doc/auto_examples/geostat/plot_variogram_codeobj.pickle
--------------------------------------------------------------------------------
/doc/auto_examples/geostat/plot_ordinary_kriging_codeobj.pickle:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VForWaTer/hydrobox/HEAD/doc/auto_examples/geostat/plot_ordinary_kriging_codeobj.pickle
--------------------------------------------------------------------------------
/doc/auto_examples/geostat/images/sphx_glr_plot_variogram_001.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VForWaTer/hydrobox/HEAD/doc/auto_examples/geostat/images/sphx_glr_plot_variogram_001.png
--------------------------------------------------------------------------------
/doc/auto_examples/geostat/images/sphx_glr_plot_variogram_002.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VForWaTer/hydrobox/HEAD/doc/auto_examples/geostat/images/sphx_glr_plot_variogram_002.png
--------------------------------------------------------------------------------
/doc/toolboxes/index.rst:
--------------------------------------------------------------------------------
1 | ==================
2 | Toolboxes Overview
3 | ==================
4 |
5 | .. toctree::
6 | :maxdepth: 1
7 | :caption: All toolboxes
8 |
9 | geostat
--------------------------------------------------------------------------------
/doc/auto_examples/geostat/images/sphx_glr_plot_gridsearch_001.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VForWaTer/hydrobox/HEAD/doc/auto_examples/geostat/images/sphx_glr_plot_gridsearch_001.png
--------------------------------------------------------------------------------
/doc/gen_modules/hydrobox.geostat.variogram.rst:
--------------------------------------------------------------------------------
1 | hydrobox.geostat.variogram
2 | ==========================
3 |
4 | .. currentmodule:: hydrobox.geostat
5 |
6 | .. autofunction:: variogram
--------------------------------------------------------------------------------
/MANIFEST.in:
--------------------------------------------------------------------------------
1 | include README.rst
2 | include VERSION.txt
3 | include requirements.txt
4 | include LICENSE
5 | include classifiers.txt
6 | graft hydrobox/data/*.csv
7 | graft hydrobox/data/*.txt
--------------------------------------------------------------------------------
/doc/gen_modules/hydrobox.geostat.gridsearch.rst:
--------------------------------------------------------------------------------
1 | hydrobox.geostat.gridsearch
2 | ===========================
3 |
4 | .. currentmodule:: hydrobox.geostat
5 |
6 | .. autofunction:: gridsearch
--------------------------------------------------------------------------------
/doc/auto_examples/geostat/images/sphx_glr_plot_ordinary_kriging_001.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VForWaTer/hydrobox/HEAD/doc/auto_examples/geostat/images/sphx_glr_plot_ordinary_kriging_001.png
--------------------------------------------------------------------------------
/doc/auto_examples/geostat/images/thumb/sphx_glr_plot_variogram_thumb.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VForWaTer/hydrobox/HEAD/doc/auto_examples/geostat/images/thumb/sphx_glr_plot_variogram_thumb.png
--------------------------------------------------------------------------------
/doc/toolboxes/gen_modules/hydrobox.geostat.variogram.rst:
--------------------------------------------------------------------------------
1 | hydrobox.geostat.variogram
2 | ==========================
3 |
4 | .. currentmodule:: hydrobox.geostat
5 |
6 | .. autofunction:: variogram
--------------------------------------------------------------------------------
/doc/auto_examples/geostat/images/thumb/sphx_glr_plot_gridsearch_thumb.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VForWaTer/hydrobox/HEAD/doc/auto_examples/geostat/images/thumb/sphx_glr_plot_gridsearch_thumb.png
--------------------------------------------------------------------------------
/doc/toolboxes/gen_modules/hydrobox.geostat.gridsearch.rst:
--------------------------------------------------------------------------------
1 | hydrobox.geostat.gridsearch
2 | ===========================
3 |
4 | .. currentmodule:: hydrobox.geostat
5 |
6 | .. autofunction:: gridsearch
--------------------------------------------------------------------------------
/doc/gen_modules/hydrobox.geostat.simple_kriging.rst:
--------------------------------------------------------------------------------
1 | hydrobox.geostat.simple\_kriging
2 | ================================
3 |
4 | .. currentmodule:: hydrobox.geostat
5 |
6 | .. autofunction:: simple_kriging
--------------------------------------------------------------------------------
/doc/auto_examples/geostat/images/thumb/sphx_glr_plot_ordinary_kriging_thumb.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/VForWaTer/hydrobox/HEAD/doc/auto_examples/geostat/images/thumb/sphx_glr_plot_ordinary_kriging_thumb.png
--------------------------------------------------------------------------------
/doc/gen_modules/hydrobox.geostat.ordinary_kriging.rst:
--------------------------------------------------------------------------------
1 | hydrobox.geostat.ordinary\_kriging
2 | ==================================
3 |
4 | .. currentmodule:: hydrobox.geostat
5 |
6 | .. autofunction:: ordinary_kriging
--------------------------------------------------------------------------------
/doc/toolboxes/gen_modules/hydrobox.geostat.simple_kriging.rst:
--------------------------------------------------------------------------------
1 | hydrobox.geostat.simple\_kriging
2 | ================================
3 |
4 | .. currentmodule:: hydrobox.geostat
5 |
6 | .. autofunction:: simple_kriging
--------------------------------------------------------------------------------
/doc/gen_modules/hydrobox.geostat.ext_drift_kriging.rst:
--------------------------------------------------------------------------------
1 | hydrobox.geostat.ext\_drift\_kriging
2 | ====================================
3 |
4 | .. currentmodule:: hydrobox.geostat
5 |
6 | .. autofunction:: ext_drift_kriging
--------------------------------------------------------------------------------
/doc/gen_modules/hydrobox.geostat.universal_kriging.rst:
--------------------------------------------------------------------------------
1 | hydrobox.geostat.universal\_kriging
2 | ===================================
3 |
4 | .. currentmodule:: hydrobox.geostat
5 |
6 | .. autofunction:: universal_kriging
--------------------------------------------------------------------------------
/doc/toolboxes/gen_modules/hydrobox.geostat.ordinary_kriging.rst:
--------------------------------------------------------------------------------
1 | hydrobox.geostat.ordinary\_kriging
2 | ==================================
3 |
4 | .. currentmodule:: hydrobox.geostat
5 |
6 | .. autofunction:: ordinary_kriging
--------------------------------------------------------------------------------
/doc/toolboxes/gen_modules/hydrobox.geostat.ext_drift_kriging.rst:
--------------------------------------------------------------------------------
1 | hydrobox.geostat.ext\_drift\_kriging
2 | ====================================
3 |
4 | .. currentmodule:: hydrobox.geostat
5 |
6 | .. autofunction:: ext_drift_kriging
--------------------------------------------------------------------------------
/doc/toolboxes/gen_modules/hydrobox.geostat.universal_kriging.rst:
--------------------------------------------------------------------------------
1 | hydrobox.geostat.universal\_kriging
2 | ===================================
3 |
4 | .. currentmodule:: hydrobox.geostat
5 |
6 | .. autofunction:: universal_kriging
--------------------------------------------------------------------------------
/hydrobox/utils/typing.py:
--------------------------------------------------------------------------------
1 | """
2 | Typing
3 | ======
4 |
5 | The typing utils package collects some more complex types
6 | of input and output data in hydrobox.
7 | """
8 | from typing import Union, Callable, Literal
9 | # geostat Package
10 |
--------------------------------------------------------------------------------
/classifiers.txt:
--------------------------------------------------------------------------------
1 | Development Status :: 4 - Beta
2 | Intended Audience :: Science/Research
3 | License :: OSI Approved :: MIT License
4 | Natural Language :: English
5 | Programming Language :: Python :: 3.8
6 | Programming Language :: Python :: 3.9
7 | Topic :: Scientific/Engineering :: Information Analysis
8 |
--------------------------------------------------------------------------------
/hydrobox/__init__.py:
--------------------------------------------------------------------------------
1 | import sys
2 |
3 | # Python 3.3 is not supported.
4 | if sys.version_info < (3, 8):
5 | raise ImportError('Python < 3.8 is not supported')
6 |
7 |
8 | import hydrobox.utils
9 | from hydrobox.plotting._backend import plotting_backend
10 | import hydrobox.geostat
11 |
12 | __version__ = '0.2.0'
13 | __plot_backend__ = 'matplotlib'
14 |
--------------------------------------------------------------------------------
/hydrobox/data/__init__.py:
--------------------------------------------------------------------------------
1 | import os
2 | import pandas as pd
3 |
4 |
5 | def __read(fname):
6 | df = pd.read_csv(os.path.join(os.path.dirname(__file__), fname))
7 | return df
8 |
9 |
10 | def pancake():
11 | return __read('pan_sample.csv')
12 |
13 |
14 | def sr():
15 | return __read('sample_sr')
16 |
17 |
18 | def lr():
19 | return __read('sample_lr')
--------------------------------------------------------------------------------
/.coveragerc:
--------------------------------------------------------------------------------
1 | [run]
2 | omit =
3 | hydrobox/tests/*
4 | hydrobox/plotting/*
5 | doc/*
6 | examples/*
7 | setup.py
8 | */typing.py
9 |
10 | [report]
11 | exclude_lines =
12 | pragma: no cover
13 | def __repr__
14 | def __str__
15 | if self\.debug:
16 | if False:
17 | if 0:
18 | raise AssertionError
19 | raise NotImplementedError
20 | if __name__ == .__main__.:
--------------------------------------------------------------------------------
/doc/gen_modules/backreferences/hydrobox.data.pancake.examples:
--------------------------------------------------------------------------------
1 |
2 |
3 | Examples using ``hydrobox.data.pancake``
4 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
5 |
6 | .. raw:: html
7 |
8 |
9 |
10 | .. only:: html
11 |
12 | .. figure:: /auto_examples/geostat/images/thumb/sphx_glr_plot_variogram_thumb.png
13 | :alt: Estimate a Variogram
14 |
15 | :ref:`sphx_glr_auto_examples_geostat_plot_variogram.py`
16 |
17 | .. raw:: html
18 |
19 |
20 |
21 | .. only:: not html
22 |
23 | * :ref:`sphx_glr_auto_examples_geostat_plot_variogram.py`
24 |
--------------------------------------------------------------------------------
/doc/gen_modules/backreferences/hydrobox.plotting_backend.examples:
--------------------------------------------------------------------------------
1 |
2 |
3 | Examples using ``hydrobox.plotting_backend``
4 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
5 |
6 | .. raw:: html
7 |
8 |
9 |
10 | .. only:: html
11 |
12 | .. figure:: /auto_examples/geostat/images/thumb/sphx_glr_plot_variogram_thumb.png
13 | :alt: Estimate a Variogram
14 |
15 | :ref:`sphx_glr_auto_examples_geostat_plot_variogram.py`
16 |
17 | .. raw:: html
18 |
19 |
20 |
21 | .. only:: not html
22 |
23 | * :ref:`sphx_glr_auto_examples_geostat_plot_variogram.py`
24 |
--------------------------------------------------------------------------------
/doc/Makefile:
--------------------------------------------------------------------------------
1 | # Minimal makefile for Sphinx documentation
2 | #
3 |
4 | # You can set these variables from the command line, and also
5 | # from the environment for the first two.
6 | SPHINXOPTS ?=
7 | SPHINXBUILD ?= sphinx-build
8 | SOURCEDIR = .
9 | BUILDDIR = _build
10 |
11 | # Put it first so that "make" without argument is like "make help".
12 | help:
13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
14 |
15 | .PHONY: help Makefile
16 |
17 | # Catch-all target: route all unknown targets to Sphinx using the new
18 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
19 | %: Makefile
20 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
21 |
--------------------------------------------------------------------------------
/doc/gen_modules/backreferences/hydrobox.geostat.variogram.examples:
--------------------------------------------------------------------------------
1 |
2 |
3 | Examples using ``hydrobox.geostat.variogram``
4 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
5 |
6 | .. raw:: html
7 |
8 |
9 |
10 | .. only:: html
11 |
12 | .. figure:: /auto_examples/geostat/images/thumb/sphx_glr_plot_variogram_thumb.png
13 | :alt: Estimate a Variogram
14 |
15 | :ref:`sphx_glr_auto_examples_geostat_plot_variogram.py`
16 |
17 | .. raw:: html
18 |
19 |
20 |
21 | .. only:: not html
22 |
23 | * :ref:`sphx_glr_auto_examples_geostat_plot_variogram.py`
24 |
--------------------------------------------------------------------------------
/doc/gen_modules/backreferences/hydrobox.geostat.gridsearch.examples:
--------------------------------------------------------------------------------
1 |
2 |
3 | Examples using ``hydrobox.geostat.gridsearch``
4 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
5 |
6 | .. raw:: html
7 |
8 |
9 |
10 | .. only:: html
11 |
12 | .. figure:: /auto_examples/geostat/images/thumb/sphx_glr_plot_gridsearch_thumb.png
13 | :alt: GridSearch optimization
14 |
15 | :ref:`sphx_glr_auto_examples_geostat_plot_gridsearch.py`
16 |
17 | .. raw:: html
18 |
19 |
20 |
21 | .. only:: not html
22 |
23 | * :ref:`sphx_glr_auto_examples_geostat_plot_gridsearch.py`
24 |
--------------------------------------------------------------------------------
/doc/gen_modules/backreferences/hydrobox.geostat.ordinary_kriging.examples:
--------------------------------------------------------------------------------
1 |
2 |
3 | Examples using ``hydrobox.geostat.ordinary_kriging``
4 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
5 |
6 | .. raw:: html
7 |
8 |
9 |
10 | .. only:: html
11 |
12 | .. figure:: /auto_examples/geostat/images/thumb/sphx_glr_plot_ordinary_kriging_thumb.png
13 | :alt: Ordinary Kriging
14 |
15 | :ref:`sphx_glr_auto_examples_geostat_plot_ordinary_kriging.py`
16 |
17 | .. raw:: html
18 |
19 |
20 |
21 | .. only:: not html
22 |
23 | * :ref:`sphx_glr_auto_examples_geostat_plot_ordinary_kriging.py`
24 |
--------------------------------------------------------------------------------
/hydrobox/plotting/__init__.py:
--------------------------------------------------------------------------------
1 | """
2 | Plotting routines
3 | -----------------
4 |
5 | Some of the tools, which have results plot may call a
6 | common interface of the `hydrobox.plotting` submodule.
7 | These interfacing functions in turn will either call
8 | a matplotlib, bokeh or plotly implementation.
9 |
10 | This is primarily implemented for convenience. The
11 | usecase in V-FOR-WaTer, the context at which this
12 | library is developed is to have a pythonic tool able to
13 | handle matplotlib plots, but also get interactive HTML
14 | versions of such by using bokeh or plotly.
15 |
16 | .. warning::
17 |
18 | This feature is experimental and may be completely or
19 | partly deprecated. Either bokeh or plotly may be removed
20 | on any version < 1.0.0 in favor of the other.
21 |
22 | """
23 | from ._backend import plotting_backend, plot_function_loader
24 |
--------------------------------------------------------------------------------
/doc/make.bat:
--------------------------------------------------------------------------------
1 | @ECHO OFF
2 |
3 | pushd %~dp0
4 |
5 | REM Command file for Sphinx documentation
6 |
7 | if "%SPHINXBUILD%" == "" (
8 | set SPHINXBUILD=sphinx-build
9 | )
10 | set SOURCEDIR=.
11 | set BUILDDIR=_build
12 |
13 | if "%1" == "" goto help
14 |
15 | %SPHINXBUILD% >NUL 2>NUL
16 | if errorlevel 9009 (
17 | echo.
18 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
19 | echo.installed, then set the SPHINXBUILD environment variable to point
20 | echo.to the full path of the 'sphinx-build' executable. Alternatively you
21 | echo.may add the Sphinx directory to PATH.
22 | echo.
23 | echo.If you don't have Sphinx installed, grab it from
24 | echo.http://sphinx-doc.org/
25 | exit /b 1
26 | )
27 |
28 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
29 | goto end
30 |
31 | :help
32 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
33 |
34 | :end
35 | popd
36 |
--------------------------------------------------------------------------------
/setup.py:
--------------------------------------------------------------------------------
1 | from setuptools import setup, find_packages
2 | import sys
3 |
4 | if sys.version_info < (3, 3):
5 | sys.exit('Python < 3.3 is not supported')
6 |
7 | with open('requirements.txt') as fs:
8 | REQUIREMENTS = fs.read().strip().split('\n')
9 |
10 | with open('VERSION.txt') as fs:
11 | VERSION = fs.read().strip()
12 |
13 | with open('classifiers.txt') as fs:
14 | CLASSIFIERS = fs.read().strip().split('\n')
15 |
16 |
17 | def readme():
18 | with open('README.md') as fs:
19 | return fs.read()
20 |
21 | setup(name='hydrobox',
22 | version=VERSION,
23 | license='MIT',
24 | description='Hydrological toolbox build on top of scipy and pandas',
25 | long_description=readme(),
26 | classifiers=CLASSIFIERS,
27 | author='Mirko Maelicke',
28 | author_email='mirko.maelicke@kit.edu',
29 | install_requires=REQUIREMENTS,
30 | test_suite='nose.collector',
31 | tests_require=['nose'],
32 | packages=find_packages(),
33 | include_package_data=True,
34 | zip_safe=False
35 | )
--------------------------------------------------------------------------------
/doc/auto_examples/geostat/sg_execution_times.rst:
--------------------------------------------------------------------------------
1 |
2 | :orphan:
3 |
4 | .. _sphx_glr_auto_examples_geostat_sg_execution_times:
5 |
6 | Computation times
7 | =================
8 | **00:15.624** total execution time for **auto_examples_geostat** files:
9 |
10 | +-----------------------------------------------------------------------------------------------+-----------+--------+
11 | | :ref:`sphx_glr_auto_examples_geostat_plot_variogram.py` (``plot_variogram.py``) | 00:15.624 | 0.0 MB |
12 | +-----------------------------------------------------------------------------------------------+-----------+--------+
13 | | :ref:`sphx_glr_auto_examples_geostat_plot_gridsearch.py` (``plot_gridsearch.py``) | 00:00.000 | 0.0 MB |
14 | +-----------------------------------------------------------------------------------------------+-----------+--------+
15 | | :ref:`sphx_glr_auto_examples_geostat_plot_ordinary_kriging.py` (``plot_ordinary_kriging.py``) | 00:00.000 | 0.0 MB |
16 | +-----------------------------------------------------------------------------------------------+-----------+--------+
17 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/hydrobox/geostat/typing.py:
--------------------------------------------------------------------------------
1 | from typing import Union, Callable, Literal
2 | import numpy as np
3 |
4 | # some typings
5 | Estimator = Union[
6 | Literal['matheron','cressie', 'dowd''genton', 'entropy', 'minmax', 'percentile'],
7 | Callable[[np.ndarray], float]
8 | ]
9 |
10 | Model = Union[
11 | Literal['spherical', 'exponential', 'gaussian', 'matern', 'cubic', 'stable'],
12 | Callable[[float, float], float],
13 | Callable[[float, float, float], float],
14 | Callable[[float, float, float, float], float]
15 | ]
16 |
17 | DistFunc = Literal[
18 | 'braycurtis', 'canberra', 'chebyshev', 'cityblock', 'correlation', 'cosine', 'dice',
19 | 'euclidean', 'hamming', 'jaccard', 'jensenshannon', 'kulsinski', 'mahalanobis',
20 | 'matching', 'minkowski', 'rogerstanimoto', 'russellrao', 'seuclidean',
21 | 'sokalmichener', 'sokalsneath', 'sqeuclidean', 'yule'],
22 |
23 | BinFunc = Literal['even', 'uniform', 'sqrt', 'scott', 'sturge', 'kmean', 'ward', 'fd', 'doane']
24 |
25 | FitMethod = Literal['trf', 'lm', 'ml', 'custom']
26 |
27 | FitSigma = Union[None, np.ndarray, Literal['linear', 'sqrt', 'sq', 'exp']]
28 |
29 | Maxlag = Union[None, Literal['mean', 'median'], int, float]
--------------------------------------------------------------------------------
/doc/index.rst:
--------------------------------------------------------------------------------
1 | .. HydroBox documentation master file, created by
2 | sphinx-quickstart on Tue May 4 09:33:00 2021.
3 | You can adapt this file completely to your liking, but it should at least
4 | contain the root `toctree` directive.
5 |
6 | Welcome to HydroBox
7 | ===================
8 |
9 | .. note::
10 | Major parts of the toolbox are currently re-written. Most interfaces of
11 | any function of version < 0.2 will most likely not work anymore.
12 | The aim is to produce a unified interface for hydrobox.
13 | Secondly, hydrobox is mainly pushed to reuse other Python packages within
14 | this scope, instead of re-implementing functions that are already there.
15 |
16 | .. toctree::
17 | :hidden:
18 | :maxdepth: 1
19 | :caption: Contents:
20 |
21 | toolboxes/index
22 | auto_examples/index
23 |
24 | Installation
25 | ============
26 |
27 | PyPI
28 | ----
29 |
30 | Install hydrobox from the Python Pachage Index like:
31 |
32 | .. code-block:: bash
33 |
34 | pip install hydrobox
35 |
36 | Github
37 | ------
38 |
39 | You can install hydrobox from source like:
40 |
41 | .. code-block:: bash
42 |
43 | git clone git@github.com:vforwater/hydrobox
44 | cd hydrobox
45 | pip install -e .
--------------------------------------------------------------------------------
/hydrobox/plotting/variogram.py:
--------------------------------------------------------------------------------
1 | from skgstat.plotting import backend
2 | from skgstat import Variogram
3 |
4 | def __plot(variogram: Variogram, plot_type: str, **kwargs):
5 | # always suppress sho
6 | kwargs['show'] = False
7 |
8 | # get the figure
9 | if plot_type == 'plot':
10 | fig = variogram.plot(**kwargs)
11 | elif plot_type == 'distance_difference':
12 | fig = variogram.distance_difference_plot(**kwargs)
13 | elif plot_type == 'location_trend':
14 | fig = variogram.location_trend(**kwargs)
15 | elif plot_type == 'scattergram':
16 | fig = variogram.scattergram(**kwargs)
17 | else:
18 | raise ValueError(f"Plot type '{plot_type}' not supported.")
19 |
20 | return fig
21 |
22 |
23 | def _plot_matplotlib(func_args, plot_args):
24 | # set matplotlib backend
25 | backend('matplotlib')
26 |
27 | # get the variogram
28 | variogram = func_args['variogram']
29 | plot_type = func_args.get('plot_type', 'plot')
30 |
31 | return __plot(variogram, plot_type, **plot_args)
32 |
33 |
34 | def _plot_plotly(func_args, plot_args):
35 | # set matplotlib backend
36 | backend('plotly')
37 |
38 | # get the variogram
39 | variogram = func_args['variogram']
40 | plot_type = func_args.get('plot_type', 'plot')
41 |
42 | return __plot(variogram, plot_type, **plot_args)
43 |
--------------------------------------------------------------------------------
/hydrobox/discharge/indices.py:
--------------------------------------------------------------------------------
1 | """
2 | Common indices frequently used to describe discharge measurements in a single
3 | coefficient.
4 |
5 | """
6 | import numpy as np
7 | import pandas as pd
8 |
9 |
10 | def richards_baker(x):
11 | r"""Richards-Baker Flashiness Index
12 |
13 | Calculates the Richards-Baker Flashiness index (RB Index), which is a
14 | extension of the Richards Pathlengh index. In contrast to the Pathlength
15 | of a signal, the R-B Index is relative to the total discharge and
16 | independend of the chosen unit.
17 |
18 | Parameters
19 | ----------
20 | x : numpy.ndarray, pd.Series
21 | The discharge input values.
22 |
23 | Returns
24 | -------
25 | numpy.ndarray
26 |
27 | Notes
28 | -----
29 | The Richards-Baker Flashiness Index [2]_ is defined as:
30 |
31 | .. math::
32 |
33 | {RBI} = \frac{\sum_{i=1}^{n}|q_i - q_{i-1}|}{\sum_{i=1}^{n} q_i}
34 |
35 |
36 |
37 | References
38 | ----------
39 | .. [2] Baker D.B., P. Richards, T.T. Loftus, J.W. Kramer. A new
40 | flashiness index: characteristics and applications to midwestern
41 | rivers and streams. JAWRA Journal of the American Water Resources
42 | Association, 40(2), 503-522, 2004.
43 |
44 | """
45 | # convert Series
46 | if isinstance(x, pd.Series):
47 | x = x.values
48 |
49 | nominator = np.sum(np.fromiter(
50 | (np.abs(x[i] - x[i -1]) for i in range(1,len(x))),
51 | dtype=x.dtype))
52 |
53 | return nominator / np.sum(x[1:])
54 |
--------------------------------------------------------------------------------
/examples/geostat/plot_ordinary_kriging.py:
--------------------------------------------------------------------------------
1 | """
2 | Ordinary Kriging
3 | ================
4 |
5 | With the help of a variogram that describes spatial properties of
6 | a sample, the sample can be interpolated.
7 |
8 | """
9 | from time import time
10 | import plotly
11 | import hydrobox
12 | from hydrobox.data import pancake
13 | from hydrobox.plotting import plotting_backend
14 | plotting_backend('plotly')
15 |
16 | #%%
17 | # Load sample data from the data sub-module
18 |
19 | df = pancake()
20 |
21 | #%%
22 | # Estimate a exponential variogram again. More details are given in the
23 | # :ref:`sphx_glr_auto_examples_geostat_plot_variogram.py` example.
24 |
25 | vario = hydrobox.geostat.variogram(
26 | coordinates=df[['x', 'y']].values,
27 | values=df.z.values,
28 | model='exponential',
29 | bin_func='kmeans',
30 | n_lags=25,
31 | return_type='object'
32 | )
33 |
34 | #%%
35 | # Run ordinary kriging on a 100x100 grid. In this run, the result is
36 | # directly plotted. Other return types are ``'grid'``, to return the
37 | # resulting interpolated grid and kriging error grid, or ``'object'``
38 | # to return the :class:`Krige ` class. This class
39 | # is already parameterized, but the interpolation was not yet performed.
40 | # This is most helpful if other grid should be constructed.
41 |
42 | t1 = time()
43 | fig = hydrobox.geostat.ordinary_kriging(
44 | variogram=vario,
45 | grid_resolution=100,
46 | exact=True,
47 | cond_err='nugget',
48 | return_type='plot'
49 | )
50 | t2 = time()
51 |
52 | print('Took: %2f sec' % (t2 - t1))
53 |
54 | # show the plot
55 | plotly.io.show(fig)
--------------------------------------------------------------------------------
/doc/auto_examples/geostat/plot_ordinary_kriging.py:
--------------------------------------------------------------------------------
1 | """
2 | Ordinary Kriging
3 | ================
4 |
5 | With the help of a variogram that describes spatial properties of
6 | a sample, the sample can be interpolated.
7 |
8 | """
9 | from time import time
10 | import plotly
11 | import hydrobox
12 | from hydrobox.data import pancake
13 | from hydrobox.plotting import plotting_backend
14 | plotting_backend('plotly')
15 |
16 | #%%
17 | # Load sample data from the data sub-module
18 |
19 | df = pancake()
20 |
21 | #%%
22 | # Estimate a exponential variogram again. More details are given in the
23 | # :ref:`sphx_glr_auto_examples_geostat_plot_variogram.py` example.
24 |
25 | vario = hydrobox.geostat.variogram(
26 | coordinates=df[['x', 'y']].values,
27 | values=df.z.values,
28 | model='exponential',
29 | bin_func='kmeans',
30 | n_lags=25,
31 | return_type='object'
32 | )
33 |
34 | #%%
35 | # Run ordinary kriging on a 100x100 grid. In this run, the result is
36 | # directly plotted. Other return types are ``'grid'``, to return the
37 | # resulting interpolated grid and kriging error grid, or ``'object'``
38 | # to return the :class:`Krige ` class. This class
39 | # is already parameterized, but the interpolation was not yet performed.
40 | # This is most helpful if other grid should be constructed.
41 |
42 | t1 = time()
43 | fig = hydrobox.geostat.ordinary_kriging(
44 | variogram=vario,
45 | grid_resolution=100,
46 | exact=True,
47 | cond_err='nugget',
48 | return_type='plot'
49 | )
50 | t2 = time()
51 |
52 | print('Took: %2f sec' % (t2 - t1))
53 |
54 | # show the plot
55 | plotly.io.show(fig)
--------------------------------------------------------------------------------
/.github/workflows/main.yaml:
--------------------------------------------------------------------------------
1 | name: Test and docs
2 |
3 | on: push
4 |
5 | jobs:
6 | test:
7 | name: Test
8 | runs-on: ubuntu-18.04
9 |
10 |
11 | steps:
12 | - name: Checkout
13 | uses: actions/checkout@master
14 |
15 | - name: Install Python
16 | uses: actions/setup-python@master
17 | with:
18 | python-version: 3.8
19 |
20 | - name: Install Hydrobox
21 | run: pip3 install -e .
22 |
23 | - name: Install PyTest
24 | run: pip install pytest pytest-cov pytest-depends
25 |
26 | - name: Test
27 | run: pytest --cov-config=.coveragerc --cov=./ --cov-report=xml
28 |
29 | - name: Upload coverage
30 | uses: codecov/codecov-action@master
31 | with:
32 | file: ./coverage.xml
33 |
34 | docs:
35 | name: Build docs
36 | runs-on: ubuntu-18.04
37 |
38 | steps:
39 | - name: Checkout
40 | uses: actions/checkout@master
41 |
42 | - name: Install Python
43 | uses: actions/setup-python@master
44 | with:
45 | python-version: 3.8
46 |
47 | - name: Install Hydrobox
48 | run: pip3 install -e .
49 |
50 | - name: Install Doc requirements
51 | run: pip install sphinx pydata_sphinx_theme sphinx-gallery sphinx_autodoc_typehints
52 |
53 | - name: Build docs
54 | run: |
55 | cd doc
56 | make html
57 |
58 | - name: Deploy
59 | uses: JamesIves/github-pages-deploy-action@4.1.1
60 | with:
61 | branch: gh-pages
62 | folder: doc/_build/html
63 |
64 |
65 |
--------------------------------------------------------------------------------
/hydrobox/tests/test_geostat.py:
--------------------------------------------------------------------------------
1 | from hydrobox import data
2 | import hydrobox
3 | import plotly.graph_objects as go
4 | import skgstat as skg
5 | from sklearn.model_selection import GridSearchCV
6 |
7 |
8 | def test_variogram():
9 | """Test the return types"""
10 | # get data
11 | df = data.pancake()
12 | hydrobox.plotting_backend('plotly')
13 |
14 | for t, type_ in zip(('object', 'describe', 'plot'), (skg.Variogram, dict, go.Figure)):
15 | vario = hydrobox.geostat.variogram(
16 | df[['x', 'y']].values,
17 | df.z.values,
18 | return_type=t
19 | )
20 |
21 | assert isinstance(vario, type_)
22 |
23 |
24 | def test_gridsearch():
25 | """Test Gridsearch with explicit param_grid"""
26 | # create the grid
27 | param_grid={'model': ('spherical', 'gaussian', 'stable')}
28 |
29 | # get data
30 | df = data.pancake()
31 |
32 | gs = hydrobox.geostat.gridsearch(
33 | param_grid=param_grid,
34 | coordinates=df[['x', 'y']].values,
35 | values=df.z.values,
36 | n_lags=25,
37 | return_type='object'
38 | )
39 |
40 | assert isinstance(gs, GridSearchCV)
41 |
42 | def test_gridsearch_variogram():
43 | """Test Gridsearch with variogram passed"""
44 | df = data.pancake()
45 | # create the grid
46 | param_grid={'fit_method': ('trf', 'lm', 'ml')}
47 | vario = hydrobox.geostat.variogram(
48 | df[['x', 'y']].values,
49 | df.z.values,
50 | n_lags=15,
51 | return_type='object'
52 | )
53 | gs = hydrobox.geostat.gridsearch(
54 | param_grid,
55 | variogram=vario,
56 | return_type='best_param'
57 | )
58 |
59 | assert isinstance(gs, dict)
--------------------------------------------------------------------------------
/hydrobox/geostat/__init__.py:
--------------------------------------------------------------------------------
1 | """
2 | Geostatistical Toolbox
3 | ----------------------
4 |
5 | This toolbox collects all functions needed to run different geostatistical
6 | tasks. Variogram analysis can be done with :func:`variogram `,
7 | which wraps the scikit-gstat Variogram class.
8 |
9 | Variogram estimation
10 | ~~~~~~~~~~~~~~~~~~~~
11 |
12 | There are two major functions to estimate variograms. The :func:`variogram `
13 | function and the :func:`gridsearch `, which will select optimal
14 | variogram parameters, based on a cross-validated score.
15 |
16 | .. minigallery:: hydrobox.geostat.variogram hydrobox.geostat.gridsearch
17 | :add-heading: Variogram examples
18 |
19 | Content of :py:mod:`hydrobox.geostat`:
20 |
21 | .. autosummary::
22 | :toctree: gen_modules/
23 | :template: module.rst
24 |
25 | variogram
26 | gridsearch
27 |
28 | Kriging
29 | ~~~~~~~
30 |
31 | Kriging can be performed, after a variogram was estimated. the :class:`Variogram `
32 | is exported to gstools and one of the :class:`Krige ` classes will be used for
33 | kriging.
34 |
35 | .. minigallery:: hydrobox.geostat.simple_kriging hydrobox.geostat.ordinary_kriging hydrobox.geostat.universal_kriging hydrobox.geostat.ext_drift_kriging
36 | :add-heading: Kriging examples
37 |
38 | .. autosummary::
39 | :toctree: gen_modules/
40 | :template: module.rst
41 |
42 | simple_kriging
43 | ordinary_kriging
44 | universal_kriging
45 | ext_drift_kriging
46 |
47 | """
48 | from .variogram import variogram
49 | from .gridsearch import gridsearch
50 | from .kriging import ordinary_kriging, simple_kriging, universal_kriging, ext_drift_kriging
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Byte-compiled / optimized / DLL files
2 | __pycache__/
3 | *.py[cod]
4 | *$py.class
5 |
6 | # C extensions
7 | *.so
8 |
9 | # Distribution / packaging
10 | .Python
11 | env/
12 | build/
13 | develop-eggs/
14 | dist/
15 | downloads/
16 | eggs/
17 | .eggs/
18 | lib/
19 | lib64/
20 | parts/
21 | sdist/
22 | var/
23 | wheels/
24 | *.egg-info/
25 | .installed.cfg
26 | *.egg
27 |
28 | # PyInstaller
29 | # Usually these files are written by a python script from a template
30 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
31 | *.manifest
32 | *.spec
33 |
34 | # Installer logs
35 | pip-log.txt
36 | pip-delete-this-directory.txt
37 |
38 | # Unit test / coverage reports
39 | htmlcov/
40 | .tox/
41 | .coverage
42 | .coverage.*
43 | .cache
44 | nosetests.xml
45 | coverage.xml
46 | *.cover
47 | .hypothesis/
48 |
49 | # Translations
50 | *.mo
51 | *.pot
52 |
53 | # Django stuff:
54 | *.log
55 | local_settings.py
56 |
57 | # Flask stuff:
58 | instance/
59 | .webassets-cache
60 |
61 | # Scrapy stuff:
62 | .scrapy
63 |
64 | # Sphinx documentation
65 | docs/_build/
66 |
67 | # PyBuilder
68 | target/
69 |
70 | # Jupyter Notebook
71 | .ipynb_checkpoints
72 |
73 | # pyenv
74 | .python-version
75 |
76 | # celery beat schedule file
77 | celerybeat-schedule
78 |
79 | # SageMath parsed files
80 | *.sage.py
81 |
82 | # dotenv
83 | .env
84 |
85 | # virtualenv
86 | .venv
87 | venv/
88 | ENV/
89 |
90 | # Spyder project settings
91 | .spyderproject
92 | .spyproject
93 |
94 | # Rope project settings
95 | .ropeproject
96 |
97 | # mkdocs documentation
98 | /site
99 |
100 | # mypy
101 | .mypy_cache/
102 |
103 | # Project specific
104 | # ignore PyCharm project folder
105 | .idea
106 |
107 | # ignore coverage.py html output
108 | cover
109 |
110 | # ignore IPython sphinx directive savefig
111 | doc/_build
112 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # HydroBox
2 |
3 |
4 | 
5 | 
6 | 
7 | [](https://zenodo.org/badge/latestdoi/129882492)
8 |
9 | ## Description
10 |
11 | **The HydroBox is mainly a toolbox used in the [V-FOR-WaTer](https://vforwater.de) Project. It will be expanded to serve general hydrological data exploration with a future release.**
12 |
13 | The HydroBox package is a toolbox for hydrological data analysis developed at the [Chair of Hydrology](https://hyd.iwg.kit.edu/english/index.php) at the
14 | [Karlsruhe Institute of Technology (KIT)](https://kit.edu/english/index.php).
15 |
16 | The full documentation can be found at: https://vforwater.github.io/hydrobox
17 |
18 | HydroBox has several submodules called toolboxes, which are a collection of functions and classes for specific purposes. As of this writing, the toolboxes are:
19 |
20 | * `geostat` for geostatistics. Mainly implemented through `scikit-gstat` and `gstools`
21 |
22 | In development are:
23 |
24 | * `uncertainty_framwork` for uncertainty analysis
25 | * `bridget` for evapotranspiration tools
26 |
27 | ## Citation
28 |
29 | If you use the package in other software or for publications, please cite it like:
30 |
31 | > Mirko Mälicke, 2021. VForWaTer/hydrobox: Version 0.2. doi:10.5281/zenodo.4774860
32 |
33 | Be aware that the dependencies of hydrobox require a citation as well. The (non-exhaustive) list of packages that you must cite are:
34 |
35 | * scipy, matplotlib, numpy - for all toolboxes
36 | * plotly - for the `plotly` plotting backend
37 | * scikit-gstat, gstools - for the `hydrobox.geostat` toolbox
38 |
--------------------------------------------------------------------------------
/hydrobox/preprocessing/union.py:
--------------------------------------------------------------------------------
1 | """
2 | Collects convenient methods for combining multiple data sets into a single one.
3 | This is typically a pandas.DataFrame then.
4 | """
5 | import pandas as pd
6 |
7 |
8 | def merge(*x, dropna=False):
9 | r"""Merge multiple data sets.
10 |
11 | This method is a general tool for combining multiple data sources into a
12 | single structure. It can be used as a preprocessing step in case the next
13 | chained tool does only accept a single input data set, but can handle
14 | multi-dimensional data.
15 | For conveniently wrapping around a single dimension data set, it will
16 | return x as it is if len(x) == 1.
17 |
18 | Parameters
19 | ----------
20 | x : pd.Series
21 | Input series. All series have to share an Index. If the type of the
22 | index is different, a ValueError will be raised. In case an Index
23 | value is missing on one of the Series, it will be filled with a NaN
24 | value.
25 | dropna : bool, optional
26 | If dropna is True, all indices with at least **one** NaN will be
27 | dropped.
28 |
29 | Returns
30 | -------
31 | pandas.DataFrame
32 |
33 | Notes
34 | -----
35 |
36 | At the current state merge does only accept ``pandas.Series``.
37 | A ``pandas.DataFrame`` with len(x) columns is returned.
38 |
39 | """
40 | # check if only one series was passed
41 | if len(x) == 1:
42 | return x[0]
43 | elif len(x) == 0:
44 | return None
45 |
46 | # convert x from tuple to list
47 | x = list(x)
48 |
49 | # check the indices to be of same kind.
50 | dtype = type(x[0].index)
51 | if not all([isinstance(series.index, dtype) for series in x]):
52 | raise ValueError(
53 | 'At least one data set was not of type %s.' % str(dtype))
54 |
55 | # build the first DataFrame
56 | df = pd.concat(x, axis=1)
57 |
58 | # if dropna was given, remove NaN values
59 | if dropna:
60 | df.dropna(axis=0, how='any', inplace=True)
61 |
62 | return df
63 |
--------------------------------------------------------------------------------
/hydrobox/plotting/_backend.py:
--------------------------------------------------------------------------------
1 | """
2 | Helper functions for getting and setting the plotting backend.
3 |
4 | You can use this function to get or set the current
5 | plotting backend.
6 |
7 | """
8 | import importlib
9 |
10 | ALLOWED_BACKENDS = ['matplotlib', 'bokeh', 'plotly']
11 | AVAILABLE_BACKENDS = []
12 |
13 | # check which one is available
14 | for be in ALLOWED_BACKENDS:
15 | try:
16 | exec('import %s' % be)
17 | AVAILABLE_BACKENDS.append(be)
18 | except ModuleNotFoundError:
19 | continue
20 |
21 |
22 | def plotting_backend(backend=None):
23 | """
24 | Set a new or get the current plotting backend.
25 |
26 | Parameters
27 | ----------
28 | backend : str, None
29 | If `None` the current plotting backend will be returned.
30 | If string, the plotting backend will be set to the given string.
31 |
32 | Raises
33 | ------
34 | ValueError : If `backend` is a string but not in ['matplotlib', 'bokeh', 'plotly']
35 | AttributeError : If `backend` is neither str or None
36 |
37 | """
38 | # need to import at runtime to avoid circular imports
39 | import hydrobox
40 |
41 | if backend is None:
42 | return hydrobox.__plot_backend__
43 | elif isinstance(backend, str):
44 | if backend not in ALLOWED_BACKENDS:
45 | raise ValueError('backend has to be one of [%s]' % ','.join(ALLOWED_BACKENDS))
46 | elif backend not in AVAILABLE_BACKENDS:
47 | raise ValueError('Seems like %s is not installed' % backend)
48 | else:
49 | hydrobox.__plot_backend__ = backend
50 | else:
51 | raise AttributeError('backend has to be None or a string.')
52 |
53 |
54 | def plot_function_loader(caller_name, backend=None):
55 | """
56 | Helper function
57 |
58 | This function can be used to load plotting functions
59 | in case they follow the naming specification
60 | """
61 | # load module
62 | module_name = 'hydrobox.plotting.%s' % caller_name
63 | try:
64 | mod_ref = importlib.import_module(module_name)
65 | except ModuleNotFoundError:
66 | raise AttributeError('%s does not have a plotting routine' % caller_name)
67 |
68 | # load function
69 | backend = plotting_backend()
70 | function_name = '_plot_%s' % backend
71 |
72 | if hasattr(mod_ref, function_name):
73 | function = getattr(mod_ref, function_name)
74 | else:
75 | raise AttributeError('%s has no plotting routine for %s-backend' % (caller_name, backend))
76 |
77 | return function
78 |
79 |
--------------------------------------------------------------------------------
/hydrobox/geostat/variogram.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | import skgstat as skg
3 | import gstools as gs
4 |
5 | from hydrobox.geostat import typing
6 | from hydrobox.plotting import plot_function_loader
7 |
8 |
9 | def variogram(
10 | coordinates: np.ndarray,
11 | values: np.ndarray,
12 | estimator: typing.Estimator = 'matheron',
13 | model: typing.Model = 'spherical',
14 | dist_func: typing.DistFunc = 'euclidean',
15 | bin_func: typing.BinFunc = 'even',
16 | fit_method: typing.FitMethod = 'trf',
17 | fit_sigma: typing.FitSigma = None,
18 | use_nugget: bool = False,
19 | maxlag: typing.Maxlag = None,
20 | n_lags: typing.Union[int, None] = 10,
21 | return_type: typing.Literal['object', 'describe', 'plot', 'distance_difference', 'location_trend', 'scattergram'] = 'object',
22 | **kwargs
23 | ) -> skg.Variogram:
24 | """
25 | Uses scikit-gstat to estimate a Variogram.
26 | Refer to the :class:`Variogram ` class
27 | to learn about the different Parameters.
28 |
29 | Parameters
30 | ----------
31 | return_type : str
32 | Specify how the Variogram instance should be returned. Object will
33 | return the actual instance. 'describe' is the dictionary output
34 | generated by the class, which is serializable. All other options
35 | return the different plot types
36 |
37 | Returns
38 | -------
39 | variogram : skgstat.Variogram
40 | If the return type is `'object'`
41 | plot : plotly.Figure, matplotlib.pyplot.Figure
42 | If the return type is one of the plots
43 | description : dict
44 | If the return type is `'describe'`
45 |
46 | """
47 | # create the variogram
48 | v = skg.Variogram(
49 | coordinates=coordinates,
50 | values=values,
51 | estimator=estimator,
52 | model=model,
53 | dist_func=dist_func,
54 | bin_func=bin_func,
55 | fit_method=fit_method,
56 | fit_sigma=fit_sigma,
57 | use_nugget=use_nugget,
58 | maxlag=maxlag,
59 | n_lags=n_lags,
60 | **kwargs
61 | )
62 |
63 | if return_type == 'object':
64 | return v
65 | elif return_type == 'describe':
66 | return v.describe(short=False, flat=False)
67 |
68 | # otherwise create a plot
69 | pfunc = plot_function_loader('variogram')
70 | fig = pfunc(
71 | func_args=dict(
72 | variogram=v,
73 | plot_type=return_type
74 | ),
75 | plot_args=kwargs
76 | )
77 | return fig
78 |
79 |
80 |
--------------------------------------------------------------------------------
/hydrobox/plotting/kriging.py:
--------------------------------------------------------------------------------
1 | try:
2 | import matplotlib.pyplot as plt
3 | except ModuleNotFoundError:
4 | pass
5 |
6 | try:
7 | import plotly.graph_objects as go
8 | from plotly.subplots import make_subplots
9 | except ModuleNotFoundError:
10 | pass
11 |
12 |
13 | def _plot_matplotlib(func_args, plot_args):
14 | # build the figure
15 | fig, axes = plt.subplots(1, 2, figsize=plot_args.get('figsize', (12, 6)))
16 |
17 | # data can be one or two dimensional
18 | field = func_args['field']
19 | sigma = func_args['sigma']
20 | variogram = func_args['variogram']
21 |
22 | if field.ndim == 1:
23 | # plot the lines
24 | axes[0].plot(field)
25 | axes[1].plot(sigma)
26 |
27 | else:
28 | # plot the im
29 | m1 = axes[0].imshow(field, origin='lower', cmap=plot_args.get('cmap', 'terrain'))
30 | m2 = axes[1].imshow(sigma, origin='lower', cmap=plot_args.get('sigma_cmap', 'hot'))
31 | plt.colorbar(m1, ax=axes[0])
32 | plt.colorbar(m2, ax=axes[1])
33 |
34 | # label
35 | axes[0].set_title('Kriging Grid')
36 | axes[1].set_title('Kriging Error')
37 | plt.tight_layout()
38 |
39 | return fig
40 |
41 |
42 | def _plot_plotly(func_args, plot_args):
43 |
44 | # get the data
45 | field = func_args['field']
46 | sigma = func_args['sigma']
47 | variogram = func_args['variogram']
48 |
49 | if field.ndim == 1:
50 | fig = go.Figure()
51 |
52 | # build only one figure with error bars
53 | fig.add_trace(
54 | go.Scatter(
55 | x=range(field.flatten().size),
56 | y=field.flatten(),
57 | mode='lines+markers',
58 | marker=dict(
59 | size=5
60 | ),
61 | error_y=dict(
62 | type='data',
63 | array=sigma.flatten(),
64 | visible=True
65 | )
66 | )
67 | )
68 | # return the figure
69 | return fig
70 |
71 | # if this point is reached, it's a 2D field
72 | if plot_args.get('surface', False):
73 | fig = make_subplots(1, 2, specs=[[{'type': 'surface'}, {'type': 'surface'}]])
74 | Trace = go.Surface
75 | else:
76 | fig = make_subplots(1, 2)
77 | Trace = go.Heatmap
78 |
79 | # add the field
80 | fig.add_trace(
81 | Trace(z=field, colorscale=plot_args.get('colorscale', 'Earth_r')),
82 | 1, 1
83 | )
84 |
85 | # add sigma
86 | fig.add_trace(
87 | Trace(z=sigma, colorscale=plot_args.get('sigma_colorscale', 'thermal')),
88 | 1, 2
89 | )
90 |
91 | return fig
92 |
--------------------------------------------------------------------------------
/hydrobox/plotting/flow_duration_curve.py:
--------------------------------------------------------------------------------
1 | """
2 | """
3 | import numpy as np
4 | try:
5 | import matplotlib.pyplot as plt
6 | except ModuleNotFoundError:
7 | # TODO here a global var can indicate that importing failed
8 | pass
9 | try:
10 | from bokeh.plotting import figure, Figure
11 | except ModuleNotFoundError:
12 | # TODO here a global var can indicate that importing failed
13 | pass
14 |
15 |
16 | def _plot_matplotlib(func_args, plot_args):
17 | # parse func-args
18 | non_exceeding = func_args.get('non_exceeding', False)
19 | log = func_args.get('log', False)
20 | x = func_args['x']
21 | y = func_args['y']
22 |
23 | # handle matplotlib figure
24 | ax = func_args.get('figure')
25 | if ax is None:
26 | fig, ax = plt.subplots(1, 1)
27 | else:
28 | fig = ax.get_figure()
29 |
30 | # set defaults
31 | plot_args.setdefault('linestyle', '-')
32 | plot_args.setdefault('color', 'b')
33 |
34 | # plot
35 | ax.plot(x, y, **plot_args)
36 |
37 | ax.set_xlabel('discharge [m3/s]')
38 | ax.set_ylabel('%sexceeding prob.' % ('non-' if non_exceeding else ''))
39 |
40 | # log, log scale
41 | if log:
42 | ax.loglog()
43 | else:
44 | ax.set_ylim((-0.05, 1.1))
45 | ax.set_xlim(np.nanmin(x) * 0.98, np.nanmax(x) * 1.02)
46 | ax.set_title('%sFDC' % ('loglog ' if log else ''))
47 | ax.grid(which='both' if log else 'major')
48 |
49 | return fig
50 |
51 | def _plot_bokeh(func_args, plot_args):
52 | # parse func-args
53 | non_exceeding = func_args.get('non_exceeding', False)
54 | log = func_args.get('log', False)
55 | x = func_args['x']
56 | y = func_args['y']
57 |
58 | # plotting args
59 | plot_args.setdefault('line_color', 'navy')
60 | plot_args.setdefault('line_width', 3)
61 |
62 | fig = func_args.get('figure')
63 | if fig is None:
64 | # some of the plot_args should go into figure
65 | args = dict()
66 |
67 | for k,v in plot_args.items():
68 | if hasattr(Figure, k):
69 | args[k] = v
70 | del plot_args[k]
71 |
72 | # handle log-log
73 | if log:
74 | args.setdefault('x_axis_type', 'log')
75 | args.setdefault('y_axis_type', 'log')
76 | else:
77 | args.setdefault('x_range', (-0.05, 1.1))
78 | args.setdefault('y_range', (np.nanmin(x) * 0.98, np.nanmax(x) * 1.02))
79 | args.setdefault('title', 'Flow duration curve')
80 |
81 | fig = figure(**args)
82 |
83 | # plot
84 | fig.line(x, y, **plot_args)
85 |
86 | fig.xaxis.axis_label = 'discharge [m3/s]'
87 | fig.yaxis.axis_label = '%sexceeding prob.' % ('non-' if non_exceeding else '')
88 |
89 | return fig
90 |
91 |
--------------------------------------------------------------------------------
/doc/auto_examples/index.rst:
--------------------------------------------------------------------------------
1 | :orphan:
2 |
3 |
4 |
5 | .. _sphx_glr_auto_examples:
6 |
7 | Hydrobox Examples
8 | =================
9 |
10 | This gallery collects example scripts for most functions in hydrobox.
11 |
12 | .. raw:: html
13 |
14 |
15 |
16 |
17 |
18 | .. _sphx_glr_auto_examples_geostat:
19 |
20 | Geostatistics Toolbox
21 | ---------------------
22 |
23 | The following examples demonstrate the usage of the geostatistics toolbox.
24 |
25 |
26 | .. raw:: html
27 |
28 |
29 |
30 | .. only:: html
31 |
32 | .. figure:: /auto_examples/geostat/images/thumb/sphx_glr_plot_ordinary_kriging_thumb.png
33 | :alt: Ordinary Kriging
34 |
35 | :ref:`sphx_glr_auto_examples_geostat_plot_ordinary_kriging.py`
36 |
37 | .. raw:: html
38 |
39 |
40 |
41 |
42 | .. toctree::
43 | :hidden:
44 |
45 | /auto_examples/geostat/plot_ordinary_kriging
46 |
47 | .. raw:: html
48 |
49 |
50 |
51 | .. only:: html
52 |
53 | .. figure:: /auto_examples/geostat/images/thumb/sphx_glr_plot_variogram_thumb.png
54 | :alt: Estimate a Variogram
55 |
56 | :ref:`sphx_glr_auto_examples_geostat_plot_variogram.py`
57 |
58 | .. raw:: html
59 |
60 |
61 |
62 |
63 | .. toctree::
64 | :hidden:
65 |
66 | /auto_examples/geostat/plot_variogram
67 |
68 | .. raw:: html
69 |
70 |
71 |
72 | .. only:: html
73 |
74 | .. figure:: /auto_examples/geostat/images/thumb/sphx_glr_plot_gridsearch_thumb.png
75 | :alt: GridSearch optimization
76 |
77 | :ref:`sphx_glr_auto_examples_geostat_plot_gridsearch.py`
78 |
79 | .. raw:: html
80 |
81 |
82 |
83 |
84 | .. toctree::
85 | :hidden:
86 |
87 | /auto_examples/geostat/plot_gridsearch
88 | .. raw:: html
89 |
90 |
91 |
92 |
93 |
94 | .. only :: html
95 |
96 | .. container:: sphx-glr-footer
97 | :class: sphx-glr-footer-gallery
98 |
99 |
100 | .. container:: sphx-glr-download sphx-glr-download-python
101 |
102 | :download:`Download all examples in Python source code: auto_examples_python.zip `
103 |
104 |
105 |
106 | .. container:: sphx-glr-download sphx-glr-download-jupyter
107 |
108 | :download:`Download all examples in Jupyter notebooks: auto_examples_jupyter.zip `
109 |
110 |
111 | .. only:: html
112 |
113 | .. rst-class:: sphx-glr-signature
114 |
115 | `Gallery generated by Sphinx-Gallery `_
116 |
--------------------------------------------------------------------------------
/examples/geostat/plot_variogram.py:
--------------------------------------------------------------------------------
1 | """
2 | Estimate a Variogram
3 | ====================
4 |
5 | Use the geostatistics toolbox to estimate a variogram and use one of the many
6 | plots. These plots help to understand the spatial properties of a variogram,
7 | and finally, the :class:`Variogram ` object itself can be
8 | returned and used in one of the Kriging routines.
9 |
10 | """
11 | from pprint import pprint
12 | import plotly
13 | import hydrobox
14 | from hydrobox.data import pancake
15 | from hydrobox.plotting import plotting_backend
16 | plotting_backend('plotly')
17 |
18 | # %%
19 | # Load sample data from the data sub-module
20 |
21 | df = pancake()
22 |
23 | # %%
24 | # Estimate a variogram using a exponential model and 25 distance lags
25 | # that are derived from a KMeans cluster algorithm
26 | # Here, we use the describe output option to get a dictionary of
27 | # all variogram parameters
28 |
29 | vario = hydrobox.geostat.variogram(
30 | coordinates=df[['x', 'y']].values,
31 | values=df.z.values,
32 | model='exponential',
33 | bin_func='kmeans',
34 | n_lags=25,
35 | return_type='describe'
36 | )
37 | # print
38 | pprint(vario)
39 |
40 | #%%
41 | # There are various return types, one of them is the plot.
42 | # This is the main plotting tool for variogram instances
43 | fig = hydrobox.geostat.variogram(
44 | coordinates=df[['x', 'y']].values,
45 | values=df.z.values,
46 | model='exponential',
47 | bin_func='kmeans',
48 | n_lags=25,
49 | return_type='plot'
50 | )
51 |
52 | # show the figure
53 | plotly.io.show(fig)
54 |
55 | #%%
56 | # Alternatively you can return the :class:`Variogram `
57 | # object itself and use all the different settings and methods directly.
58 |
59 | v = hydrobox.geostat.variogram(
60 | coordinates=df[['x', 'y']].values,
61 | values=df.z.values,
62 | model='exponential',
63 | bin_func='kmeans',
64 | n_lags=25,
65 | return_type='object'
66 | )
67 |
68 | pprint(v)
69 |
70 | #%%
71 | # The :class:`Variogram ` has a plotting method for
72 | # all point pairs at their separating distances. It is available as a
73 | # return type, but can also be called directly:
74 | fig = v.distance_difference_plot()
75 |
76 | plotly.io.show(fig)
77 |
78 | #%%
79 | # The variogram instance has a lot of quality measures to judge the goodness
80 | # of fit for the theoretical model. They are implemented as properties and can
81 | # be used like attribtues, while being always up to date if the variogram is mutated.
82 | # Another helpful method is :func:`cross_validate `.
83 | # This will run a leave-one-out cross validation by interpolating the missing point for
84 | # all points. This is especially useful in cases, where a theoretical model fits well,
85 | # but the spatial properties are not well captured.
86 |
87 | # calculate the rmse of the model
88 | print(f"{v.model.__name__} RMSE: {v.rmse}")
89 |
90 | # get the cross-validation time
91 | from time import time
92 | t1 = time()
93 | rmse = v.cross_validate()
94 | t2 = time()
95 | print('Cross-validated RMSE: %.2f (took: %2fs)' % (rmse, t2 - t1))
96 |
--------------------------------------------------------------------------------
/hydrobox/stats/rolling.py:
--------------------------------------------------------------------------------
1 | """Rolling statistics
2 |
3 | Helper functions to apply rolling statistics to input data.
4 |
5 | """
6 | import pandas as pd
7 | import numpy as np
8 |
9 |
10 | def moving_window(x, window_size=5, window_type=None, func='nanmean'):
11 | r"""Moving window statistics
12 |
13 | Applies a moving window function to the input data. Each of the grouped
14 | windows will be aggregated into a resulting time series.
15 |
16 | Parameters
17 | ----------
18 | x : ``pandas.Series``, ``pandas.DataFrame``
19 | Input data. The data should have a ``pandas.DatetimeIndex`` in order
20 | to produce meaningful results. However, this is not needed and will
21 | technically work on different indexed data.
22 | window_size : int
23 | The specified number of values will be grouped into a window. This
24 | parameter might have different behavior in case the window_type is
25 | not `None`.
26 | window_type : str, default=None
27 | If `None`, an even spaced window will be used and shifted by one for
28 | each group. Else, a window constructing class can be specified.
29 | Possible constructors are specified in ``pandas.DataFrame.rolling``.
30 | func : str
31 | Aggregating function for calculating the new window value. It has to
32 | be importable from ``numpy``, accept various input values and return
33 | only a single value like ``numpy.std`` or ``numpy.median``.
34 |
35 | Returns
36 | -------
37 | pandas.Series
38 | pandas.DataFrame
39 |
40 | Notes
41 | -----
42 |
43 | Be aware that most window types (if window_type is not None) do only
44 | work with either ``numpy.sum`` or ``numpy.mean``.
45 |
46 | Furthermore, most windows cannot work with the 'nan' versions of
47 | numpy aggregating function. Therefore in case window_type is None, any
48 | 'nan' will be removed from the func string. In case you want to force this
49 | behaviour, wrap the numpy function into a ``lambda``.
50 |
51 | Examples
52 | --------
53 | This way, you can prevent the replacement of a np.nan* function:
54 |
55 | >>> moving_window(x, func=lambda x: np.nanmean(x))
56 | array([NaN, NaN, NaN, 4.7445, 4.784 ... 6.34532])
57 |
58 | """
59 | # remove NaNs from the function name if a window_type was set
60 | if window_type is not None and isinstance(func, str):
61 | func = func.replace('nan', '')
62 |
63 | # get the function or load it from numpy
64 | if callable(func):
65 | f = func
66 | else:
67 | try:
68 | f = getattr(np, func)
69 | except AttributeError:
70 | raise ValueError(
71 | 'The function %s cannot be imported from numpy.' % func)
72 |
73 | # apply and return
74 | try:
75 | return x.rolling(window=window_size, win_type=window_type).aggregate(f)
76 | except AttributeError as e:
77 | raise AttributeError('This did not work. Maybe the func %s is not \
78 | allowed for this window type?\n original Error: \
79 | %s.' % (func, str(e)))
80 |
--------------------------------------------------------------------------------
/doc/auto_examples/geostat/plot_variogram.py:
--------------------------------------------------------------------------------
1 | """
2 | Estimate a Variogram
3 | ====================
4 |
5 | Use the geostatistics toolbox to estimate a variogram and use one of the many
6 | plots. These plots help to understand the spatial properties of a variogram,
7 | and finally, the :class:`Variogram ` object itself can be
8 | returned and used in one of the Kriging routines.
9 |
10 | """
11 | from pprint import pprint
12 | import plotly
13 | import hydrobox
14 | from hydrobox.data import pancake
15 | from hydrobox.plotting import plotting_backend
16 | plotting_backend('plotly')
17 |
18 | # %%
19 | # Load sample data from the data sub-module
20 |
21 | df = pancake()
22 |
23 | # %%
24 | # Estimate a variogram using a exponential model and 25 distance lags
25 | # that are derived from a KMeans cluster algorithm
26 | # Here, we use the describe output option to get a dictionary of
27 | # all variogram parameters
28 |
29 | vario = hydrobox.geostat.variogram(
30 | coordinates=df[['x', 'y']].values,
31 | values=df.z.values,
32 | model='exponential',
33 | bin_func='kmeans',
34 | n_lags=25,
35 | return_type='describe'
36 | )
37 | # print
38 | pprint(vario)
39 |
40 | #%%
41 | # There are various return types, one of them is the plot.
42 | # This is the main plotting tool for variogram instances
43 | fig = hydrobox.geostat.variogram(
44 | coordinates=df[['x', 'y']].values,
45 | values=df.z.values,
46 | model='exponential',
47 | bin_func='kmeans',
48 | n_lags=25,
49 | return_type='plot'
50 | )
51 |
52 | # show the figure
53 | plotly.io.show(fig)
54 |
55 | #%%
56 | # Alternatively you can return the :class:`Variogram `
57 | # object itself and use all the different settings and methods directly.
58 |
59 | v = hydrobox.geostat.variogram(
60 | coordinates=df[['x', 'y']].values,
61 | values=df.z.values,
62 | model='exponential',
63 | bin_func='kmeans',
64 | n_lags=25,
65 | return_type='object'
66 | )
67 |
68 | pprint(v)
69 |
70 | #%%
71 | # The :class:`Variogram ` has a plotting method for
72 | # all point pairs at their separating distances. It is available as a
73 | # return type, but can also be called directly:
74 | fig = v.distance_difference_plot()
75 |
76 | plotly.io.show(fig)
77 |
78 | #%%
79 | # The variogram instance has a lot of quality measures to judge the goodness
80 | # of fit for the theoretical model. They are implemented as properties and can
81 | # be used like attribtues, while being always up to date if the variogram is mutated.
82 | # Another helpful method is :func:`cross_validate `.
83 | # This will run a leave-one-out cross validation by interpolating the missing point for
84 | # all points. This is especially useful in cases, where a theoretical model fits well,
85 | # but the spatial properties are not well captured.
86 |
87 | # calculate the rmse of the model
88 | print(f"{v.model.__name__} RMSE: {v.rmse}")
89 |
90 | # get the cross-validation time
91 | from time import time
92 | t1 = time()
93 | rmse = v.cross_validate()
94 | t2 = time()
95 | print('Cross-validated RMSE: %.2f (took: %2fs)' % (rmse, t2 - t1))
96 |
--------------------------------------------------------------------------------
/doc/conf.py:
--------------------------------------------------------------------------------
1 | # Configuration file for the Sphinx documentation builder.
2 | #
3 | # This file only contains a selection of the most common options. For a full
4 | # list see the documentation:
5 | # https://www.sphinx-doc.org/en/master/usage/configuration.html
6 |
7 | # -- Path setup --------------------------------------------------------------
8 |
9 | # If extensions (or modules to document with autodoc) are in another directory,
10 | # add these directories to sys.path here. If the directory is relative to the
11 | # documentation root, use os.path.abspath to make it absolute, like shown here.
12 | #
13 | import os
14 | import sys
15 | sys.path.insert(0, os.path.abspath('.'))
16 |
17 |
18 | # -- Project information -----------------------------------------------------
19 |
20 | project = 'HydroBox'
21 | copyright = '2021, Mirko Mälicke'
22 | author = 'Mirko Mälicke'
23 |
24 | # The full version, including alpha/beta/rc tags
25 | release = '0.2.0'
26 |
27 |
28 | # -- General configuration ---------------------------------------------------
29 |
30 | # Add any Sphinx extension module names here, as strings. They can be
31 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
32 | # ones.
33 | extensions = [
34 | 'sphinx.ext.napoleon',
35 | 'sphinx.ext.autodoc',
36 | 'sphinx_autodoc_typehints',
37 | 'sphinx.ext.autosummary',
38 | 'sphinx.ext.intersphinx',
39 | 'sphinx_gallery.gen_gallery',
40 | 'sphinx.ext.todo'
41 | ]
42 |
43 | # Add any paths that contain templates here, relative to this directory.
44 | templates_path = ['_templates']
45 |
46 | # List of patterns, relative to source directory, that match files and
47 | # directories to ignore when looking for source files.
48 | # This pattern also affects html_static_path and html_extra_path.
49 | exclude_patterns = []
50 |
51 |
52 | # -- Options for HTML output -------------------------------------------------
53 |
54 | # The theme to use for HTML and HTML Help pages. See the documentation for
55 | # a list of builtin themes.
56 | #
57 | html_theme = 'pydata_sphinx_theme'
58 |
59 | html_theme_options = {
60 | 'github_url': 'https://github.com/vforwater/hydrobox',
61 | }
62 |
63 | # Add any paths that contain custom static files (such as style sheets) here,
64 | # relative to this directory. They are copied after the builtin static files,
65 | # so a file named "default.css" will overwrite the builtin "default.css".
66 | html_static_path = ['_static']
67 |
68 | # intesphinx
69 | intersphinx_mapping = {
70 | 'python': ('https://docs.python.org/3', None),
71 | 'sklearn': ('http://scikit-learn.org/stable', None),
72 | 'numpy': ('http://docs.scipy.org/doc/numpy', None),
73 | 'skgstat': ('https://mmaelicke.github.io/scikit-gstat', None),
74 | 'gstools': ('https://geostat-framework.readthedocs.io/projects/gstools/en/latest', None)
75 | }
76 |
77 | from plotly.io._sg_scraper import plotly_sg_scraper
78 | image_scrapers = ('matplotlib', plotly_sg_scraper,)
79 |
80 | import sphinx_gallery
81 |
82 | # Sphinx Gallery config
83 | sphinx_gallery_conf = {
84 | 'examples_dirs': '../examples',
85 | 'gallery_dirs': 'auto_examples',
86 | 'backreferences_dir': 'gen_modules/backreferences',
87 | 'doc_module': ('hydrobox',),
88 | 'image_scrapers': image_scrapers,
89 | }
90 |
91 | autosummary_generate = True
92 |
--------------------------------------------------------------------------------
/hydrobox/plotting/regime.py:
--------------------------------------------------------------------------------
1 | """
2 | """
3 | import numpy as np
4 | import colorcet as cc
5 | try:
6 | import matplotlib.pyplot as plt
7 | except ModuleNotFoundError:
8 | # TODO here a global var can indicate that importing failed
9 | pass
10 | try:
11 | from bokeh.plotting import figure, Figure
12 | except ModuleNotFoundError:
13 | # TODO here a global var can indicate that importing failed
14 | pass
15 |
16 | MONTHS = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
17 |
18 |
19 | def _plot_matplotlib(func_args, plot_args):
20 | # get the df with data
21 | df = func_args['df']
22 |
23 | # load the correct cmap
24 | cm = getattr(cc.cm, func_args['cmap'])
25 |
26 | # handle matplotlib figure
27 | ax = func_args.get('figure')
28 | if ax is None:
29 | fig, ax = plt.subplots(1, 1)
30 | else:
31 | fig = ax.get_figure()
32 |
33 | # set plot defaults
34 | plot_args.setdefault('lw', 3)
35 | plot_args.setdefault('linestyle', '-')
36 |
37 |
38 | # check if there are quantiles
39 | if len(df.columns) > 1:
40 | # build the colormap
41 | n = int((len(df.columns) - 1) / 2)
42 | cmap = [cm(1. * _ / n) for _ in range(n)]
43 | cmap = np.concatenate((cmap, cmap[::-1]))
44 |
45 | # plot
46 | for i in range(len(df.columns) - 2, 1, -1):
47 | ax.fill_between(df.index, df.iloc[:, i], df.iloc[:, i - 1],
48 | interpolate=True, color=cmap[i - 1])
49 |
50 | # plot the main aggregate
51 | if 'color' not in plot_args.keys():
52 | plot_args['color'] = cm(0.0)
53 | ax.plot(df.index, df.iloc[:, 0], **plot_args)
54 | ax.set_xlim(0, 12)
55 | plt.xticks(df.index, MONTHS, rotation=45)
56 |
57 | return fig
58 |
59 |
60 | def _plot_bokeh(func_args, plot_args):
61 | # get the df with data
62 | df = func_args['df']
63 |
64 | # load the correct cmap
65 | cm = getattr(cc, func_args['cmap'])
66 |
67 | # get figure
68 | fig = func_args.get('figure')
69 |
70 | if fig is None:
71 | # some of the plot_args should go into figure
72 | args = dict()
73 |
74 | for k,v in plot_args.items():
75 | if hasattr(Figure, k):
76 | args[k] = v
77 | del plot_args[k]
78 |
79 | # set some defaults
80 | args.setdefault('title', 'Hydrological Regime')
81 |
82 | fig = figure(**args)
83 |
84 | # plot the percentiles at first
85 | if len(df.columns) > 1:
86 | n = int((len(df.columns) - 1) / 2)
87 | cmap = [cm[_] for _ in range(0, len(cm), int(len(cm) / n))]
88 | cmap = np.concatenate((cmap, cmap[::-1]))
89 |
90 | # plot
91 | for i in range(len(df.columns) - 2, 1, -1):
92 | fig.varea(
93 | x=df.index, y1=df.iloc[:, i], y2=df.iloc[:, i - 1],
94 | fill_color=cmap[i-1], fill_alpha=0.9
95 | )
96 |
97 | # plot the main regime
98 | if 'color' not in plot_args.keys():
99 | plot_args['color'] = cm[n]
100 |
101 | fig.line(df.index, df.iloc[:,0], **plot_args)
102 |
103 | # set the axis labels
104 | fig.xaxis.major_label_orientation = 45
105 | fig.xaxis.major_label_overrides = {i:m for i,m in enumerate(MONTHS)}
106 |
107 | return fig
--------------------------------------------------------------------------------
/examples/geostat/plot_gridsearch.py:
--------------------------------------------------------------------------------
1 | """
2 | GridSearch optimization
3 | =======================
4 |
5 | The SciKit-GStat package can be connected to scikit-learn i.e. to use
6 | the model optimization sub-package. In this example, different options
7 | are compared and cross-validated.
8 | The Interface has two different options to evaluate a variogram model fit:
9 |
10 | * goodness of fit measures of the spatial model itself
11 | * cross-validation of the variogram by interpolating the observation points
12 |
13 | Both options can use the RMSE, MSE and MAE as a metric.
14 |
15 | """
16 | import plotly
17 | import plotly.graph_objects as go
18 | import hydrobox
19 | from hydrobox.data import pancake
20 | from hydrobox.plotting import plotting_backend
21 | plotting_backend('plotly')
22 |
23 | #%%
24 | # Load sample data from the data sub-module
25 |
26 | df = pancake()
27 |
28 | #%%
29 | # First, a Variogram is estimated, which will fix all arguments that
30 | # should not be evaluated by the Grid Search.
31 |
32 | vario = hydrobox.geostat.variogram(
33 | coordinates=df[['x', 'y']].values,
34 | values=df.z.values,
35 | maxlag=500,
36 | bin_func='kmeans',
37 | return_type='object'
38 | )
39 |
40 | #%%
41 | # The next step is to create a parameter grid, which specifies the
42 | # value space for each parameter that should be checked.
43 | # Here, we will try all combinations of different models and lag classes.
44 |
45 | param_grid = {
46 | 'model': ('spherical', 'exponential', 'matern'),
47 | 'n_lags': (15, 20, 25, 30, 35)
48 | }
49 |
50 | #%%
51 | # First the model fit itself is evaluated and only the best parameter
52 | # set will be returned
53 |
54 | best_param = hydrobox.geostat.gridsearch(
55 | param_grid=param_grid,
56 | variogram=vario,
57 | coordinates=None, # must be set if variogram is None
58 | values=None, # must be set if variogram is None
59 | score='rmse', # default
60 | cross_validate=False, # evaluate model fit,
61 | n_jobs=-1, # use parallel mode
62 | return_type='best_param'
63 | )
64 |
65 | print(best_param)
66 |
67 | #%%
68 | # It is also possible to return the underlying
69 | # :class:`GridSearchCV ` instance.
70 | # This class holds way more information than just the best parameter.
71 |
72 | # reun the same Gridsearch, return the object
73 | clf = hydrobox.geostat.gridsearch(
74 | param_grid=param_grid,
75 | variogram=vario,
76 | coordinates=None, # must be set if variogram is None
77 | values=None, # must be set if variogram is None
78 | score='rmse', # default
79 | cross_validate=False, # evaluate model fit,
80 | n_jobs=-1, # use parallel mode
81 | return_type='object'
82 | )
83 |
84 | # get the scores and their std
85 | scores = clf.cv_results_['mean_test_score']
86 | scores_std = clf.cv_results_['std_test_score']
87 | x = list(range(len(scores)))
88 |
89 | #%%
90 | # Plot the result
91 | fig = go.Figure()
92 | fig.add_trace(
93 | go.Scatter(x=x, y=scores, mode='lines', line_color='#A3ACF7', name='RMSE score')
94 | )
95 | fig.add_trace(
96 | go.Scatter(x=x, y=scores + scores_std, mode='lines', line_color='#BAC1F2', fill='tonexty', name='RMSE + std')
97 | )
98 | fig.add_trace(
99 | go.Scatter(x=x, y=scores - scores_std, mode='lines', line_color='#BAC1F2', fill='tonexty', name='RMSE - std')
100 | )
101 | fig.update_layout(
102 | template='plotly_white'
103 | )
104 |
105 | # show the plot
106 | plotly.io.show(fig)
--------------------------------------------------------------------------------
/doc/auto_examples/geostat/plot_gridsearch.py:
--------------------------------------------------------------------------------
1 | """
2 | GridSearch optimization
3 | =======================
4 |
5 | The SciKit-GStat package can be connected to scikit-learn i.e. to use
6 | the model optimization sub-package. In this example, different options
7 | are compared and cross-validated.
8 | The Interface has two different options to evaluate a variogram model fit:
9 |
10 | * goodness of fit measures of the spatial model itself
11 | * cross-validation of the variogram by interpolating the observation points
12 |
13 | Both options can use the RMSE, MSE and MAE as a metric.
14 |
15 | """
16 | import plotly
17 | import plotly.graph_objects as go
18 | import hydrobox
19 | from hydrobox.data import pancake
20 | from hydrobox.plotting import plotting_backend
21 | plotting_backend('plotly')
22 |
23 | #%%
24 | # Load sample data from the data sub-module
25 |
26 | df = pancake()
27 |
28 | #%%
29 | # First, a Variogram is estimated, which will fix all arguments that
30 | # should not be evaluated by the Grid Search.
31 |
32 | vario = hydrobox.geostat.variogram(
33 | coordinates=df[['x', 'y']].values,
34 | values=df.z.values,
35 | maxlag=500,
36 | bin_func='kmeans',
37 | return_type='object'
38 | )
39 |
40 | #%%
41 | # The next step is to create a parameter grid, which specifies the
42 | # value space for each parameter that should be checked.
43 | # Here, we will try all combinations of different models and lag classes.
44 |
45 | param_grid = {
46 | 'model': ('spherical', 'exponential', 'matern'),
47 | 'n_lags': (15, 20, 25, 30, 35)
48 | }
49 |
50 | #%%
51 | # First the model fit itself is evaluated and only the best parameter
52 | # set will be returned
53 |
54 | best_param = hydrobox.geostat.gridsearch(
55 | param_grid=param_grid,
56 | variogram=vario,
57 | coordinates=None, # must be set if variogram is None
58 | values=None, # must be set if variogram is None
59 | score='rmse', # default
60 | cross_validate=False, # evaluate model fit,
61 | n_jobs=-1, # use parallel mode
62 | return_type='best_param'
63 | )
64 |
65 | print(best_param)
66 |
67 | #%%
68 | # It is also possible to return the underlying
69 | # :class:`GridSearchCV ` instance.
70 | # This class holds way more information than just the best parameter.
71 |
72 | # reun the same Gridsearch, return the object
73 | clf = hydrobox.geostat.gridsearch(
74 | param_grid=param_grid,
75 | variogram=vario,
76 | coordinates=None, # must be set if variogram is None
77 | values=None, # must be set if variogram is None
78 | score='rmse', # default
79 | cross_validate=False, # evaluate model fit,
80 | n_jobs=-1, # use parallel mode
81 | return_type='object'
82 | )
83 |
84 | # get the scores and their std
85 | scores = clf.cv_results_['mean_test_score']
86 | scores_std = clf.cv_results_['std_test_score']
87 | x = list(range(len(scores)))
88 |
89 | #%%
90 | # Plot the result
91 | fig = go.Figure()
92 | fig.add_trace(
93 | go.Scatter(x=x, y=scores, mode='lines', line_color='#A3ACF7', name='RMSE score')
94 | )
95 | fig.add_trace(
96 | go.Scatter(x=x, y=scores + scores_std, mode='lines', line_color='#BAC1F2', fill='tonexty', name='RMSE + std')
97 | )
98 | fig.add_trace(
99 | go.Scatter(x=x, y=scores - scores_std, mode='lines', line_color='#BAC1F2', fill='tonexty', name='RMSE - std')
100 | )
101 | fig.update_layout(
102 | template='plotly_white'
103 | )
104 |
105 | # show the plot
106 | plotly.io.show(fig)
--------------------------------------------------------------------------------
/doc/auto_examples/geostat/plot_ordinary_kriging.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "code",
5 | "execution_count": null,
6 | "metadata": {
7 | "collapsed": false
8 | },
9 | "outputs": [],
10 | "source": [
11 | "%matplotlib inline"
12 | ]
13 | },
14 | {
15 | "cell_type": "markdown",
16 | "metadata": {},
17 | "source": [
18 | "\n# Ordinary Kriging\n\nWith the help of a variogram that describes spatial properties of \na sample, the sample can be interpolated. \n"
19 | ]
20 | },
21 | {
22 | "cell_type": "code",
23 | "execution_count": null,
24 | "metadata": {
25 | "collapsed": false
26 | },
27 | "outputs": [],
28 | "source": [
29 | "from time import time\nimport plotly\nimport hydrobox\nfrom hydrobox.data import pancake\nfrom hydrobox.plotting import plotting_backend\nplotting_backend('plotly')"
30 | ]
31 | },
32 | {
33 | "cell_type": "markdown",
34 | "metadata": {},
35 | "source": [
36 | "Load sample data from the data sub-module\n\n"
37 | ]
38 | },
39 | {
40 | "cell_type": "code",
41 | "execution_count": null,
42 | "metadata": {
43 | "collapsed": false
44 | },
45 | "outputs": [],
46 | "source": [
47 | "df = pancake()"
48 | ]
49 | },
50 | {
51 | "cell_type": "markdown",
52 | "metadata": {},
53 | "source": [
54 | "Estimate a exponential variogram again. More details are given in the \n`sphx_glr_auto_examples_geostat_plot_variogram.py` example.\n\n"
55 | ]
56 | },
57 | {
58 | "cell_type": "code",
59 | "execution_count": null,
60 | "metadata": {
61 | "collapsed": false
62 | },
63 | "outputs": [],
64 | "source": [
65 | "vario = hydrobox.geostat.variogram(\n coordinates=df[['x', 'y']].values,\n values=df.z.values,\n model='exponential',\n bin_func='kmeans',\n n_lags=25,\n return_type='object'\n)"
66 | ]
67 | },
68 | {
69 | "cell_type": "markdown",
70 | "metadata": {},
71 | "source": [
72 | "Run ordinary kriging on a 100x100 grid. In this run, the result is \ndirectly plotted. Other return types are ``'grid'``, to return the \nresulting interpolated grid and kriging error grid, or ``'object'``\nto return the :class:`Krige ` class. This class \nis already parameterized, but the interpolation was not yet performed.\nThis is most helpful if other grid should be constructed.\n\n"
73 | ]
74 | },
75 | {
76 | "cell_type": "code",
77 | "execution_count": null,
78 | "metadata": {
79 | "collapsed": false
80 | },
81 | "outputs": [],
82 | "source": [
83 | "t1 = time()\nfig = hydrobox.geostat.ordinary_kriging(\n variogram=vario,\n grid_resolution=100,\n exact=True,\n cond_err='nugget',\n return_type='plot'\n)\nt2 = time()\n\nprint('Took: %2f sec' % (t2 - t1))\n\n# show the plot\nplotly.io.show(fig)"
84 | ]
85 | }
86 | ],
87 | "metadata": {
88 | "kernelspec": {
89 | "display_name": "Python 3",
90 | "language": "python",
91 | "name": "python3"
92 | },
93 | "language_info": {
94 | "codemirror_mode": {
95 | "name": "ipython",
96 | "version": 3
97 | },
98 | "file_extension": ".py",
99 | "mimetype": "text/x-python",
100 | "name": "python",
101 | "nbconvert_exporter": "python",
102 | "pygments_lexer": "ipython3",
103 | "version": "3.8.5"
104 | }
105 | },
106 | "nbformat": 4,
107 | "nbformat_minor": 0
108 | }
--------------------------------------------------------------------------------
/hydrobox/geostat/gridsearch.py:
--------------------------------------------------------------------------------
1 | from typing import Dict, List, Tuple, Any, Literal
2 | import skgstat as skg
3 | from sklearn.model_selection import GridSearchCV
4 | import numpy as np
5 |
6 |
7 | def gridsearch(
8 | param_grid: Dict[str, Tuple],
9 | variogram: skg.Variogram = None,
10 | coordinates: np.ndarray = None,
11 | values: np.ndarray = None,
12 | score: Literal['rmse', 'mse', 'mae'] = 'rmse',
13 | cross_validate: bool = True,
14 | n_jobs=-1,
15 | return_type: Literal['object', 'best_param'] = 'object',
16 | **kwargs
17 | ) -> Dict[str, Any]:
18 | """
19 | Automated GridSerarch for best variogram parameters.
20 | Uses :class:`GridSearchCV ` to
21 | find the best parameter set.
22 |
23 | .. todo::
24 | with scikit-gstat 0.6, remove the cross_validate check.
25 |
26 | Parameters
27 | ----------
28 | param_grid : dict
29 | List of parameters that should be used to form the grid.
30 | Each key has to be a valid argument to :class:`Variogram `
31 | along with a list of valid options to try.
32 | variogram : skgstat.Variogram
33 | Variogram instance that should be used to find more suitable
34 | parameters. If given, coordinates, values and kwargs will be
35 | ignored
36 | coordinates : numpy.ndarray
37 | Array of coordinates. Mandatory if variogram is None.
38 | values : numpy.ndarray
39 | Array of values. Mandatory if variogram is None.
40 | score : str
41 | Score to find the best parameter set. Has to be one of
42 | ['rmse', 'mse', 'mae']
43 | cross_validate : bool
44 | If True (default) the score will be applied to a leave-one-out
45 | cross-validation of a Kriging using the current Variogram.
46 | If False, the model fit to the experimental variogra, will be scored.
47 | .. note::
48 | Needs at least `scikit-gstat>=0.5.4`.
49 | n_jobs : int
50 | Will be passed down to :class:`GridSearchCV `
51 | return_type : str
52 | Either `'object'`, to return the GridSerachCV object or
53 | `'best_param'` to return a dictionary of the best params.
54 |
55 |
56 | Returns
57 | -------
58 | gridSearch : sklearn.model_selection.GridSearchCV
59 | if return type is `'object'`
60 | best_params : dict
61 | if return type is `'best_param'`
62 |
63 | Raises
64 | ------
65 | AttributeError :
66 | if neither a :class:`Variogram ` or both
67 | coordinates and values are given
68 |
69 | See Also
70 | --------
71 | skgstat.interface.VariogramEstimator
72 | sklearn.model_selection.GridSearchCV
73 |
74 | """
75 | if variogram is None and (coordinates is None or values is None):
76 | raise AttributeError('Either a Variogram or the coorinates, values and kwargs needs to be set')
77 |
78 | # extract the parameters
79 | if variogram is not None:
80 | coordinates = variogram.coordinates
81 | values = variogram.values
82 | kwargs.update(variogram.describe().get('params'))
83 |
84 | # handle cross-validate
85 | _, skg_m, skg_p = skg.__version__.split('.')
86 | if int(skg_m) > 5 or int(skg_p) >= 4: # pragma: no cover
87 | kwargs['cross_validate'] = cross_validate
88 |
89 | # initialize the estimator
90 | estimator = skg.interfaces.VariogramEstimator(
91 | use_score=score,
92 | **kwargs
93 | )
94 |
95 | # inistialize the GridSearch
96 | gs = GridSearchCV(estimator, param_grid, cv=5, n_jobs=n_jobs)
97 |
98 | # run
99 | gs_fit = gs.fit(coordinates, values)
100 |
101 | if return_type.lower() == 'object':
102 | return gs_fit
103 | elif return_type.lower() == 'best_param':
104 | return gs_fit.best_params_
105 |
106 |
--------------------------------------------------------------------------------
/hydrobox/preprocessing/scale.py:
--------------------------------------------------------------------------------
1 | """
2 | The scale module combines low-level aggregation functionality for time series
3 | data. The single functions operate on single time series instances.
4 | All functions aiming on aggregating multi-dimensional data or multiple time
5 | series are have a preceding 'm' in their function name.
6 | """
7 | from datetime import datetime
8 |
9 | import numpy as np
10 | import pandas as pd
11 |
12 |
13 | def aggregate(x, by, func='mean'):
14 | """Time series aggregation
15 |
16 | This function version will only operate on a single ``pandas.Series`` or
17 | ``pandas.DataFrame`` instance. It has to be indexed by a
18 | `pandas.DatetimeIndex`. The input data will be aggregated to the given
19 | frequency by passing a `pandas.Grouper` conform string argument
20 | specifying the desired period like: '1M' for one month or '3Y-Sep' for
21 | three years starting at the first of October.
22 |
23 |
24 | Parameters
25 | ----------
26 | x: ``pandas.Series``, ``pandas.DataFrame``
27 | The input data, will be aggregated over the index.
28 | by : string
29 | Specifies the desired temporal resolution. Will be passed as
30 | ``freq`` argument of a ``pandas.Grouper`` object for grouping the
31 | data into the new resolution.
32 | If by is ``None``, the whole Series will be aggregated to only one
33 | value. The same applies to ``by='all'``.
34 | func : string
35 | Function identifier used for aggregation. Has to be importable from
36 | ``numpy``. The function must accept n input values and aggregate them
37 | to only a single one.
38 |
39 | Returns
40 | -------
41 | pandas.Series :
42 | if x was of type ``pandas.Series``
43 | pandas.DataFrame :
44 | if c was of type ``pandas.DataFrame``
45 |
46 | """
47 | # check for being a time series
48 | if not isinstance(x.index, pd.DatetimeIndex) \
49 | and not (by is None or by == 'all'):
50 | raise ValueError('The data has to be indexed by a DatetimeIndex.')
51 |
52 | if by is not None and by == 'all':
53 | by = None
54 |
55 | # get the function
56 | if callable(func):
57 | f = func
58 | else:
59 | try:
60 | f = getattr(np, func)
61 | except AttributeError:
62 | raise ValueError('The function %s cannot be imported. the \
63 | aggregation function has to be importable \
64 | from numpy.' % func)
65 |
66 | if by is None:
67 | return x.aggregate(f)
68 | else:
69 | return x.groupby(pd.Grouper(freq=by)).aggregate(f)
70 |
71 |
72 | def cut_period(x, start, stop):
73 | """Truncate Time series
74 |
75 | Truncates a ``pandas.Series`` or ``pandas.DataFrame`` to the given
76 | period. The start and stop parameter need to be either a string or a
77 | ``datetime.datetime``, which will then be converted. Returns the
78 | truncated time series.
79 |
80 | Parameters
81 | ----------
82 | x : ``pandas.Series``, ``pandas.DataFrame``
83 | The input data, will be truncated
84 | start : string, datetime
85 | Begin of truncation. Can be a ``datetime.datetime`` or a string.
86 | If a string is passed, it has to use the format 'YYYYMMDDhhmmss',
87 | where the time component 'hhmmss' can be omitted.
88 | stop : string, datetime,
89 | End of truncation. Can be a ``datetime.datetime`` or a string.
90 | If a string is passed, it has to use the format 'YYYYMMDDhhmmss',
91 | where the time component 'hhmmss' can be omitted.
92 |
93 | """
94 | # check for being a time series
95 | if not isinstance(x.index, pd.DatetimeIndex):
96 | raise ValueError('The data has to be indexed by a DatetimeIndex.')
97 |
98 | if isinstance(start, datetime):
99 | start = start.strftime('%Y%m%d%H%M%S')
100 | if isinstance(stop, datetime):
101 | stop = stop.strftime('%Y%m%d%H%M%S')
102 |
103 | return x[start:stop].copy()
104 |
--------------------------------------------------------------------------------
/doc/auto_examples/geostat/plot_ordinary_kriging.rst:
--------------------------------------------------------------------------------
1 |
2 | .. DO NOT EDIT.
3 | .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY.
4 | .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE:
5 | .. "auto_examples/geostat/plot_ordinary_kriging.py"
6 | .. LINE NUMBERS ARE GIVEN BELOW.
7 |
8 | .. only:: html
9 |
10 | .. note::
11 | :class: sphx-glr-download-link-note
12 |
13 | Click :ref:`here `
14 | to download the full example code
15 |
16 | .. rst-class:: sphx-glr-example-title
17 |
18 | .. _sphx_glr_auto_examples_geostat_plot_ordinary_kriging.py:
19 |
20 |
21 | Ordinary Kriging
22 | ================
23 |
24 | With the help of a variogram that describes spatial properties of
25 | a sample, the sample can be interpolated.
26 |
27 | .. GENERATED FROM PYTHON SOURCE LINES 9-16
28 |
29 | .. code-block:: default
30 |
31 | from time import time
32 | import plotly
33 | import hydrobox
34 | from hydrobox.data import pancake
35 | from hydrobox.plotting import plotting_backend
36 | plotting_backend('plotly')
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 | .. GENERATED FROM PYTHON SOURCE LINES 17-18
46 |
47 | Load sample data from the data sub-module
48 |
49 | .. GENERATED FROM PYTHON SOURCE LINES 18-21
50 |
51 | .. code-block:: default
52 |
53 |
54 | df = pancake()
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 | .. GENERATED FROM PYTHON SOURCE LINES 22-24
64 |
65 | Estimate a exponential variogram again. More details are given in the
66 | :ref:`sphx_glr_auto_examples_geostat_plot_variogram.py` example.
67 |
68 | .. GENERATED FROM PYTHON SOURCE LINES 24-34
69 |
70 | .. code-block:: default
71 |
72 |
73 | vario = hydrobox.geostat.variogram(
74 | coordinates=df[['x', 'y']].values,
75 | values=df.z.values,
76 | model='exponential',
77 | bin_func='kmeans',
78 | n_lags=25,
79 | return_type='object'
80 | )
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 | .. GENERATED FROM PYTHON SOURCE LINES 35-41
90 |
91 | Run ordinary kriging on a 100x100 grid. In this run, the result is
92 | directly plotted. Other return types are ``'grid'``, to return the
93 | resulting interpolated grid and kriging error grid, or ``'object'``
94 | to return the :class:`Krige ` class. This class
95 | is already parameterized, but the interpolation was not yet performed.
96 | This is most helpful if other grid should be constructed.
97 |
98 | .. GENERATED FROM PYTHON SOURCE LINES 41-55
99 |
100 | .. code-block:: default
101 |
102 |
103 | t1 = time()
104 | fig = hydrobox.geostat.ordinary_kriging(
105 | variogram=vario,
106 | grid_resolution=100,
107 | exact=True,
108 | cond_err='nugget',
109 | return_type='plot'
110 | )
111 | t2 = time()
112 |
113 | print('Took: %2f sec' % (t2 - t1))
114 |
115 | # show the plot
116 | plotly.io.show(fig)
117 |
118 |
119 | .. raw:: html
120 | :file: images/sphx_glr_plot_ordinary_kriging_001.html
121 |
122 |
123 | .. rst-class:: sphx-glr-script-out
124 |
125 | Out:
126 |
127 | .. code-block:: none
128 |
129 | Took: 2.842178 sec
130 |
131 |
132 |
133 |
134 |
135 | .. rst-class:: sphx-glr-timing
136 |
137 | **Total running time of the script:** ( 0 minutes 6.564 seconds)
138 |
139 |
140 | .. _sphx_glr_download_auto_examples_geostat_plot_ordinary_kriging.py:
141 |
142 |
143 | .. only :: html
144 |
145 | .. container:: sphx-glr-footer
146 | :class: sphx-glr-footer-example
147 |
148 |
149 |
150 | .. container:: sphx-glr-download sphx-glr-download-python
151 |
152 | :download:`Download Python source code: plot_ordinary_kriging.py `
153 |
154 |
155 |
156 | .. container:: sphx-glr-download sphx-glr-download-jupyter
157 |
158 | :download:`Download Jupyter notebook: plot_ordinary_kriging.ipynb `
159 |
160 |
161 | .. only:: html
162 |
163 | .. rst-class:: sphx-glr-signature
164 |
165 | `Gallery generated by Sphinx-Gallery `_
166 |
--------------------------------------------------------------------------------
/hydrobox/data/sample_sr.csv:
--------------------------------------------------------------------------------
1 | x,y,z
2 | 94,20,-0.39444438053747594
3 | 82,37,-2.283663062708473
4 | 43,13,-0.5462130280740465
5 | 78,42,-3.681383697834789
6 | 50,28,0.5045382784070095
7 | 20,74,-1.5041741384342935
8 | 71,88,1.3503808134843678
9 | 7,9,-1.1638796197023304
10 | 24,69,-0.34051346127283
11 | 77,28,-1.1920728498239048
12 | 71,17,-1.2669163335465252
13 | 29,74,-0.7427182051736556
14 | 49,59,0.48750491266151463
15 | 100,12,-2.962001584534514
16 | 5,52,-1.9117585922891978
17 | 16,82,-0.8417505208808288
18 | 16,17,-1.4281827604814472
19 | 88,58,0.7782599543685997
20 | 52,49,0.1786421715317022
21 | 63,85,0.7522280061388416
22 | 26,13,-0.7991250342467555
23 | 19,36,0.6432892058776345
24 | 36,79,-1.5280696290326905
25 | 57,97,-0.8259657245833522
26 | 62,99,-0.06959396015894331
27 | 32,30,0.8022020533234546
28 | 39,59,-0.05292820972410184
29 | 29,90,-1.0204864471818211
30 | 99,32,-0.6091409530661445
31 | 44,6,0.22039696575581752
32 | 43,58,0.4599801140437183
33 | 85,39,-2.31679305625176
34 | 70,54,0.5223039952706272
35 | 91,79,-0.3759977848107796
36 | 72,73,0.7416405213029846
37 | 26,14,-0.7804675204942965
38 | 74,27,-1.0553595338690305
39 | 95,81,-0.7486241434516918
40 | 57,64,1.7616136632222261
41 | 91,89,0.04677627985012556
42 | 16,15,-1.7478697007635944
43 | 43,64,0.16499520258020345
44 | 51,23,0.7437586449805585
45 | 48,15,-0.7098517053077216
46 | 44,62,0.6186416952805267
47 | 89,87,-0.16867483733838862
48 | 75,44,-3.514204440866991
49 | 28,60,-2.7366690143837133
50 | 40,15,-1.1281865226107042
51 | 93,11,-3.118152626954697
52 | 15,63,-1.2690922003864293
53 | 88,29,-0.18836588223815826
54 | 2,23,0.6799045629833986
55 | 46,96,0.21739536724147307
56 | 65,3,-1.4592660391212884
57 | 88,37,-1.107244883929112
58 | 65,95,0.2275609725399672
59 | 41,7,-0.2496356070766711
60 | 25,80,-1.1211940215729022
61 | 21,27,-0.09661807637216241
62 | 91,12,-2.406230668399388
63 | 32,81,-1.3500805459402252
64 | 65,83,0.5888676370398311
65 | 72,27,-0.9654962013539982
66 | 31,80,-1.456316317242763
67 | 34,77,-1.5715611436569268
68 | 75,52,-0.9936717510754695
69 | 83,57,-0.3972504171528985
70 | 53,54,0.9579444554514525
71 | 5,48,-0.9110466214925685
72 | 63,37,-1.668719852071336
73 | 52,88,0.30155665085569183
74 | 52,80,-0.11393389488718508
75 | 88,59,0.9498500062624038
76 | 82,40,-2.8630741280292114
77 | 88,97,-0.5724965644599087
78 | 16,39,0.3509623844845141
79 | 50,30,0.30712552582481484
80 | 94,10,-3.2346378326811025
81 | 32,38,0.4552089340350225
82 | 44,24,-0.7574018163971681
83 | 49,69,1.2356342827899252
84 | 80,28,-1.0178539036303835
85 | 44,97,0.04065055111399368
86 | 9,72,-1.5862874790244033
87 | 62,83,0.713159046633232
88 | 55,87,1.0014195983263146
89 | 73,88,0.9887212215545849
90 | 74,77,0.8412936419422302
91 | 41,10,-0.47373270525578615
92 | 80,70,0.1989277467301741
93 | 84,91,0.4362331855173341
94 | 19,41,0.008772448868853477
95 | 74,95,0.21200274251186702
96 | 53,77,-0.44142991018893873
97 | 77,71,0.3737558041580218
98 | 26,80,-1.3080066480679053
99 | 60,29,-0.8604750005960811
100 | 87,66,0.4825254242707143
101 | 49,26,0.2699907908494049
102 | 58,7,-1.7509555878489427
103 | 83,34,-1.9690554078818678
104 | 98,71,-0.3072215482324351
105 | 19,33,0.8195543425614512
106 | 69,37,-0.9869471073868279
107 | 77,16,-0.3032695851580103
108 | 17,5,-1.2189964119667087
109 | 12,3,-0.27257057240043464
110 | 36,10,-0.39356133696987433
111 | 60,92,0.8447638349149216
112 | 87,26,0.04083935755339871
113 | 42,88,-0.6016648813493206
114 | 95,68,-0.6153052578521497
115 | 26,73,0.10972407867717388
116 | 75,87,0.4837705304898816
117 | 8,72,-1.5017658843299335
118 | 72,38,-2.1548409371968544
119 | 91,53,-0.29640401021767016
120 | 17,43,-0.19065596156743903
121 | 78,44,-3.470794267709495
122 | 47,80,-0.15092944771479289
123 | 44,90,-0.2891096089347041
124 | 14,73,-1.6282848473826248
125 | 1,99,-2.7485938529435496
126 | 89,52,-1.0444974789331405
127 | 44,88,-0.23148281964714834
128 | 56,6,-1.2489821829912962
129 | 70,64,-0.1985023790465692
130 | 40,85,-0.6119284650766149
131 | 46,21,-1.0575872709845917
132 | 41,39,-0.49010823408513315
133 | 45,93,-0.14813508543192433
134 | 8,46,-0.6957694579956841
135 | 29,41,0.2925915080992926
136 | 32,98,-1.6807270769546596
137 | 80,100,-1.8149269806059642
138 | 65,94,0.4077290290404864
139 | 26,63,-1.475875594477606
140 | 49,6,0.05498998205253869
141 | 56,48,-0.22702813291513896
142 | 22,92,-0.8249706202797014
143 | 56,35,-0.9263564590999971
144 | 66,26,-0.8561138896895382
145 | 48,67,1.2573632103954488
146 | 100,75,0.06842200444814739
147 | 81,75,0.5473099797622492
148 | 33,49,-1.0321496503984102
149 | 27,99,-1.8838634225902282
150 | 85,68,0.4802607641737733
151 | 82,71,0.3196478743792045
152 | 80,82,0.5695006144567061
153 | 65,13,-1.06228576338799
154 | 96,76,-0.3524376227895107
155 | 2,74,0.5690909889388418
156 | 85,31,-1.246452342132829
157 | 4,33,-0.7953412470737332
158 | 67,50,0.5625661264080491
159 | 55,83,0.24351590040811572
160 | 15,38,0.36411193448911594
161 | 71,100,-0.4536559855457971
162 | 83,1,0.07933936128007926
163 | 88,45,-2.7457207428781283
164 | 39,95,0.23219385937063947
165 | 25,6,-0.2788122287793571
166 | 100,49,0.23626716108476928
167 | 44,86,-0.09441530966039002
168 | 18,92,-1.0357957584175066
169 | 89,36,-0.38685322915900544
170 | 7,35,-1.0239078717951824
171 | 63,46,-0.34438971963090154
172 | 22,84,0.23396407807136554
173 | 68,34,-0.903632978192785
174 | 96,11,-3.434910889878696
175 | 87,38,-1.785802886697303
176 | 29,79,-1.5565194005756282
177 | 83,59,0.6088959380848571
178 | 82,99,-1.5779406861904615
179 | 65,17,-1.7956575523376384
180 | 11,54,-1.5236653807493452
181 | 70,100,-0.4958109890037088
182 | 89,27,0.08154828239071249
183 | 59,70,0.8365371624753974
184 | 57,19,-1.070650685896748
185 | 14,47,-0.8417245700628229
186 | 77,1,0.37906792145208323
187 | 64,6,-1.8521839941654208
188 | 81,29,-1.224269671546148
189 | 78,97,-0.6538359282489696
190 | 98,48,-0.20965379737882728
191 | 13,16,-0.24930407680322653
192 | 53,92,0.4209881693233034
193 | 82,7,0.19664362382501466
194 | 6,56,-1.9742588680541977
195 | 15,51,-1.1446294699147188
196 | 90,76,-0.6174841523716045
197 | 24,11,-1.4410912136779468
198 | 70,15,-1.3418968539974467
199 | 42,82,-0.037885272206712395
200 | 88,40,-2.0035919907455177
201 | 85,88,0.12049021523462489
202 |
--------------------------------------------------------------------------------
/doc/auto_examples/geostat/plot_variogram.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "code",
5 | "execution_count": null,
6 | "metadata": {
7 | "collapsed": false
8 | },
9 | "outputs": [],
10 | "source": [
11 | "%matplotlib inline"
12 | ]
13 | },
14 | {
15 | "cell_type": "markdown",
16 | "metadata": {},
17 | "source": [
18 | "\n# Estimate a Variogram\n\nUse the geostatistics toolbox to estimate a variogram and use one of the many\nplots. These plots help to understand the spatial properties of a variogram,\nand finally, the :class:`Variogram ` object itself can be\nreturned and used in one of the Kriging routines.\n"
19 | ]
20 | },
21 | {
22 | "cell_type": "code",
23 | "execution_count": null,
24 | "metadata": {
25 | "collapsed": false
26 | },
27 | "outputs": [],
28 | "source": [
29 | "from pprint import pprint\nimport plotly\nimport hydrobox\nfrom hydrobox.data import pancake\nfrom hydrobox.plotting import plotting_backend\nplotting_backend('plotly')"
30 | ]
31 | },
32 | {
33 | "cell_type": "markdown",
34 | "metadata": {},
35 | "source": [
36 | "Load sample data from the data sub-module\n\n"
37 | ]
38 | },
39 | {
40 | "cell_type": "code",
41 | "execution_count": null,
42 | "metadata": {
43 | "collapsed": false
44 | },
45 | "outputs": [],
46 | "source": [
47 | "df = pancake()"
48 | ]
49 | },
50 | {
51 | "cell_type": "markdown",
52 | "metadata": {},
53 | "source": [
54 | "Estimate a variogram using a exponential model and 25 distance lags\nthat are derived from a KMeans cluster algorithm\nHere, we use the describe output option to get a dictionary of \nall variogram parameters\n\n"
55 | ]
56 | },
57 | {
58 | "cell_type": "code",
59 | "execution_count": null,
60 | "metadata": {
61 | "collapsed": false
62 | },
63 | "outputs": [],
64 | "source": [
65 | "vario = hydrobox.geostat.variogram(\n coordinates=df[['x', 'y']].values,\n values=df.z.values,\n model='exponential',\n bin_func='kmeans',\n n_lags=25,\n return_type='describe'\n)\n# print\npprint(vario)"
66 | ]
67 | },
68 | {
69 | "cell_type": "markdown",
70 | "metadata": {},
71 | "source": [
72 | "There are various return types, one of them is the plot.\nThis is the main plotting tool for variogram instances\n\n"
73 | ]
74 | },
75 | {
76 | "cell_type": "code",
77 | "execution_count": null,
78 | "metadata": {
79 | "collapsed": false
80 | },
81 | "outputs": [],
82 | "source": [
83 | "fig = hydrobox.geostat.variogram(\n coordinates=df[['x', 'y']].values,\n values=df.z.values,\n model='exponential',\n bin_func='kmeans',\n n_lags=25,\n return_type='plot'\n)\n\n# show the figure\nplotly.io.show(fig)"
84 | ]
85 | },
86 | {
87 | "cell_type": "markdown",
88 | "metadata": {},
89 | "source": [
90 | "Alternatively you can return the :class:`Variogram `\nobject itself and use all the different settings and methods directly.\n\n"
91 | ]
92 | },
93 | {
94 | "cell_type": "code",
95 | "execution_count": null,
96 | "metadata": {
97 | "collapsed": false
98 | },
99 | "outputs": [],
100 | "source": [
101 | "v = hydrobox.geostat.variogram(\n coordinates=df[['x', 'y']].values,\n values=df.z.values,\n model='exponential',\n bin_func='kmeans',\n n_lags=25,\n return_type='object'\n)\n\npprint(v)"
102 | ]
103 | },
104 | {
105 | "cell_type": "markdown",
106 | "metadata": {},
107 | "source": [
108 | "The :class:`Variogram ` has a plotting method for\nall point pairs at their separating distances. It is available as a \nreturn type, but can also be called directly:\n\n"
109 | ]
110 | },
111 | {
112 | "cell_type": "code",
113 | "execution_count": null,
114 | "metadata": {
115 | "collapsed": false
116 | },
117 | "outputs": [],
118 | "source": [
119 | "fig = v.distance_difference_plot() \n\nplotly.io.show(fig)"
120 | ]
121 | },
122 | {
123 | "cell_type": "markdown",
124 | "metadata": {},
125 | "source": [
126 | "The variogram instance has a lot of quality measures to judge the goodness\nof fit for the theoretical model. They are implemented as properties and can\nbe used like attribtues, while being always up to date if the variogram is mutated.\nAnother helpful method is :func:`cross_validate `.\nThis will run a leave-one-out cross validation by interpolating the missing point for \nall points. This is especially useful in cases, where a theoretical model fits well,\nbut the spatial properties are not well captured. \n\n"
127 | ]
128 | },
129 | {
130 | "cell_type": "code",
131 | "execution_count": null,
132 | "metadata": {
133 | "collapsed": false
134 | },
135 | "outputs": [],
136 | "source": [
137 | "# calculate the rmse of the model\nprint(f\"{v.model.__name__} RMSE: {v.rmse}\")\n\n# get the cross-validation time\nfrom time import time\nt1 = time()\nrmse = v.cross_validate()\nt2 = time()\nprint('Cross-validated RMSE: %.2f (took: %2fs)' % (rmse, t2 - t1))"
138 | ]
139 | }
140 | ],
141 | "metadata": {
142 | "kernelspec": {
143 | "display_name": "Python 3",
144 | "language": "python",
145 | "name": "python3"
146 | },
147 | "language_info": {
148 | "codemirror_mode": {
149 | "name": "ipython",
150 | "version": 3
151 | },
152 | "file_extension": ".py",
153 | "mimetype": "text/x-python",
154 | "name": "python",
155 | "nbconvert_exporter": "python",
156 | "pygments_lexer": "ipython3",
157 | "version": "3.8.5"
158 | }
159 | },
160 | "nbformat": 4,
161 | "nbformat_minor": 0
162 | }
--------------------------------------------------------------------------------
/hydrobox/utils/decorators.py:
--------------------------------------------------------------------------------
1 | """
2 | These decorators can be used to annotate the tool functions.
3 | Most decorators will check the argument types or input data.
4 | """
5 | from functools import wraps
6 |
7 |
8 | def accept(**types):
9 | """
10 | Decorator used to define accepted argument types for the toolbox functions.
11 |
12 | Usage
13 | -----
14 |
15 | .. code-block:: python
16 |
17 | @accept(foo=str, bar=(int,float))
18 | def f(foo, bar):
19 | pass
20 |
21 | :param types: arguments to the decorated function and the allowed types
22 | :return: decorated function
23 | """
24 | def decorator(f):
25 | # dig down to the original wrapped function in case more than one decorator was used
26 | _f = f
27 | while hasattr(_f, '__wrapped__'):
28 | _f = getattr(_f, '__wrapped__')
29 |
30 | # get the code, name and argnames
31 | code = _f.__code__
32 | fname = _f.__name__
33 | names = code.co_varnames[:code.co_argcount]
34 |
35 | @wraps(f)
36 | def decorated(*args, **kwargs):
37 | for argname, argtype in types.items():
38 | # check for argnames in kwargs
39 | if argname in kwargs:
40 | argval = kwargs.get(argname)
41 | else:
42 | try:
43 | argval = args[names.index(argname)]
44 | except IndexError:
45 | # TODO: Turn this into a develop level log
46 | #print('DevelWarning: arg %s not passed by function %s. (Maybe default?).' % (argname, fname))
47 | continue
48 |
49 | # check type
50 | if argtype == 'callable':
51 | if not callable(argval):
52 | raise TypeError('%s(...): arg %s: type is %s, but shall be callable.' % (fname, argname, type(argval)))
53 | else:
54 | continue
55 |
56 | elif argval is None:
57 | if not (argtype == 'None' or (isinstance(argtype, (list, tuple)) and 'None' in argtype)):
58 | raise TypeError('%s(...): arg %s: is None, must be %s.' %(fname, argname, argtype))
59 | else:
60 | continue
61 |
62 | # check if there is a None in argtype
63 | if isinstance(argtype, (tuple, list)) and 'None' in argtype:
64 | argtype = list(argtype)
65 | argtype.remove('None')
66 | argtype = tuple(argtype)
67 |
68 | # check if there is a 'callable' in argtype
69 | if isinstance(argtype, (tuple, list)) and 'callable' in argtype:
70 | argtype = list(argtype)
71 | argtype.remove('callable')
72 | argtype = tuple(argtype)
73 | # this is a special case
74 | if not isinstance(argval, argtype) and not callable(argval):
75 | raise TypeError("{0}(...); arg {1}: is not callable or of type {2}".format(fname, argname, argtype))
76 | else:
77 | continue
78 |
79 | if not isinstance(argval, argtype):
80 | raise TypeError("%s(...): arg %s: type is %s, must be %s." %
81 | (fname, argname, type(argval), argtype))
82 |
83 | # all checkes passed
84 | return f(*args, **kwargs)
85 | return decorated
86 | return decorator
87 |
88 |
89 | def enforce(**types):
90 | """
91 | Decorator used to define enforcing of argument type casts for the toolbox functions.
92 |
93 | In case a cast on one of the arguments raises a :py:class: `ValueError`, the cast will be ignored.
94 | Therefore it might make sense to combine a enforce decorator with a :py:func: `hydrobox.utils.decorators.accept`
95 | decorator in order to accept only the enforced type. In this case the
96 | :py:func: `hydrobox.utils.decorators.accept` decorator raises a :py:class: `ValueError`.
97 |
98 | Usage
99 | -----
100 |
101 | .. code-block:: python
102 |
103 | @accept(foo=str)
104 | def f(foo):
105 | return 'Result: %s' % foo
106 |
107 | The f function can now be called and foo will be casted to a string
108 |
109 | .. code-block:: python
110 |
111 | a = f(5)
112 | print(type(a))
113 |
114 | .. code-block:: bash
115 |
116 | >>
117 |
118 | :param types: arguments to the decorated function and the desired types
119 | :return: decorated function
120 | """
121 | def decorator(f):
122 | # dig down to the original wrapped function in case more than one decorator was used
123 | _f = f
124 | while hasattr(_f, '__wrapped__'):
125 | _f = getattr(_f, '__wrapped__')
126 |
127 | # get the code, name and argnames
128 | code = _f.__code__
129 | fname = _f.__name__
130 | names = code.co_varnames[:code.co_argcount]
131 |
132 | @wraps(f)
133 | def decorated(*args, **kwargs):
134 | def caster(value, destination):
135 | try:
136 | return destination(value)
137 | except (ValueError, Exception):
138 | # TODO: On develop log note that the cast failed
139 | return value
140 |
141 | # turn args into a list
142 | args = list(args)
143 |
144 | # cast all defined types
145 | for argname, argtype in types.items():
146 | if argname in kwargs:
147 | argval = kwargs.get(argname)
148 | kwargs.update({argname: caster(argval, argtype)})
149 | else:
150 | try:
151 | index = names.index(argname)
152 | args[index] = caster(args[index], argtype)
153 | except IndexError:
154 | # TODO: Turn this into a develop level log
155 | continue
156 |
157 | return f(*args, **kwargs)
158 | return decorated
159 | return decorator
160 |
--------------------------------------------------------------------------------
/doc/auto_examples/geostat/plot_gridsearch.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "code",
5 | "execution_count": null,
6 | "metadata": {
7 | "collapsed": false
8 | },
9 | "outputs": [],
10 | "source": [
11 | "%matplotlib inline"
12 | ]
13 | },
14 | {
15 | "cell_type": "markdown",
16 | "metadata": {},
17 | "source": [
18 | "\n# GridSearch optimization\n\nThe SciKit-GStat package can be connected to scikit-learn i.e. to use\nthe model optimization sub-package. In this example, different options\nare compared and cross-validated.\nThe Interface has two different options to evaluate a variogram model fit:\n\n* goodness of fit measures of the spatial model itself\n* cross-validation of the variogram by interpolating the observation points\n\nBoth options can use the RMSE, MSE and MAE as a metric.\n"
19 | ]
20 | },
21 | {
22 | "cell_type": "code",
23 | "execution_count": null,
24 | "metadata": {
25 | "collapsed": false
26 | },
27 | "outputs": [],
28 | "source": [
29 | "import plotly\nimport plotly.graph_objects as go\nimport hydrobox\nfrom hydrobox.data import pancake\nfrom hydrobox.plotting import plotting_backend\nplotting_backend('plotly')"
30 | ]
31 | },
32 | {
33 | "cell_type": "markdown",
34 | "metadata": {},
35 | "source": [
36 | "Load sample data from the data sub-module\n\n"
37 | ]
38 | },
39 | {
40 | "cell_type": "code",
41 | "execution_count": null,
42 | "metadata": {
43 | "collapsed": false
44 | },
45 | "outputs": [],
46 | "source": [
47 | "df = pancake()"
48 | ]
49 | },
50 | {
51 | "cell_type": "markdown",
52 | "metadata": {},
53 | "source": [
54 | "First, a Variogram is estimated, which will fix all arguments that\nshould not be evaluated by the Grid Search.\n\n"
55 | ]
56 | },
57 | {
58 | "cell_type": "code",
59 | "execution_count": null,
60 | "metadata": {
61 | "collapsed": false
62 | },
63 | "outputs": [],
64 | "source": [
65 | "vario = hydrobox.geostat.variogram(\n coordinates=df[['x', 'y']].values,\n values=df.z.values,\n maxlag=500,\n bin_func='kmeans',\n return_type='object'\n)"
66 | ]
67 | },
68 | {
69 | "cell_type": "markdown",
70 | "metadata": {},
71 | "source": [
72 | "The next step is to create a parameter grid, which specifies the\nvalue space for each parameter that should be checked.\nHere, we will try all combinations of different models and lag classes.\n\n"
73 | ]
74 | },
75 | {
76 | "cell_type": "code",
77 | "execution_count": null,
78 | "metadata": {
79 | "collapsed": false
80 | },
81 | "outputs": [],
82 | "source": [
83 | "param_grid = {\n 'model': ('spherical', 'exponential', 'matern'),\n 'n_lags': (15, 20, 25, 30, 35)\n}"
84 | ]
85 | },
86 | {
87 | "cell_type": "markdown",
88 | "metadata": {},
89 | "source": [
90 | "First the model fit itself is evaluated and only the best parameter\nset will be returned\n\n"
91 | ]
92 | },
93 | {
94 | "cell_type": "code",
95 | "execution_count": null,
96 | "metadata": {
97 | "collapsed": false
98 | },
99 | "outputs": [],
100 | "source": [
101 | "best_param = hydrobox.geostat.gridsearch(\n param_grid=param_grid,\n variogram=vario,\n coordinates=None, # must be set if variogram is None\n values=None, # must be set if variogram is None\n score='rmse', # default\n cross_validate=False, # evaluate model fit,\n n_jobs=-1, # use parallel mode\n return_type='best_param'\n)\n\nprint(best_param)"
102 | ]
103 | },
104 | {
105 | "cell_type": "markdown",
106 | "metadata": {},
107 | "source": [
108 | "It is also possible to return the underlying \n:class:`GridSearchCV ` instance.\nThis class holds way more information than just the best parameter.\n\n"
109 | ]
110 | },
111 | {
112 | "cell_type": "code",
113 | "execution_count": null,
114 | "metadata": {
115 | "collapsed": false
116 | },
117 | "outputs": [],
118 | "source": [
119 | "# reun the same Gridsearch, return the object\nclf = hydrobox.geostat.gridsearch(\n param_grid=param_grid,\n variogram=vario,\n coordinates=None, # must be set if variogram is None\n values=None, # must be set if variogram is None\n score='rmse', # default\n cross_validate=False, # evaluate model fit,\n n_jobs=-1, # use parallel mode\n return_type='object'\n)\n\n# get the scores and their std\nscores = clf.cv_results_['mean_test_score']\nscores_std = clf.cv_results_['std_test_score']\nx = list(range(len(scores)))"
120 | ]
121 | },
122 | {
123 | "cell_type": "markdown",
124 | "metadata": {},
125 | "source": [
126 | "Plot the result\n\n"
127 | ]
128 | },
129 | {
130 | "cell_type": "code",
131 | "execution_count": null,
132 | "metadata": {
133 | "collapsed": false
134 | },
135 | "outputs": [],
136 | "source": [
137 | "fig = go.Figure()\nfig.add_trace(\n go.Scatter(x=x, y=scores, mode='lines', line_color='#A3ACF7', name='RMSE score')\n)\nfig.add_trace(\n go.Scatter(x=x, y=scores + scores_std, mode='lines', line_color='#BAC1F2', fill='tonexty', name='RMSE + std')\n)\nfig.add_trace(\n go.Scatter(x=x, y=scores - scores_std, mode='lines', line_color='#BAC1F2', fill='tonexty', name='RMSE - std')\n)\nfig.update_layout(\n template='plotly_white'\n)\n\n# show the plot\nplotly.io.show(fig)"
138 | ]
139 | }
140 | ],
141 | "metadata": {
142 | "kernelspec": {
143 | "display_name": "Python 3",
144 | "language": "python",
145 | "name": "python3"
146 | },
147 | "language_info": {
148 | "codemirror_mode": {
149 | "name": "ipython",
150 | "version": 3
151 | },
152 | "file_extension": ".py",
153 | "mimetype": "text/x-python",
154 | "name": "python",
155 | "nbconvert_exporter": "python",
156 | "pygments_lexer": "ipython3",
157 | "version": "3.8.5"
158 | }
159 | },
160 | "nbformat": 4,
161 | "nbformat_minor": 0
162 | }
--------------------------------------------------------------------------------
/hydrobox/stats/regression.py:
--------------------------------------------------------------------------------
1 | """Regression Module
2 |
3 | Common tools for calculating linear regression and produce scatter plots.
4 |
5 | """
6 | from itertools import product
7 |
8 | from scipy.stats import linregress
9 | import matplotlib.pyplot as plt
10 | import numpy as np
11 |
12 | from hydrobox.toolbox import merge
13 |
14 |
15 | def linear_regression(*x, df=None, plot=False, ax=None, notext=False):
16 | """Linear Regression tool
17 |
18 | This tool can be used for a number of regression related tasks. It can
19 | calculate a linear regression between two observables and also return a
20 | scatter plot including the regression parameters and function.
21 |
22 | In case more than two ``Series`` or ``arrays`` are passed, they will be
23 | merged into a ``DataFrame`` and a linear regression between all
24 | combinations will be calculated and potted if desired.
25 |
26 | Parameters
27 | ----------
28 | x : pandas.Series, numpy.ndarray
29 | If df is None, at least two Series or arrays have to be passed. If
30 | more are passed, a multi output will be produced.
31 | df : pandas.DataFrame
32 | If df is set, all x occurrences will be ignored. DataFrame of the
33 | input to be used for calculating the linear regression,
34 | This attribute can be useful, whenever a multi input to x does not
35 | get merged correctly. Note that linear_regression will only use the
36 | DataFrame.data array and ignore all other structural elements.
37 | plot : bool
38 | If True, the function will output a matplotlib Figure or plot into an
39 | existing instance. If False (default) the data used for the plots
40 | will be returned.
41 | ax : matplotlib.Axes.Axessubplot
42 | Has to be a single matplotlib Axes instance if two data sets are
43 | passed or a list of Axes if more than two data sets are passed.
44 | notext : bool
45 | If True, the output of the fitting parameters as a text into the plot
46 | will be suppressed. This setting is ignored, is plot is set to False.
47 |
48 | Returns
49 | -------
50 | matplotlib.Figure
51 | numpy.ndarray
52 |
53 | Notes
54 | -----
55 |
56 | If plot is True and ax is not None, the number of passed Axes has to match
57 | the total combinations between the data sets. This is
58 |
59 | .. math:: N^2
60 |
61 | where N is the length of x, or the length of df.columns.
62 |
63 | .. warning::
64 |
65 | This function does just calculate a linear regression. It handles a
66 | multi input recursively and has some data wrangling overhead. If you are
67 | seeking a fast linear regression tool, use the scipy.stats.linregress
68 | function directly.
69 |
70 | """
71 | # combine all inputs
72 | if df is None:
73 | df = merge(*x, dropna=True)
74 |
75 | if len(df.columns) == 2:
76 | slope, intercept, rvalue, pvalue, stderr = linregress(df.values[:, 0],
77 | df.values[:, 1])
78 |
79 | # calculate regression
80 | reg = dict(slope=slope, intercept=intercept, rvalue=rvalue,
81 | pvalue=pvalue, stderr=stderr)
82 |
83 | # return data
84 | if not plot:
85 | return reg
86 |
87 | # return plot
88 | else: # pragma: no cover
89 | # build the ax if necessary
90 | if ax is None:
91 | fig, ax = plt.subplots(1, 1, figsize=(6, 6))
92 | else:
93 | fig = ax.get_figure()
94 |
95 | ax.scatter(df.values[:, 0], df.values[:, 1], 25, marker='.',
96 | color='blue')
97 | if not notext:
98 | ax.text(0.05, 0.95,
99 | '\n'.join(
100 | ['%s: %.2f' % (k, v) for k, v in reg.items()]),
101 | ha='left', va='top', transform=ax.transAxes
102 | )
103 | x = df.values[:, 0]
104 | y = x * reg['slope'] + reg['intercept']
105 | ax.plot(x, y, '-g')
106 |
107 | return fig
108 |
109 | # more than two are given, call recursively
110 | else:
111 | # get the number of data sets
112 | n = len(df.columns)
113 |
114 | # create a plot
115 | if plot: # pragma: no cover
116 | if ax is None:
117 | fig, axes = plt.subplots(n, n, figsize=(n * 5, n * 5),
118 | sharex=True, sharey=True)
119 | else:
120 | axes = ax
121 | fig = axes.flatten()[0].get_figure()
122 | # make sure there are enough AxesSubplots
123 | assert len(axes.flatten()) == n * n
124 |
125 | # call linear regression for all combinations
126 | for i, col_names in zip(
127 | range(n * n),
128 | product(df.columns, df.columns)
129 | ):
130 | if col_names[0] == col_names[1]:
131 | # TODO: as soon as implemented, use the histogram tool here
132 | continue
133 | linear_regression(df=df[[*col_names]],
134 | plot=True, ax=axes.flatten()[i],
135 | notext=notext)
136 |
137 | # return the whole figure
138 | plt.tight_layout()
139 | return fig
140 |
141 | else:
142 | p = product(df.columns, df.columns)
143 |
144 | # define a sorting function
145 | # before the .values method of the resulting dictionary was used,
146 | # but Python 3.5 and 3.6 return the dictionary with a different
147 | # order. therefore a explicit sorting function is needed
148 | def to_array(d):
149 | return [d['slope'], d['intercept'], d['rvalue'],
150 | d['pvalue'], d['stderr']]
151 |
152 | # old function, kept for reference
153 | # to_array = lambda d: np.array(list(d.values()))
154 | res = [to_array(linear_regression(df[[*n]])) for n in p]
155 |
156 | # build the results
157 | np_res = [np.array(el).reshape((n, n)) for el in zip(*res)]
158 | for el in np_res:
159 | np.fill_diagonal(el, np.NaN)
160 |
161 | # extract and return
162 | slope, intercept, rvalue, pvalue, stderr = np_res
163 | return slope, intercept, rvalue, pvalue, stderr
164 |
--------------------------------------------------------------------------------
/doc/auto_examples/geostat/plot_gridsearch.rst:
--------------------------------------------------------------------------------
1 |
2 | .. DO NOT EDIT.
3 | .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY.
4 | .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE:
5 | .. "auto_examples/geostat/plot_gridsearch.py"
6 | .. LINE NUMBERS ARE GIVEN BELOW.
7 |
8 | .. only:: html
9 |
10 | .. note::
11 | :class: sphx-glr-download-link-note
12 |
13 | Click :ref:`here `
14 | to download the full example code
15 |
16 | .. rst-class:: sphx-glr-example-title
17 |
18 | .. _sphx_glr_auto_examples_geostat_plot_gridsearch.py:
19 |
20 |
21 | GridSearch optimization
22 | =======================
23 |
24 | The SciKit-GStat package can be connected to scikit-learn i.e. to use
25 | the model optimization sub-package. In this example, different options
26 | are compared and cross-validated.
27 | The Interface has two different options to evaluate a variogram model fit:
28 |
29 | * goodness of fit measures of the spatial model itself
30 | * cross-validation of the variogram by interpolating the observation points
31 |
32 | Both options can use the RMSE, MSE and MAE as a metric.
33 |
34 | .. GENERATED FROM PYTHON SOURCE LINES 16-23
35 |
36 | .. code-block:: default
37 |
38 | import plotly
39 | import plotly.graph_objects as go
40 | import hydrobox
41 | from hydrobox.data import pancake
42 | from hydrobox.plotting import plotting_backend
43 | plotting_backend('plotly')
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 | .. GENERATED FROM PYTHON SOURCE LINES 24-25
53 |
54 | Load sample data from the data sub-module
55 |
56 | .. GENERATED FROM PYTHON SOURCE LINES 25-28
57 |
58 | .. code-block:: default
59 |
60 |
61 | df = pancake()
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 | .. GENERATED FROM PYTHON SOURCE LINES 29-31
71 |
72 | First, a Variogram is estimated, which will fix all arguments that
73 | should not be evaluated by the Grid Search.
74 |
75 | .. GENERATED FROM PYTHON SOURCE LINES 31-40
76 |
77 | .. code-block:: default
78 |
79 |
80 | vario = hydrobox.geostat.variogram(
81 | coordinates=df[['x', 'y']].values,
82 | values=df.z.values,
83 | maxlag=500,
84 | bin_func='kmeans',
85 | return_type='object'
86 | )
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 | .. GENERATED FROM PYTHON SOURCE LINES 41-44
96 |
97 | The next step is to create a parameter grid, which specifies the
98 | value space for each parameter that should be checked.
99 | Here, we will try all combinations of different models and lag classes.
100 |
101 | .. GENERATED FROM PYTHON SOURCE LINES 44-50
102 |
103 | .. code-block:: default
104 |
105 |
106 | param_grid = {
107 | 'model': ('spherical', 'exponential', 'matern'),
108 | 'n_lags': (15, 20, 25, 30, 35)
109 | }
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 | .. GENERATED FROM PYTHON SOURCE LINES 51-53
119 |
120 | First the model fit itself is evaluated and only the best parameter
121 | set will be returned
122 |
123 | .. GENERATED FROM PYTHON SOURCE LINES 53-67
124 |
125 | .. code-block:: default
126 |
127 |
128 | best_param = hydrobox.geostat.gridsearch(
129 | param_grid=param_grid,
130 | variogram=vario,
131 | coordinates=None, # must be set if variogram is None
132 | values=None, # must be set if variogram is None
133 | score='rmse', # default
134 | cross_validate=False, # evaluate model fit,
135 | n_jobs=-1, # use parallel mode
136 | return_type='best_param'
137 | )
138 |
139 | print(best_param)
140 |
141 |
142 |
143 |
144 |
145 | .. rst-class:: sphx-glr-script-out
146 |
147 | Out:
148 |
149 | .. code-block:: none
150 |
151 | {'model': 'spherical', 'n_lags': 35}
152 |
153 |
154 |
155 |
156 | .. GENERATED FROM PYTHON SOURCE LINES 68-71
157 |
158 | It is also possible to return the underlying
159 | :class:`GridSearchCV ` instance.
160 | This class holds way more information than just the best parameter.
161 |
162 | .. GENERATED FROM PYTHON SOURCE LINES 71-89
163 |
164 | .. code-block:: default
165 |
166 |
167 | # reun the same Gridsearch, return the object
168 | clf = hydrobox.geostat.gridsearch(
169 | param_grid=param_grid,
170 | variogram=vario,
171 | coordinates=None, # must be set if variogram is None
172 | values=None, # must be set if variogram is None
173 | score='rmse', # default
174 | cross_validate=False, # evaluate model fit,
175 | n_jobs=-1, # use parallel mode
176 | return_type='object'
177 | )
178 |
179 | # get the scores and their std
180 | scores = clf.cv_results_['mean_test_score']
181 | scores_std = clf.cv_results_['std_test_score']
182 | x = list(range(len(scores)))
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 | .. GENERATED FROM PYTHON SOURCE LINES 90-91
192 |
193 | Plot the result
194 |
195 | .. GENERATED FROM PYTHON SOURCE LINES 91-106
196 |
197 | .. code-block:: default
198 |
199 | fig = go.Figure()
200 | fig.add_trace(
201 | go.Scatter(x=x, y=scores, mode='lines', line_color='#A3ACF7', name='RMSE score')
202 | )
203 | fig.add_trace(
204 | go.Scatter(x=x, y=scores + scores_std, mode='lines', line_color='#BAC1F2', fill='tonexty', name='RMSE + std')
205 | )
206 | fig.add_trace(
207 | go.Scatter(x=x, y=scores - scores_std, mode='lines', line_color='#BAC1F2', fill='tonexty', name='RMSE - std')
208 | )
209 | fig.update_layout(
210 | template='plotly_white'
211 | )
212 |
213 | # show the plot
214 | plotly.io.show(fig)
215 |
216 |
217 | .. raw:: html
218 | :file: images/sphx_glr_plot_gridsearch_001.html
219 |
220 |
221 |
222 |
223 |
224 |
225 | .. rst-class:: sphx-glr-timing
226 |
227 | **Total running time of the script:** ( 1 minutes 23.717 seconds)
228 |
229 |
230 | .. _sphx_glr_download_auto_examples_geostat_plot_gridsearch.py:
231 |
232 |
233 | .. only :: html
234 |
235 | .. container:: sphx-glr-footer
236 | :class: sphx-glr-footer-example
237 |
238 |
239 |
240 | .. container:: sphx-glr-download sphx-glr-download-python
241 |
242 | :download:`Download Python source code: plot_gridsearch.py `
243 |
244 |
245 |
246 | .. container:: sphx-glr-download sphx-glr-download-jupyter
247 |
248 | :download:`Download Jupyter notebook: plot_gridsearch.ipynb `
249 |
250 |
251 | .. only:: html
252 |
253 | .. rst-class:: sphx-glr-signature
254 |
255 | `Gallery generated by Sphinx-Gallery `_
256 |
--------------------------------------------------------------------------------
/doc/auto_examples/geostat/plot_variogram.rst:
--------------------------------------------------------------------------------
1 |
2 | .. DO NOT EDIT.
3 | .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY.
4 | .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE:
5 | .. "auto_examples/geostat/plot_variogram.py"
6 | .. LINE NUMBERS ARE GIVEN BELOW.
7 |
8 | .. only:: html
9 |
10 | .. note::
11 | :class: sphx-glr-download-link-note
12 |
13 | Click :ref:`here `
14 | to download the full example code
15 |
16 | .. rst-class:: sphx-glr-example-title
17 |
18 | .. _sphx_glr_auto_examples_geostat_plot_variogram.py:
19 |
20 |
21 | Estimate a Variogram
22 | ====================
23 |
24 | Use the geostatistics toolbox to estimate a variogram and use one of the many
25 | plots. These plots help to understand the spatial properties of a variogram,
26 | and finally, the :class:`Variogram ` object itself can be
27 | returned and used in one of the Kriging routines.
28 |
29 | .. GENERATED FROM PYTHON SOURCE LINES 11-18
30 |
31 | .. code-block:: default
32 |
33 | from pprint import pprint
34 | import plotly
35 | import hydrobox
36 | from hydrobox.data import pancake
37 | from hydrobox.plotting import plotting_backend
38 | plotting_backend('plotly')
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 | .. GENERATED FROM PYTHON SOURCE LINES 19-20
48 |
49 | Load sample data from the data sub-module
50 |
51 | .. GENERATED FROM PYTHON SOURCE LINES 20-23
52 |
53 | .. code-block:: default
54 |
55 |
56 | df = pancake()
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 | .. GENERATED FROM PYTHON SOURCE LINES 24-28
66 |
67 | Estimate a variogram using a exponential model and 25 distance lags
68 | that are derived from a KMeans cluster algorithm
69 | Here, we use the describe output option to get a dictionary of
70 | all variogram parameters
71 |
72 | .. GENERATED FROM PYTHON SOURCE LINES 28-40
73 |
74 | .. code-block:: default
75 |
76 |
77 | vario = hydrobox.geostat.variogram(
78 | coordinates=df[['x', 'y']].values,
79 | values=df.z.values,
80 | model='exponential',
81 | bin_func='kmeans',
82 | n_lags=25,
83 | return_type='describe'
84 | )
85 | # print
86 | pprint(vario)
87 |
88 |
89 |
90 |
91 |
92 | .. rst-class:: sphx-glr-script-out
93 |
94 | Out:
95 |
96 | .. code-block:: none
97 |
98 | {'dist_func': 'euclidean',
99 | 'effective_range': 440.23387689607966,
100 | 'estimator': 'matheron',
101 | 'kwargs': {},
102 | 'model': 'exponential',
103 | 'normalized_effective_range': 246442.01433239583,
104 | 'normalized_nugget': 0,
105 | 'normalized_sill': 2423777.7530702623,
106 | 'nugget': 0,
107 | 'params': {'bin_func': 'kmeans',
108 | 'dist_func': 'euclidean',
109 | 'estimator': 'matheron',
110 | 'fit_method': 'trf',
111 | 'fit_sigma': None,
112 | 'maxlag': None,
113 | 'model': 'exponential',
114 | 'n_lags': 25,
115 | 'normalize': False,
116 | 'use_nugget': False,
117 | 'verbose': False},
118 | 'sill': 1556.8486609398685}
119 |
120 |
121 |
122 |
123 | .. GENERATED FROM PYTHON SOURCE LINES 41-43
124 |
125 | There are various return types, one of them is the plot.
126 | This is the main plotting tool for variogram instances
127 |
128 | .. GENERATED FROM PYTHON SOURCE LINES 43-55
129 |
130 | .. code-block:: default
131 |
132 | fig = hydrobox.geostat.variogram(
133 | coordinates=df[['x', 'y']].values,
134 | values=df.z.values,
135 | model='exponential',
136 | bin_func='kmeans',
137 | n_lags=25,
138 | return_type='plot'
139 | )
140 |
141 | # show the figure
142 | plotly.io.show(fig)
143 |
144 |
145 |
146 |
147 | .. raw:: html
148 | :file: images/sphx_glr_plot_variogram_001.html
149 |
150 |
151 |
152 |
153 |
154 | .. GENERATED FROM PYTHON SOURCE LINES 56-58
155 |
156 | Alternatively you can return the :class:`Variogram `
157 | object itself and use all the different settings and methods directly.
158 |
159 | .. GENERATED FROM PYTHON SOURCE LINES 58-70
160 |
161 | .. code-block:: default
162 |
163 |
164 | v = hydrobox.geostat.variogram(
165 | coordinates=df[['x', 'y']].values,
166 | values=df.z.values,
167 | model='exponential',
168 | bin_func='kmeans',
169 | n_lags=25,
170 | return_type='object'
171 | )
172 |
173 | pprint(v)
174 |
175 |
176 |
177 |
178 |
179 | .. rst-class:: sphx-glr-script-out
180 |
181 | Out:
182 |
183 | .. code-block:: none
184 |
185 | < exponential Semivariogram fitted to 25 bins >
186 |
187 |
188 |
189 |
190 | .. GENERATED FROM PYTHON SOURCE LINES 71-74
191 |
192 | The :class:`Variogram ` has a plotting method for
193 | all point pairs at their separating distances. It is available as a
194 | return type, but can also be called directly:
195 |
196 | .. GENERATED FROM PYTHON SOURCE LINES 74-78
197 |
198 | .. code-block:: default
199 |
200 | fig = v.distance_difference_plot()
201 |
202 | plotly.io.show(fig)
203 |
204 |
205 |
206 |
207 | .. raw:: html
208 | :file: images/sphx_glr_plot_variogram_002.html
209 |
210 |
211 |
212 |
213 |
214 | .. GENERATED FROM PYTHON SOURCE LINES 79-86
215 |
216 | The variogram instance has a lot of quality measures to judge the goodness
217 | of fit for the theoretical model. They are implemented as properties and can
218 | be used like attribtues, while being always up to date if the variogram is mutated.
219 | Another helpful method is :func:`cross_validate `.
220 | This will run a leave-one-out cross validation by interpolating the missing point for
221 | all points. This is especially useful in cases, where a theoretical model fits well,
222 | but the spatial properties are not well captured.
223 |
224 | .. GENERATED FROM PYTHON SOURCE LINES 86-96
225 |
226 | .. code-block:: default
227 |
228 |
229 | # calculate the rmse of the model
230 | print(f"{v.model.__name__} RMSE: {v.rmse}")
231 |
232 | # get the cross-validation time
233 | from time import time
234 | t1 = time()
235 | rmse = v.cross_validate()
236 | t2 = time()
237 | print('Cross-validated RMSE: %.2f (took: %2fs)' % (rmse, t2 - t1))
238 |
239 |
240 |
241 |
242 | .. rst-class:: sphx-glr-script-out
243 |
244 | Out:
245 |
246 | .. code-block:: none
247 |
248 | exponential RMSE: 39.91457083112962
249 | Cross-validated RMSE: 12.08 (took: 5.382931s)
250 |
251 |
252 |
253 |
254 |
255 | .. rst-class:: sphx-glr-timing
256 |
257 | **Total running time of the script:** ( 0 minutes 15.624 seconds)
258 |
259 |
260 | .. _sphx_glr_download_auto_examples_geostat_plot_variogram.py:
261 |
262 |
263 | .. only :: html
264 |
265 | .. container:: sphx-glr-footer
266 | :class: sphx-glr-footer-example
267 |
268 |
269 |
270 | .. container:: sphx-glr-download sphx-glr-download-python
271 |
272 | :download:`Download Python source code: plot_variogram.py `
273 |
274 |
275 |
276 | .. container:: sphx-glr-download sphx-glr-download-jupyter
277 |
278 | :download:`Download Jupyter notebook: plot_variogram.ipynb `
279 |
280 |
281 | .. only:: html
282 |
283 | .. rst-class:: sphx-glr-signature
284 |
285 | `Gallery generated by Sphinx-Gallery `_
286 |
--------------------------------------------------------------------------------
/hydrobox/data/pan_sample.csv:
--------------------------------------------------------------------------------
1 | x,y,z
2 | 102,435,190
3 | 348,270,218
4 | 106,71,162
5 | 188,20,208
6 | 102,121,229
7 | 466,214,132
8 | 330,458,165
9 | 87,372,203
10 | 99,359,165
11 | 151,130,184
12 | 149,308,207
13 | 257,343,194
14 | 491,413,171
15 | 293,385,152
16 | 191,443,106
17 | 276,160,221
18 | 459,313,99
19 | 21,252,196
20 | 235,344,209
21 | 48,474,196
22 | 58,169,126
23 | 475,187,137
24 | 463,270,124
25 | 189,445,105
26 | 174,445,142
27 | 50,363,209
28 | 54,243,200
29 | 319,130,234
30 | 484,306,114
31 | 134,20,216
32 | 328,166,217
33 | 273,387,150
34 | 88,315,217
35 | 13,241,201
36 | 264,345,191
37 | 52,385,202
38 | 339,91,238
39 | 366,443,138
40 | 454,427,153
41 | 263,430,190
42 | 34,205,143
43 | 80,419,196
44 | 49,359,210
45 | 387,1,227
46 | 389,53,231
47 | 105,259,214
48 | 309,476,167
49 | 190,401,189
50 | 217,43,227
51 | 161,201,212
52 | 445,483,159
53 | 269,350,197
54 | 303,270,212
55 | 455,461,150
56 | 214,251,192
57 | 189,295,162
58 | 212,207,179
59 | 236,337,194
60 | 366,52,223
61 | 279,409,173
62 | 216,251,177
63 | 187,379,191
64 | 492,40,160
65 | 156,14,222
66 | 300,64,245
67 | 344,326,129
68 | 8,343,199
69 | 128,491,189
70 | 135,471,188
71 | 62,138,197
72 | 498,80,184
73 | 391,162,214
74 | 418,288,136
75 | 378,260,216
76 | 489,230,110
77 | 40,27,216
78 | 134,200,171
79 | 327,267,218
80 | 417,32,229
81 | 47,406,195
82 | 61,215,103
83 | 292,98,225
84 | 171,359,172
85 | 213,474,130
86 | 34,448,187
87 | 226,100,176
88 | 430,461,157
89 | 130,256,215
90 | 4,217,218
91 | 254,397,179
92 | 358,282,187
93 | 392,206,211
94 | 14,345,199
95 | 41,379,209
96 | 460,178,200
97 | 62,351,201
98 | 230,240,179
99 | 51,95,225
100 | 387,221,208
101 | 484,406,174
102 | 230,236,178
103 | 142,170,178
104 | 28,35,218
105 | 12,159,193
106 | 326,186,221
107 | 242,85,194
108 | 283,65,243
109 | 169,44,215
110 | 61,440,190
111 | 133,283,218
112 | 27,107,218
113 | 43,339,203
114 | 285,445,175
115 | 330,127,228
116 | 347,472,153
117 | 230,189,189
118 | 224,384,174
119 | 376,282,165
120 | 445,120,221
121 | 115,460,197
122 | 232,258,224
123 | 358,197,216
124 | 455,410,165
125 | 136,317,203
126 | 164,224,225
127 | 306,233,197
128 | 171,151,167
129 | 462,314,95
130 | 373,159,215
131 | 95,471,189
132 | 232,179,206
133 | 112,317,216
134 | 496,441,147
135 | 51,267,191
136 | 294,385,152
137 | 386,112,226
138 | 100,112,170
139 | 439,80,225
140 | 186,112,185
141 | 1,129,215
142 | 219,53,215
143 | 342,484,164
144 | 223,224,181
145 | 384,402,122
146 | 125,129,179
147 | 52,171,118
148 | 217,159,220
149 | 197,415,184
150 | 246,323,191
151 | 438,202,188
152 | 183,122,187
153 | 400,254,213
154 | 293,279,211
155 | 324,371,134
156 | 97,197,129
157 | 469,394,181
158 | 239,143,198
159 | 96,200,141
160 | 123,186,145
161 | 325,463,166
162 | 348,258,218
163 | 147,251,216
164 | 442,419,109
165 | 402,345,97
166 | 450,146,211
167 | 147,351,196
168 | 198,307,207
169 | 488,416,171
170 | 423,127,221
171 | 38,337,202
172 | 359,128,229
173 | 266,475,184
174 | 440,472,159
175 | 433,150,216
176 | 414,477,151
177 | 297,98,229
178 | 262,251,181
179 | 143,345,189
180 | 111,499,184
181 | 59,368,204
182 | 1,384,203
183 | 303,253,213
184 | 139,452,179
185 | 36,159,181
186 | 8,232,211
187 | 98,146,141
188 | 303,207,221
189 | 130,403,202
190 | 151,53,181
191 | 119,160,161
192 | 407,115,223
193 | 74,112,189
194 | 455,419,163
195 | 421,103,227
196 | 339,253,211
197 | 226,111,196
198 | 472,98,228
199 | 152,348,204
200 | 401,383,110
201 | 365,337,110
202 | 193,309,201
203 | 162,207,225
204 | 444,168,207
205 | 483,160,199
206 | 67,288,204
207 | 397,276,218
208 | 303,403,143
209 | 383,391,115
210 | 134,194,167
211 | 400,127,220
212 | 32,175,175
213 | 459,442,158
214 | 370,469,134
215 | 374,21,233
216 | 237,157,193
217 | 37,229,204
218 | 364,50,222
219 | 437,263,212
220 | 282,26,243
221 | 225,276,230
222 | 285,96,215
223 | 283,366,172
224 | 447,480,155
225 | 452,316,101
226 | 303,146,223
227 | 3,34,222
228 | 191,48,226
229 | 16,171,211
230 | 219,157,199
231 | 476,45,189
232 | 372,5,230
233 | 98,379,211
234 | 232,36,235
235 | 279,348,157
236 | 496,301,109
237 | 180,94,197
238 | 98,187,130
239 | 480,115,198
240 | 190,252,221
241 | 468,415,162
242 | 470,160,195
243 | 255,322,187
244 | 127,17,221
245 | 280,489,171
246 | 222,53,216
247 | 57,322,202
248 | 359,173,218
249 | 279,113,192
250 | 287,430,202
251 | 341,150,205
252 | 449,126,218
253 | 154,489,184
254 | 385,473,127
255 | 272,103,200
256 | 416,392,115
257 | 298,245,216
258 | 175,38,216
259 | 476,169,203
260 | 246,25,222
261 | 354,305,148
262 | 408,407,115
263 | 12,315,202
264 | 390,312,141
265 | 35,172,155
266 | 19,320,202
267 | 263,493,160
268 | 399,141,220
269 | 459,370,148
270 | 470,142,207
271 | 91,353,157
272 | 321,287,179
273 | 214,446,131
274 | 341,50,232
275 | 152,185,170
276 | 62,189,109
277 | 124,149,182
278 | 313,57,241
279 | 341,304,166
280 | 179,169,187
281 | 325,270,223
282 | 53,490,187
283 | 443,100,223
284 | 480,263,118
285 | 52,59,193
286 | 491,107,185
287 | 4,102,192
288 | 195,261,209
289 | 364,479,129
290 | 371,349,95
291 | 46,354,205
292 | 310,423,145
293 | 307,143,225
294 | 268,369,199
295 | 123,105,152
296 | 157,146,166
297 | 144,119,173
298 | 318,274,217
299 | 91,57,187
300 | 438,345,105
301 | 228,473,159
302 | 116,317,214
303 | 278,126,221
304 | 392,395,131
305 | 128,57,168
306 | 121,0,217
307 | 238,289,209
308 | 95,125,165
309 | 117,47,203
310 | 88,487,187
311 | 236,372,156
312 | 384,271,218
313 | 188,486,177
314 | 191,446,97
315 | 68,277,204
316 | 348,246,208
317 | 450,75,225
318 | 153,143,170
319 | 434,484,166
320 | 85,184,137
321 | 284,461,142
322 | 219,68,206
323 | 46,496,181
324 | 93,237,218
325 | 445,499,152
326 | 452,203,139
327 | 399,217,209
328 | 473,431,156
329 | 340,38,235
330 | 99,288,194
331 | 253,221,139
332 | 356,22,236
333 | 249,9,209
334 | 245,324,173
335 | 99,289,193
336 | 179,222,226
337 | 393,249,216
338 | 146,441,185
339 | 95,256,213
340 | 324,492,158
341 | 3,15,216
342 | 279,335,149
343 | 246,257,213
344 | 496,475,138
345 | 383,159,219
346 | 474,339,146
347 | 151,395,183
348 | 177,162,178
349 | 379,32,239
350 | 416,444,121
351 | 178,426,188
352 | 100,267,223
353 | 322,64,240
354 | 416,167,205
355 | 329,42,238
356 | 43,284,208
357 | 396,11,218
358 | 94,301,212
359 | 385,252,213
360 | 498,241,172
361 | 34,214,194
362 | 336,89,241
363 | 263,92,216
364 | 409,457,133
365 | 89,417,196
366 | 114,104,150
367 | 390,195,208
368 | 313,113,225
369 | 492,74,183
370 | 412,375,105
371 | 419,216,203
372 | 276,248,181
373 | 163,393,170
374 | 356,456,142
375 | 407,191,206
376 | 226,176,200
377 | 98,495,185
378 | 35,465,183
379 | 496,486,147
380 | 95,151,133
381 | 150,189,173
382 | 223,36,232
383 | 267,368,198
384 | 182,12,212
385 | 278,216,143
386 | 354,360,105
387 | 285,272,203
388 | 368,61,229
389 | 83,367,197
390 | 216,341,208
391 | 396,186,205
392 | 18,176,216
393 | 99,395,211
394 | 444,232,161
395 | 402,75,229
396 | 264,454,182
397 | 283,205,175
398 | 222,383,172
399 | 51,338,200
400 | 366,143,219
401 | 372,68,230
402 | 98,395,210
403 | 24,435,189
404 | 378,468,134
405 | 483,52,194
406 | 150,143,170
407 | 56,38,207
408 | 108,180,128
409 | 41,185,129
410 | 422,397,109
411 | 222,121,180
412 | 132,162,164
413 | 214,220,184
414 | 234,330,190
415 | 145,238,225
416 | 75,8,225
417 | 73,441,191
418 | 491,400,177
419 | 252,229,140
420 | 6,173,214
421 | 140,167,172
422 | 169,392,180
423 | 433,282,128
424 | 121,193,148
425 | 4,28,222
426 | 164,421,182
427 | 338,135,226
428 | 495,364,195
429 | 320,341,132
430 | 499,144,196
431 | 326,216,218
432 | 300,131,225
433 | 291,69,247
434 | 251,414,187
435 | 274,444,176
436 | 363,181,214
437 | 166,90,168
438 | 201,345,210
439 | 18,38,221
440 | 125,450,194
441 | 172,140,206
442 | 241,219,145
443 | 125,57,169
444 | 147,475,180
445 | 455,316,101
446 | 382,360,87
447 | 422,0,202
448 | 386,460,131
449 | 347,189,218
450 | 190,368,195
451 | 408,311,147
452 | 416,421,106
453 | 116,133,168
454 | 57,43,203
455 | 172,159,175
456 | 172,316,204
457 | 302,148,223
458 | 79,373,201
459 | 212,202,171
460 | 251,228,144
461 | 163,226,229
462 | 146,19,225
463 | 440,401,110
464 | 46,232,188
465 | 304,13,229
466 | 142,414,196
467 | 0,372,192
468 | 53,373,206
469 | 258,143,228
470 | 470,440,152
471 | 458,11,176
472 | 329,223,215
473 | 271,455,165
474 | 357,459,140
475 | 407,155,213
476 | 372,7,231
477 | 121,347,171
478 | 163,89,160
479 | 135,185,166
480 | 315,177,218
481 | 27,219,207
482 | 356,40,227
483 | 227,191,198
484 | 410,446,109
485 | 144,200,168
486 | 416,211,196
487 | 460,219,122
488 | 239,412,186
489 | 396,45,235
490 | 34,252,196
491 | 389,81,230
492 | 370,255,211
493 | 196,302,191
494 | 408,449,123
495 | 9,311,203
496 | 285,241,197
497 | 250,364,193
498 | 4,118,218
499 | 288,373,170
500 | 64,145,212
501 | 223,238,179
502 |
--------------------------------------------------------------------------------
/doc/auto_examples/geostat/images/sphx_glr_plot_gridsearch_001.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
6 |
7 |
--------------------------------------------------------------------------------
/hydrobox/discharge/catchment.py:
--------------------------------------------------------------------------------
1 | """
2 | Common tools for diagnosic tools frequently used in catchment hydrology.
3 |
4 | """
5 | from typing import Union, Optional, Any
6 | from matplotlib.axes import SubplotBase
7 | from matplotlib.pyplot import Figure
8 | import numpy as np
9 | import pandas as pd
10 | from datetime import datetime
11 | from scipy.stats import rankdata
12 |
13 | from hydrobox.plotting import plot_function_loader
14 |
15 |
16 | def flow_duration_curve(
17 | x: Union[np.ndarray, pd.Series],
18 | log: bool = True,
19 | plot: bool = True,
20 | non_exceeding:bool = True,
21 | ax: Optional[Union[SubplotBase, Any]] = None,
22 | **kwargs
23 | ) -> Union[np.ndarray, Figure]:
24 | """Calculate a flow duration curve
25 |
26 | Calculate flow duration curve from the discharge measurements. The
27 | function can either return a ``matplotlib`` plot or return the ordered (
28 | non)-exceeding probabilities of the observations. These values can then
29 | be used in any external plotting environment.
30 |
31 | In case x.ndim > 1, the function will be called iteratively along axis 0.
32 |
33 | Parameters
34 | ----------
35 | x : numpy.ndarray, pandas.Series
36 | Series of prefereably discharge measurements
37 | log : bool, default=True
38 | if `True` plot on loglog axis, ignored when plot is `False`
39 | plot : bool, default=True
40 | if `False` plotting will be suppressed and the resulting array will
41 | be returned
42 | non_exceeding : bool, default=True
43 | if `True` use non-exceeding probabilities
44 | ax : matplotlib.AxesSubplot | bokeh.Figure , default=None
45 | if not None, will plot into that AxesSubplot or Figure instance.
46 | .. note::
47 | If you pass an object, be sure to set the correct plotting
48 | backend first.
49 | kwargs : kwargs,
50 | will be passed to the ``matplotlib.pyplot.plot`` function
51 |
52 | Returns
53 | -------
54 | matplotlib.Figure :
55 | if `plot` was `True`
56 | numpy.ndarray :
57 | if `plot was `False`
58 |
59 | Notes
60 | -----
61 | The probabilities are calculated using the Weibull empirical probability.
62 | Following [1]_, this probability can be calculated as:
63 |
64 | .. math:: p =m/(n + 1)
65 |
66 | where `m` is the rank of an observation in the ordered time series and
67 | `n` are the total observations. The increasion by one will prevent 0%
68 | and 100% probabilities.
69 |
70 | References
71 | ----------
72 | .. [1] Sloto, R. a., & Crouse, M. Y. (1996). Hysep: a computer program
73 | for streamflow hydrograph separation and analysis. U.S. Geological
74 | Survey Water-Resources Investigations Report, 96(4040), 54.
75 |
76 | """
77 | # omit the Series index
78 | if isinstance(x, pd.Series):
79 | x = x.values
80 |
81 | # if x has more than one dimension call this func recursive along axis=0
82 | if x.ndim > 1:
83 | # check if plot was None, then iterate along axis=0
84 | if not plot:
85 | return np.apply_along_axis(flow_duration_curve, 0, x, non_exceeding=non_exceeding, plot=False)
86 | else:
87 | # plot, if ax is None, create
88 | if ax is None:
89 | fig, ax = plt.subplots(1,1)
90 | last_ax = list(map(lambda x: flow_duration_curve(x, log=log, non_exceeding=non_exceeding, ax=ax), x.T))[-1]
91 | return last_ax
92 |
93 | # calculate the ranks
94 | ranks = rankdata(x, method='average')
95 |
96 | # calculate weibull pdf
97 | N = x.size
98 |
99 | # calculate probabilities
100 | p = np.fromiter(map(lambda r: r / (N + 1), ranks), dtype=np.float)
101 |
102 | # create sorting index
103 | if non_exceeding:
104 | index = np.argsort(p)
105 | else:
106 | index = np.argsort(p)[::-1]
107 |
108 | if not plot:
109 | return p[index]
110 | else:
111 | pfunc = plot_function_loader('flow_duration_curve')
112 |
113 | fig = pfunc(func_args=dict(
114 | x=x[index],
115 | y=p[index],
116 | non_exceeding=non_exceeding,
117 | log=log,
118 | figure=ax),
119 | plot_args=kwargs
120 | )
121 | return fig
122 |
123 |
124 | def regime(x, percentiles=None, normalize=False, agg='nanmedian', plot=True,
125 | ax=None, cmap='blues', **kwargs):
126 | r"""Calculate hydrological regime
127 |
128 | Calculate a hydrological regime from discharge measurements. A regime is
129 | a annual overview, where all observations are aggregated across the
130 | month. Therefore it does only make sense to calculate a regime over more
131 | than one year with a temporal resolution higher than monthly.
132 |
133 | The regime can either be plotted or the calculated monthly aggreates can
134 | be returned (along with the quantiles, if any were calculated).
135 |
136 | Parameters
137 | ----------
138 | x : pandas.Series
139 | The ``Series`` has to be indexed by a ``pandas.DatetimeIndex`` and
140 | hold the preferably discharge measurements. However, the methods
141 | does also work for other observables, if `agg` is adjusted.
142 | percentiles : int, list, numpy.ndarray, default=None
143 | percentiles can be used to calculate percentiles along with the main
144 | aggregate. The percentiles can either be set by an integer or a list.
145 | If an integer is passed, that many percentiles will be evenly spreaded
146 | between the 0th and 100th percentiles. A list can set the desired
147 | percentiles directly.
148 | normalize : bool, default=False
149 | If `True`, the regime will be normalized by the aggregate over all
150 | months. Then the numbers do not give the discharge itself, but the
151 | ratio of the monthly discharge to the overall discharge.
152 | agg : string, default='nanmedian'
153 | Define the function used for aggregation. Usually this will be
154 | 'mean' or 'median'. If there might be `NaN` values in the
155 | observations, the 'nan' prefixed functions can be used. In general,
156 | any aggregating function, which can be imported from ``numpy`` can
157 | be used.
158 | plot : bool, default=True
159 | if `False` plotting will be suppressed and the resulting
160 | ``pandas.DataFrame`` will be returned. In case `quantiles` was None,
161 | only the regime values will be returned as `numpy.ndarray`
162 | ax : matplotlib.AxesSubplot, default=None
163 | if not None, will plot into that AxesSubplot instance
164 | cmap : string, optional
165 | Specify a colormap for generating the Percentile areas is a smooth
166 | color gradient. This has to be a valid
167 | `colorcet colormap reference `_.
168 | Defaults to ``'Blue'``.
169 | color : string, optional
170 | Define the color of the main aggregate. If ``None``, the first color
171 | of the specified cmap will be used.
172 | lw : int, optinal
173 | linewidth parameter in pixel. Defaults to 3.
174 | linestyle : string, optional
175 | Any valid matplotlib linestyle definition is accepted.
176 |
177 | ``':'`` - dotted
178 |
179 | ``'-.'`` - dash-dotted
180 |
181 | ``'--'`` - dashed
182 |
183 | ``'-'`` - solid
184 |
185 |
186 | Returns
187 | -------
188 | matplotlib.Figure :
189 | if `plot` was `True`
190 | pandas.DataFrame :
191 | if `plot` was `False` and `quantiles` are not None
192 | numpy.ndarray :
193 | if `plot` was `False` and `quantiles` is None
194 |
195 | Notes
196 | -----
197 |
198 | In case the color argument is not passed it will default to the first
199 | color in the the specified colormap (cmap). You might want to overwrite
200 | this in case no percentiles are produced, as many colormaps range from
201 | light to dark colors and the first color might just default to while.
202 |
203 | """
204 | if not isinstance(x.index, pd.DatetimeIndex):
205 | raise ValueError('Data has to be indexed by a pandas.DatetimeIndex.')
206 |
207 | # create the percentiles
208 | if isinstance(percentiles, int):
209 | percentiles = np.linspace(0, 100, percentiles + 1, endpoint=False)[1:]
210 |
211 | if callable(agg):
212 | f = agg
213 | else:
214 | try:
215 | f = getattr(np, agg)
216 | except AttributeError:
217 | raise ValueError('The function %s cannot be imported from numpy')
218 |
219 | # create month index
220 | idx = [int(datetime.strftime(_, '%m')) for _ in x.index]
221 |
222 | # aggregate the regime and set the index
223 | if isinstance(x, pd.Series):
224 | x = pd.DataFrame(index=x.index, data=x.values)
225 | df = x.groupby(idx).aggregate(f)
226 | df.set_index(np.unique(idx), inplace=True)
227 |
228 | # build percentiles
229 | if percentiles is not None:
230 | for q in percentiles:
231 | df['q%d' % q] = x.groupby(idx).aggregate(
232 | lambda v: np.nanpercentile(v, q))
233 |
234 | # handle normalize
235 | if normalize:
236 | for col in df.columns:
237 | df[col] = df[col] / f(df[col])
238 |
239 | if not plot:
240 | if len(df.columns) == 1:
241 | return df.values
242 | else:
243 | return df
244 | else:
245 | pfunc = plot_function_loader('regime')
246 |
247 | # check if a colormap was set
248 | fig = pfunc(
249 | func_args=dict(df=df, figure=ax, cmap=cmap),
250 | plot_args=kwargs
251 | )
252 |
253 | return fig
254 |
--------------------------------------------------------------------------------
/doc/auto_examples/geostat/images/sphx_glr_plot_variogram_001.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
6 |
7 |
--------------------------------------------------------------------------------
/hydrobox/geostat/kriging.py:
--------------------------------------------------------------------------------
1 | from typing import List, Union, Literal
2 | import numpy as np
3 | import skgstat as skg
4 | import plotly.graph_objects as go
5 |
6 | from hydrobox.plotting import plot_function_loader
7 |
8 | def _kriging(
9 | variogram: skg.Variogram,
10 | grid_resolution = None,
11 | return_type = 'plot',
12 | plot_kwargs = {},
13 | **kwargs
14 | ) -> Union[List[np.ndarray], go.Figure]:
15 | """
16 | Actual interface to gstools
17 | """
18 | # get the kriging class
19 | krige = variogram.to_gs_krige(**kwargs)
20 |
21 | if return_type == 'object':
22 | return krige
23 |
24 | # build the grid
25 | if isinstance(grid_resolution, int):
26 | # get the coordinate ranges
27 | lower = np.min(variogram.coordinates, axis=0)
28 | upper = np.max(variogram.coordinates, axis=0)
29 | dims = [np.linspace(l, u, grid_resolution) for l, u in zip(lower, upper)]
30 | else:
31 | raise AttributeError('Right now, only integer grid_resolutions are supported.')
32 |
33 | # call structured
34 | field, sigma = krige.structured(dims)
35 |
36 | if return_type == 'grid':
37 | return (field, sigma)
38 |
39 | # return the plot
40 | if field.ndim > 2:
41 | raise ValueError('Plotting not supported for dim > 2.')
42 |
43 | pfunc = plot_function_loader('kriging')
44 | fig = pfunc(
45 | func_args=dict(
46 | variogram=variogram,
47 | field=field,
48 | sigma=sigma
49 | ),
50 | plot_args=plot_kwargs
51 | )
52 |
53 | return fig
54 |
55 |
56 | def ordinary_kriging(
57 | variogram: skg.Variogram,
58 | grid_resolution: int,
59 | exact: bool = True,
60 | cond_err: Union[Literal['nugget'], float, list] = 'nugget',
61 | pseudo_inv: bool = True,
62 | pseudo_inv_type: Literal['pinv', 'pinv2', 'pinvh'] = 'pinv',
63 | return_type: Literal['object', 'plot', 'grid'] = 'plot',
64 | **kwargs
65 | ) -> Union[List[np.ndarray], go.Figure]:
66 | """
67 | Use a scikit-gstat :class:`Variogram ` to estimate
68 | spatial properties of a sample. Uses this variogram to interpolate
69 | using kriging. The Kriging is done with the
70 | :class:`Ordinary ` class. Refer to the docs
71 | of :class:`Ordinary ` to learn about the
72 | parameters.
73 |
74 | .. note::
75 | Right now, there are only very limited possibilities to specify
76 | an interpolation grid. Only setting the resolution of the result
77 | like: ``50x50`` is possible by passing the integer ``50``.
78 | More fine-grained control will be added with a future release.
79 |
80 | Parameters
81 | ----------
82 | variogram : skgstat.Variogram
83 | Variogram used for kriging
84 | grid_resolution : int
85 | Resoultion of the interpolation grid. The resolution will be used
86 | in all input data dimensions, which can lead to non-quadratic
87 | grid cells.
88 | exact : bool
89 | If True (default), the input data will be matched exactly.
90 | Refer to :class:`Ordinary `
91 | for more info.
92 | cond_err : str, float, list
93 | Measurement error, or variogram nugget.
94 | Refer to :class:`Ordinary `
95 | for more info.
96 | pseudo_inv : bool
97 | If True, the Kriging is more robust, but also slower.
98 | Refer to :class:`Ordinary `
99 | for more info.
100 | pseudo_inv_type : str
101 | Type of matrix inversion used if pseudo_inv is True.
102 | Refer to :class:`Ordinary `
103 | for more info.
104 | return_type : str
105 | Specify how the result should be retuned. Can be the
106 | kriging class itself (``'object'``), the interpolated
107 | grid (``'grid'``) or a plot of the grid (``'plot'``).
108 |
109 | Returns
110 | -------
111 | results : numpy.ndarray, numpy.ndarray
112 | Interpolation grid and kriging error grid
113 | fig : plotly.graph_objects.Figure, matplotlib.Figure
114 | Figure of the result plot.
115 |
116 | """
117 | # build the kwargs
118 | args = dict(
119 | exact=exact,
120 | cond_err=cond_err,
121 | pseudo_inv=pseudo_inv,
122 | pseudo_inv_type=pseudo_inv_type
123 | )
124 |
125 | # return the results
126 | return _kriging(
127 | variogram=variogram,
128 | grid_resolution=grid_resolution,
129 | return_type=return_type,
130 | plot_kwargs=kwargs,
131 | **args
132 | )
133 |
134 | def simple_kriging(
135 | variogram: skg.Variogram,
136 | grid_resolution: int,
137 | mean: float,
138 | exact: bool = True,
139 | cond_err: Union[Literal['nugget'], float, list] = 'nugget',
140 | pseudo_inv: bool = True,
141 | pseudo_inv_type: Literal['pinv', 'pinv2', 'pinvh'] = 'pinv',
142 |
143 | return_type: Literal['object', 'plot', 'grid'] = 'plot',
144 | **kwargs
145 | ) -> Union[List[np.ndarray], go.Figure]:
146 | """
147 | Use a scikit-gstat :class:`Variogram ` to estimate
148 | spatial properties of a sample. Uses this variogram to interpolate
149 | using kriging. The Kriging is done with the
150 | :class:`Simple ` class. Refer to the docs
151 | of :class:`Simple ` to learn about the
152 | parameters.
153 |
154 | For simple kriging you need to pass the real mean value of the
155 | field (not the sample) in order to work correctly. If that is not
156 | available, refer to :func:`ordinary_kriging `.
157 |
158 | .. note::
159 | Right now, there are only very limited possibilities to specify
160 | an interpolation grid. Only setting the resolution of the result
161 | like: ``50x50`` is possible by passing the integer ``50``.
162 | More fine-grained control will be added with a future release.
163 |
164 | Parameters
165 | ----------
166 | variogram : skgstat.Variogram
167 | Variogram used for kriging
168 | grid_resolution : int
169 | Resoultion of the interpolation grid. The resolution will be used
170 | in all input data dimensions, which can lead to non-quadratic
171 | grid cells.
172 | mean : float
173 | The mean value of the field, that has to be known a priori.
174 | If you pass bs here, you will interpolate bs.
175 | exact : bool
176 | If True (default), the input data will be matched exactly.
177 | Refer to :class:`Simple `
178 | for more info.
179 | cond_err : str, float, list
180 | Measurement error, or variogram nugget.
181 | Refer to :class:`Simple `
182 | for more info.
183 | pseudo_inv : bool
184 | If True, the Kriging is more robust, but also slower.
185 | Refer to :class:`Simple `
186 | for more info.
187 | pseudo_inv_type : str
188 | Type of matrix inversion used if pseudo_inv is True.
189 | Refer to :class:`Simple `
190 | for more info.
191 | return_type : str
192 | Specify how the result should be retuned. Can be the
193 | kriging class itself (``'object'``), the interpolated
194 | grid (``'grid'``) or a plot of the grid (``'plot'``).
195 |
196 | Returns
197 | -------
198 | results : numpy.ndarray, numpy.ndarray
199 | Interpolation grid and kriging error grid
200 | fig : plotly.graph_objects.Figure, matplotlib.Figure
201 | Figure of the result plot.
202 |
203 | """
204 | # build the kwargs
205 | args = dict(
206 | mean=mean,
207 | exact=exact,
208 | cond_err=cond_err,
209 | pseudo_inv=pseudo_inv,
210 | pseudo_inv_type=pseudo_inv_type
211 | )
212 |
213 | # return the results
214 | return _kriging(
215 | variogram=variogram,
216 | grid_resolution=grid_resolution,
217 | return_type=return_type,
218 | plot_kwargs=kwargs,
219 | **args
220 | )
221 |
222 |
223 | def universal_kriging(
224 | variogram: skg.Variogram,
225 | grid_resolution: int,
226 | drift_functions: Literal['linear', 'quadratic'],
227 | exact: bool = True,
228 | cond_err: Union[Literal['nugget'], float, list] = 'nugget',
229 | pseudo_inv: bool = True,
230 | pseudo_inv_type: Literal['pinv', 'pinv2', 'pinvh'] = 'pinv',
231 |
232 | return_type: Literal['object', 'plot', 'grid'] = 'plot',
233 | **kwargs
234 | ) -> Union[List[np.ndarray], go.Figure]:
235 | """
236 | Use a scikit-gstat :class:`Variogram ` to estimate
237 | spatial properties of a sample. Uses this variogram to interpolate
238 | using kriging. The Kriging is done with the
239 | :class:`Universal ` class. Refer to the docs
240 | of :class:`Universal ` to learn about the
241 | parameters.
242 |
243 | For universal kriging you need to specify the interal drift term of
244 | the field. Then, this auto-regression will be taken into account
245 | for kriging. This is useful for fields, that acutally show a drift.
246 | If that is not the case, refer to
247 | :func:`ordinary_kriging ` or
248 | :func:`ext_drift_kriging ` for
249 | external drifts.
250 |
251 | .. note::
252 | Right now, there are only very limited possibilities to specify
253 | an interpolation grid. Only setting the resolution of the result
254 | like: ``50x50`` is possible by passing the integer ``50``.
255 | More fine-grained control will be added with a future release.
256 |
257 | Parameters
258 | ----------
259 | variogram : skgstat.Variogram
260 | Variogram used for kriging
261 | grid_resolution : int
262 | Resoultion of the interpolation grid. The resolution will be used
263 | in all input data dimensions, which can lead to non-quadratic
264 | grid cells.
265 | drift_functions : str
266 | The drift function used to perform regression kriging on the
267 | values of the sample. Can be either ``'linear'`` or ``'quadratic'``.
268 | Polynomials of higher order are currently only supported, if you use
269 | :class:`Universal ` directly.
270 | exact : bool
271 | If True (default), the input data will be matched exactly.
272 | Refer to :class:`Universal `
273 | for more info.
274 | cond_err : str, float, list
275 | Measurement error, or variogram nugget.
276 | Refer to :class:`Universal `
277 | for more info.
278 | pseudo_inv : bool
279 | If True, the Kriging is more robust, but also slower.
280 | Refer to :class:`Universal `
281 | for more info.
282 | pseudo_inv_type : str
283 | Type of matrix inversion used if pseudo_inv is True.
284 | Refer to :class:`Universal `
285 | for more info.
286 | return_type : str
287 | Specify how the result should be retuned. Can be the
288 | kriging class itself (``'object'``), the interpolated
289 | grid (``'grid'``) or a plot of the grid (``'plot'``).
290 |
291 | Returns
292 | -------
293 | results : numpy.ndarray, numpy.ndarray
294 | Interpolation grid and kriging error grid
295 | fig : plotly.graph_objects.Figure, matplotlib.Figure
296 | Figure of the result plot.
297 |
298 | """
299 | # build the kwargs
300 | args = dict(
301 | drift_functions=drift_functions,
302 | exact=exact,
303 | cond_err=cond_err,
304 | pseudo_inv=pseudo_inv,
305 | pseudo_inv_type=pseudo_inv_type
306 | )
307 |
308 | # return the results
309 | return _kriging(
310 | variogram=variogram,
311 | grid_resolution=grid_resolution,
312 | return_type=return_type,
313 | plot_kwargs=kwargs,
314 | **args
315 | )
316 |
317 |
318 | def ext_drift_kriging(
319 | variogram: skg.Variogram,
320 | grid_resolution: int,
321 | ext_drift: np.ndarray,
322 | exact: bool = True,
323 | cond_err: Union[Literal['nugget'], float, list] = 'nugget',
324 | pseudo_inv: bool = True,
325 | pseudo_inv_type: Literal['pinv', 'pinv2', 'pinvh'] = 'pinv',
326 |
327 | return_type: Literal['object', 'plot', 'grid'] = 'plot',
328 | **kwargs
329 | ) -> Union[List[np.ndarray], go.Figure]:
330 | """
331 | Use a scikit-gstat :class:`Variogram ` to estimate
332 | spatial properties of a sample. Uses this variogram to interpolate
333 | using kriging. The Kriging is done with the
334 | :class:`ExtDrift ` class. Refer to the docs
335 | of :class:`ExtDrift ` to learn about the
336 | parameters.
337 |
338 | For external drift kriging you need to specify the external drift term of
339 | the field. Then, the regression between drift and sample will be taken
340 | into account for kriging. This is useful for fields, that are actually
341 | correlated to other fields, which are (more) available.
342 | If that is not the case, refer to
343 | :func:`ordinary_kriging ` for kriging
344 | without drift.
345 |
346 | .. note::
347 | Right now, there are only very limited possibilities to specify
348 | an interpolation grid. Only setting the resolution of the result
349 | like: ``50x50`` is possible by passing the integer ``50``.
350 | More fine-grained control will be added with a future release.
351 |
352 | Parameters
353 | ----------
354 | variogram : skgstat.Variogram
355 | Variogram used for kriging
356 | grid_resolution : int
357 | Resoultion of the interpolation grid. The resolution will be used
358 | in all input data dimensions, which can lead to non-quadratic
359 | grid cells.
360 | ext_drift : np.ndarray
361 | External drift values at the observation points
362 | exact : bool
363 | If True (default), the input data will be matched exactly.
364 | Refer to :class:`ExtDrift `
365 | for more info.
366 | cond_err : str, float, list
367 | Measurement error, or variogram nugget.
368 | Refer to :class:`ExtDrift `
369 | for more info.
370 | pseudo_inv : bool
371 | If True, the Kriging is more robust, but also slower.
372 | Refer to :class:`ExtDrift `
373 | for more info.
374 | pseudo_inv_type : str
375 | Type of matrix inversion used if pseudo_inv is True.
376 | Refer to :class:`ExtDrift `
377 | for more info.
378 | return_type : str
379 | Specify how the result should be retuned. Can be the
380 | kriging class itself (``'object'``), the interpolated
381 | grid (``'grid'``) or a plot of the grid (``'plot'``).
382 |
383 | Returns
384 | -------
385 | results : numpy.ndarray, numpy.ndarray
386 | Interpolation grid and kriging error grid
387 | fig : plotly.graph_objects.Figure, matplotlib.Figure
388 | Figure of the result plot.
389 |
390 | """
391 | # build the kwargs
392 | args = dict(
393 | ext_drift=ext_drift,
394 | exact=exact,
395 | cond_err=cond_err,
396 | pseudo_inv=pseudo_inv,
397 | pseudo_inv_type=pseudo_inv_type
398 | )
399 |
400 | # return the results
401 | return _kriging(
402 | variogram=variogram,
403 | grid_resolution=grid_resolution,
404 | return_type=return_type,
405 | plot_kwargs=kwargs,
406 | **args
407 | )
408 |
--------------------------------------------------------------------------------
/hydrobox/data/sample_lr.csv:
--------------------------------------------------------------------------------
1 | x,y,z
2 | 94,20,0.17661322082829045
3 | 82,37,-0.3207010463901736
4 | 43,13,-1.5791608633401637
5 | 78,42,-0.12918176158773187
6 | 50,28,0.06193013878439768
7 | 20,74,-1.6374827765933684
8 | 71,88,-1.858503546615741
9 | 7,9,-2.2898204111891904
10 | 24,69,-1.3764931871575385
11 | 77,28,-0.51886478030234
12 | 71,17,-1.1181432792909387
13 | 29,74,-0.748229238419845
14 | 49,59,-0.6779915431776902
15 | 100,12,0.6980337958864397
16 | 5,52,-1.8623145942239685
17 | 16,82,-1.525733702020418
18 | 16,17,-2.235361716564011
19 | 88,58,-0.9473674557929835
20 | 52,49,-0.6218424486113452
21 | 63,85,-0.7137101006679549
22 | 26,13,-2.233203327988773
23 | 19,36,-2.7690793642446856
24 | 36,79,0.0885996449094657
25 | 57,97,-1.2891444652552995
26 | 62,99,-1.6955816715574992
27 | 32,30,-1.636720746148537
28 | 39,59,-0.6014147884625802
29 | 29,90,-0.3405554569305569
30 | 99,32,-1.0648224187732502
31 | 44,6,-1.780445089380506
32 | 43,58,-0.707720879391547
33 | 85,39,-0.2971655349137281
34 | 70,54,-0.562919352659155
35 | 91,79,-1.9355653555392103
36 | 72,73,-0.8608591121279774
37 | 26,14,-2.1637093061703965
38 | 74,27,-0.6562635968364894
39 | 95,81,-1.9809567707197226
40 | 57,64,-0.38711158283427416
41 | 91,89,-1.87401068011749
42 | 16,15,-2.2566753026598363
43 | 43,64,-0.18779952749791776
44 | 51,23,-0.24391077717583054
45 | 48,15,-1.0182932663054767
46 | 44,62,-0.3916939427844982
47 | 89,87,-1.9013742125644497
48 | 75,44,-0.12259321072147955
49 | 28,60,-1.2435869570024023
50 | 40,15,-1.6411211195497688
51 | 93,11,0.9901342952119029
52 | 15,63,-1.8971163726900049
53 | 88,29,-0.3906580021712931
54 | 2,23,-2.297950025708991
55 | 46,96,-0.5177499765223532
56 | 65,3,-0.6385024731290623
57 | 88,37,-0.43989363732161757
58 | 65,95,-1.615015156438801
59 | 41,7,-2.066419299383491
60 | 25,80,-1.1585321573984553
61 | 21,27,-2.3369205465026006
62 | 91,12,0.8747629151859433
63 | 32,81,-0.3357578212761244
64 | 65,83,-0.7916270264730879
65 | 72,27,-0.7166782020050888
66 | 31,80,-0.4456177296618178
67 | 34,77,-0.09253809790344958
68 | 75,52,-0.4944770605931659
69 | 83,57,-0.8842660134072124
70 | 53,54,-0.688018526555087
71 | 5,48,-1.9007745541601544
72 | 63,37,-0.036396820195912394
73 | 52,88,-0.11755753250379702
74 | 52,80,0.26083445224418955
75 | 88,59,-1.0235448405655787
76 | 82,40,-0.21308806967593508
77 | 88,97,-2.192149582082118
78 | 16,39,-2.57650062187516
79 | 50,30,0.08647437324546103
80 | 94,10,1.0438097256819132
81 | 32,38,-1.7634540702631607
82 | 44,24,-0.5655178353752265
83 | 49,69,0.10714984406004735
84 | 80,28,-0.4022423169385094
85 | 44,97,-0.3529837795434546
86 | 9,72,-1.493369502775304
87 | 62,83,-0.43023196900276084
88 | 55,87,-0.13966611700693143
89 | 73,88,-2.001203548269883
90 | 74,77,-1.2379156042029587
91 | 41,10,-1.9249687471386818
92 | 80,70,-1.1829197791574524
93 | 84,91,-2.0139814304259325
94 | 19,41,-2.648833447808755
95 | 74,95,-2.144917804214962
96 | 53,77,0.33511688709641435
97 | 77,71,-1.0958441907152565
98 | 26,80,-1.0484840863497462
99 | 60,29,-0.15746426177681877
100 | 87,66,-1.4554380448773045
101 | 49,26,-0.05826749235010553
102 | 58,7,-0.47144621640817697
103 | 83,34,-0.39094849493512274
104 | 98,71,-1.9237550851324507
105 | 19,33,-2.724482730994292
106 | 69,37,-0.19617085984139937
107 | 77,16,-0.6982227690277982
108 | 17,5,-2.679609599992811
109 | 12,3,-2.393815880403184
110 | 36,10,-2.200362886449826
111 | 60,92,-0.9653420438677074
112 | 87,26,-0.22706606640650318
113 | 42,88,-0.017394586984581628
114 | 95,68,-1.7949386705859134
115 | 26,73,-1.1494570516013114
116 | 75,87,-2.0476740998248477
117 | 8,72,-1.453241687219668
118 | 72,38,-0.2239143636791041
119 | 91,53,-0.5343666751715851
120 | 17,43,-2.470978552057021
121 | 78,44,-0.11886190567323107
122 | 47,80,0.29971188155784123
123 | 44,90,-0.14506121193081833
124 | 14,73,-1.6464001409249398
125 | 1,99,0.8621365077720762
126 | 89,52,-0.517258377611627
127 | 44,88,-0.0363550476333383
128 | 56,6,-0.4356724214414587
129 | 70,64,-0.7483161345237008
130 | 40,85,0.11266127425524186
131 | 46,21,-0.6348481212770275
132 | 41,39,-0.9151652582357036
133 | 45,93,-0.32709656867469084
134 | 8,46,-1.956116172182285
135 | 29,41,-2.0518284286335646
136 | 32,98,0.5108174703489414
137 | 80,100,-2.3718975366467783
138 | 65,94,-1.558318900246572
139 | 26,63,-1.3136947673080608
140 | 49,6,-1.0853779497566807
141 | 56,48,-0.4746929723443394
142 | 22,92,-0.050939348864365686
143 | 56,35,0.10521867373159269
144 | 66,26,-0.6878157094089083
145 | 48,67,-0.04724092238592936
146 | 100,75,-1.9502445541949465
147 | 81,75,-1.380494282386387
148 | 33,49,-1.37446193234031
149 | 27,99,0.7820546540086415
150 | 85,68,-1.397462150202891
151 | 82,71,-1.2858483945142325
152 | 80,82,-1.8152881183906717
153 | 65,13,-1.0749494112946858
154 | 96,76,-2.071341870001821
155 | 2,74,-1.1474806263319375
156 | 85,31,-0.3949454326592716
157 | 4,33,-2.0216392960998353
158 | 67,50,-0.3776767866561772
159 | 55,83,0.09336374628318461
160 | 15,38,-2.5498408545196662
161 | 71,100,-2.124660532422709
162 | 83,1,0.00753106904473122
163 | 88,45,-0.29848335196099796
164 | 39,95,-0.017715934399532784
165 | 25,6,-2.7799209048687734
166 | 100,49,-0.8099195511680906
167 | 44,86,0.07335949065343661
168 | 18,92,-0.02618846088130722
169 | 89,36,-0.49680436983084364
170 | 7,35,-2.087743834816001
171 | 63,46,-0.21817431581240973
172 | 22,84,-1.1700386981447077
173 | 68,34,-0.3061988541921356
174 | 96,11,1.0078034603595811
175 | 87,38,-0.38175987635970254
176 | 29,79,-0.6963000891333997
177 | 83,59,-0.981709233461278
178 | 82,99,-2.3483083534752787
179 | 65,17,-1.0499038793943516
180 | 11,54,-2.0803785700683717
181 | 70,100,-2.0839131681963616
182 | 89,27,-0.3176001715557155
183 | 59,70,0.055612810840010185
184 | 57,19,-0.6883903772704523
185 | 14,47,-2.1729197642131926
186 | 77,1,-0.5267518387415159
187 | 64,6,-0.7333618231393997
188 | 81,29,-0.3902969453115981
189 | 78,97,-2.2302849940746485
190 | 98,48,-0.7387425066645357
191 | 13,16,-2.2739593266738316
192 | 53,92,-0.5402081195779718
193 | 82,7,-0.2123184354314288
194 | 6,56,-1.8080489427304802
195 | 15,51,-2.2052121688938855
196 | 90,76,-1.8663876215638298
197 | 24,11,-2.417109991316271
198 | 70,15,-1.1805092648280848
199 | 42,82,0.2630835801096074
200 | 88,40,-0.373680890383314
201 | 85,88,-1.9428871090998012
202 | 10,71,-1.5196561538025293
203 | 23,88,-0.6562316524018308
204 | 98,73,-2.000726315288191
205 | 65,57,-0.6868317632131439
206 | 32,16,-1.8735371946700585
207 | 50,93,-0.5418013679886537
208 | 60,24,-0.4798449995240417
209 | 13,71,-1.6127038067606148
210 | 11,32,-2.4717564222383475
211 | 52,82,0.19495400241951066
212 | 54,66,-0.1673704661258293
213 | 39,41,-1.0884098541110165
214 | 95,32,-0.8090650853502542
215 | 31,13,-2.1201157878945995
216 | 88,18,0.41588964674209783
217 | 4,96,0.7992532380652542
218 | 43,31,-0.5503366257619469
219 | 26,17,-1.9899582693934583
220 | 38,73,0.2160606828095507
221 | 61,50,-0.39970101959180576
222 | 76,34,-0.4454865189856453
223 | 19,79,-1.6303187866323594
224 | 77,92,-2.163166980019689
225 | 77,98,-2.2465901175266922
226 | 43,26,-0.5811592080226924
227 | 27,44,-2.1659560829252635
228 | 83,37,-0.32736459067796686
229 | 87,44,-0.25946413563689963
230 | 10,32,-2.4009731778059358
231 | 99,81,-1.84711795069224
232 | 83,42,-0.170447818369019
233 | 46,42,-0.5598270985322223
234 | 95,31,-0.7854633078108808
235 | 74,35,-0.40003093809914714
236 | 17,11,-2.4055715871298533
237 | 72,95,-2.07321342744388
238 | 11,9,-2.378030753046553
239 | 20,96,0.6070206479774166
240 | 7,99,1.1549742981454196
241 | 80,91,-2.108705875301451
242 | 55,44,-0.33029033830123533
243 | 39,97,0.0869365336455864
244 | 85,66,-1.3447517859904923
245 | 77,58,-0.7596157342630092
246 | 63,28,-0.40013088372553773
247 | 13,85,-1.1694233617957366
248 | 16,34,-2.7083348507444938
249 | 40,50,-0.9975796979615644
250 | 80,14,-0.34663881702460553
251 | 47,16,-1.0272045496768052
252 | 100,77,-1.933338746114981
253 | 38,37,-1.19666485903018
254 | 88,49,-0.376030345473334
255 | 81,31,-0.4126154276943079
256 | 94,27,-0.5431767284514204
257 | 45,84,0.16637372642528714
258 | 47,2,-1.4629518756615267
259 | 61,58,-0.6693361835816842
260 | 97,14,0.7277068357623439
261 | 31,33,-1.784518372104861
262 | 68,28,-0.6484261059439498
263 | 92,71,-1.9091105207618067
264 | 58,25,-0.2990684187478496
265 | 27,23,-1.8509669330818217
266 | 32,67,-0.43981530630801824
267 | 54,36,0.07160993532756277
268 | 88,57,-0.8724587676276928
269 | 61,19,-0.8202804612468682
270 | 48,86,0.04737373834869518
271 | 65,45,-0.1603088069708744
272 | 42,46,-0.9030319241688518
273 | 75,23,-0.6996396596136966
274 | 3,94,0.5935545401356204
275 | 49,25,-0.119924124206507
276 | 83,98,-2.2962661247365572
277 | 55,68,0.005055518821373728
278 | 86,42,-0.24681158077717424
279 | 65,77,-0.31109737877072463
280 | 76,16,-0.8070442492571166
281 | 52,4,-0.7120755312685864
282 | 60,35,0.025353676484393836
283 | 3,44,-1.8841880519984286
284 | 44,22,-0.7109857890284509
285 | 90,64,-1.441133243180356
286 | 23,77,-1.4255213743863067
287 | 83,60,-1.0258471197761212
288 | 55,49,-0.5337726100012276
289 | 27,78,-0.9633024499031962
290 | 78,29,-0.48083268587573513
291 | 86,44,-0.22312828850070832
292 | 11,47,-2.0301206045123497
293 | 80,42,-0.13680844933323422
294 | 88,90,-1.9287367785011216
295 | 22,27,-2.2767585014155842
296 | 19,37,-2.7624806147649297
297 | 25,43,-2.3951643666403806
298 | 3,81,-1.0522323698108018
299 | 58,93,-0.9157170129985064
300 | 62,78,-0.06808766637252983
301 | 80,84,-1.9245503368082435
302 | 84,20,0.05197178054786278
303 | 7,92,0.25640730675505585
304 | 29,83,-0.6635008628255967
305 | 79,18,-0.42852333773414775
306 | 55,11,-0.6772572424783635
307 | 67,4,-0.8145840905452186
308 | 95,67,-1.7125262821861973
309 | 26,98,0.6988532821573911
310 | 69,98,-1.9829209172948892
311 | 52,21,-0.43413164518615915
312 | 41,31,-0.7894071008395798
313 | 1,32,-2.021082447595921
314 | 67,26,-0.7286519848015482
315 | 12,78,-1.6099048966492246
316 | 7,43,-1.9503287681291854
317 | 88,70,-1.6441213899982543
318 | 23,79,-1.3839146024857325
319 | 59,61,-0.6061669487715279
320 | 40,76,0.33647237902735977
321 | 99,93,-1.5131556276360314
322 | 4,61,-1.312841069859096
323 | 47,99,-0.7054180640384552
324 | 31,96,0.2957618701695621
325 | 67,79,-0.6816015728870042
326 | 18,23,-2.305234257266516
327 | 47,65,-0.2054151646239622
328 | 16,60,-2.0583054033899275
329 | 72,4,-0.9478750623013474
330 | 98,69,-1.8022541761504738
331 | 62,7,-0.6519758224492036
332 | 96,60,-0.9147423631400617
333 | 45,96,-0.4325546141387169
334 | 77,74,-1.2088699196705512
335 | 5,8,-2.194439503020854
336 | 35,70,-0.059516207326285375
337 | 97,41,-0.9469436721204711
338 | 97,67,-1.6674138401181522
339 | 45,19,-0.9075864481672704
340 | 45,78,0.36708512139085625
341 | 65,61,-0.748316957891198
342 | 58,97,-1.3413376504593888
343 | 89,53,-0.5736887108603895
344 | 1,40,-1.8799341171740838
345 | 84,42,-0.19021339943706572
346 | 41,46,-0.9493165165250845
347 | 32,96,0.27163824403899306
348 | 97,34,-0.9677459536912152
349 | 81,3,-0.28535499483789384
350 | 24,91,-0.2259835810942934
351 | 27,31,-2.0907366075979077
352 | 20,25,-2.2928609179030985
353 | 100,6,1.067384126216814
354 | 37,45,-1.1833548239475973
355 | 47,9,-1.315514618566741
356 | 22,58,-1.936113932900406
357 | 78,80,-1.6619949712899333
358 | 26,77,-1.1033306062531536
359 | 1,22,-2.3487546957332164
360 | 5,60,-1.48510109836679
361 | 22,17,-2.1084750910363876
362 | 71,39,-0.16659605253694498
363 | 70,17,-1.139012471863528
364 | 71,8,-1.1218376152974852
365 | 20,28,-2.4480672386179525
366 | 23,63,-1.610499822368222
367 | 61,34,-0.01828317470181351
368 | 10,60,-1.8785428385222194
369 | 63,11,-0.916863005355644
370 | 37,7,-2.332207067259491
371 | 64,89,-1.1438171215681223
372 | 29,29,-1.8519176365738326
373 | 46,84,0.15844410900332428
374 | 57,63,-0.45736648768143506
375 | 9,60,-1.8149892954947524
376 | 48,1,-1.3449425893591203
377 | 81,15,-0.1953620011462096
378 | 3,61,-1.2034451897431466
379 | 86,86,-1.9026864308593892
380 | 31,49,-1.5507323627899527
381 | 93,60,-1.0013008675210189
382 | 75,65,-0.886044305016085
383 | 89,5,0.6478414118880481
384 | 62,67,-0.3431391216275167
385 | 57,60,-0.5907989022911636
386 | 32,34,-1.7171286885541428
387 | 18,59,-2.0770792021233886
388 | 40,90,-0.08639875271252495
389 | 53,37,0.012997939662930585
390 | 40,97,0.013203527911123558
391 | 79,36,-0.356042452522373
392 | 37,46,-1.1647165176333263
393 | 61,40,-0.0547529676783714
394 | 99,82,-1.800638229375744
395 | 63,47,-0.2561718226661246
396 | 91,49,-0.42857777335179514
397 | 70,44,-0.12630305000354325
398 | 86,51,-0.47911901752063457
399 | 58,50,-0.46887219639213473
400 | 37,28,-1.2114636319137753
401 | 74,18,-0.9325395373565384
402 | 59,41,-0.11070353287488192
403 | 50,61,-0.5585685919820131
404 | 73,21,-0.8953220244754807
405 | 92,62,-1.2450189362445978
406 | 81,71,-1.2440186870693406
407 | 72,49,-0.32780406293231573
408 | 96,3,1.054319840949935
409 | 78,51,-0.46279424792813195
410 | 11,64,-1.7091771536050244
411 | 68,23,-0.9110161835295323
412 | 28,79,-0.823395549557471
413 | 60,48,-0.35456214936511354
414 | 76,6,-0.8615152042689993
415 | 24,73,-1.3678209248300819
416 | 13,7,-2.4515669549145724
417 | 4,3,-1.9498434591068001
418 | 7,53,-1.9290225738898186
419 | 12,7,-2.418516576259508
420 | 99,72,-1.9325668641061262
421 | 66,81,-0.7358032564110454
422 | 2,75,-1.1707297873798912
423 | 67,71,-0.420981565968635
424 | 94,30,-0.6913426735657044
425 | 73,97,-2.1361420384354397
426 | 59,92,-0.8829228787658867
427 | 82,72,-1.3083179436683112
428 | 19,92,-0.028828354963474023
429 | 69,5,-0.9638369921319903
430 | 67,28,-0.6128224198310096
431 | 79,89,-2.101636806194354
432 | 62,30,-0.22208337378938717
433 | 25,23,-1.9555335612504359
434 | 12,28,-2.5624736756175657
435 | 6,45,-1.9278542557900962
436 | 92,25,-0.2760868564813428
437 | 67,100,-1.9552508699403284
438 | 82,55,-0.7602476434380687
439 | 11,26,-2.5069910827523585
440 | 99,70,-1.8343681155255418
441 | 53,75,0.3552749480824071
442 | 49,73,0.3241301743686026
443 | 96,14,0.78289761078143
444 | 72,17,-1.0815041828102399
445 | 41,100,0.04213124501571175
446 | 45,88,-0.048093515823306454
447 | 99,16,0.32887973839150275
448 | 1,34,-1.9680331184997661
449 | 13,42,-2.2386113092934687
450 | 8,58,-1.853650829040446
451 | 43,28,-0.5383918545554864
452 | 72,69,-0.8038614480322568
453 | 21,17,-2.1353707762667185
454 | 80,86,-2.0046117471599034
455 | 71,97,-2.055967866773185
456 | 13,33,-2.578213319566314
457 | 61,13,-0.8810555940007759
458 | 12,87,-0.8426089055446344
459 | 79,8,-0.5811807367316317
460 | 23,86,-0.9092037573862705
461 | 31,47,-1.6316822461199156
462 | 54,2,-0.5417380967547616
463 | 44,19,-0.9872845795374234
464 | 49,75,0.357997087066144
465 | 73,77,-1.1612530511763641
466 | 8,73,-1.468353641733726
467 | 57,99,-1.4648346434962636
468 | 36,18,-1.5908363980043303
469 | 16,69,-1.6868599108054636
470 | 46,49,-0.826752683752012
471 | 69,10,-1.1595643593431566
472 | 99,91,-1.5068502733465463
473 | 37,52,-1.0455233936432196
474 | 76,78,-1.4347754493813079
475 | 70,46,-0.19017865664948308
476 | 91,64,-1.4521251539864188
477 | 19,47,-2.4037145669655398
478 | 40,10,-1.9989670407724591
479 | 66,19,-1.0262669276590644
480 | 7,46,-1.939853583864939
481 | 27,9,-2.504554859498235
482 | 19,48,-2.3716311464795954
483 | 2,52,-1.7060702157320724
484 | 95,71,-1.9742139843402908
485 | 92,72,-1.934879748125853
486 | 27,1,-3.0181060405737363
487 | 30,56,-1.2841282179990154
488 | 84,25,-0.19921755576101363
489 | 79,54,-0.6563564412172758
490 | 15,35,-2.6483938360699755
491 | 77,14,-0.735759456289288
492 | 41,98,-0.033625414188334646
493 | 22,49,-2.299453645239997
494 | 63,56,-0.6378721190276777
495 | 53,62,-0.4843086761189376
496 | 21,9,-2.5827204873043303
497 | 8,96,0.7946327615226626
498 | 52,2,-0.754913074602668
499 | 20,67,-1.6690371109347628
500 | 18,83,-1.4232192696269024
501 | 64,16,-1.0283709710489455
502 | 41,76,0.3644623684844036
503 | 48,79,0.3169191256645389
504 | 62,60,-0.7058589423367679
505 | 100,73,-1.9222564003535763
506 | 42,40,-0.832808464693552
507 | 7,78,-1.414982875357314
508 | 96,75,-2.0704780539929595
509 | 22,68,-1.545121905758538
510 | 42,19,-1.1483937846750991
511 | 35,51,-1.166306563550643
512 | 29,65,-0.8708666365676441
513 | 35,76,0.00722323097117239
514 | 47,23,-0.3813558808654251
515 | 83,99,-2.3588068406610763
516 | 30,77,-0.5811664980967979
517 | 4,43,-1.899153965375696
518 | 40,72,0.28324095177112796
519 | 86,60,-1.0905265086471922
520 | 68,6,-0.9766633246008862
521 | 33,59,-0.8196386861865608
522 | 30,44,-1.850673116613042
523 | 71,96,-2.0389408116947796
524 | 8,44,-1.967314326298686
525 | 31,38,-1.864777676695268
526 | 31,14,-2.0465441981219863
527 | 98,37,-1.0481313396199918
528 | 18,24,-2.347170022536147
529 | 79,42,-0.13197019430705736
530 | 1,92,0.38008376892995965
531 | 23,87,-0.7880517661770725
532 | 99,10,0.9398485442782152
533 | 32,63,-0.6181002624147119
534 | 98,97,-1.7072518247457567
535 | 8,5,-2.2368617974728298
536 | 32,52,-1.3339795788255935
537 | 95,51,-0.5028913235800136
538 | 92,67,-1.711462234964014
539 | 56,21,-0.5264511833890746
540 | 44,44,-0.7527344417279833
541 | 12,40,-2.2447363711366464
542 | 13,40,-2.3169290792000594
543 | 54,12,-0.7356217320781144
544 | 6,100,1.227254092127576
545 | 42,96,-0.17716294683257372
546 | 82,52,-0.5592924583984337
547 | 32,10,-2.3049674861935054
548 | 72,24,-0.8278308849032249
549 | 68,85,-1.345706748298969
550 | 97,60,-0.8969469937794285
551 | 45,18,-1.0051614878225805
552 | 56,14,-0.7698223750997265
553 | 84,19,0.09564099940832538
554 | 36,56,-0.8914996152478826
555 | 71,98,-2.0759821489316153
556 | 84,69,-1.3552281035654254
557 | 23,1,-3.068988921169429
558 | 15,48,-2.2160465399539913
559 | 87,29,-0.37124203872478323
560 | 63,57,-0.6735143611854157
561 | 59,3,-0.3543501580905018
562 | 57,9,-0.565262832513776
563 | 15,49,-2.2081468235848476
564 | 91,77,-1.9306317820850145
565 | 79,74,-1.2770316398817467
566 | 8,23,-2.383238581267964
567 | 77,100,-2.309611686602484
568 | 25,84,-0.9779716688959315
569 | 55,45,-0.3809195779762311
570 | 17,15,-2.2495875065847333
571 | 86,37,-0.37589885180134697
572 | 23,11,-2.428964593101172
573 | 61,67,-0.2928007964661541
574 | 100,96,-1.4970651554826153
575 | 17,25,-2.4354594071528624
576 | 57,75,0.3085251984517763
577 | 39,52,-0.9943127563121311
578 | 62,29,-0.27853393683917627
579 | 87,22,0.06457626208620026
580 | 97,48,-0.6829868870442757
581 | 61,53,-0.5102478245348054
582 | 28,36,-2.1641418798775667
583 | 51,57,-0.7224137994697368
584 | 79,88,-2.0814629285374298
585 | 71,60,-0.7249037118888615
586 | 90,94,-1.9804169242892842
587 | 81,89,-2.0520706532531685
588 | 22,30,-2.4439811903882873
589 | 55,97,-1.1851939708737174
590 | 22,75,-1.526750644082616
591 | 60,93,-1.061944517779756
592 | 9,65,-1.5431833522874623
593 | 65,79,-0.4445949808668536
594 | 4,1,-1.884632085685426
595 | 68,4,-0.8653764319806004
596 | 27,68,-1.0539526842953977
597 | 28,3,-2.8706516167100604
598 | 2,70,-0.9917407414894048
599 | 85,2,0.19624752616162078
600 | 10,99,1.1547223512811096
601 | 83,70,-1.3158679986819846
602 |
--------------------------------------------------------------------------------