eo-tides 0.0.21__tar.gz → 0.0.22__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: eo-tides
3
- Version: 0.0.21
3
+ Version: 0.0.22
4
4
  Summary: Tide modelling tools for large-scale satellite earth observation analysis
5
5
  Author-email: Robbi Bishop-Taylor <Robbi.BishopTaylor@ga.gov.au>
6
6
  Project-URL: Homepage, https://GeoscienceAustralia.github.io/eo-tides/
@@ -22,23 +22,24 @@ Classifier: Programming Language :: Python :: 3.12
22
22
  Requires-Python: <4.0,>=3.9
23
23
  Description-Content-Type: text/markdown
24
24
  License-File: LICENSE
25
- Requires-Dist: colorama
26
- Requires-Dist: geopandas>=1.0.0
27
- Requires-Dist: numpy
28
- Requires-Dist: odc-geo
29
- Requires-Dist: pandas
30
- Requires-Dist: pyproj
25
+ Requires-Dist: colorama>=0.4.3
26
+ Requires-Dist: geopandas>=0.10.0
27
+ Requires-Dist: matplotlib>=3.8.0
28
+ Requires-Dist: numpy>=1.26.0
29
+ Requires-Dist: odc-geo>=0.4.7
30
+ Requires-Dist: pandas>=2.2.0
31
+ Requires-Dist: pyproj>=3.6.1
31
32
  Requires-Dist: pyTMD==2.1.6
32
- Requires-Dist: scikit-learn
33
- Requires-Dist: scipy
34
- Requires-Dist: shapely
35
- Requires-Dist: tqdm
36
- Requires-Dist: xarray
33
+ Requires-Dist: scikit-learn>=1.4.0
34
+ Requires-Dist: scipy>=1.11.2
35
+ Requires-Dist: shapely>=2.0.6
36
+ Requires-Dist: tqdm>=4.55.0
37
+ Requires-Dist: xarray>=2022.3.0
37
38
  Provides-Extra: notebooks
38
39
  Requires-Dist: odc-stac>=0.3.10; extra == "notebooks"
39
- Requires-Dist: pystac-client; extra == "notebooks"
40
- Requires-Dist: folium; extra == "notebooks"
41
- Requires-Dist: matplotlib; extra == "notebooks"
40
+ Requires-Dist: pystac-client>=0.8.3; extra == "notebooks"
41
+ Requires-Dist: folium>=0.16.0; extra == "notebooks"
42
+ Requires-Dist: planetary_computer>=1.0.0; extra == "notebooks"
42
43
 
43
44
  # `eo-tides`: Tide modelling tools for large-scale satellite earth observation analysis
44
45
 
