eo-tides 0.5.0__py3-none-any.whl → 0.6.1__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/eo.py CHANGED
@@ -15,7 +15,7 @@ from odc.geo.geobox import GeoBox
15
15
  if TYPE_CHECKING:
16
16
  from odc.geo import Shape2d
17
17
 
18
- from .model import model_tides
18
+ from .model import model_phases, model_tides
19
19
  from .utils import DatetimeLike, _standardise_time
20
20
 
21
21
 
@@ -168,26 +168,28 @@ def tag_tides(
168
168
  directory: str | os.PathLike | None = None,
169
169
  tidepost_lat: float | None = None,
170
170
  tidepost_lon: float | None = None,
171
+ return_phases: bool = False,
171
172
  **model_tides_kwargs,
172
- ) -> xr.DataArray:
173
+ ) -> xr.DataArray | xr.Dataset:
173
174
  """
174
- Model tide heights for every timestep in a multi-dimensional
175
- dataset, and return a new `tide_height` array that can
176
- be used to "tag" each observation with tide heights.
175
+ Model tide heights and tide phases for every timestep in a
176
+ multi-dimensional dataset, and return a new array that can
177
+ be used to "tag" each observation with tide information.
177
178
 
178
179
  The function models tides at the centroid of the dataset
179
- by default, but a custom tidal modelling location can
180
- be specified using `tidepost_lat` and `tidepost_lon`.
180
+ by default, but a custom tidal modelling location can be
181
+ specified using `tidepost_lat` and `tidepost_lon`.
181
182
 
182
- This function uses the parallelised `model_tides` function
183
- under the hood. It supports all tidal models supported by
184
- `pyTMD`, including:
183
+ This function uses the parallelised `model_tides` and
184
+ `model_phases` functions under the hood. It supports all tidal
185
+ models supported by `pyTMD`, including:
185
186
 
186
187
  - Empirical Ocean Tide model (EOT20)
187
188
  - Finite Element Solution tide models (FES2022, FES2014, FES2012)
188
189
  - TOPEX/POSEIDON global tide models (TPXO10, TPXO9, TPXO8)
189
190
  - Global Ocean Tide models (GOT5.6, GOT5.5, GOT4.10, GOT4.8, GOT4.7)
190
191
  - Hamburg direct data Assimilation Methods for Tides models (HAMTIDE11)
192
+ - Technical University of Denmark tide models (DTU23)
191
193
 
192
194
  Parameters
193
195
  ----------
@@ -209,7 +211,7 @@ def tag_tides(
209
211
  added to the `xarray.DataArray` outputs. Defaults to "EOT20";
210
212
  specify "all" to use all models available in `directory`.
211
213
  For a full list of available and supported models, run
212
- `eo_tides.utils.list_models`.
214
+ `from eo_tides.utils import list_models; list_models()`.
213
215
  directory : str, optional
214
216
  The directory containing tide model data files. If no path is
215
217
  provided, this will default to the environment variable
@@ -221,6 +223,10 @@ def tag_tides(
221
223
  Optional coordinates used to model tides. The default is None,
222
224
  which uses the centroid of the dataset as the tide modelling
223
225
  location.
226
+ return_phases : bool, optional
227
+ Whether to model and return tide phases in addition to tide heights.
228
+ If True, outputs will be returned as an xr.Dataset containing both
229
+ "tide_height" and "tide_phase" variables.
224
230
  **model_tides_kwargs :
225
231
  Optional parameters passed to the `eo_tides.model.model_tides`
226
232
  function. Important parameters include `cutoff` (used to
@@ -230,10 +236,12 @@ def tag_tides(
230
236
 
231
237
  Returns
232
238
  -------
233
- tides_da : xr.DataArray
234
- A one-dimensional tide height array. This will contain either
235
- tide heights for every timestep in `data`, or for every time in
236
- `times` if provided.
239
+ tides_da : xr.DataArray or xr.Dataset
240
+ If `return_phases=False`: a one-dimensional "tide_height" xr.DataArray.
241
+ If `return_phases=True`: a one-dimensional xr.Dataset containing
242
+ "tide_height" and "tide_phase" variables.
243
+ Outputs will contain values for every timestep in `data`, or for
244
+ every time in `times` if provided.
237
245
  """
238
246
  # Standardise data inputs, time and models
239
247
  gbox, time_coords = _standardise_inputs(data, time)
