teehr 0.4.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- teehr-0.4.1/LICENSE.md +21 -0
- teehr-0.4.1/PKG-INFO +92 -0
- teehr-0.4.1/README.md +52 -0
- teehr-0.4.1/pyproject.toml +76 -0
- teehr-0.4.1/src/teehr/__init__.py +40 -0
- teehr-0.4.1/src/teehr/const.py +36 -0
- teehr-0.4.1/src/teehr/evaluation/__init__.py +1 -0
- teehr-0.4.1/src/teehr/evaluation/evaluation.py +324 -0
- teehr-0.4.1/src/teehr/evaluation/fetch.py +844 -0
- teehr-0.4.1/src/teehr/evaluation/metrics.py +175 -0
- teehr-0.4.1/src/teehr/evaluation/tables.py +1541 -0
- teehr-0.4.1/src/teehr/evaluation/utils.py +60 -0
- teehr-0.4.1/src/teehr/example_data/__init__.py +0 -0
- teehr-0.4.1/src/teehr/example_data/two_locations.py +39 -0
- teehr-0.4.1/src/teehr/example_data/v0_3_test_study.py +55 -0
- teehr-0.4.1/src/teehr/examples/01-evaluation_setup.ipynb +360 -0
- teehr-0.4.1/src/teehr/examples/02-table_queries.ipynb +227 -0
- teehr-0.4.1/src/teehr/examples/03-metric_queries.ipynb +328 -0
- teehr-0.4.1/src/teehr/examples/04-table_filters.ipynb +219 -0
- teehr-0.4.1/src/teehr/examples/05-2_site_setup.ipynb +231 -0
- teehr-0.4.1/src/teehr/examples/06-2_site_query.ipynb +290 -0
- teehr-0.4.1/src/teehr/examples/07-2_site_plotting.ipynb +136 -0
- teehr-0.4.1/src/teehr/examples/08-sql.ipynb +93 -0
- teehr-0.4.1/src/teehr/examples/__init__.py +1 -0
- teehr-0.4.1/src/teehr/examples/clone_from_s3.ipynb +175 -0
- teehr-0.4.1/src/teehr/examples/ngen_example.py +76 -0
- teehr-0.4.1/src/teehr/examples/setup_evaluation.py +114 -0
- teehr-0.4.1/src/teehr/examples/two_site_debug_script.py +49 -0
- teehr-0.4.1/src/teehr/fetching/__init__.py +1 -0
- teehr-0.4.1/src/teehr/fetching/const.py +281 -0
- teehr-0.4.1/src/teehr/fetching/nwm/__init__.py +1 -0
- teehr-0.4.1/src/teehr/fetching/nwm/grid_utils.py +240 -0
- teehr-0.4.1/src/teehr/fetching/nwm/nwm_grids.py +269 -0
- teehr-0.4.1/src/teehr/fetching/nwm/nwm_points.py +247 -0
- teehr-0.4.1/src/teehr/fetching/nwm/point_utils.py +243 -0
- teehr-0.4.1/src/teehr/fetching/nwm/retrospective_grids.py +457 -0
- teehr-0.4.1/src/teehr/fetching/nwm/retrospective_points.py +329 -0
- teehr-0.4.1/src/teehr/fetching/readme.md +2 -0
- teehr-0.4.1/src/teehr/fetching/usgs/__init__.py +1 -0
- teehr-0.4.1/src/teehr/fetching/usgs/usgs.py +369 -0
- teehr-0.4.1/src/teehr/fetching/utils.py +736 -0
- teehr-0.4.1/src/teehr/loading/__init__.py +1 -0
- teehr-0.4.1/src/teehr/loading/add_domains.py +253 -0
- teehr-0.4.1/src/teehr/loading/joined_timeseries.py +213 -0
- teehr-0.4.1/src/teehr/loading/location_attributes.py +220 -0
- teehr-0.4.1/src/teehr/loading/location_crosswalks.py +201 -0
- teehr-0.4.1/src/teehr/loading/locations.py +204 -0
- teehr-0.4.1/src/teehr/loading/readme.md +1 -0
- teehr-0.4.1/src/teehr/loading/s3/clone_from_s3.py +259 -0
- teehr-0.4.1/src/teehr/loading/timeseries.py +280 -0
- teehr-0.4.1/src/teehr/loading/utils.py +240 -0
- teehr-0.4.1/src/teehr/metrics/__init__.py +1 -0
- teehr-0.4.1/src/teehr/metrics/bootstrap_funcs.py +106 -0
- teehr-0.4.1/src/teehr/metrics/gumboot_bootstrap.py +185 -0
- teehr-0.4.1/src/teehr/metrics/metric_funcs.py +301 -0
- teehr-0.4.1/src/teehr/metrics/readme.md +2 -0
- teehr-0.4.1/src/teehr/models/__init__.py +1 -0
- teehr-0.4.1/src/teehr/models/fetching/__init__.py +1 -0
- teehr-0.4.1/src/teehr/models/fetching/nwm22_grid.py +268 -0
- teehr-0.4.1/src/teehr/models/fetching/nwm22_point.py +331 -0
- teehr-0.4.1/src/teehr/models/fetching/nwm30_grid.py +136 -0
- teehr-0.4.1/src/teehr/models/fetching/nwm30_point.py +142 -0
- teehr-0.4.1/src/teehr/models/fetching/utils.py +98 -0
- teehr-0.4.1/src/teehr/models/filters.py +142 -0
- teehr-0.4.1/src/teehr/models/metrics/__init__.py +1 -0
- teehr-0.4.1/src/teehr/models/metrics/bootstrap_models.py +154 -0
- teehr-0.4.1/src/teehr/models/metrics/metric_attributes.py +237 -0
- teehr-0.4.1/src/teehr/models/metrics/metric_enums.py +47 -0
- teehr-0.4.1/src/teehr/models/metrics/metric_models.py +839 -0
- teehr-0.4.1/src/teehr/models/readme.md +1 -0
- teehr-0.4.1/src/teehr/models/str_enum.py +11 -0
- teehr-0.4.1/src/teehr/models/table_enums.py +56 -0
- teehr-0.4.1/src/teehr/models/tables.py +91 -0
- teehr-0.4.1/src/teehr/querying/__init__.py +1 -0
- teehr-0.4.1/src/teehr/querying/filter_format.py +177 -0
- teehr-0.4.1/src/teehr/querying/metric_format.py +64 -0
- teehr-0.4.1/src/teehr/querying/readme.md +2 -0
- teehr-0.4.1/src/teehr/querying/utils.py +100 -0
- teehr-0.4.1/src/teehr/template/__init__.py +1 -0
- teehr-0.4.1/src/teehr/template/cache/readme.md +1 -0
- teehr-0.4.1/src/teehr/template/dataset/attributes/_readme.md +1 -0
- teehr-0.4.1/src/teehr/template/dataset/attributes/attributes.csv +2 -0
- teehr-0.4.1/src/teehr/template/dataset/configurations/_readme.md +1 -0
- teehr-0.4.1/src/teehr/template/dataset/configurations/configurations.csv +162 -0
- teehr-0.4.1/src/teehr/template/dataset/joined_timeseries/_readme.md +1 -0
- teehr-0.4.1/src/teehr/template/dataset/location_attributes/_readme.md +1 -0
- teehr-0.4.1/src/teehr/template/dataset/location_crosswalks/_readme.md +1 -0
- teehr-0.4.1/src/teehr/template/dataset/locations/_readme.md +1 -0
- teehr-0.4.1/src/teehr/template/dataset/primary_timeseries/_readme.md +1 -0
- teehr-0.4.1/src/teehr/template/dataset/secondary_timeseries/_readme.md +1 -0
- teehr-0.4.1/src/teehr/template/dataset/units/_readme.md +1 -0
- teehr-0.4.1/src/teehr/template/dataset/units/units.csv +5 -0
- teehr-0.4.1/src/teehr/template/dataset/variables/_readme.md +1 -0
- teehr-0.4.1/src/teehr/template/dataset/variables/variables.csv +4 -0
- teehr-0.4.1/src/teehr/template/gitignore_template +2 -0
- teehr-0.4.1/src/teehr/template/readme.md +18 -0
- teehr-0.4.1/src/teehr/template/scripts/__init__.py +1 -0
- teehr-0.4.1/src/teehr/template/scripts/user_defined_fields.py +98 -0
- teehr-0.4.1/src/teehr/utilities/__init__.py +1 -0
- teehr-0.4.1/src/teehr/utilities/generate_weights.py +302 -0
- teehr-0.4.1/src/teehr/utils/install_spark_jars.py +32 -0
- teehr-0.4.1/src/teehr/visualization/__init__.py +1 -0
- teehr-0.4.1/src/teehr/visualization/dataframe_accessor.py +511 -0
teehr-0.4.1/LICENSE.md
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2023 RTI International
|
|
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.
|
teehr-0.4.1/PKG-INFO
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: teehr
|
|
3
|
+
Version: 0.4.1
|
|
4
|
+
Summary: Tools for Exploratory Evaluation in Hydrologic Research
|
|
5
|
+
License: GNU v3
|
|
6
|
+
Author: RTI International
|
|
7
|
+
Requires-Python: >=3.10,<4.0
|
|
8
|
+
Classifier: License :: Other/Proprietary License
|
|
9
|
+
Classifier: Programming Language :: Python :: 3
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
13
|
+
Requires-Dist: arch (>=7.0.0,<8.0.0)
|
|
14
|
+
Requires-Dist: bokeh (>=3.5.0,<4.0.0)
|
|
15
|
+
Requires-Dist: dask[dataframe] (>=2024.11.1,<2025.0.0)
|
|
16
|
+
Requires-Dist: dataretrieval (>=1.0.9,<2.0.0)
|
|
17
|
+
Requires-Dist: duckdb (>=1.0.0,<2.0.0)
|
|
18
|
+
Requires-Dist: fsspec (>=2023.10.0)
|
|
19
|
+
Requires-Dist: gcsfs (>=2023.10.0)
|
|
20
|
+
Requires-Dist: geopandas (>=0.14.0,<0.15.0)
|
|
21
|
+
Requires-Dist: h5py (==3.12.1)
|
|
22
|
+
Requires-Dist: httpx (>=0.25.1,<0.26.0)
|
|
23
|
+
Requires-Dist: hydrotools-metrics (>=1.3.3,<2.0.0)
|
|
24
|
+
Requires-Dist: hydrotools-nwis-client (>=3.3.1,<4.0.0)
|
|
25
|
+
Requires-Dist: kerchunk (>=0.2.2,<0.3.0)
|
|
26
|
+
Requires-Dist: netcdf4 (==1.6.5)
|
|
27
|
+
Requires-Dist: numba (>=0.60.0,<0.61.0)
|
|
28
|
+
Requires-Dist: pandas (>=2.2.0,<3.0.0)
|
|
29
|
+
Requires-Dist: pandera[pyspark] (>=0.20.4,<0.21.0)
|
|
30
|
+
Requires-Dist: pyarrow (>=15.0.0,<16.0.0)
|
|
31
|
+
Requires-Dist: pydantic (>=2.4.2,<3.0.0)
|
|
32
|
+
Requires-Dist: pyspark[pandas-on-spark] (>=3.5.2,<4.0.0)
|
|
33
|
+
Requires-Dist: rasterio (>=1.3.9,<2.0.0)
|
|
34
|
+
Requires-Dist: rioxarray (>=0.15.0,<0.16.0)
|
|
35
|
+
Requires-Dist: s3fs (>=2023.10.0)
|
|
36
|
+
Requires-Dist: ujson (>=5.8.0,<6.0.0)
|
|
37
|
+
Requires-Dist: zarr (>=2.16.1,<3.0.0)
|
|
38
|
+
Description-Content-Type: text/markdown
|
|
39
|
+
|
|
40
|
+

