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.
Files changed (103) hide show
  1. teehr-0.4.1/LICENSE.md +21 -0
  2. teehr-0.4.1/PKG-INFO +92 -0
  3. teehr-0.4.1/README.md +52 -0
  4. teehr-0.4.1/pyproject.toml +76 -0
  5. teehr-0.4.1/src/teehr/__init__.py +40 -0
  6. teehr-0.4.1/src/teehr/const.py +36 -0
  7. teehr-0.4.1/src/teehr/evaluation/__init__.py +1 -0
  8. teehr-0.4.1/src/teehr/evaluation/evaluation.py +324 -0
  9. teehr-0.4.1/src/teehr/evaluation/fetch.py +844 -0
  10. teehr-0.4.1/src/teehr/evaluation/metrics.py +175 -0
  11. teehr-0.4.1/src/teehr/evaluation/tables.py +1541 -0
  12. teehr-0.4.1/src/teehr/evaluation/utils.py +60 -0
  13. teehr-0.4.1/src/teehr/example_data/__init__.py +0 -0
  14. teehr-0.4.1/src/teehr/example_data/two_locations.py +39 -0
  15. teehr-0.4.1/src/teehr/example_data/v0_3_test_study.py +55 -0
  16. teehr-0.4.1/src/teehr/examples/01-evaluation_setup.ipynb +360 -0
  17. teehr-0.4.1/src/teehr/examples/02-table_queries.ipynb +227 -0
  18. teehr-0.4.1/src/teehr/examples/03-metric_queries.ipynb +328 -0
  19. teehr-0.4.1/src/teehr/examples/04-table_filters.ipynb +219 -0
  20. teehr-0.4.1/src/teehr/examples/05-2_site_setup.ipynb +231 -0
  21. teehr-0.4.1/src/teehr/examples/06-2_site_query.ipynb +290 -0
  22. teehr-0.4.1/src/teehr/examples/07-2_site_plotting.ipynb +136 -0
  23. teehr-0.4.1/src/teehr/examples/08-sql.ipynb +93 -0
  24. teehr-0.4.1/src/teehr/examples/__init__.py +1 -0
  25. teehr-0.4.1/src/teehr/examples/clone_from_s3.ipynb +175 -0
  26. teehr-0.4.1/src/teehr/examples/ngen_example.py +76 -0
  27. teehr-0.4.1/src/teehr/examples/setup_evaluation.py +114 -0
  28. teehr-0.4.1/src/teehr/examples/two_site_debug_script.py +49 -0
  29. teehr-0.4.1/src/teehr/fetching/__init__.py +1 -0
  30. teehr-0.4.1/src/teehr/fetching/const.py +281 -0
  31. teehr-0.4.1/src/teehr/fetching/nwm/__init__.py +1 -0
  32. teehr-0.4.1/src/teehr/fetching/nwm/grid_utils.py +240 -0
  33. teehr-0.4.1/src/teehr/fetching/nwm/nwm_grids.py +269 -0
  34. teehr-0.4.1/src/teehr/fetching/nwm/nwm_points.py +247 -0
  35. teehr-0.4.1/src/teehr/fetching/nwm/point_utils.py +243 -0
  36. teehr-0.4.1/src/teehr/fetching/nwm/retrospective_grids.py +457 -0
  37. teehr-0.4.1/src/teehr/fetching/nwm/retrospective_points.py +329 -0
  38. teehr-0.4.1/src/teehr/fetching/readme.md +2 -0
  39. teehr-0.4.1/src/teehr/fetching/usgs/__init__.py +1 -0
  40. teehr-0.4.1/src/teehr/fetching/usgs/usgs.py +369 -0
  41. teehr-0.4.1/src/teehr/fetching/utils.py +736 -0
  42. teehr-0.4.1/src/teehr/loading/__init__.py +1 -0
  43. teehr-0.4.1/src/teehr/loading/add_domains.py +253 -0
  44. teehr-0.4.1/src/teehr/loading/joined_timeseries.py +213 -0
  45. teehr-0.4.1/src/teehr/loading/location_attributes.py +220 -0
  46. teehr-0.4.1/src/teehr/loading/location_crosswalks.py +201 -0
  47. teehr-0.4.1/src/teehr/loading/locations.py +204 -0
  48. teehr-0.4.1/src/teehr/loading/readme.md +1 -0
  49. teehr-0.4.1/src/teehr/loading/s3/clone_from_s3.py +259 -0
  50. teehr-0.4.1/src/teehr/loading/timeseries.py +280 -0
  51. teehr-0.4.1/src/teehr/loading/utils.py +240 -0
  52. teehr-0.4.1/src/teehr/metrics/__init__.py +1 -0
  53. teehr-0.4.1/src/teehr/metrics/bootstrap_funcs.py +106 -0
  54. teehr-0.4.1/src/teehr/metrics/gumboot_bootstrap.py +185 -0
  55. teehr-0.4.1/src/teehr/metrics/metric_funcs.py +301 -0
  56. teehr-0.4.1/src/teehr/metrics/readme.md +2 -0
  57. teehr-0.4.1/src/teehr/models/__init__.py +1 -0
  58. teehr-0.4.1/src/teehr/models/fetching/__init__.py +1 -0
  59. teehr-0.4.1/src/teehr/models/fetching/nwm22_grid.py +268 -0
  60. teehr-0.4.1/src/teehr/models/fetching/nwm22_point.py +331 -0
  61. teehr-0.4.1/src/teehr/models/fetching/nwm30_grid.py +136 -0
  62. teehr-0.4.1/src/teehr/models/fetching/nwm30_point.py +142 -0
  63. teehr-0.4.1/src/teehr/models/fetching/utils.py +98 -0
  64. teehr-0.4.1/src/teehr/models/filters.py +142 -0
  65. teehr-0.4.1/src/teehr/models/metrics/__init__.py +1 -0
  66. teehr-0.4.1/src/teehr/models/metrics/bootstrap_models.py +154 -0
  67. teehr-0.4.1/src/teehr/models/metrics/metric_attributes.py +237 -0
  68. teehr-0.4.1/src/teehr/models/metrics/metric_enums.py +47 -0
  69. teehr-0.4.1/src/teehr/models/metrics/metric_models.py +839 -0
  70. teehr-0.4.1/src/teehr/models/readme.md +1 -0
  71. teehr-0.4.1/src/teehr/models/str_enum.py +11 -0
  72. teehr-0.4.1/src/teehr/models/table_enums.py +56 -0
  73. teehr-0.4.1/src/teehr/models/tables.py +91 -0
  74. teehr-0.4.1/src/teehr/querying/__init__.py +1 -0
  75. teehr-0.4.1/src/teehr/querying/filter_format.py +177 -0
  76. teehr-0.4.1/src/teehr/querying/metric_format.py +64 -0
  77. teehr-0.4.1/src/teehr/querying/readme.md +2 -0
  78. teehr-0.4.1/src/teehr/querying/utils.py +100 -0
  79. teehr-0.4.1/src/teehr/template/__init__.py +1 -0
  80. teehr-0.4.1/src/teehr/template/cache/readme.md +1 -0
  81. teehr-0.4.1/src/teehr/template/dataset/attributes/_readme.md +1 -0
  82. teehr-0.4.1/src/teehr/template/dataset/attributes/attributes.csv +2 -0
  83. teehr-0.4.1/src/teehr/template/dataset/configurations/_readme.md +1 -0
  84. teehr-0.4.1/src/teehr/template/dataset/configurations/configurations.csv +162 -0
  85. teehr-0.4.1/src/teehr/template/dataset/joined_timeseries/_readme.md +1 -0
  86. teehr-0.4.1/src/teehr/template/dataset/location_attributes/_readme.md +1 -0
  87. teehr-0.4.1/src/teehr/template/dataset/location_crosswalks/_readme.md +1 -0
  88. teehr-0.4.1/src/teehr/template/dataset/locations/_readme.md +1 -0
  89. teehr-0.4.1/src/teehr/template/dataset/primary_timeseries/_readme.md +1 -0
  90. teehr-0.4.1/src/teehr/template/dataset/secondary_timeseries/_readme.md +1 -0
  91. teehr-0.4.1/src/teehr/template/dataset/units/_readme.md +1 -0
  92. teehr-0.4.1/src/teehr/template/dataset/units/units.csv +5 -0
  93. teehr-0.4.1/src/teehr/template/dataset/variables/_readme.md +1 -0
  94. teehr-0.4.1/src/teehr/template/dataset/variables/variables.csv +4 -0
  95. teehr-0.4.1/src/teehr/template/gitignore_template +2 -0
  96. teehr-0.4.1/src/teehr/template/readme.md +18 -0
  97. teehr-0.4.1/src/teehr/template/scripts/__init__.py +1 -0
  98. teehr-0.4.1/src/teehr/template/scripts/user_defined_fields.py +98 -0
  99. teehr-0.4.1/src/teehr/utilities/__init__.py +1 -0
  100. teehr-0.4.1/src/teehr/utilities/generate_weights.py +302 -0
  101. teehr-0.4.1/src/teehr/utils/install_spark_jars.py +32 -0
  102. teehr-0.4.1/src/teehr/visualization/__init__.py +1 -0
  103. 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
+ ![alt text](https://github.com/RTIInternational/teehr/blob/main/docs/images/teehr.png)
41
+
42
+ | | |
43
+ | --- | --- |
44
+ | ![alt text](https://ciroh.ua.edu/wp-content/uploads/2022/08/CIROHLogo_200x200.png) | 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
+ ![alt text](https://github.com/RTIInternational/teehr/blob/main/docs/images/teehr.png)
2
+
3
+ | | |
4
+ | --- | --- |
5
+ | ![alt text](https://ciroh.ua.edu/wp-content/uploads/2022/08/CIROHLogo_200x200.png) | 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)