@@ -243,7 +243,7 @@ def _model_tides(
243
243
  lon,
244
244
  lat,
245
245
  pytmd_model.model_file,
246
- grid=pytmd_model.type,
246
+ grid=pytmd_model.file_format,
247
247
  crop=crop,
248
248
  bounds=bounds,
249
249
  method=method,
@@ -277,6 +277,10 @@ def _model_tides(
277
277
 
278
278
  # Delta time (TT - UT1)
279
279
  deltat = timescale.tt_ut1
280
+ else:
281
+ raise Exception(
282
+ f"Unsupported model format ({pytmd_model.format}). This may be due to an incompatible version of `pyTMD`."
283
+ )
280
284
 
281
285
  # Calculate complex phase in radians for Euler's
282
286
  cph = -1j * ph * np.pi / 180.0
@@ -26,8 +26,10 @@ def tide_stats(
26
26
  tidepost_lon: float | None = None,
27
27
  plain_english: bool = True,
28
28
  plot: bool = True,
29
+ plot_col: str | None = None,
29
30
  modelled_freq: str = "2h",
30
31
  linear_reg: bool = False,
32
+ min_max_q: tuple = (0.0, 1.0),
31
33
  round_stats: int = 3,
32
34
  **model_tides_kwargs,
33
35
  ) -> pd.Series:
@@ -73,6 +75,10 @@ def tide_stats(
73
75
  An optional boolean indicating whether to plot how satellite-
74
76
  observed tide heights compare against the full tidal range.
75
77
  Defaults to True.
78
+ plot_col : str, optional
79
+ Optional name of a coordinate, dimension or variable in the array
80
+ that will be used to plot observations with unique symbols.
81
+ Defaults to None, which will plot all observations as circles.
76
82
  modelled_freq : str, optional
77
83
  An optional string giving the frequency at which to model tides
78
84
  when computing the full modelled tidal range. Defaults to '2h',
@@ -84,6 +90,11 @@ def tide_stats(
84
90
  increasing trends over time. This may indicate whether your
85
91
  satellite data may produce misleading trends based on uneven
86
92
  sampling of the local tide regime.
93
+ min_max_q : tuple, optional
94
+ Quantiles used to calculate max and min observed and modelled
95
+ astronomical tides. By default `(0.0, 1.0)` which is equivalent
96
+ to minimum and maximum; to use a softer threshold that is more
97
+ robust to outliers, use e.g. `(0.1, 0.9)`.
87
98
  round_stats : int, optional
88
99
  The number of decimal places used to round the output statistics.
89
100
  Defaults to 3.
@@ -135,6 +146,7 @@ def tide_stats(
135
146
  return_tideposts=True,
136
147
  **model_tides_kwargs,
137
148
  )
149
+ ds_tides = ds_tides.sortby("time")
138
150
 
139
151
  # Drop spatial ref for nicer plotting
140
152
  ds_tides = ds_tides.drop_vars("spatial_ref")
@@ -160,8 +172,8 @@ def tide_stats(
160
172
  # Get coarse statistics on all and observed tidal ranges
161
173
  obs_mean = ds_tides.tide_height.mean().item()
162
174
  all_mean = all_tides_df.tide_height.mean()
163
- obs_min, obs_max = ds_tides.tide_height.quantile([0.0, 1.0]).values
164
- all_min, all_max = all_tides_df.tide_height.quantile([0.0, 1.0]).values
175
+ obs_min, obs_max = ds_tides.tide_height.quantile(min_max_q).values
176
+ all_min, all_max = all_tides_df.tide_height.quantile(min_max_q).values
165
177
 
166
178
  # Calculate tidal range
167
179
  obs_range = obs_max - obs_min
@@ -169,47 +181,89 @@ def tide_stats(
169
181
 
170
182
  # Calculate Bishop-Taylor et al. 2018 tidal metrics
171
183
  spread = obs_range / all_range
172
- low_tide_offset = abs(all_min - obs_min) / all_range
173
- high_tide_offset = abs(all_max - obs_max) / all_range
184
+ low_tide_offset_m = abs(all_min - obs_min)
185
+ high_tide_offset_m = abs(all_max - obs_max)
186
+ low_tide_offset = low_tide_offset_m / all_range
187
+ high_tide_offset = high_tide_offset_m / all_range
188
+
189
+ # Plain text descriptors
190
+ mean_diff = "higher" if obs_mean > all_mean else "lower"
191
+ mean_diff_icon = "⬆️" if obs_mean > all_mean else "⬇️"
192
+ spread_icon = "🟢" if spread >= 0.9 else "🟡" if 0.7 < spread <= 0.9 else "🔴"
193
+ low_tide_icon = "🟢" if low_tide_offset <= 0.1 else "🟡" if 0.1 <= low_tide_offset < 0.2 else "🔴"
194
+ high_tide_icon = "🟢" if high_tide_offset <= 0.1 else "🟡" if 0.1 <= high_tide_offset < 0.2 else "🔴"
174
195
 
175
196
  # Extract x (time in decimal years) and y (distance) values
176
197
  all_times = all_tides_df.index.get_level_values("time")
177
- all_x = all_times.year + ((all_times.dayofyear - 1) / 365) + ((all_times.hour - 1) / 24)
198
+ all_x = all_times.year + ((all_times.dayofyear - 1) / 365) + ((all_times.hour) / 24)
178
199
  time_period = all_x.max() - all_x.min()
179
200
 
180
201
  # Extract x (time in decimal years) and y (distance) values
181
- obs_x = ds_tides.time.dt.year + ((ds_tides.time.dt.dayofyear - 1) / 365) + ((ds_tides.time.dt.hour - 1) / 24)
202
+ obs_x = ds_tides.time.dt.year + ((ds_tides.time.dt.dayofyear - 1) / 365) + ((ds_tides.time.dt.hour) / 24)
182
203
  obs_y = ds_tides.tide_height.values.astype(np.float32)
183
204
 
184
205
  # Compute linear regression
185
206
  obs_linreg = stats.linregress(x=obs_x, y=obs_y)
186
207
 
208
+ # return obs_linreg
209
+
187
210
  if plain_english:
211
+ print(f"\n\n🌊 Modelled astronomical tide range: {all_range:.2f} metres.")
212
+ print(f"🛰️ Observed tide range: {obs_range:.2f} metres.\n")
213
+ print(f" {spread_icon} {spread:.0%} of the modelled astronomical tide range was observed at this location.")
214
+ print(
215
+ f" {high_tide_icon} The highest {high_tide_offset:.0%} ({high_tide_offset_m:.2f} metres) of the tide range was never observed."
216
+ )
188
217
  print(
189
- f"\n{spread:.0%} of the {all_range:.2f} m modelled astronomical "
190
- f"tidal range is observed at this location.\nThe lowest "
191
- f"{low_tide_offset:.0%} and highest {high_tide_offset:.0%} "
192
- f"of astronomical tides are never observed.\n"
218
+ f" {low_tide_icon} The lowest {low_tide_offset:.0%} ({low_tide_offset_m:.2f} metres) of the tide range was never observed.\n"
219
+ )
220
+ print(f"🌊 Mean modelled astronomical tide height: {all_mean:.2f} metres.")
221
+ print(f"🛰️ Mean observed tide height: {obs_mean:.2f} metres.\n")
222
+ print(
223
+ f" {mean_diff_icon} The mean observed tide height was {obs_mean - all_mean:.2f} metres {mean_diff} than the mean modelled astronomical tide height."
193
224
  )
194
225
 
195
226
  if linear_reg:
196
- if obs_linreg.pvalue > 0.05:
197
- print(f"Observed tides show no significant trends " f"over the ~{time_period:.0f} year period.")
227
+ if obs_linreg.pvalue > 0.01:
228
+ print("Observed tides showed no significant trends over time.")
198
229
  else:
199
- obs_slope_desc = "decrease" if obs_linreg.slope < 0 else "increase"
230
+ obs_slope_desc = "decreasing" if obs_linreg.slope < 0 else "increasing"
200
231
  print(
201
- f"Observed tides {obs_slope_desc} significantly "
202
- f"(p={obs_linreg.pvalue:.3f}) over time by "
203
- f"{obs_linreg.slope:.03f} m per year (i.e. a "
204
- f"~{time_period * obs_linreg.slope:.2f} m "
205
- f"{obs_slope_desc} over the ~{time_period:.0f} year period)."
232
+ f" ⚠️ Observed tides showed a significant {obs_slope_desc} trend over time (p={obs_linreg.pvalue:.3f}, {obs_linreg.slope:.2f} metres per year)"
206
233
  )
207
234
 
208
235
  if plot:
209
236
  # Create plot and add all time and observed tide data
210
- fig, ax = plt.subplots(figsize=(10, 5))
211
- all_tides_df.reset_index(["x", "y"]).tide_height.plot(ax=ax, alpha=0.4)
212
- ds_tides.tide_height.plot.line(ax=ax, marker="o", linewidth=0.0, color="black", markersize=2)
237
+ fig, ax = plt.subplots(figsize=(10, 6))
238
+ all_tides_df.reset_index(["x", "y"]).tide_height.plot(ax=ax, alpha=0.4, label="Modelled tides")
239
+
240
+ # Look through custom column values if provided
241
+ if plot_col is not None:
242
+ # Create a list of marker styles
243
+ markers = ["o", "^", "s", "D", "v", "<", ">", "p", "*", "h", "H", "+", "x", "d", "|", "_"]
244
+ for i, value in enumerate(np.unique(ds_tides[plot_col])):
245
+ ds_tides.where(ds_tides[plot_col] == value, drop=True).tide_height.plot.line(
246
+ ax=ax,
247
+ linewidth=0.0,
248
+ color="black",
249
+ marker=markers[i % len(markers)],
250
+ markersize=4,
251
+ label=value,
252
+ )
253
+ # Otherwise, plot all data at once
254
+ else:
255
+ ds_tides.tide_height.plot.line(
256
+ ax=ax, marker="o", linewidth=0.0, color="black", markersize=3.5, label="Satellite observations"
257
+ )
258
+
259
+ ax.legend(loc="upper center", bbox_to_anchor=(0.5, 1.04), ncol=20, borderaxespad=0, frameon=False)
260
+
261
+ ax.plot(
262
+ ds_tides.time.isel(time=[0, -1]),
263
+ obs_linreg.intercept + obs_linreg.slope * obs_x[[0, -1]],
264
+ "r",
265
+ label="fitted line",
266
+ )
213
267
 
214
268
  # Add horizontal lines for spread/offsets
215
269
  ax.axhline(obs_min, color="black", linestyle=":", linewidth=1)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: eo-tides
3
- Version: 0.0.21
3
+ Version: 0.0.22
4
4
  Summary: Tide modelling tools for large-scale satellite earth observation analysis
5
5
  Author-email: Robbi Bishop-Taylor <Robbi.BishopTaylor@ga.gov.au>
6
6
  Project-URL: Homepage, https://GeoscienceAustralia.github.io/eo-tides/
@@ -22,23 +22,24 @@ Classifier: Programming Language :: Python :: 3.12
22
22
  Requires-Python: <4.0,>=3.9
23
23
  Description-Content-Type: text/markdown
24
24
  License-File: LICENSE
25
- Requires-Dist: colorama
26
- Requires-Dist: geopandas>=1.0.0
27
- Requires-Dist: numpy
28
- Requires-Dist: odc-geo
29
- Requires-Dist: pandas
30
- Requires-Dist: pyproj
25
+ Requires-Dist: colorama>=0.4.3
26
+ Requires-Dist: geopandas>=0.10.0
27
+ Requires-Dist: matplotlib>=3.8.0
28
+ Requires-Dist: numpy>=1.26.0
29
+ Requires-Dist: odc-geo>=0.4.7
30
+ Requires-Dist: pandas>=2.2.0
31
+ Requires-Dist: pyproj>=3.6.1
31
32
  Requires-Dist: pyTMD==2.1.6
32
- Requires-Dist: scikit-learn
33
- Requires-Dist: scipy
34
- Requires-Dist: shapely
35
- Requires-Dist: tqdm
36
- Requires-Dist: xarray
33
+ Requires-Dist: scikit-learn>=1.4.0
34
+ Requires-Dist: scipy>=1.11.2
35
+ Requires-Dist: shapely>=2.0.6
36
+ Requires-Dist: tqdm>=4.55.0
37
+ Requires-Dist: xarray>=2022.3.0
37
38
  Provides-Extra: notebooks
38
39
  Requires-Dist: odc-stac>=0.3.10; extra == "notebooks"
39
- Requires-Dist: pystac-client; extra == "notebooks"
40
- Requires-Dist: folium; extra == "notebooks"
41
- Requires-Dist: matplotlib; extra == "notebooks"
40
+ Requires-Dist: pystac-client>=0.8.3; extra == "notebooks"
41
+ Requires-Dist: folium>=0.16.0; extra == "notebooks"
42
+ Requires-Dist: planetary_computer>=1.0.0; extra == "notebooks"
42
43
 
43
44
  # `eo-tides`: Tide modelling tools for large-scale satellite earth observation analysis
44
45
 
@@ -0,0 +1,19 @@
1
+ colorama>=0.4.3
2
+ geopandas>=0.10.0
3
+ matplotlib>=3.8.0
4
+ numpy>=1.26.0
5
+ odc-geo>=0.4.7
6
+ pandas>=2.2.0
7
+ pyproj>=3.6.1
8
+ pyTMD==2.1.6
9
+ scikit-learn>=1.4.0
10
+ scipy>=1.11.2
11
+ shapely>=2.0.6
12
+ tqdm>=4.55.0
13
+ xarray>=2022.3.0
14
+
15
+ [notebooks]
16
+ odc-stac>=0.3.10
17
+ pystac-client>=0.8.3
18
+ folium>=0.16.0
19
+ planetary_computer>=1.0.0
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "eo-tides"
3
- version = "0.0.21"
3
+ version = "0.0.22"
4
4
  description = "Tide modelling tools for large-scale satellite earth observation analysis"
5
5
  authors = [{ name = "Robbi Bishop-Taylor", email = "Robbi.BishopTaylor@ga.gov.au" }]
6
6
  readme = "README.md"
@@ -30,19 +30,19 @@ classifiers = [
30
30
  ]
31
31
  requires-python = ">=3.9,<4.0"
32
32
  dependencies = [
33
- "colorama",
34
- "geopandas>=1.0.0",
35
- "numpy",
36
- "odc-geo",
37
- "pandas",
38
- "pyproj",
39
- "pyTMD==2.1.6",
40
- # "pyTMD@git+https://github.com/tsutterley/pyTMD",
41
- "scikit-learn",
42
- "scipy",
43
- "shapely",
44
- "tqdm",
45
- "xarray",
33
+ "colorama>=0.4.3",
34
+ "geopandas>=0.10.0",
35
+ "matplotlib>=3.8.0",
36
+ "numpy>=1.26.0",
37
+ "odc-geo>=0.4.7",
38
+ "pandas>=2.2.0",
39
+ "pyproj>=3.6.1",
40
+ "pyTMD==2.1.6",
41
+ "scikit-learn>=1.4.0",
42
+ "scipy>=1.11.2",
43
+ "shapely>=2.0.6",
44
+ "tqdm>=4.55.0",
45
+ "xarray>=2022.3.0",
46
46
  ]
47
47
 
48
48
  [project.urls]
@@ -53,28 +53,27 @@ Documentation = "https://GeoscienceAustralia.github.io/eo-tides/"
53
53
  [project.optional-dependencies]
54
54
  notebooks = [
55
55
  "odc-stac>=0.3.10",
56
- "pystac-client",
57
- "folium",
58
- "matplotlib",
56
+ "pystac-client>=0.8.3",
57
+ "folium>=0.16.0",
58
+ "planetary_computer>=1.0.0",
59
59
  ]
60
60
 
61
61
  [tool.uv]
62
62
  dev-dependencies = [
63
- "pytest>=7.2.0",
64
- "nbval>=0.11.0",
65
- "pre-commit>=2.20.0",
66
- "tox-uv>=1.11.3",
63
+ "pytest>=6.0.0",
64
+ "pre-commit>=0.2.0",
67
65
  "deptry>=0.20.0",
68
- "mypy>=0.991",
69
- "pytest-cov>=4.0.0",
70
- "ruff>=0.6.9",
71
- "mkdocs>=1.4.2",
72
- "mkdocs-material>=8.5.10",
73
- "mkdocs-jupyter>=0.25.0",
74
- "mkdocstrings[python]>=0.19.0",
66
+ "mypy>=0.900",
67
+ "pytest-cov>=0.6",
68
+ "ruff>=0.0.200",
69
+ "mkdocs>=1.2",
70
+ "mkdocs-material>=9.5.0",
71
+ "mkdocs-jupyter>=0.24.0",
72
+ "mkdocstrings[python]>=0.20.0",
73
+ "nbval>=0.10.0",
74
+ "odc-stac>=0.3.8",
75
75
  "pystac-client>=0.8.3",
76
- "odc-stac>=0.3.10",
77
- "black>=24.8.0",
76
+ "planetary_computer>=1.0.0",
78
77
  ]
79
78
 
80
79
  [build-system]
@@ -3,8 +3,9 @@ import pathlib
3
3
  import numpy as np
4
4
  import pandas as pd
5
5
  import pytest
6
+ from pyTMD.compute import tide_elevations
6
7
 
7
- from eo_tides.model import list_models, model_tides
8
+ from eo_tides.model import _set_directory, list_models, model_tides
8
9
  from eo_tides.validation import eval_metrics
9
10
 
10
11
  GAUGE_X = 122.2183
@@ -12,94 +13,92 @@ GAUGE_Y = -18.0008
12
13
  ENSEMBLE_MODELS = ["EOT20", "HAMTIDE11"] # simplified for tests
13
14
 
14
15
 
15
- @pytest.fixture()
16
- def measured_tides_ds():
17
- """
18
- Load measured sea level data from the Broome ABSLMP tidal station:
19
- http://www.bom.gov.au/oceanography/projects/abslmp/data/data.shtml
20
- """
21
- # Metadata for Broome ABSLMP tidal station:
22
- # http://www.bom.gov.au/oceanography/projects/abslmp/data/data.shtml
23
- ahd_offset = -5.322
24
-
25
- # Load measured tides from ABSLMP tide gauge data
26
- measured_tides_df = pd.read_csv(
27
- "tests/data/IDO71013_2020.csv",
28
- index_col=0,
29
- parse_dates=True,
30
- na_values=-9999,
31
- )[["Sea Level"]]
32
-
33
- # Update index and column names
34
- measured_tides_df.index.name = "time"
35
- measured_tides_df.columns = ["tide_height"]
36
-
37
- # Apply station AHD offset
38
- measured_tides_df += ahd_offset
39
-
40
- # Return as xarray dataset
41
- return measured_tides_df.to_xarray()
42
-
43
-
44
16
  # Test available tide models
45
17
  def test_list_models():
46
18
  # Using env var
47
19
  available_models, supported_models = list_models()
48
- assert available_models == ["EOT20", "HAMTIDE11"]
49
- assert len(supported_models) > 2
20
+ assert available_models == ["EOT20", "GOT5.5", "HAMTIDE11"]
21
+ assert len(supported_models) > 3
50
22
 
51
23
  # Not printing outputs
52
24
  available_models, supported_models = list_models(show_available=False, show_supported=False)
53
- assert available_models == ["EOT20", "HAMTIDE11"]
25
+ assert available_models == ["EOT20", "GOT5.5", "HAMTIDE11"]
54
26
 
55
27
  # Providing a string path
56
28
  available_models, supported_models = list_models(directory="./tests/data/tide_models")
57
- assert available_models == ["EOT20", "HAMTIDE11"]
29
+ assert available_models == ["EOT20", "GOT5.5", "HAMTIDE11"]
58
30
 
59
31
  # Providing a pathlib
60
32
  path = pathlib.Path("./tests/data/tide_models")
61
33
  available_models, supported_models = list_models(directory=path)
62
- assert available_models == ["EOT20", "HAMTIDE11"]
34
+ assert available_models == ["EOT20", "GOT5.5", "HAMTIDE11"]
63
35
 
64
36
 
65
37
  # Run test for multiple input coordinates, CRSs and interpolation methods
66
38
  @pytest.mark.parametrize(
67
- "x, y, crs, method",
39
+ "x, y, crs, method, model",
68
40
  [
69
- (GAUGE_X, GAUGE_Y, "EPSG:4326", "bilinear"), # WGS84, bilinear interp
70
- (GAUGE_X, GAUGE_Y, "EPSG:4326", "spline"), # WGS84, spline interp
41
+ (GAUGE_X, GAUGE_Y, "EPSG:4326", "bilinear", "EOT20"), # WGS84, bilinear interp
42
+ (GAUGE_X, GAUGE_Y, "EPSG:4326", "spline", "EOT20"), # WGS84, spline interp
71
43
  (
72
44
  -1034913,
73
45
  -1961916,
74
46
  "EPSG:3577",
75
47
  "bilinear",
48
+ "EOT20",
76
49
  ), # Australian Albers, bilinear interp
50
+ (GAUGE_X, GAUGE_Y, "EPSG:4326", "spline", "GOT5.5"),
51
+ (GAUGE_X, GAUGE_Y, "EPSG:4326", "spline", "HAMTIDE11"),
77
52
  ],
78
53
  )
79
- def test_model_tides(measured_tides_ds, x, y, crs, method):
80
- # Run EOT20 tidal model for locations and timesteps in tide gauge data
54
+ def test_model_tides(measured_tides_ds, x, y, crs, method, model):
55
+ # Run modelling for locations and timesteps in tide gauge data
81
56
  modelled_tides_df = model_tides(
82
57
  x=[x],
83
58
  y=[y],
84
59
  time=measured_tides_ds.time,
85
60
  crs=crs,
86
61
  method=method,
62
+ model=model,
87
63
  )
88
64
 
89
- # Compare measured and modelled tides
90
- val_stats = eval_metrics(x=measured_tides_ds.tide_height, y=modelled_tides_df.tide_height)
91
-
92
65
  # Test that modelled tides contain correct headings and have same
93
66
  # number of timesteps
94
67
  assert modelled_tides_df.index.names == ["time", "x", "y"]
95
68
  assert modelled_tides_df.columns.tolist() == ["tide_model", "tide_height"]
96
69
  assert len(modelled_tides_df.index) == len(measured_tides_ds.time)
97
70
 
71
+ # Run equivalent pyTMD code
72
+ pytmd_tides = tide_elevations(
73
+ x=x,
74
+ y=y,
75
+ delta_time=measured_tides_ds.time,
76
+ DIRECTORY=_set_directory(None),
77
+ MODEL=model,
78
+ EPSG=int(crs[-4:]),
79
+ TIME="datetime",
80
+ EXTRAPOLATE=True,
81
+ CUTOFF=np.inf,
82
+ METHOD=method,
83
+ )
84
+
85
+ # Verify that pyTMD produces same results as `model_tides`
86
+ assert np.allclose(modelled_tides_df.tide_height.values, pytmd_tides.data)
87
+
88
+ # Compare measured and modelled tides
89
+ val_stats = eval_metrics(x=measured_tides_ds.tide_height, y=modelled_tides_df.tide_height)
90
+
98
91
  # Test that modelled tides meet expected accuracy
99
- assert val_stats["Correlation"] > 0.99
100
- assert val_stats["RMSE"] < 0.27
101
- assert val_stats["R-squared"] > 0.96
102
- assert abs(val_stats["Bias"]) < 0.20
92
+ if model == "HAMTIDE11":
93
+ assert val_stats["Correlation"] > 0.99
94
+ assert val_stats["RMSE"] < 0.34
95
+ assert val_stats["R-squared"] > 0.98
96
+ assert abs(val_stats["Bias"]) < 0.20
97
+ else:
98
+ assert val_stats["Correlation"] > 0.99
99
+ assert val_stats["RMSE"] < 0.27
100
+ assert val_stats["R-squared"] > 0.99
101
+ assert abs(val_stats["Bias"]) < 0.20
103
102
 
104
103
 
105
104
  # Run tests for one or multiple models, and long and wide format outputs
@@ -108,8 +107,8 @@ def test_model_tides(measured_tides_ds, x, y, crs, method):
108
107
  [
109
108
  (["EOT20"], "long"),
110
109
  (["EOT20"], "wide"),
111
- (["EOT20", "HAMTIDE11"], "long"),
112
- (["EOT20", "HAMTIDE11"], "wide"),
110
+ (["EOT20", "GOT5.5", "HAMTIDE11"], "long"),
111
+ (["EOT20", "GOT5.5", "HAMTIDE11"], "wide"),
113
112
  ],
114
113
  ids=[
115
114
  "single_model_long",
@@ -1,18 +0,0 @@
1
- colorama
2
- geopandas>=1.0.0
3
- numpy
4
- odc-geo
5
- pandas
6
- pyproj
7
- pyTMD==2.1.6
8
- scikit-learn
9
- scipy
10
- shapely
11
- tqdm
12
- xarray
13
-
14
- [notebooks]
15
- odc-stac>=0.3.10
16
- pystac-client
17
- folium
18
- matplotlib
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes