rainfallqc 0.2.2__tar.gz → 0.2.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.2.2 → rainfallqc-0.2.4}/PKG-INFO +1 -1
  2. {rainfallqc-0.2.2 → rainfallqc-0.2.4}/pyproject.toml +1 -1
  3. {rainfallqc-0.2.2 → rainfallqc-0.2.4}/src/rainfallqc/__init__.py +1 -1
  4. {rainfallqc-0.2.2 → rainfallqc-0.2.4}/src/rainfallqc/checks/neighbourhood_checks.py +25 -12
  5. {rainfallqc-0.2.2 → rainfallqc-0.2.4}/src/rainfallqc/core/all_qc_checks.py +10 -5
  6. {rainfallqc-0.2.2 → rainfallqc-0.2.4}/src/rainfallqc/utils/spatial_utils.py +11 -8
  7. {rainfallqc-0.2.2 → rainfallqc-0.2.4}/LICENSE +0 -0
  8. {rainfallqc-0.2.2 → rainfallqc-0.2.4}/README.rst +0 -0
  9. {rainfallqc-0.2.2 → rainfallqc-0.2.4}/src/rainfallqc/checks/__init__.py +0 -0
  10. {rainfallqc-0.2.2 → rainfallqc-0.2.4}/src/rainfallqc/checks/comparison_checks.py +0 -0
  11. {rainfallqc-0.2.2 → rainfallqc-0.2.4}/src/rainfallqc/checks/gauge_checks.py +0 -0
  12. {rainfallqc-0.2.2 → rainfallqc-0.2.4}/src/rainfallqc/checks/pypwsqc_filters.py +0 -0
  13. {rainfallqc-0.2.2 → rainfallqc-0.2.4}/src/rainfallqc/checks/timeseries_checks.py +0 -0
  14. {rainfallqc-0.2.2 → rainfallqc-0.2.4}/src/rainfallqc/core/__init__.py +0 -0
  15. {rainfallqc-0.2.2 → rainfallqc-0.2.4}/src/rainfallqc/data/ETCCDI/RawData_HADEX2_CDD_1951-2010_ANN_from-90to90_from-180to180.nc +0 -0
  16. {rainfallqc-0.2.2 → rainfallqc-0.2.4}/src/rainfallqc/data/ETCCDI/RawData_HADEX2_CWD_1951-2010_ANN_from-90to90_from-180to180.nc +0 -0
  17. {rainfallqc-0.2.2 → rainfallqc-0.2.4}/src/rainfallqc/data/ETCCDI/RawData_HADEX2_PRCPTOT_1951-2010_ANN_from-90to90_from-180to180.nc +0 -0
  18. {rainfallqc-0.2.2 → rainfallqc-0.2.4}/src/rainfallqc/data/ETCCDI/RawData_HADEX2_R99p_1951-2010_ANN_from-90to90_from-180to180.nc +0 -0
  19. {rainfallqc-0.2.2 → rainfallqc-0.2.4}/src/rainfallqc/data/ETCCDI/RawData_HADEX2_Rx1day_1951-2010_ANN_from-90to90_from-180to180.nc +0 -0
  20. {rainfallqc-0.2.2 → rainfallqc-0.2.4}/src/rainfallqc/data/ETCCDI/RawData_HADEX2_SDII_1951-2010_ANN_from-90to90_from-180to180.nc +0 -0
  21. {rainfallqc-0.2.2 → rainfallqc-0.2.4}/src/rainfallqc/data/ETCCDI/__init__.py +0 -0
  22. {rainfallqc-0.2.2 → rainfallqc-0.2.4}/src/rainfallqc/data/__init__.py +0 -0
  23. {rainfallqc-0.2.2 → rainfallqc-0.2.4}/src/rainfallqc/qc_frameworks/__init__.py +0 -0
  24. {rainfallqc-0.2.2 → rainfallqc-0.2.4}/src/rainfallqc/qc_frameworks/apply_qc_framework.py +0 -0
  25. {rainfallqc-0.2.2 → rainfallqc-0.2.4}/src/rainfallqc/qc_frameworks/inbuilt_qc_frameworks.py +0 -0
  26. {rainfallqc-0.2.2 → rainfallqc-0.2.4}/src/rainfallqc/utils/__init__.py +0 -0
  27. {rainfallqc-0.2.2 → rainfallqc-0.2.4}/src/rainfallqc/utils/data_readers.py +0 -0
  28. {rainfallqc-0.2.2 → rainfallqc-0.2.4}/src/rainfallqc/utils/data_utils.py +0 -0
  29. {rainfallqc-0.2.2 → rainfallqc-0.2.4}/src/rainfallqc/utils/neighbourhood_utils.py +0 -0
  30. {rainfallqc-0.2.2 → rainfallqc-0.2.4}/src/rainfallqc/utils/stats.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: rainfallqc
