rainfallqc 0.0.9__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.
- rainfallqc-0.0.9/LICENSE +33 -0
- rainfallqc-0.0.9/PKG-INFO +201 -0
- rainfallqc-0.0.9/README.rst +146 -0
- rainfallqc-0.0.9/pyproject.toml +158 -0
- rainfallqc-0.0.9/src/rainfallqc/__init__.py +22 -0
- rainfallqc-0.0.9/src/rainfallqc/checks/__init__.py +1 -0
- rainfallqc-0.0.9/src/rainfallqc/checks/comparison_checks.py +342 -0
- rainfallqc-0.0.9/src/rainfallqc/checks/gauge_checks.py +234 -0
- rainfallqc-0.0.9/src/rainfallqc/checks/neighbourhood_checks.py +341 -0
- rainfallqc-0.0.9/src/rainfallqc/checks/timeseries_checks.py +1042 -0
- rainfallqc-0.0.9/src/rainfallqc/core/__init__.py +1 -0
- rainfallqc-0.0.9/src/rainfallqc/data/ETCCDI/RawData_HADEX2_CDD_1951-2010_ANN_from-90to90_from-180to180.nc +0 -0
- rainfallqc-0.0.9/src/rainfallqc/data/ETCCDI/RawData_HADEX2_CWD_1951-2010_ANN_from-90to90_from-180to180.nc +0 -0
- rainfallqc-0.0.9/src/rainfallqc/data/ETCCDI/RawData_HADEX2_PRCPTOT_1951-2010_ANN_from-90to90_from-180to180.nc +0 -0
- rainfallqc-0.0.9/src/rainfallqc/data/ETCCDI/RawData_HADEX2_R99p_1951-2010_ANN_from-90to90_from-180to180.nc +0 -0
- rainfallqc-0.0.9/src/rainfallqc/data/ETCCDI/RawData_HADEX2_Rx1day_1951-2010_ANN_from-90to90_from-180to180.nc +0 -0
- rainfallqc-0.0.9/src/rainfallqc/data/ETCCDI/RawData_HADEX2_SDII_1951-2010_ANN_from-90to90_from-180to180.nc +0 -0
- rainfallqc-0.0.9/src/rainfallqc/data/ETCCDI/__init__.py +1 -0
- rainfallqc-0.0.9/src/rainfallqc/data/__init__.py +1 -0
- rainfallqc-0.0.9/src/rainfallqc/qc_frameworks/__init__.py +1 -0
- rainfallqc-0.0.9/src/rainfallqc/qc_frameworks/apply_qc_framework.py +63 -0
- rainfallqc-0.0.9/src/rainfallqc/qc_frameworks/inbuilt_qc_frameworks.py +25 -0
- rainfallqc-0.0.9/src/rainfallqc/utils/__init__.py +1 -0
- rainfallqc-0.0.9/src/rainfallqc/utils/data_readers.py +713 -0
- rainfallqc-0.0.9/src/rainfallqc/utils/data_utils.py +259 -0
- rainfallqc-0.0.9/src/rainfallqc/utils/neighbourhood_utils.py +355 -0
- rainfallqc-0.0.9/src/rainfallqc/utils/spatial_utils.py +40 -0
- rainfallqc-0.0.9/src/rainfallqc/utils/stats.py +260 -0
rainfallqc-0.0.9/LICENSE
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
GNU GENERAL PUBLIC LICENSE
|
|
2
|
+
Version 3, 29 June 2007
|
|
3
|
+
|
|
4
|
+
Quality control procedure for rainfall data
|
|
5
|
+
Copyright (C) 2025 Tom Keel
|
|
6
|
+
|
|
7
|
+
This program is free software: you can redistribute it and/or modify
|
|
8
|
+
it under the terms of the GNU General Public License as published by
|
|
9
|
+
the Free Software Foundation, either version 3 of the License, or
|
|
10
|
+
(at your option) any later version.
|
|
11
|
+
|
|
12
|
+
This program is distributed in the hope that it will be useful,
|
|
13
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
14
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
15
|
+
GNU General Public License for more details.
|
|
16
|
+
|
|
17
|
+
You should have received a copy of the GNU General Public License
|
|
18
|
+
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
19
|
+
|
|
20
|
+
Also add information on how to contact you by electronic and paper mail.
|
|
21
|
+
|
|
22
|
+
You should also get your employer (if you work as a programmer) or school,
|
|
23
|
+
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
|
24
|
+
For more information on this, and how to apply and follow the GNU GPL, see
|
|
25
|
+
<http://www.gnu.org/licenses/>.
|
|
26
|
+
|
|
27
|
+
The GNU General Public License does not permit incorporating your program
|
|
28
|
+
into proprietary programs. If your program is a subroutine library, you
|
|
29
|
+
may consider it more useful to permit linking proprietary applications with
|
|
30
|
+
the library. If this is what you want to do, use the GNU Lesser General
|
|
31
|
+
Public License instead of this License. But first, please read
|
|
32
|
+
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
|
|
33
|
+
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: rainfallqc
|
|
3
|
+
Version: 0.0.9
|
|
4
|
+
Summary: Quality control for rainfall data
|
|
5
|
+
Author-email: Tom Keel <tomkee@ceh.ac.uk>
|
|
6
|
+
Maintainer-email: Tom Keel <tomkee@ceh.ac.uk>
|
|
7
|
+
Requires-Python: >=3.10.0
|
|
8
|
+
Description-Content-Type: text/x-rst
|
|
9
|
+
Classifier: Development Status :: 4 - Beta
|
|
10
|
+
Classifier: Intended Audience :: Developers
|
|
11
|
+
Classifier: Intended Audience :: Science/Research
|
|
12
|
+
Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
|
|
13
|
+
Classifier: Natural Language :: English
|
|
14
|
+
Classifier: Operating System :: OS Independent
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
20
|
+
Classifier: Topic :: Scientific/Engineering :: Hydrology
|
|
21
|
+
License-File: LICENSE
|
|
22
|
+
Requires-Dist: scipy
|
|
23
|
+
Requires-Dist: numpy
|
|
24
|
+
Requires-Dist: polars
|
|
25
|
+
Requires-Dist: pandas
|
|
26
|
+
Requires-Dist: xarray
|
|
27
|
+
Requires-Dist: bottleneck
|
|
28
|
+
Requires-Dist: geopy
|
|
29
|
+
Requires-Dist: pip ; extra == "dev"
|
|
30
|
+
Requires-Dist: numpy ; extra == "dev"
|
|
31
|
+
Requires-Dist: bump-my-version ; extra == "dev"
|
|
32
|
+
Requires-Dist: ruff ; extra == "dev"
|
|
33
|
+
Requires-Dist: black ; extra == "dev"
|
|
34
|
+
Requires-Dist: pre_commit ; extra == "dev"
|
|
35
|
+
Requires-Dist: pylint ; extra == "dev"
|
|
36
|
+
Requires-Dist: pytest ; extra == "dev"
|
|
37
|
+
Requires-Dist: pytest-cov ; extra == "dev"
|
|
38
|
+
Requires-Dist: matplotlib ; extra == "dev"
|
|
39
|
+
Requires-Dist: sphinx ; extra == "dev"
|
|
40
|
+
Requires-Dist: sphinx ; extra == "docs"
|
|
41
|
+
Requires-Dist: sphinx-copybutton ; extra == "docs"
|
|
42
|
+
Requires-Dist: sphinx-rtd-theme ; extra == "docs"
|
|
43
|
+
Requires-Dist: mypy ; extra == "lint"
|
|
44
|
+
Requires-Dist: ruff ; extra == "lint"
|
|
45
|
+
Requires-Dist: pytest ; extra == "test"
|
|
46
|
+
Requires-Dist: pytest-cov ; extra == "test"
|
|
47
|
+
Project-URL: bugs, https://github.com/thomasjkeel/RainfallQC/issues
|
|
48
|
+
Project-URL: changelog, https://github.com/thomasjkeel/RainfallQC/blob/master/changelog.md
|
|
49
|
+
Project-URL: homepage, https://github.com/thomasjkeel/RainfallQC
|
|
50
|
+
Provides-Extra: dev
|
|
51
|
+
Provides-Extra: docs
|
|
52
|
+
Provides-Extra: lint
|
|
53
|
+
Provides-Extra: test
|
|
54
|
+
|
|
55
|
+
===============================================
|
|
56
|
+
RainfallQC - Quality control for rainfall data
|
|
57
|
+
===============================================
|
|
58
|
+
|
|
59
|
+
..
|
|
60
|
+
image:: https://img.shields.io/pypi/v/rainfallqc.svg
|
|
61
|
+
:target: https://pypi.python.org/pypi/rainfallqc
|
|
62
|
+
|
|
63
|
+
..
|
|
64
|
+
image:: https://readthedocs.org/projects/rainfallqc/badge/?version=latest
|
|
65
|
+
:target: https://rainfallqc.readthedocs.io/en/latest/?version=latest
|
|
66
|
+
:alt: Documentation Status
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
Provides methods for running QC frameworks.
|
|
70
|
+
|
|
71
|
+
**NOTEBOOK DEMO AVAILABLE** `HERE <https://github.com/Thomasjkeel/RainfallQC-notebooks/blob/main/notebooks/demo/rainfallQC_demo.ipynb>`_
|
|
72
|
+
|
|
73
|
+
Please email tomkee@ceh.ac.uk if you have any questions.
|
|
74
|
+
|
|
75
|
+
Project To Do:
|
|
76
|
+
|
|
77
|
+
- add flag descriptions
|
|
78
|
+
- Use timestep str maker to the checks
|
|
79
|
+
|
|
80
|
+
Example use
|
|
81
|
+
-----------
|
|
82
|
+
|
|
83
|
+
Example 1. - Individual quality checks on single rain gauge
|
|
84
|
+
===========================================================
|
|
85
|
+
|
|
86
|
+
.. code-block:: python
|
|
87
|
+
|
|
88
|
+
# Load two types of QC'ing modules from RainfallQC
|
|
89
|
+
from rainfallqc import gauge_checks, comparison_checks
|
|
90
|
+
|
|
91
|
+
# 1. Simple 1 gauge QC
|
|
92
|
+
# 1.1. Run 1 qc method for 1 gauge
|
|
93
|
+
intermittency_flag = gauge_checks.check_intermittency(data, rain_col="rain_mm")
|
|
94
|
+
|
|
95
|
+
# 1.2. Run 1 qc method for 1 gauge using in-built comparison dataset
|
|
96
|
+
wr_flags = comparison_checks.check_exceedance_of_rainfall_world_record(data, rain_col="rain_mm", time_res='hourly')
|
|
97
|
+
|
|
98
|
+
# 1.3. Run 1 qc method for 1 gauge using in-built comparison dataset and location of gauge
|
|
99
|
+
rx1day_flags = comparison_checks.check_annual_exceedance_etccdi_rx1day(data, rain_col="rain_mm", gauge_lon=1.0, gauge_lat=55.0)
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
Example 2. - Individual quality checks on networks of rain gauges
|
|
103
|
+
=================================================================
|
|
104
|
+
|
|
105
|
+
.. code-block:: python
|
|
106
|
+
|
|
107
|
+
# 2. Run neighbour/network checks on a subset of a rain gauge network
|
|
108
|
+
from rainfallqc import neighbourhood_checks
|
|
109
|
+
from rainfallqc.utils import data_readers
|
|
110
|
+
|
|
111
|
+
# 2.1. Read in GDSR gauge network metadata
|
|
112
|
+
gdsr_obj = data_readers.GDSRNetworkReader(path_to_gdsr_dir="./tests/data/GDSR/")
|
|
113
|
+
|
|
114
|
+
# 2.2. subset by max 10 gauges within 50 km and with at least 500 days of overlap
|
|
115
|
+
nearby_ids = list(
|
|
116
|
+
gdsr_obj.get_nearest_overlapping_neighbours_to_target(
|
|
117
|
+
target_id="DE_00310", distance_threshold=50, n_closest=10, min_overlap_days=500
|
|
118
|
+
)
|
|
119
|
+
)
|
|
120
|
+
nearby_ids.append(target_id)
|
|
121
|
+
nearby_data_paths = gdsr_obj.metadata.filter(pl.col("station_id").is_in(nearby_ids))["path"]
|
|
122
|
+
|
|
123
|
+
# 2.3. Load those nearest gauges from network metadata
|
|
124
|
+
gdsr_network = gdsr_obj.load_network_data(data_paths=nearby_data_paths)
|
|
125
|
+
|
|
126
|
+
# 2.4 Run a neighbourhood check (checking if suspiciously large rainfall values were seen in neighbours)
|
|
127
|
+
extreme_wet_flags = neighbourhood_checks.check_wet_neighbours(
|
|
128
|
+
gdsr_network,
|
|
129
|
+
target_gauge_col="rain_mm_DE_02483",
|
|
130
|
+
neighbouring_gauge_cols=gdsr_network.columns[1:], # exclude time
|
|
131
|
+
time_res="hourly",
|
|
132
|
+
wet_threshold=1.0, # threshold for rainfall intensity to be considered
|
|
133
|
+
min_n_neighbours=5, # number of neighbours needed for comparison
|
|
134
|
+
n_neighbours_ignored=0, # ignore no neighbours and include all
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
Example 3. - Applying a framework of QC methods (e.g. IntenseQC)
|
|
138
|
+
================================================================
|
|
139
|
+
|
|
140
|
+
.. code-block:: python
|
|
141
|
+
|
|
142
|
+
# 3. Applying multiple QC methods in framework (e.g. IntenseQC)
|
|
143
|
+
from rainfallqc.qc_frameworks import apply_qc_framework
|
|
144
|
+
|
|
145
|
+
# 3.1. Decide which QC methods of IntenseQC will be run
|
|
146
|
+
qc_framework = "IntenseQC"
|
|
147
|
+
qc_methods_to_run = ["QC1", "QC8", "QC9", "QC10", "QC11", "QC12", "QC14", "QC15", "QC16"]
|
|
148
|
+
|
|
149
|
+
# 3.2 Decide which parameters for QC
|
|
150
|
+
qc_kwargs = {
|
|
151
|
+
"QC1": {"quantile": 5},
|
|
152
|
+
"QC14": {"wet_day_threshold": 1.0, "accumulation_multiplying_factor": 2.0},
|
|
153
|
+
"QC16": {
|
|
154
|
+
"neighbouring_gauge_cols": daily_gpcc_network.columns[2:],
|
|
155
|
+
"wet_threshold": 1.0,
|
|
156
|
+
"min_n_neighbours": 5,
|
|
157
|
+
"n_neighbours_ignored": 0,
|
|
158
|
+
},
|
|
159
|
+
# Shared defaults applied to all
|
|
160
|
+
"shared": {
|
|
161
|
+
"rain_col": "rain_mm_DE_02483",
|
|
162
|
+
"target_gauge_col": "rain_mm_DE_02483",
|
|
163
|
+
"gauge_lat": gpcc_metadata["latitude"],
|
|
164
|
+
"gauge_lon": gpcc_metadata["longitude"],
|
|
165
|
+
"time_res": "daily",
|
|
166
|
+
"data_resolution": 0.1,
|
|
167
|
+
},
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
# 3.3. Run QC methods on network data
|
|
171
|
+
qc_result = apply_qc_framework.run_qc_framework(
|
|
172
|
+
daily_gpcc_network, qc_framework=qc_framework, qc_methods_to_run=qc_methods_to_run, qc_kwargs=qc_kwargs
|
|
173
|
+
)
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
Other examples
|
|
177
|
+
===================
|
|
178
|
+
Also see example Jupyter Notebooks here: https://github.com/Thomasjkeel/RainfallQC-notebooks/tree/main
|
|
179
|
+
|
|
180
|
+
Documents
|
|
181
|
+
---------
|
|
182
|
+
* Free software: GNU General Public License v3
|
|
183
|
+
* Documentation: https://rainfallqc.readthedocs.io.
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
Features
|
|
187
|
+
--------
|
|
188
|
+
|
|
189
|
+
- 25 rainfall QC methods (all from IntenseQC)
|
|
190
|
+
- editable parameters so you can tweak thresholds, streak or accumulation lengths, and distances to neighbouring gauges
|
|
191
|
+
|
|
192
|
+
Credits
|
|
193
|
+
-------
|
|
194
|
+
Based on the IntenseQC: https://github.com/nclwater/intense-qc/tree/master
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
This package was created with Cookiecutter_ and the `audreyr/cookiecutter-pypackage`_ project template.
|
|
198
|
+
|
|
199
|
+
.. _Cookiecutter: https://github.com/audreyr/cookiecutter
|
|
200
|
+
.. _`audreyr/cookiecutter-pypackage`: https://github.com/audreyr/cookiecutter-pypackage
|
|
201
|
+
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
===============================================
|
|
2
|
+
RainfallQC - Quality control for rainfall data
|
|
3
|
+
===============================================
|
|
4
|
+
|
|
5
|
+
..
|
|
6
|
+
image:: https://img.shields.io/pypi/v/rainfallqc.svg
|
|
7
|
+
:target: https://pypi.python.org/pypi/rainfallqc
|
|
8
|
+
|
|
9
|
+
..
|
|
10
|
+
image:: https://readthedocs.org/projects/rainfallqc/badge/?version=latest
|
|
11
|
+
:target: https://rainfallqc.readthedocs.io/en/latest/?version=latest
|
|
12
|
+
:alt: Documentation Status
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
Provides methods for running QC frameworks.
|
|
16
|
+
|
|
17
|
+
**NOTEBOOK DEMO AVAILABLE** `HERE <https://github.com/Thomasjkeel/RainfallQC-notebooks/blob/main/notebooks/demo/rainfallQC_demo.ipynb>`_
|
|
18
|
+
|
|
19
|
+
Please email tomkee@ceh.ac.uk if you have any questions.
|
|
20
|
+
|
|
21
|
+
Project To Do:
|
|
22
|
+
|
|
23
|
+
- add flag descriptions
|
|
24
|
+
- Use timestep str maker to the checks
|
|
25
|
+
|
|
26
|
+
Example use
|
|
27
|
+
-----------
|
|
28
|
+
|
|
29
|
+
Example 1. - Individual quality checks on single rain gauge
|
|
30
|
+
===========================================================
|
|
31
|
+
|
|
32
|
+
.. code-block:: python
|
|
33
|
+
|
|
34
|
+
# Load two types of QC'ing modules from RainfallQC
|
|
35
|
+
from rainfallqc import gauge_checks, comparison_checks
|
|
36
|
+
|
|
37
|
+
# 1. Simple 1 gauge QC
|
|
38
|
+
# 1.1. Run 1 qc method for 1 gauge
|
|
39
|
+
intermittency_flag = gauge_checks.check_intermittency(data, rain_col="rain_mm")
|
|
40
|
+
|
|
41
|
+
# 1.2. Run 1 qc method for 1 gauge using in-built comparison dataset
|
|
42
|
+
wr_flags = comparison_checks.check_exceedance_of_rainfall_world_record(data, rain_col="rain_mm", time_res='hourly')
|
|
43
|
+
|
|
44
|
+
# 1.3. Run 1 qc method for 1 gauge using in-built comparison dataset and location of gauge
|
|
45
|
+
rx1day_flags = comparison_checks.check_annual_exceedance_etccdi_rx1day(data, rain_col="rain_mm", gauge_lon=1.0, gauge_lat=55.0)
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
Example 2. - Individual quality checks on networks of rain gauges
|
|
49
|
+
=================================================================
|
|
50
|
+
|
|
51
|
+
.. code-block:: python
|
|
52
|
+
|
|
53
|
+
# 2. Run neighbour/network checks on a subset of a rain gauge network
|
|
54
|
+
from rainfallqc import neighbourhood_checks
|
|
55
|
+
from rainfallqc.utils import data_readers
|
|
56
|
+
|
|
57
|
+
# 2.1. Read in GDSR gauge network metadata
|
|
58
|
+
gdsr_obj = data_readers.GDSRNetworkReader(path_to_gdsr_dir="./tests/data/GDSR/")
|
|
59
|
+
|
|
60
|
+
# 2.2. subset by max 10 gauges within 50 km and with at least 500 days of overlap
|
|
61
|
+
nearby_ids = list(
|
|
62
|
+
gdsr_obj.get_nearest_overlapping_neighbours_to_target(
|
|
63
|
+
target_id="DE_00310", distance_threshold=50, n_closest=10, min_overlap_days=500
|
|
64
|
+
)
|
|
65
|
+
)
|
|
66
|
+
nearby_ids.append(target_id)
|
|
67
|
+
nearby_data_paths = gdsr_obj.metadata.filter(pl.col("station_id").is_in(nearby_ids))["path"]
|
|
68
|
+
|
|
69
|
+
# 2.3. Load those nearest gauges from network metadata
|
|
70
|
+
gdsr_network = gdsr_obj.load_network_data(data_paths=nearby_data_paths)
|
|
71
|
+
|
|
72
|
+
# 2.4 Run a neighbourhood check (checking if suspiciously large rainfall values were seen in neighbours)
|
|
73
|
+
extreme_wet_flags = neighbourhood_checks.check_wet_neighbours(
|
|
74
|
+
gdsr_network,
|
|
75
|
+
target_gauge_col="rain_mm_DE_02483",
|
|
76
|
+
neighbouring_gauge_cols=gdsr_network.columns[1:], # exclude time
|
|
77
|
+
time_res="hourly",
|
|
78
|
+
wet_threshold=1.0, # threshold for rainfall intensity to be considered
|
|
79
|
+
min_n_neighbours=5, # number of neighbours needed for comparison
|
|
80
|
+
n_neighbours_ignored=0, # ignore no neighbours and include all
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
Example 3. - Applying a framework of QC methods (e.g. IntenseQC)
|
|
84
|
+
================================================================
|
|
85
|
+
|
|
86
|
+
.. code-block:: python
|
|
87
|
+
|
|
88
|
+
# 3. Applying multiple QC methods in framework (e.g. IntenseQC)
|
|
89
|
+
from rainfallqc.qc_frameworks import apply_qc_framework
|
|
90
|
+
|
|
91
|
+
# 3.1. Decide which QC methods of IntenseQC will be run
|
|
92
|
+
qc_framework = "IntenseQC"
|
|
93
|
+
qc_methods_to_run = ["QC1", "QC8", "QC9", "QC10", "QC11", "QC12", "QC14", "QC15", "QC16"]
|
|
94
|
+
|
|
95
|
+
# 3.2 Decide which parameters for QC
|
|
96
|
+
qc_kwargs = {
|
|
97
|
+
"QC1": {"quantile": 5},
|
|
98
|
+
"QC14": {"wet_day_threshold": 1.0, "accumulation_multiplying_factor": 2.0},
|
|
99
|
+
"QC16": {
|
|
100
|
+
"neighbouring_gauge_cols": daily_gpcc_network.columns[2:],
|
|
101
|
+
"wet_threshold": 1.0,
|
|
102
|
+
"min_n_neighbours": 5,
|
|
103
|
+
"n_neighbours_ignored": 0,
|
|
104
|
+
},
|
|
105
|
+
# Shared defaults applied to all
|
|
106
|
+
"shared": {
|
|
107
|
+
"rain_col": "rain_mm_DE_02483",
|
|
108
|
+
"target_gauge_col": "rain_mm_DE_02483",
|
|
109
|
+
"gauge_lat": gpcc_metadata["latitude"],
|
|
110
|
+
"gauge_lon": gpcc_metadata["longitude"],
|
|
111
|
+
"time_res": "daily",
|
|
112
|
+
"data_resolution": 0.1,
|
|
113
|
+
},
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
# 3.3. Run QC methods on network data
|
|
117
|
+
qc_result = apply_qc_framework.run_qc_framework(
|
|
118
|
+
daily_gpcc_network, qc_framework=qc_framework, qc_methods_to_run=qc_methods_to_run, qc_kwargs=qc_kwargs
|
|
119
|
+
)
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
Other examples
|
|
123
|
+
===================
|
|
124
|
+
Also see example Jupyter Notebooks here: https://github.com/Thomasjkeel/RainfallQC-notebooks/tree/main
|
|
125
|
+
|
|
126
|
+
Documents
|
|
127
|
+
---------
|
|
128
|
+
* Free software: GNU General Public License v3
|
|
129
|
+
* Documentation: https://rainfallqc.readthedocs.io.
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
Features
|
|
133
|
+
--------
|
|
134
|
+
|
|
135
|
+
- 25 rainfall QC methods (all from IntenseQC)
|
|
136
|
+
- editable parameters so you can tweak thresholds, streak or accumulation lengths, and distances to neighbouring gauges
|
|
137
|
+
|
|
138
|
+
Credits
|
|
139
|
+
-------
|
|
140
|
+
Based on the IntenseQC: https://github.com/nclwater/intense-qc/tree/master
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
This package was created with Cookiecutter_ and the `audreyr/cookiecutter-pypackage`_ project template.
|
|
144
|
+
|
|
145
|
+
.. _Cookiecutter: https://github.com/audreyr/cookiecutter
|
|
146
|
+
.. _`audreyr/cookiecutter-pypackage`: https://github.com/audreyr/cookiecutter-pypackage
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["flit_core >=3.4"]
|
|
3
|
+
build-backend = "flit_core.buildapi"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "rainfallqc"
|
|
7
|
+
dynamic = ["version"]
|
|
8
|
+
description = "Quality control for rainfall data"
|
|
9
|
+
readme = "README.rst"
|
|
10
|
+
requires-python = ">=3.10.0"
|
|
11
|
+
authors = [{ name = "Tom Keel", email = "tomkee@ceh.ac.uk" }]
|
|
12
|
+
maintainers = [{ name = "Tom Keel", email = "tomkee@ceh.ac.uk" }]
|
|
13
|
+
classifiers = [
|
|
14
|
+
"Development Status :: 4 - Beta",
|
|
15
|
+
"Intended Audience :: Developers",
|
|
16
|
+
"Intended Audience :: Science/Research",
|
|
17
|
+
"License :: OSI Approved :: GNU General Public License v3 (GPLv3)",
|
|
18
|
+
"Natural Language :: English",
|
|
19
|
+
"Operating System :: OS Independent",
|
|
20
|
+
"Programming Language :: Python :: 3",
|
|
21
|
+
"Programming Language :: Python :: 3.10",
|
|
22
|
+
"Programming Language :: Python :: 3.11",
|
|
23
|
+
"Programming Language :: Python :: 3.12",
|
|
24
|
+
"Programming Language :: Python :: 3.13",
|
|
25
|
+
"Topic :: Scientific/Engineering :: Hydrology",
|
|
26
|
+
]
|
|
27
|
+
license = { file = "LICENSE" }
|
|
28
|
+
dependencies = [
|
|
29
|
+
"scipy",
|
|
30
|
+
"numpy",
|
|
31
|
+
"polars",
|
|
32
|
+
"pandas",
|
|
33
|
+
"xarray",
|
|
34
|
+
"bottleneck",
|
|
35
|
+
"geopy"
|
|
36
|
+
]
|
|
37
|
+
|
|
38
|
+
[project.optional-dependencies]
|
|
39
|
+
test = ["pytest", "pytest-cov"]
|
|
40
|
+
docs = ["sphinx", "sphinx-copybutton", "sphinx-rtd-theme"]
|
|
41
|
+
lint = ["mypy", "ruff"]
|
|
42
|
+
dev = [
|
|
43
|
+
"pip",
|
|
44
|
+
"numpy",
|
|
45
|
+
"bump-my-version",
|
|
46
|
+
"ruff",
|
|
47
|
+
"black",
|
|
48
|
+
"pre_commit",
|
|
49
|
+
"pylint",
|
|
50
|
+
"pytest",
|
|
51
|
+
"pytest-cov",
|
|
52
|
+
"matplotlib",
|
|
53
|
+
"sphinx",
|
|
54
|
+
]
|
|
55
|
+
|
|
56
|
+
[project.urls]
|
|
57
|
+
bugs = "https://github.com/thomasjkeel/RainfallQC/issues"
|
|
58
|
+
changelog = "https://github.com/thomasjkeel/RainfallQC/blob/master/changelog.md"
|
|
59
|
+
homepage = "https://github.com/thomasjkeel/RainfallQC"
|
|
60
|
+
|
|
61
|
+
[tool]
|
|
62
|
+
|
|
63
|
+
[tool.black]
|
|
64
|
+
target-version = ["py310", "py311", "py312", "py313"]
|
|
65
|
+
|
|
66
|
+
[tool.bumpversion]
|
|
67
|
+
current_version = "0.0.9"
|
|
68
|
+
commit = true
|
|
69
|
+
message = "Bump version: {current_version} → {new_version}"
|
|
70
|
+
commit_args = ""
|
|
71
|
+
allow_dirty = false
|
|
72
|
+
parse = "(?P<major>\\d+)\\.(?P<minor>\\d+)\\.(?P<patch>\\d+)(\\-(?P<release>[a-z]+))?"
|
|
73
|
+
serialize = ["{major}.{minor}.{patch}-{release}", "{major}.{minor}.{patch}"]
|
|
74
|
+
search = "{current_version}"
|
|
75
|
+
replace = "{new_version}"
|
|
76
|
+
regex = false
|
|
77
|
+
ignore_missing_version = false
|
|
78
|
+
tag = false
|
|
79
|
+
sign_tags = false
|
|
80
|
+
tag_name = "v{new_version}"
|
|
81
|
+
tag_message = "Bump version: {current_version} → {new_version}"
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
[[tool.bumpversion.files]]
|
|
85
|
+
filename = "src/rainfallqc/__init__.py"
|
|
86
|
+
search = "__version__ = \"{current_version}\""
|
|
87
|
+
replace = "__version__ = \"{new_version}\""
|
|
88
|
+
|
|
89
|
+
[tool.bumpversion.parts.release]
|
|
90
|
+
optional_value = "gamma"
|
|
91
|
+
values = ["alpha", "beta", "gamma"]
|
|
92
|
+
|
|
93
|
+
[tool.pytest.ini_options]
|
|
94
|
+
addopts = "--cov=rainfallqc"
|
|
95
|
+
markers = ["slow: Marks slow tests"]
|
|
96
|
+
testpaths = ["tests"]
|
|
97
|
+
pythonpath = ["src"]
|
|
98
|
+
|
|
99
|
+
[tool.setuptools]
|
|
100
|
+
package-dir = { "src" = "src" }
|
|
101
|
+
|
|
102
|
+
[tool.setuptools.package-data]
|
|
103
|
+
"rainfallqc" = ["data/ETCCDI/*.nc"]
|
|
104
|
+
|
|
105
|
+
[tool.coverage.run]
|
|
106
|
+
omit = ["tests/*.py", "*__init__.py"]
|
|
107
|
+
relative_files = true
|
|
108
|
+
|
|
109
|
+
[tool.ruff]
|
|
110
|
+
src = ["src", "tests"]
|
|
111
|
+
include = ["src/**.py"]
|
|
112
|
+
line-length = 120
|
|
113
|
+
|
|
114
|
+
[tool.ruff.lint]
|
|
115
|
+
ignore = [
|
|
116
|
+
"D203", # incorrect-blank-line-before-class
|
|
117
|
+
"D212", # multi-line-summary-first-line
|
|
118
|
+
]
|
|
119
|
+
preview = true
|
|
120
|
+
select = [
|
|
121
|
+
"A",
|
|
122
|
+
"B", # bugbear
|
|
123
|
+
"D", # docstrings
|
|
124
|
+
"E", # pycodestyle errors
|
|
125
|
+
"F", # pyflakes
|
|
126
|
+
"I", # imports
|
|
127
|
+
"W", # pycodestyle warnings
|
|
128
|
+
"PLC",
|
|
129
|
+
"PLE",
|
|
130
|
+
"PLW",
|
|
131
|
+
"N816",
|
|
132
|
+
"ANN001",
|
|
133
|
+
"ANN201",
|
|
134
|
+
"ANN202",
|
|
135
|
+
"ANN205",
|
|
136
|
+
"ANN206", # TODO
|
|
137
|
+
]
|
|
138
|
+
exclude = ["docs/conf.py", "docs/notebooks/*.ipynb"]
|
|
139
|
+
|
|
140
|
+
[tool.ruff.lint.flake8-type-checking]
|
|
141
|
+
strict = true
|
|
142
|
+
|
|
143
|
+
[tool.ruff.lint.isort]
|
|
144
|
+
case-sensitive = true
|
|
145
|
+
|
|
146
|
+
[tool.ruff.lint.per-file-ignores]
|
|
147
|
+
"tests/*.py" = [
|
|
148
|
+
"ANN001", "ANN201", "ANN202", # Missing type annotation
|
|
149
|
+
"D103" # Missing docstring in public function
|
|
150
|
+
]
|
|
151
|
+
|
|
152
|
+
[tool.mypy]
|
|
153
|
+
files = "."
|
|
154
|
+
|
|
155
|
+
# Use strict defaults
|
|
156
|
+
strict = true
|
|
157
|
+
warn_unreachable = true
|
|
158
|
+
warn_no_return = true
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"""Top-level package for RainfallQC."""
|
|
2
|
+
|
|
3
|
+
__author__ = """Tom Keel"""
|
|
4
|
+
__email__ = "tomkee@ceh.ac.uk"
|
|
5
|
+
__version__ = "0.0.9"
|
|
6
|
+
|
|
7
|
+
from rainfallqc.checks import (
|
|
8
|
+
comparison_checks,
|
|
9
|
+
gauge_checks,
|
|
10
|
+
neighbourhood_checks,
|
|
11
|
+
timeseries_checks,
|
|
12
|
+
)
|
|
13
|
+
from rainfallqc.qc_frameworks import apply_qc_framework
|
|
14
|
+
|
|
15
|
+
__all__ = [
|
|
16
|
+
"apply_qc_framework",
|
|
17
|
+
"comparison_checks",
|
|
18
|
+
"gauge_checks",
|
|
19
|
+
"neighbourhood_checks",
|
|
20
|
+
"timeseries_checks",
|
|
21
|
+
"apply_qc_framework",
|
|
22
|
+
]
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Quality checks."""
|