rainfallqc 0.4.2__tar.gz → 0.4.4__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 (30) hide show
  1. {rainfallqc-0.4.2 → rainfallqc-0.4.4}/PKG-INFO +2 -2
  2. {rainfallqc-0.4.2 → rainfallqc-0.4.4}/pyproject.toml +2 -2
  3. {rainfallqc-0.4.2 → rainfallqc-0.4.4}/src/rainfallqc/__init__.py +1 -1
  4. {rainfallqc-0.4.2 → rainfallqc-0.4.4}/src/rainfallqc/checks/neighbourhood_checks.py +6 -2
  5. {rainfallqc-0.4.2 → rainfallqc-0.4.4}/src/rainfallqc/checks/timeseries_checks.py +3 -1
  6. {rainfallqc-0.4.2 → rainfallqc-0.4.4}/src/rainfallqc/qc_frameworks/inbuilt_qc_frameworks.py +34 -1
  7. {rainfallqc-0.4.2 → rainfallqc-0.4.4}/src/rainfallqc/utils/data_utils.py +6 -1
  8. {rainfallqc-0.4.2 → rainfallqc-0.4.4}/src/rainfallqc/utils/neighbourhood_utils.py +7 -0
  9. {rainfallqc-0.4.2 → rainfallqc-0.4.4}/src/rainfallqc/utils/stats.py +3 -1
  10. {rainfallqc-0.4.2 → rainfallqc-0.4.4}/LICENSE +0 -0
  11. {rainfallqc-0.4.2 → rainfallqc-0.4.4}/README.rst +0 -0
  12. {rainfallqc-0.4.2 → rainfallqc-0.4.4}/src/rainfallqc/checks/__init__.py +0 -0
  13. {rainfallqc-0.4.2 → rainfallqc-0.4.4}/src/rainfallqc/checks/comparison_checks.py +0 -0
  14. {rainfallqc-0.4.2 → rainfallqc-0.4.4}/src/rainfallqc/checks/gauge_checks.py +0 -0
  15. {rainfallqc-0.4.2 → rainfallqc-0.4.4}/src/rainfallqc/checks/pypwsqc_filters.py +0 -0
  16. {rainfallqc-0.4.2 → rainfallqc-0.4.4}/src/rainfallqc/core/__init__.py +0 -0
  17. {rainfallqc-0.4.2 → rainfallqc-0.4.4}/src/rainfallqc/core/all_qc_checks.py +0 -0
  18. {rainfallqc-0.4.2 → rainfallqc-0.4.4}/src/rainfallqc/data/ETCCDI/RawData_HADEX2_CDD_1951-2010_ANN_from-90to90_from-180to180.nc +0 -0
  19. {rainfallqc-0.4.2 → rainfallqc-0.4.4}/src/rainfallqc/data/ETCCDI/RawData_HADEX2_CWD_1951-2010_ANN_from-90to90_from-180to180.nc +0 -0
  20. {rainfallqc-0.4.2 → rainfallqc-0.4.4}/src/rainfallqc/data/ETCCDI/RawData_HADEX2_PRCPTOT_1951-2010_ANN_from-90to90_from-180to180.nc +0 -0
  21. {rainfallqc-0.4.2 → rainfallqc-0.4.4}/src/rainfallqc/data/ETCCDI/RawData_HADEX2_R99p_1951-2010_ANN_from-90to90_from-180to180.nc +0 -0
  22. {rainfallqc-0.4.2 → rainfallqc-0.4.4}/src/rainfallqc/data/ETCCDI/RawData_HADEX2_Rx1day_1951-2010_ANN_from-90to90_from-180to180.nc +0 -0
  23. {rainfallqc-0.4.2 → rainfallqc-0.4.4}/src/rainfallqc/data/ETCCDI/RawData_HADEX2_SDII_1951-2010_ANN_from-90to90_from-180to180.nc +0 -0
  24. {rainfallqc-0.4.2 → rainfallqc-0.4.4}/src/rainfallqc/data/ETCCDI/__init__.py +0 -0
  25. {rainfallqc-0.4.2 → rainfallqc-0.4.4}/src/rainfallqc/data/__init__.py +0 -0
  26. {rainfallqc-0.4.2 → rainfallqc-0.4.4}/src/rainfallqc/qc_frameworks/__init__.py +0 -0
  27. {rainfallqc-0.4.2 → rainfallqc-0.4.4}/src/rainfallqc/qc_frameworks/apply_qc_framework.py +0 -0
  28. {rainfallqc-0.4.2 → rainfallqc-0.4.4}/src/rainfallqc/utils/__init__.py +0 -0
  29. {rainfallqc-0.4.2 → rainfallqc-0.4.4}/src/rainfallqc/utils/data_readers.py +0 -0
  30. {rainfallqc-0.4.2 → rainfallqc-0.4.4}/src/rainfallqc/utils/spatial_utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: rainfallqc