3
- Version: 0.2.2
3
+ Version: 0.2.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>
@@ -68,7 +68,7 @@ homepage = "https://github.com/thomasjkeel/RainfallQC"
68
68
  target-version = ["py310", "py311", "py312", "py313"]
69
69
 
70
70
  [tool.bumpversion]
71
- current_version = "0.2.2"
71
+ current_version = "0.2.4"
72
72
  commit = true
73
73
  message = "Bump version: {current_version} → {new_version}"
74
74
  commit_args = ""
@@ -2,7 +2,7 @@
2
2
 
3
3
  __author__ = """Tom Keel"""
4
4
  __email__ = "tomkee@ceh.ac.uk"
5
- __version__ = "0.2.2"
5
+ __version__ = "0.2.4"
6
6
 
7
7
  from rainfallqc import core, utils
8
8
  from rainfallqc.checks import (
@@ -80,11 +80,17 @@ def check_wet_neighbours(
80
80
  )
81
81
 
82
82
  # 2. Loop through each neighbour and get wet_flags
83
- for neighbouring_gauge_col in neighbouring_gauge_cols_new:
83
+ neighbouring_gauge_cols_iterable = neighbouring_gauge_cols_new.copy() # make copy again to allow removal in loop
84
+ for neighbouring_gauge_col in neighbouring_gauge_cols_iterable:
84
85
  # 2.1 Flag data based on comparison of wet values in neighbours
85
- one_neighbour_data_wet_flags = flag_wet_day_errors_based_on_neighbours(
86
- neighbour_data, target_gauge_col, neighbouring_gauge_col, wet_threshold
87
- )
86
+ try:
87
+ one_neighbour_data_wet_flags = flag_wet_day_errors_based_on_neighbours(
88
+ neighbour_data, target_gauge_col, neighbouring_gauge_col, wet_threshold
89
+ )
90
+ except ValueError as ve:
91
+ neighbouring_gauge_cols_new.remove(neighbouring_gauge_col)
92
+ print(f"Warning: removing '{neighbouring_gauge_col}' from neighbouring_gauge_cols because: {ve}")
93
+ continue
88
94
 
89
95
  # 2.2 Join to all data
90
96
  neighbour_data = neighbour_data.join(
@@ -197,15 +203,21 @@ def check_dry_neighbours(
197
203
  neighbour_data, rain_cols=rain_cols, hour_offset=hour_offset
198
204
  )
199
205
 
200
- # 3. Loop through each neighbour and get wet_flags
201
- for neighbouring_gauge_col in neighbouring_gauge_cols_new:
206
+ # 3. Loop through each neighbour and get dry_flags
207
+ neighbouring_gauge_cols_iterable = neighbouring_gauge_cols_new.copy() # make copy again to allow removal in loop
208
+ for neighbouring_gauge_col in neighbouring_gauge_cols_iterable:
202
209
  # 3.1 Convert to dry spell fraction
203
- one_neighbour_data = get_dry_spell_fraction_col(
204
- neighbour_data,
205
- target_gauge_col=target_gauge_col,
206
- dry_period_days=dry_period_days,
207
- neighbouring_gauge_col=neighbouring_gauge_col,
208
- )
210
+ try:
211
+ one_neighbour_data = get_dry_spell_fraction_col(
212
+ neighbour_data,
213
+ target_gauge_col=target_gauge_col,
214
+ dry_period_days=dry_period_days,
215
+ neighbouring_gauge_col=neighbouring_gauge_col,
216
+ )
217
+ except ValueError as ve:
218
+ neighbouring_gauge_cols_new.remove(neighbouring_gauge_col)
219
+ print(f"Warning: {ve}. Removing {neighbouring_gauge_col} from neighbouring_gauge_cols.")
220
+ continue
209
221
 
210
222
  # 3.2 Flag dry spell fractions
211
223
  one_neighbour_data_dry_flags = flag_dry_spell_fractions(
@@ -1092,6 +1104,7 @@ def flag_wet_day_errors_based_on_neighbours(
1092
1104
  expon_percentiles = stats.fit_expon_and_get_percentile(
1093
1105
  neighbour_data_filtered_diff[f"diff_{neighbouring_gauge_col}"], percentiles=[0.95, 0.99, 0.999]
1094
1106
  )
1107
+
1095
1108
  # 5. Assign flags
1096
1109
  all_neighbour_data_wet_flags = add_wet_flags_to_data(
1097
1110
  neighbour_data_diff, target_gauge_col, neighbouring_gauge_col, expon_percentiles, wet_threshold
@@ -2,6 +2,7 @@
2
2
  """Registry of all the QC checks in RainfallQC."""
3
3
 
4
4
  import functools
5
+ import inspect
5
6
  import itertools
6
7
 
7
8
  import polars as pl
@@ -37,16 +38,20 @@ def qc_check(name: str, require_non_negative: bool = False) -> callable:
37
38
  def decorator(func: callable) -> callable:
38
39
  @functools.wraps(func)
39
40
  def wrapper(df: pl.DataFrame, *args, **kwargs) -> list:
40
- # Determine which column the user wants checked
41
+ # Bind args/kwargs to signature to include defaults
42
+ bound = inspect.signature(func).bind_partial(df, *args, **kwargs)
43
+ bound.apply_defaults()
44
+ full_kwargs = bound.arguments # dict including defaults
45
+
41
46
  columns_to_check = []
42
47
  columns_to_check = get_columns_in_kwargs(
43
- kwargs, kwarg_name="target_gauge_col", column_list=columns_to_check, name=name
48
+ full_kwargs, kwarg_name="target_gauge_col", column_list=columns_to_check, name=name
44
49
  )
45
50
 
46
51
  for kwarg_name in ["neighbouring_gauge_col", "neighbouring_gauge_cols"]:
47
- if kwarg_name in kwargs:
52
+ if kwarg_name in full_kwargs:
48
53
  columns_to_check = get_columns_in_kwargs(
49
- kwargs, kwarg_name=kwarg_name, column_list=columns_to_check, name=name
54
+ full_kwargs, kwarg_name=kwarg_name, column_list=columns_to_check, name=name
50
55
  )
51
56
 
52
57
  # flatten column list for neighbouring_gauge_cols
@@ -93,6 +98,6 @@ def get_columns_in_kwargs(kwargs: dict, kwarg_name: str, column_list: list, name
93
98
  col_name = kwargs.get(kwarg_name) # user defined column name for that kwarg
94
99
 
95
100
  if col_name is None:
96
- raise ValueError(f"{name} requires '{kwarg_name}' to be provided.")
101
+ raise ValueError(f"The QC check '{name}' requires the '{kwarg_name}' to be set.")
97
102
  column_list.append(col_name)
98
103
  return column_list
@@ -42,19 +42,19 @@ def compute_spatial_mean_xr(data: xr.Dataset, var_name: str) -> xr.Dataset:
42
42
  return data
43
43
 
44
44
 
45
- def haversine(lon1: float, lat1: float, lon2: float, lat2: float) -> float:
45
+ def haversine(lon1: xr.DataArray, lat1: xr.DataArray, lon2: np.ndarray | float, lat2: np.ndarray | float) -> float:
46
46
  """
47
47
  Great circle distance (km) between two points on Earth.
48
48
 
49
49
  Parameters
50
50
  ----------
51
- lon1 : float
51
+ lon1 : xr.DataArray
52
52
  Longitude of point 1
53
- lat1 : float
53
+ lat1 : xr.DataArray
54
54
  Latitude of point 1
55
- lon2 : float
55
+ lon2 : np.ndarray | float
56
56
  Longitude of point 2
57
- lat2 : float
57
+ lat2 : np.ndarray | float
58
58
  Latitude of point 2
59
59
 
60
60
  Returns
@@ -63,10 +63,13 @@ def haversine(lon1: float, lat1: float, lon2: float, lat2: float) -> float:
63
63
  Distance between the two points in km
64
64
 
65
65
  """
66
- R = EARTH_RADIUS_KM
67
- lon1, lat1, lon2, lat2 = map(np.radians, [lon1, lat1, float(lon2), float(lat2)])
66
+ # convert lat2 and lon2 to numpy arrays for safety
67
+ lon2 = np.asarray(lon2, dtype=np.float64)
68
+ lat2 = np.asarray(lat2, dtype=np.float64)
69
+
70
+ lon1, lat1, lon2, lat2 = map(np.radians, [lon1, lat1, lon2, lat2])
68
71
  dlon = lon2 - lon1
69
72
  dlat = lat2 - lat1
70
73
  a = np.sin(dlat / 2) ** 2 + np.cos(lat1) * np.cos(lat2) * np.sin(dlon / 2) ** 2
71
74
  c = 2 * np.arcsin(np.sqrt(a))
72
- return R * c
75
+ return EARTH_RADIUS_KM * c
File without changes
File without changes