|
|
41
|
+
|
|
42
|
+
| | |
|
|
43
|
+
| --- | --- |
|
|
44
|
+
|  | Funding for this project was provided by the National Oceanic & Atmospheric Administration (NOAA), awarded to the Cooperative Institute for Research to Operations in Hydrology (CIROH) through the NOAA Cooperative Agreement with The University of Alabama (NA22NWS4320003). |
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
# TEEHR - Tools for Exploratory Evaluation in Hydrologic Research
|
|
48
|
+
TEEHR (pronounced "tier") is a python tool set for loading, storing,
|
|
49
|
+
processing and visualizing hydrologic data, particularly National Water
|
|
50
|
+
Model data, for the purpose of exploring and evaluating the datasets to
|
|
51
|
+
assess their skill and performance.
|
|
52
|
+
|
|
53
|
+
NOTE: THIS PROJECT IS UNDER DEVELOPMENT - EXPECT TO FIND BROKEN AND INCOMPLETE CODE.
|
|
54
|
+
|
|
55
|
+
## Documentation
|
|
56
|
+
[TEEHR Documentation](https://rtiinternational.github.io/teehr/)
|
|
57
|
+
|
|
58
|
+
## How to Install TEEHR
|
|
59
|
+
We do not currently push TEEHR to PyPI, so the easiest way to install it is directly from GitHub.
|
|
60
|
+
If using `pip` to install TEEHR, we recommend installing TEEHR in a virtual environment.
|
|
61
|
+
The code below should create a new virtual environment and install TEEHR in it.
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
# Create directory for your code and create a new virtual environment.
|
|
65
|
+
mkdir teehr_examples
|
|
66
|
+
cd teehr_examples
|
|
67
|
+
python3 -m venv .venv
|
|
68
|
+
source .venv/bin/activate
|
|
69
|
+
|
|
70
|
+
# Install using pip. The version can be changed to install a different version.
|
|
71
|
+
pip install 'teehr @ git+https://github.com/RTIInternational/teehr@v0.4.1'
|
|
72
|
+
|
|
73
|
+
# Download the required JAR files for Spark to interact with AWS S3.
|
|
74
|
+
python -m teehr.utils.install_spark_jars
|
|
75
|
+
```
|
|
76
|
+
Use Docker
|
|
77
|
+
```bash
|
|
78
|
+
$ docker build -t teehr:v0.4.1 .
|
|
79
|
+
$ docker run -it --rm --volume $HOME:$HOME -p 8888:8888 teehr:v0.4.1 jupyter lab --ip 0.0.0.0 $HOME
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Examples
|
|
83
|
+
For examples of how to use TEEHR, see the [examples](examples). We will maintain a basic set of example Jupyter Notebooks demonstrating how to use the TEEHR tools.
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
## Resources
|
|
87
|
+
In May of 2023 we put on a workshop at the CIROH 1st Annual Training and Developers Conference. The workshop materials and presentation are available in the workshop GitHub repository: [teehr-may-2023-workshop](https://github.com/RTIInternational/teehr-may-2023-workshop). This workshop was based on version 0.1.0.
|
|
88
|
+
|
|
89
|
+
## Versioning
|
|
90
|
+
The TEEHR project follows semantic versioning as described here: [https://semver.org/](https://semver.org/).
|
|
91
|
+
Note, per the specification, "Major version zero (0.y.z) is for initial development. Anything MAY change at any time. The public API SHOULD NOT be considered stable.". We are solidly in "major version zero" territory, and trying to move fast, so expect breaking changes often.
|
|
92
|
+
|
teehr-0.4.1/README.md
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+

|
|
2
|
+
|
|
3
|
+
| | |
|
|
4
|
+
| --- | --- |
|
|
5
|
+
|  | Funding for this project was provided by the National Oceanic & Atmospheric Administration (NOAA), awarded to the Cooperative Institute for Research to Operations in Hydrology (CIROH) through the NOAA Cooperative Agreement with The University of Alabama (NA22NWS4320003). |
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
# TEEHR - Tools for Exploratory Evaluation in Hydrologic Research
|
|
9
|
+
TEEHR (pronounced "tier") is a python tool set for loading, storing,
|
|
10
|
+
processing and visualizing hydrologic data, particularly National Water
|
|
11
|
+
Model data, for the purpose of exploring and evaluating the datasets to
|
|
12
|
+
assess their skill and performance.
|
|
13
|
+
|
|
14
|
+
NOTE: THIS PROJECT IS UNDER DEVELOPMENT - EXPECT TO FIND BROKEN AND INCOMPLETE CODE.
|
|
15
|
+
|
|
16
|
+
## Documentation
|
|
17
|
+
[TEEHR Documentation](https://rtiinternational.github.io/teehr/)
|
|
18
|
+
|
|
19
|
+
## How to Install TEEHR
|
|
20
|
+
We do not currently push TEEHR to PyPI, so the easiest way to install it is directly from GitHub.
|
|
21
|
+
If using `pip` to install TEEHR, we recommend installing TEEHR in a virtual environment.
|
|
22
|
+
The code below should create a new virtual environment and install TEEHR in it.
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
# Create directory for your code and create a new virtual environment.
|
|
26
|
+
mkdir teehr_examples
|
|
27
|
+
cd teehr_examples
|
|
28
|
+
python3 -m venv .venv
|
|
29
|
+
source .venv/bin/activate
|
|
30
|
+
|
|
31
|
+
# Install using pip. The version can be changed to install a different version.
|
|
32
|
+
pip install 'teehr @ git+https://github.com/RTIInternational/teehr@v0.4.1'
|
|
33
|
+
|
|
34
|
+
# Download the required JAR files for Spark to interact with AWS S3.
|
|
35
|
+
python -m teehr.utils.install_spark_jars
|
|
36
|
+
```
|
|
37
|
+
Use Docker
|
|
38
|
+
```bash
|
|
39
|
+
$ docker build -t teehr:v0.4.1 .
|
|
40
|
+
$ docker run -it --rm --volume $HOME:$HOME -p 8888:8888 teehr:v0.4.1 jupyter lab --ip 0.0.0.0 $HOME
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Examples
|
|
44
|
+
For examples of how to use TEEHR, see the [examples](examples). We will maintain a basic set of example Jupyter Notebooks demonstrating how to use the TEEHR tools.
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
## Resources
|
|
48
|
+
In May of 2023 we put on a workshop at the CIROH 1st Annual Training and Developers Conference. The workshop materials and presentation are available in the workshop GitHub repository: [teehr-may-2023-workshop](https://github.com/RTIInternational/teehr-may-2023-workshop). This workshop was based on version 0.1.0.
|
|
49
|
+
|
|
50
|
+
## Versioning
|
|
51
|
+
The TEEHR project follows semantic versioning as described here: [https://semver.org/](https://semver.org/).
|
|
52
|
+
Note, per the specification, "Major version zero (0.y.z) is for initial development. Anything MAY change at any time. The public API SHOULD NOT be considered stable.". We are solidly in "major version zero" territory, and trying to move fast, so expect breaking changes often.
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
[tool.poetry]
|
|
2
|
+
name = "teehr"
|
|
3
|
+
version = "0.4.1"
|
|
4
|
+
description = "Tools for Exploratory Evaluation in Hydrologic Research"
|
|
5
|
+
authors = [
|
|
6
|
+
"RTI International",
|
|
7
|
+
"Matthew Denno <mdenno@rti.org>",
|
|
8
|
+
"Katie van Werkhoven <kvanwerkhoven@rti.org>",
|
|
9
|
+
"Sam Lamont <slamont@rti.org>",
|
|
10
|
+
]
|
|
11
|
+
license = "GNU v3"
|
|
12
|
+
readme = "README.md"
|
|
13
|
+
|
|
14
|
+
[tool.poetry.dependencies]
|
|
15
|
+
python = "^3.10"
|
|
16
|
+
geopandas = "^0.14.0"
|
|
17
|
+
duckdb = "^1.0.0"
|
|
18
|
+
pydantic = "^2.4.2"
|
|
19
|
+
hydrotools-metrics = "^1.3.3"
|
|
20
|
+
hydrotools-nwis-client = "^3.3.1"
|
|
21
|
+
dask = {extras = ["dataframe"], version = "^2024.11.1"}
|
|
22
|
+
fsspec = ">=2023.10.0"
|
|
23
|
+
ujson = "^5.8.0"
|
|
24
|
+
kerchunk = "^0.2.2"
|
|
25
|
+
gcsfs = ">=2023.10.0"
|
|
26
|
+
s3fs = ">=2023.10.0"
|
|
27
|
+
zarr = "^2.16.1"
|
|
28
|
+
rioxarray = "^0.15.0"
|
|
29
|
+
rasterio = "^1.3.9"
|
|
30
|
+
h5py = "3.12.1"
|
|
31
|
+
pyarrow = "^15.0.0"
|
|
32
|
+
httpx = "^0.25.1"
|
|
33
|
+
pandas = "^2.2.0"
|
|
34
|
+
pyspark = {extras = ["pandas-on-spark"], version = "^3.5.2"}
|
|
35
|
+
dataretrieval = "^1.0.9"
|
|
36
|
+
numba = "^0.60.0"
|
|
37
|
+
arch = "^7.0.0"
|
|
38
|
+
pandera = {extras = ["pyspark"], version = "^0.20.4"}
|
|
39
|
+
netcdf4 = "1.6.5"
|
|
40
|
+
bokeh = "^3.5.0"
|
|
41
|
+
|
|
42
|
+
[tool.poetry.group.test.dependencies]
|
|
43
|
+
pytest = "^7.4.3"
|
|
44
|
+
flake8 = "^6.1.0"
|
|
45
|
+
|
|
46
|
+
[tool.poetry.group.dev.dependencies]
|
|
47
|
+
sphinx = "^7.2.6"
|
|
48
|
+
sphinx-design = "^0.5.0"
|
|
49
|
+
numpydoc = "^1.6.0"
|
|
50
|
+
pre-commit = "^3.6.0"
|
|
51
|
+
pre-commit-hooks = "^4.5.0"
|
|
52
|
+
flake8-docstrings = "^1.7.0"
|
|
53
|
+
myst-nb = "^1.0.0"
|
|
54
|
+
nbstripout = "^0.7.1"
|
|
55
|
+
pickleshare = "^0.7.5"
|
|
56
|
+
sphinx-autoapi = "3.0.0"
|
|
57
|
+
pydata-sphinx-theme = "^0.16.0"
|
|
58
|
+
sphinx-autobuild = "^2024.10.3"
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
[tool.numpydoc_validation]
|
|
62
|
+
checks = [
|
|
63
|
+
"all", # report on all checks, except the below
|
|
64
|
+
"EX01", # No examples section found
|
|
65
|
+
"RT01", # No Returns section found
|
|
66
|
+
"SA01", # See Also section not found
|
|
67
|
+
"ES01", # No extended summary found
|
|
68
|
+
"GL01", # Docstring text (summary) should start in the line immediately
|
|
69
|
+
"SS06", # Summary should fit in a single line
|
|
70
|
+
"PR01", # Parameters {missing_params} not documented
|
|
71
|
+
"GL02" # Closing quotes should be placed in the line after the last text in docstring"
|
|
72
|
+
]
|
|
73
|
+
|
|
74
|
+
[build-system]
|
|
75
|
+
requires = ["poetry-core"]
|
|
76
|
+
build-backend = "poetry.core.masonry.api"
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
from teehr.evaluation.evaluation import Evaluation # noqa
|
|
2
|
+
from teehr.models.metrics.metric_models import Metrics # noqa
|
|
3
|
+
from teehr.models.metrics.metric_enums import Operators # noqa
|
|
4
|
+
from teehr.models.tables import ( # noqa
|
|
5
|
+
Configuration,
|
|
6
|
+
Attribute,
|
|
7
|
+
Unit,
|
|
8
|
+
Variable
|
|
9
|
+
)
|
|
10
|
+
from teehr.models.metrics.bootstrap_models import Bootstrappers # noqa
|
|
11
|
+
from teehr.models.filters import ( # noqa
|
|
12
|
+
UnitFilter,
|
|
13
|
+
ConfigurationFilter,
|
|
14
|
+
VariableFilter,
|
|
15
|
+
AttributeFilter,
|
|
16
|
+
LocationFilter,
|
|
17
|
+
LocationAttributeFilter,
|
|
18
|
+
LocationCrosswalkFilter,
|
|
19
|
+
TimeseriesFilter,
|
|
20
|
+
JoinedTimeseriesFilter
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
# For docs
|
|
24
|
+
from teehr.evaluation.tables import ( # noqa
|
|
25
|
+
BaseTable,
|
|
26
|
+
UnitTable,
|
|
27
|
+
VariableTable,
|
|
28
|
+
AttributeTable,
|
|
29
|
+
ConfigurationTable,
|
|
30
|
+
LocationTable,
|
|
31
|
+
LocationAttributeTable,
|
|
32
|
+
LocationCrosswalkTable,
|
|
33
|
+
PrimaryTimeseriesTable,
|
|
34
|
+
SecondaryTimeseriesTable,
|
|
35
|
+
JoinedTimeseriesTable,
|
|
36
|
+
)
|
|
37
|
+
from teehr.evaluation.fetch import Fetch # noqa
|
|
38
|
+
from teehr.visualization.dataframe_accessor import TEEHRDataFrameAccessor # noqa
|
|
39
|
+
from teehr.models.metrics import metric_models, bootstrap_models # noqa
|
|
40
|
+
from teehr.metrics import metric_funcs # noqa
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"""This module contains constants
|
|
2
|
+
used throughout the package."""
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
# Primary evaluation directories
|
|
6
|
+
DATASET_DIR = "dataset"
|
|
7
|
+
CACHE_DIR = "cache"
|
|
8
|
+
SCRIPTS_DIR = "scripts"
|
|
9
|
+
LOCATIONS_DIR = "locations"
|
|
10
|
+
PRIMARY_TIMESERIES_DIR = "primary_timeseries"
|
|
11
|
+
LOCATION_CROSSWALKS_DIR = "location_crosswalks"
|
|
12
|
+
LOCATION_ATTRIBUTES_DIR = "location_attributes"
|
|
13
|
+
SECONDARY_TIMESERIES_DIR = "secondary_timeseries"
|
|
14
|
+
JOINED_TIMESERIES_DIR = "joined_timeseries"
|
|
15
|
+
|
|
16
|
+
# Domain files and directories
|
|
17
|
+
VARIABLES_DIR = "variables"
|
|
18
|
+
CONFIGURATIONS_DIR = "configurations"
|
|
19
|
+
UNITS_DIR = "units"
|
|
20
|
+
ATTRIBUTES_DIR = "attributes"
|
|
21
|
+
VARIABLES_FILE = "variables.csv"
|
|
22
|
+
CONFIGURATIONS_FILE = "configurations.csv"
|
|
23
|
+
UNITS_FILE = "units.csv"
|
|
24
|
+
ATTRIBUTES_FILE = "attributes.csv"
|
|
25
|
+
|
|
26
|
+
# Fetching cache directories
|
|
27
|
+
FETCHING_CACHE_DIR = "fetching"
|
|
28
|
+
USGS_CACHE_DIR = "usgs"
|
|
29
|
+
NWM_CACHE_DIR = "nwm"
|
|
30
|
+
KERCHUNK_DIR = "kerchunk"
|
|
31
|
+
WEIGHTS_DIR = "weights"
|
|
32
|
+
|
|
33
|
+
# Loading cache directories
|
|
34
|
+
LOADING_CACHE_DIR = "loading"
|
|
35
|
+
|
|
36
|
+
S3_EVALUATIONS_PATH = "s3://ciroh-rti-public-data/teehr-data-warehouse/v0_4_evaluations/evaluations.yaml"
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Evaluation module for TEEHR."""
|
|
@@ -0,0 +1,324 @@
|
|
|
1
|
+
"""Evaluation module."""
|
|
2
|
+
from datetime import datetime
|
|
3
|
+
from typing import Union, Literal, List
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
from pyspark.sql import SparkSession
|
|
6
|
+
from pyspark import SparkConf
|
|
7
|
+
import logging
|
|
8
|
+
from teehr.loading.utils import (
|
|
9
|
+
copy_template_to,
|
|
10
|
+
)
|
|
11
|
+
from teehr.loading.s3.clone_from_s3 import (
|
|
12
|
+
list_s3_evaluations,
|
|
13
|
+
clone_from_s3
|
|
14
|
+
)
|
|
15
|
+
import teehr.const as const
|
|
16
|
+
from teehr.evaluation.fetch import Fetch
|
|
17
|
+
from teehr.evaluation.metrics import Metrics
|
|
18
|
+
from teehr.evaluation.tables import (
|
|
19
|
+
UnitTable,
|
|
20
|
+
VariableTable,
|
|
21
|
+
AttributeTable,
|
|
22
|
+
ConfigurationTable,
|
|
23
|
+
LocationTable,
|
|
24
|
+
LocationAttributeTable,
|
|
25
|
+
LocationCrosswalkTable,
|
|
26
|
+
PrimaryTimeseriesTable,
|
|
27
|
+
SecondaryTimeseriesTable,
|
|
28
|
+
JoinedTimeseriesTable,
|
|
29
|
+
)
|
|
30
|
+
import pandas as pd
|
|
31
|
+
from teehr.visualization.dataframe_accessor import TEEHRDataFrameAccessor # noqa
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
logger = logging.getLogger(__name__)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class Evaluation:
|
|
38
|
+
"""The Evaluation class.
|
|
39
|
+
|
|
40
|
+
This is the main class for the TEEHR evaluation.
|
|
41
|
+
"""
|
|
42
|
+
|
|
43
|
+
def __init__(
|
|
44
|
+
self,
|
|
45
|
+
dir_path: Union[str, Path],
|
|
46
|
+
create_dir: bool = False,
|
|
47
|
+
spark: SparkSession = None
|
|
48
|
+
):
|
|
49
|
+
"""
|
|
50
|
+
Initialize the Evaluation class.
|
|
51
|
+
|
|
52
|
+
Parameters
|
|
53
|
+
----------
|
|
54
|
+
dir_path : Union[str, Path]
|
|
55
|
+
The path to the evaluation directory.
|
|
56
|
+
spark : SparkSession, optional
|
|
57
|
+
The SparkSession object, by default None
|
|
58
|
+
"""
|
|
59
|
+
self.dir_path = dir_path
|
|
60
|
+
self.spark = spark
|
|
61
|
+
|
|
62
|
+
self.dataset_dir = Path(
|
|
63
|
+
self.dir_path, const.DATASET_DIR
|
|
64
|
+
)
|
|
65
|
+
self.cache_dir = Path(
|
|
66
|
+
self.dir_path, const.CACHE_DIR
|
|
67
|
+
)
|
|
68
|
+
self.scripts_dir = Path(
|
|
69
|
+
self.dir_path, const.SCRIPTS_DIR
|
|
70
|
+
)
|
|
71
|
+
self.units_dir = Path(
|
|
72
|
+
self.dataset_dir, const.UNITS_DIR
|
|
73
|
+
)
|
|
74
|
+
self.variables_dir = Path(
|
|
75
|
+
self.dataset_dir, const.VARIABLES_DIR
|
|
76
|
+
)
|
|
77
|
+
self.configurations_dir = Path(
|
|
78
|
+
self.dataset_dir, const.CONFIGURATIONS_DIR
|
|
79
|
+
)
|
|
80
|
+
self.attributes_dir = Path(
|
|
81
|
+
self.dataset_dir, const.ATTRIBUTES_DIR
|
|
82
|
+
)
|
|
83
|
+
self.locations_dir = Path(
|
|
84
|
+
self.dataset_dir, const.LOCATIONS_DIR
|
|
85
|
+
)
|
|
86
|
+
self.location_crosswalks_dir = Path(
|
|
87
|
+
self.dataset_dir, const.LOCATION_CROSSWALKS_DIR
|
|
88
|
+
)
|
|
89
|
+
self.location_attributes_dir = Path(
|
|
90
|
+
self.dataset_dir, const.LOCATION_ATTRIBUTES_DIR
|
|
91
|
+
)
|
|
92
|
+
self.primary_timeseries_dir = Path(
|
|
93
|
+
self.dataset_dir, const.PRIMARY_TIMESERIES_DIR
|
|
94
|
+
)
|
|
95
|
+
self.secondary_timeseries_dir = Path(
|
|
96
|
+
self.dataset_dir, const.SECONDARY_TIMESERIES_DIR
|
|
97
|
+
)
|
|
98
|
+
self.joined_timeseries_dir = Path(
|
|
99
|
+
self.dataset_dir, const.JOINED_TIMESERIES_DIR
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
if not Path(self.dir_path).is_dir():
|
|
103
|
+
if create_dir:
|
|
104
|
+
logger.info(f"Creating directory {self.dir_path}.")
|
|
105
|
+
Path(self.dir_path).mkdir(parents=True, exist_ok=True)
|
|
106
|
+
else:
|
|
107
|
+
logger.error(f"Directory {self.dir_path} does not exist.")
|
|
108
|
+
raise NotADirectoryError
|
|
109
|
+
|
|
110
|
+
# Create a local Spark Session if one is not provided.
|
|
111
|
+
if not self.spark:
|
|
112
|
+
logger.info("Creating a new Spark session.")
|
|
113
|
+
conf = (
|
|
114
|
+
SparkConf()
|
|
115
|
+
.setAppName("TEEHR")
|
|
116
|
+
.setMaster("local[*]")
|
|
117
|
+
.set("spark.sql.sources.partitionOverwriteMode", "dynamic")
|
|
118
|
+
.set("spark.hadoop.fs.s3a.impl", "org.apache.hadoop.fs.s3a.S3AFileSystem")
|
|
119
|
+
.set("spark.hadoop.fs.s3a.aws.credentials.provider", "org.apache.hadoop.fs.s3a.AnonymousAWSCredentialsProvider")
|
|
120
|
+
.set("spark.sql.execution.arrow.pyspark.enabled", "true")
|
|
121
|
+
)
|
|
122
|
+
self.spark = SparkSession.builder.config(conf=conf).getOrCreate()
|
|
123
|
+
|
|
124
|
+
@property
|
|
125
|
+
def fetch(self) -> Fetch:
|
|
126
|
+
"""The fetch component class for accessing external data."""
|
|
127
|
+
return Fetch(self)
|
|
128
|
+
|
|
129
|
+
@property
|
|
130
|
+
def metrics(self) -> Metrics:
|
|
131
|
+
"""The metrics component class for calculating performance metrics."""
|
|
132
|
+
return Metrics(self)
|
|
133
|
+
|
|
134
|
+
@property
|
|
135
|
+
def units(self) -> UnitTable:
|
|
136
|
+
"""Access the units table."""
|
|
137
|
+
return UnitTable(self)
|
|
138
|
+
|
|
139
|
+
@property
|
|
140
|
+
def variables(self) -> VariableTable:
|
|
141
|
+
"""Access the variables table."""
|
|
142
|
+
return VariableTable(self)
|
|
143
|
+
|
|
144
|
+
@property
|
|
145
|
+
def attributes(self) -> AttributeTable:
|
|
146
|
+
"""Access the attributes table."""
|
|
147
|
+
return AttributeTable(self)
|
|
148
|
+
|
|
149
|
+
@property
|
|
150
|
+
def configurations(self) -> ConfigurationTable:
|
|
151
|
+
"""Access the configurations table."""
|
|
152
|
+
return ConfigurationTable(self)
|
|
153
|
+
|
|
154
|
+
@property
|
|
155
|
+
def locations(self) -> LocationTable:
|
|
156
|
+
"""Access the locations table."""
|
|
157
|
+
return LocationTable(self)
|
|
158
|
+
|
|
159
|
+
@property
|
|
160
|
+
def location_attributes(self) -> LocationAttributeTable:
|
|
161
|
+
"""Access the location attributes table."""
|
|
162
|
+
return LocationAttributeTable(self)
|
|
163
|
+
|
|
164
|
+
@property
|
|
165
|
+
def location_crosswalks(self) -> LocationCrosswalkTable:
|
|
166
|
+
"""Access the location crosswalks table."""
|
|
167
|
+
return LocationCrosswalkTable(self)
|
|
168
|
+
|
|
169
|
+
@property
|
|
170
|
+
def primary_timeseries(self) -> PrimaryTimeseriesTable:
|
|
171
|
+
"""Access the primary timeseries table."""
|
|
172
|
+
return PrimaryTimeseriesTable(self)
|
|
173
|
+
|
|
174
|
+
@property
|
|
175
|
+
def secondary_timeseries(self) -> SecondaryTimeseriesTable:
|
|
176
|
+
"""Access the secondary timeseries table."""
|
|
177
|
+
return SecondaryTimeseriesTable(self)
|
|
178
|
+
|
|
179
|
+
@property
|
|
180
|
+
def joined_timeseries(self) -> JoinedTimeseriesTable:
|
|
181
|
+
"""Access the joined timeseries table."""
|
|
182
|
+
return JoinedTimeseriesTable(self)
|
|
183
|
+
|
|
184
|
+
def enable_logging(self):
|
|
185
|
+
"""Enable logging."""
|
|
186
|
+
logger = logging.getLogger("teehr")
|
|
187
|
+
# logger.addHandler(logging.StreamHandler())
|
|
188
|
+
handler = logging.FileHandler(Path(self.dir_path, 'teehr.log'))
|
|
189
|
+
handler.setFormatter(
|
|
190
|
+
logging.Formatter(
|
|
191
|
+
"%(asctime)s %(levelname)s %(message)s"
|
|
192
|
+
)
|
|
193
|
+
)
|
|
194
|
+
logger.addHandler(
|
|
195
|
+
handler
|
|
196
|
+
)
|
|
197
|
+
logger.setLevel(logging.DEBUG)
|
|
198
|
+
|
|
199
|
+
def clone_template(self):
|
|
200
|
+
"""Create a study from the standard template.
|
|
201
|
+
|
|
202
|
+
This method mainly copies the template directory to the specified
|
|
203
|
+
evaluation directory.
|
|
204
|
+
"""
|
|
205
|
+
teehr_root = Path(__file__).parent.parent
|
|
206
|
+
template_dir = Path(teehr_root, "template")
|
|
207
|
+
logger.info(f"Copying template from {template_dir} to {self.dir_path}")
|
|
208
|
+
copy_template_to(template_dir, self.dir_path)
|
|
209
|
+
|
|
210
|
+
@staticmethod
|
|
211
|
+
def list_s3_evaluations(
|
|
212
|
+
format: Literal["pandas", "list"] = "pandas"
|
|
213
|
+
) -> Union[list, pd.DataFrame]:
|
|
214
|
+
"""List the evaluations available on S3.
|
|
215
|
+
|
|
216
|
+
Parameters
|
|
217
|
+
----------
|
|
218
|
+
format : str, optional
|
|
219
|
+
The format of the output. Either "pandas" or "list".
|
|
220
|
+
The default is "pandas".
|
|
221
|
+
"""
|
|
222
|
+
return list_s3_evaluations(format=format)
|
|
223
|
+
|
|
224
|
+
def clone_from_s3(
|
|
225
|
+
self,
|
|
226
|
+
evaluation_name: str,
|
|
227
|
+
primary_location_ids: List[str] = None,
|
|
228
|
+
start_date: Union[str, datetime] = None,
|
|
229
|
+
end_date: Union[str, datetime] = None,
|
|
230
|
+
):
|
|
231
|
+
"""Fetch the study data from S3.
|
|
232
|
+
|
|
233
|
+
Copies the study from s3 to the local directory, with the option
|
|
234
|
+
to subset the dataset by primary location ID, start and end dates.
|
|
235
|
+
|
|
236
|
+
Parameters
|
|
237
|
+
----------
|
|
238
|
+
evaluation_name : str
|
|
239
|
+
The name of the evaluation to clone from S3.
|
|
240
|
+
Use the list_s3_evaluations method to get the available
|
|
241
|
+
evaluations.
|
|
242
|
+
primary_location_ids : List[str], optional
|
|
243
|
+
The list of primary location ids to subset the data.
|
|
244
|
+
The default is None.
|
|
245
|
+
start_date : Union[str, datetime], optional
|
|
246
|
+
The start date to subset the data.
|
|
247
|
+
The default is None.
|
|
248
|
+
end_date : Union[str, datetime], optional
|
|
249
|
+
The end date to subset the data.
|
|
250
|
+
The default is None.
|
|
251
|
+
|
|
252
|
+
Notes
|
|
253
|
+
-----
|
|
254
|
+
|
|
255
|
+
Includes the following tables:
|
|
256
|
+
- units
|
|
257
|
+
- variables
|
|
258
|
+
- attributes
|
|
259
|
+
- configurations
|
|
260
|
+
- locations
|
|
261
|
+
- location_attributes
|
|
262
|
+
- location_crosswalks
|
|
263
|
+
- primary_timeseries
|
|
264
|
+
- secondary_timeseries
|
|
265
|
+
- joined_timeseries
|
|
266
|
+
|
|
267
|
+
Also includes the user_defined_fields.py script.
|
|
268
|
+
|
|
269
|
+
"""
|
|
270
|
+
return clone_from_s3(
|
|
271
|
+
self,
|
|
272
|
+
evaluation_name,
|
|
273
|
+
primary_location_ids,
|
|
274
|
+
start_date,
|
|
275
|
+
end_date
|
|
276
|
+
)
|
|
277
|
+
|
|
278
|
+
def clean_cache(self):
|
|
279
|
+
"""Clean temporary files.
|
|
280
|
+
|
|
281
|
+
Includes removing temporary files.
|
|
282
|
+
"""
|
|
283
|
+
logger.info(f"Removing temporary files from {self.cache_dir}")
|
|
284
|
+
self.cache_dir.rmdir()
|
|
285
|
+
self.cache_dir.mkdir()
|
|
286
|
+
|
|
287
|
+
def sql(self, query: str):
|
|
288
|
+
"""Run a SQL query on the Spark session against the TEEHR tables.
|
|
289
|
+
|
|
290
|
+
Parameters
|
|
291
|
+
----------
|
|
292
|
+
query : str
|
|
293
|
+
The SQL query to run.
|
|
294
|
+
|
|
295
|
+
Returns
|
|
296
|
+
-------
|
|
297
|
+
pyspark.sql.DataFrame
|
|
298
|
+
The result of the SQL query.
|
|
299
|
+
This is lazily evaluated so you need to call an action (e.g., sdf.show()) to get the result.
|
|
300
|
+
|
|
301
|
+
This method has access to the following tables preloaded as temporary views:
|
|
302
|
+
- units
|
|
303
|
+
- variables
|
|
304
|
+
- attributes
|
|
305
|
+
- configurations
|
|
306
|
+
- locations
|
|
307
|
+
- location_attributes
|
|
308
|
+
- location_crosswalks
|
|
309
|
+
- primary_timeseries
|
|
310
|
+
- secondary_timeseries
|
|
311
|
+
- joined_timeseries
|
|
312
|
+
"""
|
|
313
|
+
self.units.to_sdf().createOrReplaceTempView("units")
|
|
314
|
+
self.variables.to_sdf().createOrReplaceTempView("variables")
|
|
315
|
+
self.attributes.to_sdf().createOrReplaceTempView("attributes")
|
|
316
|
+
self.configurations.to_sdf().createOrReplaceTempView("configurations")
|
|
317
|
+
self.locations.to_sdf().createOrReplaceTempView("locations")
|
|
318
|
+
self.location_attributes.to_sdf().createOrReplaceTempView("location_attributes")
|
|
319
|
+
self.location_crosswalks.to_sdf().createOrReplaceTempView("location_crosswalks")
|
|
320
|
+
self.primary_timeseries.to_sdf().createOrReplaceTempView("primary_timeseries")
|
|
321
|
+
self.secondary_timeseries.to_sdf().createOrReplaceTempView("secondary_timeseries")
|
|
322
|
+
self.joined_timeseries.to_sdf().createOrReplaceTempView("joined_timeseries")
|
|
323
|
+
|
|
324
|
+
return self.spark.sql(query)
|