3
- Version: 0.4.2
3
+ Version: 0.4.4
4
4
  Summary: Quality control for rainfall data
5
5
  Author-email: Tom Keel <tomkee@ceh.ac.uk>
6
6
  Maintainer-email: Tom Keel <tomkee@ceh.ac.uk>
@@ -21,7 +21,7 @@ Classifier: Topic :: Scientific/Engineering :: Hydrology
21
21
  License-File: LICENSE
22
22
  Requires-Dist: scipy
23
23
  Requires-Dist: numpy
24
- Requires-Dist: polars>=1.30
24
+ Requires-Dist: polars
25
25
  Requires-Dist: pandas
26
26
  Requires-Dist: pyarrow
27
27
  Requires-Dist: xarray
@@ -28,7 +28,7 @@ license = { file = "LICENSE" }
28
28
  dependencies = [
29
29
  "scipy",
30
30
  "numpy",
31
- "polars>=1.30",
31
+ "polars",
32
32
  "pandas",
33
33
  "pyarrow",
34
34
  "xarray",
@@ -80,7 +80,7 @@ homepage = "https://github.com/thomasjkeel/RainfallQC"
80
80
  target-version = ["py310", "py311", "py312", "py313"]
81
81
 
82
82
  [tool.bumpversion]
83
- current_version = "0.4.2"
83
+ current_version = "0.4.4"
84
84
  commit = true
85
85
  message = "Bump version: {current_version} → {new_version}"
86
86
  commit_args = ""
@@ -2,7 +2,7 @@
2
2
 
3
3
  __author__ = """Tom Keel"""
4
4
  __email__ = "tomkee@ceh.ac.uk"
5
- __version__ = "0.4.2"
5
+ __version__ = "0.4.4"
6
6
 
7
7
  from rainfallqc import core, utils
8
8
  from rainfallqc.checks import (
@@ -980,7 +980,9 @@ def flag_percentage_diff_of_neighbour(neighbour_data: pl.DataFrame, nearest_neig
980
980
 
981
981
  """
982
982
  return neighbour_data.with_columns(
983
- pl.when((pl.col("perc_diff") <= -100.0))
983
+ pl.when(pl.col("perc_diff").is_null() | pl.col("perc_diff").is_nan())
984
+ .then(np.nan)
985
+ .when((pl.col("perc_diff") <= -100.0))
984
986
  .then(-3)
985
987
  .when((pl.col("perc_diff") <= -50.0) & (pl.col("perc_diff") > -100.0))
986
988
  .then(-2)
@@ -1183,7 +1185,9 @@ def add_wet_flags_to_data(
1183
1185
 
1184
1186
  """
1185
1187
  return neighbour_data_diff.with_columns(
1186
- pl.when(
1188
+ pl.when(pl.col(target_gauge_col).is_null() | pl.col(target_gauge_col).is_nan())
1189
+ .then(np.nan)
1190
+ .when(
1187
1191
  (pl.col(target_gauge_col) >= wet_threshold)
1188
1192
  & (pl.col(f"diff_{nearest_neighbour}") <= expon_percentiles[0.95])
1189
1193
  )
@@ -1045,7 +1045,9 @@ def flag_dry_spell_duration(
1045
1045
  """
1046
1046
  # May need to rethink how this is done uniformly (as could use day check)
1047
1047
  dry_spell_lengths_flags = dry_spell_lengths.with_columns(
1048
- pl.when(pl.col("dry_spell_length") / DAILY_DIVIDING_FACTOR[time_res] >= ref_dry_spell_length * 1.5)
1048
+ pl.when(pl.col("dry_spell_length").is_null() | pl.col("dry_spell_length").is_nan())
1049
+ .then(np.nan)
1050
+ .when(pl.col("dry_spell_length") / DAILY_DIVIDING_FACTOR[time_res] >= ref_dry_spell_length * 1.5)
1049
1051
  .then(4)
1050
1052
  .when(pl.col("dry_spell_length") / DAILY_DIVIDING_FACTOR[time_res] >= ref_dry_spell_length * 1.33)
1051
1053
  .then(3)
@@ -31,6 +31,39 @@ INTENSE_QC = {
31
31
  "QC25": {"function": neighbourhood_checks.check_monthly_factor},
32
32
  }
33
33
 
34
+ INTENSE_RULEBASE_QC = {
35
+ "QC2": {
36
+ "function": gauge_checks.check_years_where_annual_mean_k_top_rows_are_zero,
37
+ },
38
+ "QC10": {
39
+ "function": comparison_checks.check_exceedance_of_rainfall_world_record,
40
+ },
41
+ "QC11": {
42
+ "function": comparison_checks.check_hourly_exceedance_etccdi_rx1day,
43
+ },
44
+ "QC12": {
45
+ "function": timeseries_checks.check_dry_period_cdd,
46
+ },
47
+ "QC13": {
48
+ "function": timeseries_checks.check_daily_accumulations,
49
+ },
50
+ "QC14": {
51
+ "function": timeseries_checks.check_monthly_accumulations,
52
+ },
53
+ "QC15": {
54
+ "function": timeseries_checks.check_streaks,
55
+ },
56
+ "QC17": {
57
+ "function": neighbourhood_checks.check_wet_neighbours,
58
+ },
59
+ "QC19": {
60
+ "function": neighbourhood_checks.check_dry_neighbours,
61
+ },
62
+ "QC20": {
63
+ "function": neighbourhood_checks.check_monthly_neighbours,
64
+ },
65
+ }
66
+
34
67
  PYPWSQC = {
35
68
  "BC": {"function": pypwsqc_filters.run_bias_correction},
36
69
  "EBF": {"function": pypwsqc_filters.run_event_based_filter},
@@ -41,4 +74,4 @@ PYPWSQC = {
41
74
  "SO": {"function": pypwsqc_filters.check_station_outlier},
42
75
  }
43
76
 
44
- INBUILT_QC_FRAMEWORKS = {"intenseqc": INTENSE_QC, "pypwsqc": PYPWSQC}
77
+ INBUILT_QC_FRAMEWORKS = {"intenseqc": INTENSE_QC, "intenseqc_rulebase_only": INTENSE_RULEBASE_QC, "pypwsqc": PYPWSQC}
@@ -422,7 +422,12 @@ def extract_positive_values_from_data(data: pl.DataFrame, cols_to_extract_from:
422
422
  [
423
423
  "time",
424
424
  *[
425
- pl.when(pl.col(col) >= 0).then(pl.col(col)).otherwise(None).alias(col)
425
+ pl.when(pl.col(col).is_null() | pl.col(col).is_nan())
426
+ .then(np.nan)
427
+ .when(pl.col(col) >= 0)
428
+ .then(pl.col(col))
429
+ .otherwise(None)
430
+ .alias(col)
426
431
  for col in cols_to_extract_from
427
432
  if col != "time"
428
433
  ],
@@ -256,6 +256,10 @@ def compute_temporal_overlap_days_from_target_id(
256
256
  """
257
257
  # 1. Get target station and start and end date
258
258
  target_station = gauge_network_metadata.filter(pl.col(station_id_col) == target_id)
259
+ assert len(target_station) > 0, (
260
+ f"gauge_network_metadata does not contain value: '{target_id}' in column '{station_id_col}'"
261
+ )
262
+
259
263
  start_1, end_1 = (
260
264
  target_station[start_datetime_col].item(),
261
265
  target_station[end_datetime_col].item(),
@@ -328,6 +332,9 @@ def compute_km_distances_from_target_id(
328
332
  """
329
333
  # 1. Get target station lat and lon
330
334
  target_station = gauge_network_metadata.filter(pl.col(station_id_col) == target_id)
335
+ assert len(target_station) > 0, (
336
+ f"gauge_network_metadata does not contain value: '{target_id}' in column '{station_id_col}'"
337
+ )
331
338
  target_latlon = (
332
339
  target_station["latitude"].item(),
333
340
  target_station["longitude"].item(),
@@ -126,7 +126,9 @@ def filter_out_rain_world_records(data: pl.DataFrame, target_gauge_col: str, tim
126
126
  rainfall_world_records = get_rainfall_world_records()
127
127
  # 2. Filter out world records
128
128
  data_not_wr = data.with_columns(
129
- pl.when(pl.col(target_gauge_col) > rainfall_world_records[time_res])
129
+ pl.when(pl.col(target_gauge_col).is_null() | pl.col(target_gauge_col).is_nan())
130
+ .then(np.nan)
131
+ .when(pl.col(target_gauge_col) > rainfall_world_records[time_res])
130
132
  .then(np.nan)
131
133
  .otherwise(pl.col(target_gauge_col))
132
134
  .alias(target_gauge_col)
File without changes
File without changes