eo-tides 0.3.0__py3-none-any.whl → 0.4.0__py3-none-any.whl
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.
- eo_tides/__init__.py +2 -1
- eo_tides/eo.py +23 -12
- eo_tides/model.py +259 -274
- eo_tides/stats.py +261 -272
- eo_tides/utils.py +112 -3
- eo_tides/validation.py +23 -21
- {eo_tides-0.3.0.dist-info → eo_tides-0.4.0.dist-info}/METADATA +23 -22
- eo_tides-0.4.0.dist-info/RECORD +11 -0
- {eo_tides-0.3.0.dist-info → eo_tides-0.4.0.dist-info}/WHEEL +1 -1
- eo_tides-0.3.0.dist-info/RECORD +0 -11
- {eo_tides-0.3.0.dist-info → eo_tides-0.4.0.dist-info}/LICENSE +0 -0
- {eo_tides-0.3.0.dist-info → eo_tides-0.4.0.dist-info}/top_level.txt +0 -0
eo_tides/utils.py
CHANGED
@@ -6,6 +6,7 @@ import os
|
|
6
6
|
import pathlib
|
7
7
|
import textwrap
|
8
8
|
import warnings
|
9
|
+
from collections import Counter
|
9
10
|
from typing import List, Union
|
10
11
|
|
11
12
|
import numpy as np
|
@@ -23,6 +24,14 @@ from tqdm import tqdm
|
|
23
24
|
DatetimeLike = Union[np.ndarray, pd.DatetimeIndex, pd.Timestamp, datetime.datetime, str, List[str]]
|
24
25
|
|
25
26
|
|
27
|
+
def _get_duplicates(array):
|
28
|
+
"""
|
29
|
+
Return any duplicates in a list or array.
|
30
|
+
"""
|
31
|
+
c = Counter(array)
|
32
|
+
return [k for k in c if c[k] > 1]
|
33
|
+
|
34
|
+
|
26
35
|
def _set_directory(
|
27
36
|
directory: str | os.PathLike | None = None,
|
28
37
|
) -> os.PathLike:
|
@@ -68,6 +77,99 @@ def _standardise_time(
|
|
68
77
|
return np.atleast_1d(time)
|
69
78
|
|
70
79
|
|
80
|
+
def _standardise_models(
|
81
|
+
model: str | list[str],
|
82
|
+
directory: str | os.PathLike,
|
83
|
+
ensemble_models: list[str] | None = None,
|
84
|
+
) -> tuple[list[str], list[str], list[str] | None]:
|
85
|
+
"""
|
86
|
+
Take an input model name or list of names, and return a list
|
87
|
+
of models to process, requested models, and ensemble models,
|
88
|
+
as required by the `model_tides` function.
|
89
|
+
|
90
|
+
Handles two special values passed to `model`: "all", which
|
91
|
+
will model tides for all models available in `directory`, and
|
92
|
+
"ensemble", which will model tides for all models in a list
|
93
|
+
of custom ensemble models.
|
94
|
+
"""
|
95
|
+
|
96
|
+
# Turn inputs into arrays for consistent handling
|
97
|
+
models_requested = list(np.atleast_1d(model))
|
98
|
+
|
99
|
+
# Raise error if list contains duplications
|
100
|
+
duplicates = _get_duplicates(models_requested)
|
101
|
+
if len(duplicates) > 0:
|
102
|
+
raise ValueError(f"The model parameter contains duplicate values: {duplicates}")
|
103
|
+
|
104
|
+
# Get full list of supported models from pyTMD database
|
105
|
+
available_models, valid_models = list_models(
|
106
|
+
directory, show_available=False, show_supported=False, raise_error=True
|
107
|
+
)
|
108
|
+
custom_options = ["ensemble", "all"]
|
109
|
+
|
110
|
+
# Error if any models are not supported
|
111
|
+
if not all(m in valid_models + custom_options for m in models_requested):
|
112
|
+
error_text = (
|
113
|
+
f"One or more of the requested models are not valid:\n"
|
114
|
+
f"{models_requested}\n\n"
|
115
|
+
"The following models are supported:\n"
|
116
|
+
f"{valid_models}"
|
117
|
+
)
|
118
|
+
raise ValueError(error_text)
|
119
|
+
|
120
|
+
# Error if any models are not available in `directory`
|
121
|
+
if not all(m in available_models + custom_options for m in models_requested):
|
122
|
+
error_text = (
|
123
|
+
f"One or more of the requested models are valid, but not available in `{directory}`:\n"
|
124
|
+
f"{models_requested}\n\n"
|
125
|
+
f"The following models are available in `{directory}`:\n"
|
126
|
+
f"{available_models}"
|
127
|
+
)
|
128
|
+
raise ValueError(error_text)
|
129
|
+
|
130
|
+
# If "all" models are requested, update requested list to include available models
|
131
|
+
if "all" in models_requested:
|
132
|
+
models_requested = available_models + [m for m in models_requested if m != "all"]
|
133
|
+
|
134
|
+
# If "ensemble" modeling is requested, use custom list of ensemble models
|
135
|
+
if "ensemble" in models_requested:
|
136
|
+
print("Running ensemble tide modelling")
|
137
|
+
ensemble_models = (
|
138
|
+
ensemble_models
|
139
|
+
if ensemble_models is not None
|
140
|
+
else [
|
141
|
+
"EOT20",
|
142
|
+
"FES2012",
|
143
|
+
"FES2014_extrapolated",
|
144
|
+
"FES2022_extrapolated",
|
145
|
+
"GOT4.10",
|
146
|
+
"GOT5.6_extrapolated",
|
147
|
+
"TPXO10-atlas-v2-nc",
|
148
|
+
"TPXO8-atlas-nc",
|
149
|
+
"TPXO9-atlas-v5-nc",
|
150
|
+
]
|
151
|
+
)
|
152
|
+
|
153
|
+
# Error if any ensemble models are not available in `directory`
|
154
|
+
if not all(m in available_models for m in ensemble_models):
|
155
|
+
error_text = (
|
156
|
+
f"One or more of the requested ensemble models are not available in `{directory}`:\n"
|
157
|
+
f"{ensemble_models}\n\n"
|
158
|
+
f"The following models are available in `{directory}`:\n"
|
159
|
+
f"{available_models}"
|
160
|
+
)
|
161
|
+
raise ValueError(error_text)
|
162
|
+
|
163
|
+
# Return set of all ensemble plus any other requested models
|
164
|
+
models_to_process = sorted(list(set(ensemble_models + [m for m in models_requested if m != "ensemble"])))
|
165
|
+
|
166
|
+
# Otherwise, models to process are the same as those requested
|
167
|
+
else:
|
168
|
+
models_to_process = models_requested
|
169
|
+
|
170
|
+
return models_to_process, models_requested, ensemble_models
|
171
|
+
|
172
|
+
|
71
173
|
def _clip_model_file(
|
72
174
|
nc: xr.Dataset,
|
73
175
|
bbox: BoundingBox,
|
@@ -178,7 +280,7 @@ def clip_models(
|
|
178
280
|
output_directory: str | os.PathLike,
|
179
281
|
bbox: tuple[float, float, float, float],
|
180
282
|
model: list | None = None,
|
181
|
-
buffer: float =
|
283
|
+
buffer: float = 5,
|
182
284
|
overwrite: bool = False,
|
183
285
|
):
|
184
286
|
"""
|
@@ -211,7 +313,7 @@ def clip_models(
|
|
211
313
|
in the input directly.
|
212
314
|
buffer : float, optional
|
213
315
|
Buffer distance (in degrees) added to the bounding box to provide
|
214
|
-
sufficient data on edges of study area. Defaults to
|
316
|
+
sufficient data on edges of study area. Defaults to 5 degrees.
|
215
317
|
overwrite : bool, optional
|
216
318
|
If True, overwrite existing files in the output directory.
|
217
319
|
Defaults to False.
|
@@ -393,7 +495,14 @@ def list_models(
|
|
393
495
|
expected_paths = {}
|
394
496
|
for m in supported_models:
|
395
497
|
model_file = model_database[m]["model_file"]
|
396
|
-
|
498
|
+
|
499
|
+
# Handle GOT5.6 differently to ensure we test for presence of GOT5.6 constituents
|
500
|
+
if m in ("GOT5.6", "GOT5.6_extrapolated"):
|
501
|
+
model_file = [file for file in model_file if "GOT5.6" in file][0]
|
502
|
+
else:
|
503
|
+
model_file = model_file[0] if isinstance(model_file, list) else model_file
|
504
|
+
|
505
|
+
# Add path to dict
|
397
506
|
expected_paths[m] = str(directory / pathlib.Path(model_file).expanduser().parent)
|
398
507
|
|
399
508
|
# Define column widths
|
eo_tides/validation.py
CHANGED
@@ -5,6 +5,7 @@ from numbers import Number
|
|
5
5
|
|
6
6
|
import geopandas as gpd
|
7
7
|
import pandas as pd
|
8
|
+
import tqdm
|
8
9
|
from odc.geo.geom import BoundingBox
|
9
10
|
from pandas.tseries.offsets import MonthBegin, MonthEnd, YearBegin, YearEnd
|
10
11
|
from scipy import stats
|
@@ -152,21 +153,24 @@ def _load_gauge_metadata(metadata_path):
|
|
152
153
|
|
153
154
|
|
154
155
|
def _load_gesla_dataset(site, path, na_value):
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
.
|
168
|
-
|
156
|
+
# Read dataset
|
157
|
+
gesla_df = pd.read_csv(
|
158
|
+
path,
|
159
|
+
skiprows=41,
|
160
|
+
names=["date", "time", "sea_level", "qc_flag", "use_flag"],
|
161
|
+
sep=r"\s+",
|
162
|
+
na_values=na_value,
|
163
|
+
)
|
164
|
+
|
165
|
+
# Combine two date fields
|
166
|
+
gesla_df = (
|
167
|
+
gesla_df.assign(
|
168
|
+
time=pd.to_datetime(gesla_df["date"] + " " + gesla_df["time"]),
|
169
|
+
site_code=site,
|
169
170
|
)
|
171
|
+
.drop(columns=["date"])
|
172
|
+
.set_index("time")
|
173
|
+
)
|
170
174
|
|
171
175
|
return gesla_df
|
172
176
|
|
@@ -301,13 +305,11 @@ def load_gauge_gesla(
|
|
301
305
|
paths_na = metadata_df.loc[site_code, ["file_name", "null_value"]]
|
302
306
|
|
303
307
|
# Load and combine into a single dataframe
|
304
|
-
|
305
|
-
|
306
|
-
.
|
307
|
-
|
308
|
-
|
309
|
-
.set_index("site_code")
|
310
|
-
)
|
308
|
+
gauge_list = [
|
309
|
+
_load_gesla_dataset(s, p, na_value=na)
|
310
|
+
for s, p, na in tqdm.tqdm(paths_na.itertuples(), total=len(paths_na), desc="Loading GESLA gauges")
|
311
|
+
]
|
312
|
+
data_df = pd.concat(gauge_list).sort_index().loc[slice(start_time, end_time)].reset_index().set_index("site_code")
|
311
313
|
|
312
314
|
# Optionally filter by use flag column
|
313
315
|
if filter_use_flag:
|
@@ -1,9 +1,9 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: eo-tides
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.4.0
|
4
4
|
Summary: Tide modelling tools for large-scale satellite earth observation analysis
|
5
|
-
Author: Stephen Sagar, Claire Phillips, Vanessa Newey
|
6
|
-
Author-email: Robbi
|
5
|
+
Author: Robbi Bishop-Taylor, Stephen Sagar, Claire Phillips, Vanessa Newey
|
6
|
+
Author-email: Robbi.BishopTaylor@ga.gov.au
|
7
7
|
Project-URL: Homepage, https://GeoscienceAustralia.github.io/eo-tides/
|
8
8
|
Project-URL: Repository, https://github.com/GeoscienceAustralia/eo-tides
|
9
9
|
Project-URL: Documentation, https://GeoscienceAustralia.github.io/eo-tides/
|
@@ -24,26 +24,27 @@ Classifier: Programming Language :: Python :: 3.13
|
|
24
24
|
Requires-Python: <4.0,>=3.9
|
25
25
|
Description-Content-Type: text/markdown
|
26
26
|
License-File: LICENSE
|
27
|
-
Requires-Dist: colorama
|
28
|
-
Requires-Dist: geopandas
|
29
|
-
Requires-Dist: matplotlib
|
30
|
-
Requires-Dist: numpy
|
31
|
-
Requires-Dist: odc-geo
|
32
|
-
Requires-Dist: pandas
|
33
|
-
Requires-Dist: psutil
|
34
|
-
Requires-Dist:
|
35
|
-
Requires-Dist:
|
36
|
-
Requires-Dist:
|
37
|
-
Requires-Dist:
|
38
|
-
Requires-Dist:
|
39
|
-
Requires-Dist:
|
40
|
-
Requires-Dist:
|
27
|
+
Requires-Dist: colorama>=0.4.3
|
28
|
+
Requires-Dist: geopandas>=0.10.0
|
29
|
+
Requires-Dist: matplotlib>=3.8.0
|
30
|
+
Requires-Dist: numpy>=1.26.0
|
31
|
+
Requires-Dist: odc-geo>=0.4.7
|
32
|
+
Requires-Dist: pandas>=2.2.0
|
33
|
+
Requires-Dist: psutil>=5.8.0
|
34
|
+
Requires-Dist: pyogrio>=0.7.0
|
35
|
+
Requires-Dist: pyproj>=3.6.1
|
36
|
+
Requires-Dist: pyTMD==2.2.0
|
37
|
+
Requires-Dist: scikit-learn>=1.4.0
|
38
|
+
Requires-Dist: scipy>=1.11.2
|
39
|
+
Requires-Dist: shapely>=2.0.6
|
40
|
+
Requires-Dist: tqdm>=4.55.0
|
41
|
+
Requires-Dist: xarray>=2022.3.0
|
41
42
|
Provides-Extra: notebooks
|
42
|
-
Requires-Dist: odc-stac
|
43
|
-
Requires-Dist: odc-geo[tiff,warp]
|
44
|
-
Requires-Dist: pystac-client
|
45
|
-
Requires-Dist: folium
|
46
|
-
Requires-Dist:
|
43
|
+
Requires-Dist: odc-stac>=0.3.10; extra == "notebooks"
|
44
|
+
Requires-Dist: odc-geo[tiff,warp]>=0.4.7; extra == "notebooks"
|
45
|
+
Requires-Dist: pystac-client>=0.8.3; extra == "notebooks"
|
46
|
+
Requires-Dist: folium>=0.16.0; extra == "notebooks"
|
47
|
+
Requires-Dist: planetary_computer>=1.0.0; extra == "notebooks"
|
47
48
|
|
48
49
|
# `eo-tides`: Tide modelling tools for large-scale satellite earth observation analysis
|
49
50
|
|
@@ -0,0 +1,11 @@
|
|
1
|
+
eo_tides/__init__.py,sha256=pGvVlxMKiYjm_273G-oYcOgVuPra7uEdNZv0oN1i69c,1693
|
2
|
+
eo_tides/eo.py,sha256=d4zFs_uhuTekJDDqiX7oIzvS1iP6nEr0rG2Yy4xbsEU,22746
|
3
|
+
eo_tides/model.py,sha256=X_nuYkBbzq3cLgJc0dUknlL6w_90O9rz_2BOqX5uxsg,34585
|
4
|
+
eo_tides/stats.py,sha256=-nL6Ay6TvA5GSdnglHoLMu5JZf6-YjQKERBGLjAZs34,22993
|
5
|
+
eo_tides/utils.py,sha256=9xJ1q-b-TVHg5zFyLy6AT_srrPQDvmFdWJmlGSPaJF0,26563
|
6
|
+
eo_tides/validation.py,sha256=KP8WLT5z7KLFjQ9oDla7VJOyLQAK4SVbcz2ySAbsbwI,11882
|
7
|
+
eo_tides-0.4.0.dist-info/LICENSE,sha256=owxWsXViCL2J6Ks3XYhot7t4Y93nstmXAT95Zf030Cc,11350
|
8
|
+
eo_tides-0.4.0.dist-info/METADATA,sha256=cqO3zJGPj-l5Xzi-cfPtkd7pzUUTt5ENVvCRM16HXFQ,8045
|
9
|
+
eo_tides-0.4.0.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
|
10
|
+
eo_tides-0.4.0.dist-info/top_level.txt,sha256=lXZDUUM1DlLdKWHRn8zdmtW8Rx-eQOIWVvt0b8VGiyQ,9
|
11
|
+
eo_tides-0.4.0.dist-info/RECORD,,
|
eo_tides-0.3.0.dist-info/RECORD
DELETED
@@ -1,11 +0,0 @@
|
|
1
|
-
eo_tides/__init__.py,sha256=rn6slQP0bAhqM9cL2W8omiEM8f0b7libt6WsQ5DvYTE,1655
|
2
|
-
eo_tides/eo.py,sha256=Vc_AHqT0_IDqdwbOpNcONjHhiCtbCe8Osk2gvzUeNmU,22377
|
3
|
-
eo_tides/model.py,sha256=T0IFvSiXjiTvlY-Vi7-jneHPfaCLt95pmcRd8CZxOjE,34478
|
4
|
-
eo_tides/stats.py,sha256=lchWWJ5gBDuZWvaD8TF-12Xlo2qCWiNI2IcgAaKWy2U,22668
|
5
|
-
eo_tides/utils.py,sha256=tqXAkLk_Dm8s3yuXPxBBkHW3PZ42ayV8VCQjNw3wDZw,22433
|
6
|
-
eo_tides/validation.py,sha256=UREsc0yWRO4x0PJXvyoIx8gYiBZiRSim4z6TmAz_VDM,11857
|
7
|
-
eo_tides-0.3.0.dist-info/LICENSE,sha256=owxWsXViCL2J6Ks3XYhot7t4Y93nstmXAT95Zf030Cc,11350
|
8
|
-
eo_tides-0.3.0.dist-info/METADATA,sha256=lajVK9XoAA2fJqA9R3HHYJ7iUJFMtmxh3U07uGTs4_4,8040
|
9
|
-
eo_tides-0.3.0.dist-info/WHEEL,sha256=P9jw-gEje8ByB7_hXoICnHtVCrEwMQh-630tKvQWehc,91
|
10
|
-
eo_tides-0.3.0.dist-info/top_level.txt,sha256=lXZDUUM1DlLdKWHRn8zdmtW8Rx-eQOIWVvt0b8VGiyQ,9
|
11
|
-
eo_tides-0.3.0.dist-info/RECORD,,
|
File without changes
|
File without changes
|