@@ -247,16 +255,31 @@ def tag_tides(
247
255
  lon, lat = tidepost_lon, tidepost_lat
248
256
  print(f"Using tide modelling location: {lon:.2f}, {lat:.2f}")
249
257
 
250
- # Model tide heights for each observation:
251
- tide_df = model_tides(
252
- x=lon, # type: ignore
253
- y=lat, # type: ignore
254
- time=time_coords,
255
- model=model,
256
- directory=directory,
257
- crs="EPSG:4326",
258
- **model_tides_kwargs,
259
- )
258
+ # Either model both tides and phases, or model only tides
259
+ if return_phases:
260
+ # Model tide phases and heights for each observation
261
+ tide_df = model_phases(
262
+ x=lon, # type: ignore
263
+ y=lat, # type: ignore
264
+ time=time_coords,
265
+ model=model,
266
+ directory=directory,
267
+ crs="EPSG:4326",
268
+ return_tides=True,
269
+ **model_tides_kwargs,
270
+ )
271
+
272
+ else:
273
+ # Model tide heights for each observation
274
+ tide_df = model_tides(
275
+ x=lon, # type: ignore
276
+ y=lat, # type: ignore
277
+ time=time_coords,
278
+ model=model,
279
+ directory=directory,
280
+ crs="EPSG:4326",
281
+ **model_tides_kwargs,
282
+ )
260
283
 
261
284
  # If tides cannot be successfully modeled (e.g. if the centre of the
262
285
  # xarray dataset is located is over land), raise an exception
@@ -269,8 +292,9 @@ def tag_tides(
269
292
  f"`tidepost_lat` and `tidepost_lon` parameters."
270
293
  )
271
294
 
272
- # Convert to xarray format
273
- tides_da = tide_df.reset_index().set_index(["time", "tide_model"]).drop(["x", "y"], axis=1).tide_height.to_xarray()
295
+ # Convert to xarray format, squeezing to return an xr.DataArray if
296
+ # dataframe contains only one "tide_height" column
297
+ tides_da = tide_df.reset_index().set_index(["time", "tide_model"]).drop(["x", "y"], axis=1).squeeze().to_xarray()
274
298
 
275
299
  # If only one tidal model exists, squeeze out "tide_model" dim
276
300
  if len(tides_da.tide_model) == 1:
@@ -313,6 +337,7 @@ def pixel_tides(
313
337
  - TOPEX/POSEIDON global tide models (TPXO10, TPXO9, TPXO8)
314
338
  - Global Ocean Tide models (GOT5.6, GOT5.5, GOT4.10, GOT4.8, GOT4.7)
315
339
  - Hamburg direct data Assimilation Methods for Tides models (HAMTIDE11)
340
+ - Technical University of Denmark tide models (DTU23)
316
341
 
317
342
  This function requires access to tide model data files.
318
343
  These should be placed in a folder with subfolders matching
@@ -340,7 +365,7 @@ def pixel_tides(
340
365
  added to the `xarray.DataArray` outputs. Defaults to "EOT20";
341
366
  specify "all" to use all models available in `directory`.
342
367
  For a full list of available and supported models, run
343
- `eo_tides.utils.list_models`.
368
+ `from eo_tides.utils import list_models; list_models()`.
344
369
  directory : str, optional
345
370
  The directory containing tide model data files. If no path is
346
371
  provided, this will default to the environment variable
eo_tides/model.py CHANGED
@@ -19,6 +19,7 @@ import numpy as np
19
19
  import pandas as pd
20
20
  import pyproj
21
21
  import pyTMD
22
+ import timescale.time
22
23
  from tqdm import tqdm
23
24
 
24
25
  from .utils import DatetimeLike, _set_directory, _standardise_models, _standardise_time, idw
@@ -95,7 +96,7 @@ def _model_tides(
95
96
  lon, lat = transformer.transform(x.flatten(), y.flatten())
96
97
 
97
98
  # Convert datetime
98
- timescale = pyTMD.time.timescale().from_datetime(time.flatten())
99
+ ts = timescale.time.Timescale().from_datetime(time.flatten())
99
100
 
100
101
  try:
101
102
  # Read tidal constants and interpolate to grid points
@@ -136,10 +137,10 @@ def _model_tides(
136
137
  # Compute delta times based on model
137
138
  if pytmd_model.corrections in ("OTIS", "ATLAS", "TMD3", "netcdf"):
138
139
  # Use delta time at 2000.0 to match TMD outputs
139
- deltat = np.zeros_like(timescale.tt_ut1)
140
+ deltat = np.zeros_like(ts.tt_ut1)
140
141
  else:
141
142
  # Use interpolated delta times
142
- deltat = timescale.tt_ut1
143
+ deltat = ts.tt_ut1
143
144
 
144
145
  # In "one-to-many" mode, extracted tidal constituents and timesteps
145
146
  # are repeated/multiplied out to match the number of input points and
@@ -149,7 +150,7 @@ def _model_tides(
149
150
  points_repeat = len(x) if mode == "one-to-many" else 1
150
151
  time_repeat = len(time) if mode == "one-to-many" else 1
151
152
  t, hc, deltat = (
152
- np.tile(timescale.tide, points_repeat),
153
+ np.tile(ts.tide, points_repeat),
153
154
  hc.repeat(time_repeat, axis=0),
154
155
  np.tile(deltat, points_repeat),
155
156
  )
@@ -416,6 +417,7 @@ def model_tides(
416
417
  - TOPEX/POSEIDON global tide models (TPXO10, TPXO9, TPXO8)
417
418
  - Global Ocean Tide models (GOT5.6, GOT5.5, GOT4.10, GOT4.8, GOT4.7)
418
419
  - Hamburg direct data Assimilation Methods for Tides models (HAMTIDE11)
420
+ - Technical University of Denmark tide models (DTU23)
419
421
 
420
422
  This function requires access to tide model data files.
421
423
  These should be placed in a folder with subfolders matching
@@ -444,7 +446,7 @@ def model_tides(
444
446
  The tide model (or list of models) to use to model tides.
445
447
  Defaults to "EOT20"; specify "all" to use all models available
446
448
  in `directory`. For a full list of available and supported models,
447
- run `eo_tides.utils.list_models`.
449
+ run `from eo_tides.utils import list_models; list_models()`.
448
450
  directory : str, optional
449
451
  The directory containing tide model data files. If no path is
450
452
  provided, this will default to the environment variable
@@ -735,7 +737,7 @@ def model_phases(
735
737
  The tide model (or list of models) to use to model tides.
736
738
  Defaults to "EOT20"; specify "all" to use all models available
737
739
  in `directory`. For a full list of available and supported models,
738
- run `eo_tides.utils.list_models`.
740
+ run `from eo_tides.utils import list_models; list_models()`.
739
741
  directory : str, optional
740
742
  The directory containing tide model data files. If no path is
741
743
  provided, this will default to the environment variable
eo_tides/stats.py CHANGED
@@ -243,10 +243,11 @@ def tide_stats(
243
243
  model : str or list of str, optional
244
244
  The tide model (or list of models) to use to model tides.
245
245
  If a list is provided, the resulting statistics will be
246
- returned as a `pandas.Dataframe`; otherwise a `pandas.Series`.
247
- Defaults to "EOT20"; specify "all" to use all models available
248
- in `directory`. For a full list of available and supported
249
- models, run `eo_tides.utils.list_models`.
246
+ returned as a `pandas.Dataframe`; otherwise a `pandas.Series`
247
+ will be returned. Defaults to "EOT20"; specify "all" to use
248
+ all models available in `directory`. For a full list of
249
+ available and supported models, run
250
+ `from eo_tides.utils import list_models; list_models()`.
250
251
  directory : str, optional
251
252
  The directory containing tide model data files. If no path is
252
253
  provided, this will default to the environment variable
@@ -453,7 +454,7 @@ def pixel_stats(
453
454
  added to the `xarray.Dataset` output. Defaults to "EOT20";
454
455
  specify "all" to use all models available in `directory`.
455
456
  For a full list of available and supported models, run
456
- `eo_tides.utils.list_models`.
457
+ `from eo_tides.utils import list_models; list_models()`.
457
458
  directory : str, optional
458
459
  The directory containing tide model data files. If no path is
459
460
  provided, this will default to the environment variable
eo_tides/utils.py CHANGED
@@ -181,9 +181,9 @@ def _clip_model_file(
181
181
  """
182
182
  Clips tide model netCDF datasets to a bounding box.
183
183
 
184
- If the bounding box crosses 0 degrees longitude (e.g. Greenwich),
185
- the function will clip the dataset into two parts and concatenate
186
- them along the x-dimension to create a continuous result.
184
+ If the bounding box crosses 0 degrees longitude (e.g. Greenwich prime
185
+ meridian), the dataset will be clipped into two parts and concatenated
186
+ along the x-dimension to create a continuous result.
187
187
 
188
188
  Parameters
189
189
  ----------
@@ -226,20 +226,22 @@ def _clip_model_file(
226
226
  xcoords = nc[xcoord].compute()
227
227
  ycoords = nc[ycoord].compute()
228
228
 
229
- # If data falls within 0-360 degree bounds, then clip directly
230
- if (bbox.left >= 0) & (bbox.right <= 360):
229
+ # Convert longitudes to 0-360 convention
230
+ left = bbox.left % 360
231
+ right = bbox.right % 360
232
+
233
+ # If left coordinate is smaller than right, bbox does not cross
234
+ # zero longitude and can be clipped directly
235
+ if left <= right: # bbox does not cross 0
231
236
  nc_clipped = nc.sel({
232
237
  ydim: (ycoords >= bbox.bottom) & (ycoords <= bbox.top),
233
- xdim: (xcoords >= bbox.left) & (xcoords <= bbox.right),
238
+ xdim: (xcoords >= left) & (xcoords <= right),
234
239
  })
235
240
 
236
- # If bbox crosses zero longitude, extract left and right
237
- # separately and then combine into one concatenated dataset
238
- elif (bbox.left < 0) & (bbox.right > 0):
239
- # Convert longitudes to 0-360 range
240
- left = bbox.left % 360
241
- right = bbox.right % 360
242
-
241
+ # If left coordinate is larger than right, bbox crosses zero longitude.
242
+ # If so, extract left and right separately and then combine into one
243
+ # concatenated dataset
244
+ elif left > right: # bbox crosses 0
243
245
  # Extract data from left of 0 longitude, and convert lon
244
246
  # coords to -180 to 0 range to enable continuous interpolation
245
247
  # across 0 boundary
@@ -357,7 +359,7 @@ def clip_models(
357
359
  model_files = model_database[m].get("model_file", [])
358
360
  grid_file = model_database[m].get("grid_file", [])
359
361
 
360
- # Convert to list if strings and combine
362
+ # Convert to list of strings and combine
361
363
  model_files = model_files if isinstance(model_files, list) else [model_files]
362
364
  grid_file = grid_file if isinstance(grid_file, list) else [grid_file]
363
365
  all_files = model_files + grid_file
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: eo-tides
3
- Version: 0.5.0
3
+ Version: 0.6.1
4
4
  Summary: Tide modelling tools for large-scale satellite earth observation analysis
5
5
  Author: Robbi Bishop-Taylor, Stephen Sagar, Claire Phillips, Vanessa Newey
6
6
  Author-email: Robbi.BishopTaylor@ga.gov.au
@@ -32,10 +32,11 @@ Requires-Dist: pandas>=2.2.0
32
32
  Requires-Dist: psutil>=5.8.0
33
33
  Requires-Dist: pyogrio>=0.10.0
34
34
  Requires-Dist: pyproj>=3.7.0
35
- Requires-Dist: pyTMD==2.2.0
35
+ Requires-Dist: pyTMD>=2.2.2
36
36
  Requires-Dist: scikit-learn>=1.4.0
37
37
  Requires-Dist: scipy>=1.14.1
38
38
  Requires-Dist: shapely>=2.0.6
39
+ Requires-Dist: timescale>=0.0.3
39
40
  Requires-Dist: tqdm>=4.55.0
40
41
  Requires-Dist: xarray>=2022.3.0
41
42
  Provides-Extra: notebooks
@@ -54,6 +55,7 @@ Requires-Dist: planetary_computer>=1.0.0; extra == "notebooks"
54
55
  [![Python Version from PEP 621 TOML](https://img.shields.io/pypi/pyversions/eo-tides)](https://github.com/GeoscienceAustralia/eo-tides/blob/main/pyproject.toml)
55
56
  [![codecov](https://codecov.io/gh/GeoscienceAustralia/eo-tides/branch/main/graph/badge.svg)](https://codecov.io/gh/GeoscienceAustralia/eo-tides)
56
57
  [![License](https://img.shields.io/github/license/GeoscienceAustralia/eo-tides)](https://img.shields.io/github/license/GeoscienceAustralia/eo-tides)
58
+ [![status](https://joss.theoj.org/papers/b5680c39bf831c1159c41a2eb7ec9c5e/status.svg)](https://joss.theoj.org/papers/b5680c39bf831c1159c41a2eb7ec9c5e)
57
59
 
58
60
  - ⚙️ **Github repository**: <https://github.com/GeoscienceAustralia/eo-tides/>
59
61
  - 📘 **Documentation**: <https://GeoscienceAustralia.github.io/eo-tides/>
@@ -87,6 +89,7 @@ These tools can be applied to petabytes of freely available satellite data (e.g.
87
89
  - [TOPEX/POSEIDON global tide models](https://www.tpxo.net/global) (TPXO10, TPXO9, TPXO8)
88
90
  - [Global Ocean Tide models](https://doi.org/10.1002/2016RG000546) (GOT5.6, GOT5.5, GOT4.10, GOT4.8, GOT4.7)
89
91
  - [Hamburg direct data Assimilation Methods for Tides models](https://doi.org/10.1002/2013JC009766) (HAMTIDE11)
92
+ - [Technical University of Denmark tide models](https://doi.org/10.11583/DTU.23828874) (DTU23)
90
93
 
91
94
  For instructions on how to set up these models for use in `eo-tides`, refer to [Setting up tide models](setup.md).
92
95
 
@@ -0,0 +1,11 @@
1
+ eo_tides/__init__.py,sha256=pGvVlxMKiYjm_273G-oYcOgVuPra7uEdNZv0oN1i69c,1693
2
+ eo_tides/eo.py,sha256=TuFt9SSiO9Z2o8Kr1g-wFPzofp0HTcgkfhT83zu03kc,23983
3
+ eo_tides/model.py,sha256=XqgV3Arvkr3Z8PR6EvTMZbg8WnnpYCDOjFL2-sOXeF0,34695
4
+ eo_tides/stats.py,sha256=ELQpqIH86442IYgjrGrIK3mi0-pu2ZijFw53arA2FYg,23072
5
+ eo_tides/utils.py,sha256=T19OuPLHzaUKcovCVGANvmOiRu-L8VuDXSTzmNlA6Bo,26647
6
+ eo_tides/validation.py,sha256=KP8WLT5z7KLFjQ9oDla7VJOyLQAK4SVbcz2ySAbsbwI,11882
7
+ eo_tides-0.6.1.dist-info/LICENSE,sha256=owxWsXViCL2J6Ks3XYhot7t4Y93nstmXAT95Zf030Cc,11350
8
+ eo_tides-0.6.1.dist-info/METADATA,sha256=sl9C1TQIgpC6ZDLeHAJOm0Ea9tyDyZU4zvJg4fd2OBE,8184
9
+ eo_tides-0.6.1.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
10
+ eo_tides-0.6.1.dist-info/top_level.txt,sha256=lXZDUUM1DlLdKWHRn8zdmtW8Rx-eQOIWVvt0b8VGiyQ,9
11
+ eo_tides-0.6.1.dist-info/RECORD,,
@@ -1,11 +0,0 @@
1
- eo_tides/__init__.py,sha256=pGvVlxMKiYjm_273G-oYcOgVuPra7uEdNZv0oN1i69c,1693
2
- eo_tides/eo.py,sha256=nuaOppYJCVL8mbFyaL9e4ahHB_LBGBrr5XfnAopmW5M,22746
3
- eo_tides/model.py,sha256=xpKaVO1_cLLwbODpffqDL80Hw7Yv9JchH42tKhX1oto,34585
4
- eo_tides/stats.py,sha256=RXs3J3YZH3yOrzDibEDp3-7wjkleOEFzO33lp27ATuE,22993
5
- eo_tides/utils.py,sha256=9xJ1q-b-TVHg5zFyLy6AT_srrPQDvmFdWJmlGSPaJF0,26563
6
- eo_tides/validation.py,sha256=KP8WLT5z7KLFjQ9oDla7VJOyLQAK4SVbcz2ySAbsbwI,11882
7
- eo_tides-0.5.0.dist-info/LICENSE,sha256=owxWsXViCL2J6Ks3XYhot7t4Y93nstmXAT95Zf030Cc,11350
8
- eo_tides-0.5.0.dist-info/METADATA,sha256=CtP3dQKJAbs1bEZaJz0egfina4OD4jba4TGDlLxxIPg,7906
9
- eo_tides-0.5.0.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
10
- eo_tides-0.5.0.dist-info/top_level.txt,sha256=lXZDUUM1DlLdKWHRn8zdmtW8Rx-eQOIWVvt0b8VGiyQ,9
11
- eo_tides-0.5.0.dist-info/RECORD,,