Skip to content

Commit

Permalink
Refactor time, rename phase func (#23)
Browse files Browse the repository at this point in the history
* Refactor time, rename phase func

* Rerun notebooks

* Try to fix typing in python3.9

* Try to fix typing in python3.9
  • Loading branch information
robbibt authored Oct 30, 2024
1 parent 404c033 commit afeca6f
Show file tree
Hide file tree
Showing 11 changed files with 286 additions and 147 deletions.
2 changes: 1 addition & 1 deletion docs/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@

### Breaking changes

See [Migrating from DEA Tools](#migration) for a guide to updating your code from the original [`Digital Earth Australia Notebooks and Tools` repository](https://github.com/GeoscienceAustralia/dea-notebooks/).
See [Migrating from DEA Tools](migration.md) for a guide to updating your code from the original [`Digital Earth Australia Notebooks and Tools` repository](https://github.com/GeoscienceAustralia/dea-notebooks/).

<!-- ### Bug fixes -->
74 changes: 37 additions & 37 deletions docs/notebooks/Model_tides.ipynb

Large diffs are not rendered by default.

56 changes: 28 additions & 28 deletions docs/notebooks/Satellite_data.ipynb

Large diffs are not rendered by default.

42 changes: 21 additions & 21 deletions docs/notebooks/Tide_statistics.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -510,7 +510,7 @@
"name": "stderr",
"output_type": "stream",
"text": [
"100%|██████████| 5/5 [00:00<00:00, 39.37it/s]\n"
"100%|██████████| 5/5 [00:00<00:00, 24.21it/s]\n"
]
},
{
Expand All @@ -527,7 +527,7 @@
"name": "stderr",
"output_type": "stream",
"text": [
"100%|██████████| 5/5 [00:02<00:00, 1.98it/s]\n"
"100%|██████████| 5/5 [00:04<00:00, 1.01it/s]\n"
]
},
{
Expand All @@ -544,10 +544,10 @@
" tide_model <U5 20B 'EOT20'\n",
" spatial_ref int32 4B 32751\n",
"Data variables:\n",
" hat (y, x) float32 256B 4.282 4.318 4.408 4.408 ... 4.797 4.797 nan\n",
" hot (y, x) float32 256B 3.773 3.794 3.844 3.844 ... 3.953 3.953 nan\n",
" lat (y, x) float32 256B -4.222 -4.264 -4.353 ... -4.692 -4.692 nan\n",
" hat (y, x) float32 256B 4.282 4.318 4.408 4.408 ... 4.797 4.797 nan\n",
" lot (y, x) float32 256B -2.109 -2.128 -2.18 ... -2.418 -2.418 nan\n",
" lat (y, x) float32 256B -4.222 -4.264 -4.353 ... -4.692 -4.692 nan\n",
" otr (y, x) float32 256B 5.882 5.922 6.023 6.023 ... 6.372 6.372 nan\n",
" tr (y, x) float32 256B 8.504 8.582 8.761 8.761 ... 9.49 9.49 nan\n",
" spread (y, x) float32 256B 0.6917 0.69 0.6875 ... 0.6714 0.6714 nan\n",
Expand Down Expand Up @@ -608,7 +608,7 @@
" &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width,\n",
" initial-scale=1.0, maximum-scale=1.0, user-scalable=no&quot; /&gt;\n",
" &lt;style&gt;\n",
" #map_de6fd6dc676e994f44d648c75f3908d6 {\n",
" #map_83191ecb651ac2f080394e790cf1f14c {\n",
" position: relative;\n",
" width: 100.0%;\n",
" height: 100.0%;\n",
Expand All @@ -635,14 +635,14 @@
"&lt;body&gt;\n",
" \n",
" \n",
" &lt;div class=&quot;folium-map&quot; id=&quot;map_de6fd6dc676e994f44d648c75f3908d6&quot; &gt;&lt;/div&gt;\n",
" &lt;div class=&quot;folium-map&quot; id=&quot;map_83191ecb651ac2f080394e790cf1f14c&quot; &gt;&lt;/div&gt;\n",
" \n",
"&lt;/body&gt;\n",
"&lt;script&gt;\n",
" \n",
" \n",
" var map_de6fd6dc676e994f44d648c75f3908d6 = L.map(\n",
" &quot;map_de6fd6dc676e994f44d648c75f3908d6&quot;,\n",
" var map_83191ecb651ac2f080394e790cf1f14c = L.map(\n",
" &quot;map_83191ecb651ac2f080394e790cf1f14c&quot;,\n",
" {\n",
" center: [0.0, 0.0],\n",
" crs: L.CRS.EPSG3857,\n",
Expand All @@ -656,51 +656,51 @@
"\n",
" \n",
" \n",
" var tile_layer_494fc2e2a73cd023d6a3adc3894b5831 = L.tileLayer(\n",
" var tile_layer_e3f47e0884f779ae12d0c17e3a14d6d5 = L.tileLayer(\n",
" &quot;https://tile.openstreetmap.org/{z}/{x}/{y}.png&quot;,\n",
" {&quot;attribution&quot;: &quot;\\u0026copy; \\u003ca href=\\&quot;https://www.openstreetmap.org/copyright\\&quot;\\u003eOpenStreetMap\\u003c/a\\u003e contributors&quot;, &quot;detectRetina&quot;: false, &quot;maxNativeZoom&quot;: 19, &quot;maxZoom&quot;: 19, &quot;minZoom&quot;: 0, &quot;noWrap&quot;: false, &quot;opacity&quot;: 1, &quot;subdomains&quot;: &quot;abc&quot;, &quot;tms&quot;: false}\n",
" );\n",
" \n",
" \n",
" tile_layer_494fc2e2a73cd023d6a3adc3894b5831.addTo(map_de6fd6dc676e994f44d648c75f3908d6);\n",
" tile_layer_e3f47e0884f779ae12d0c17e3a14d6d5.addTo(map_83191ecb651ac2f080394e790cf1f14c);\n",
" \n",
" \n",
" var image_overlay_9c270895249960ab066c6c4b656cf1ac = L.imageOverlay(\n",
" var image_overlay_c913033bca0c9be16541be2e2e42c5f7 = L.imageOverlay(\n",
" &quot;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAsAAAALCAYAAACprHcmAAAAwUlEQVQYla2Qvw7BUBjFf71u6s8g QiRXTBKD0eIZvItnMXsKHsArMFgESQeCpBhaiuJStXWQikic8eSck9/3wQ8yAAK7Gg5ud3r7BgDt eteICwuA9eOEpdXXZQEw1gWGp0pkNlUrbKpW+B6WAJNrmeleYc3KANSYR6X+phMhCYDpucTKzSEu BvmRIKjEI0kA61Dk4qTJOALz+ET4mmC7i2e23SzSkSSdEPMYIDz/84HaTWF6BgkNZyV5LJbfHvNn vQB1QUKDARyVYAAAAABJRU5ErkJggg== &quot;,\n",
" [[-17.774369088074852, 121.96465246015089], [-18.24423443292681, 122.45872586641661]],\n",
" {}\n",
" );\n",
" \n",
" \n",
" image_overlay_9c270895249960ab066c6c4b656cf1ac.addTo(map_de6fd6dc676e994f44d648c75f3908d6);\n",
" image_overlay_c913033bca0c9be16541be2e2e42c5f7.addTo(map_83191ecb651ac2f080394e790cf1f14c);\n",
" \n",
" \n",
" map_de6fd6dc676e994f44d648c75f3908d6.fitBounds(\n",
" map_83191ecb651ac2f080394e790cf1f14c.fitBounds(\n",
" [[-17.815037709843487, 122.00921674324115], [-18.178111016594787, 122.38538624620925]],\n",
" {}\n",
" );\n",
" \n",
" \n",
" var layer_control_14aad14024c22f1728b36440adc243e8_layers = {\n",
" var layer_control_0276faa5315da9837b347f196fe02065_layers = {\n",
" base_layers : {\n",
" &quot;openstreetmap&quot; : tile_layer_494fc2e2a73cd023d6a3adc3894b5831,\n",
" &quot;openstreetmap&quot; : tile_layer_e3f47e0884f779ae12d0c17e3a14d6d5,\n",
" },\n",
" overlays : {\n",
" &quot;spread&quot; : image_overlay_9c270895249960ab066c6c4b656cf1ac,\n",
" &quot;spread&quot; : image_overlay_c913033bca0c9be16541be2e2e42c5f7,\n",
" },\n",
" };\n",
" let layer_control_14aad14024c22f1728b36440adc243e8 = L.control.layers(\n",
" layer_control_14aad14024c22f1728b36440adc243e8_layers.base_layers,\n",
" layer_control_14aad14024c22f1728b36440adc243e8_layers.overlays,\n",
" let layer_control_0276faa5315da9837b347f196fe02065 = L.control.layers(\n",
" layer_control_0276faa5315da9837b347f196fe02065_layers.base_layers,\n",
" layer_control_0276faa5315da9837b347f196fe02065_layers.overlays,\n",
" {&quot;autoZIndex&quot;: true, &quot;collapsed&quot;: true, &quot;position&quot;: &quot;topright&quot;}\n",
" ).addTo(map_de6fd6dc676e994f44d648c75f3908d6);\n",
" ).addTo(map_83191ecb651ac2f080394e790cf1f14c);\n",
"\n",
" \n",
"&lt;/script&gt;\n",
"&lt;/html&gt;\" style=\"position:absolute;width:100%;height:100%;left:0;top:0;border:none !important;\" allowfullscreen webkitallowfullscreen mozallowfullscreen></iframe></div></div>"
],
"text/plain": [
"<folium.folium.Map at 0x7f1deaa0ae00>"
"<folium.folium.Map at 0x7f76f0452e60>"
]
},
"execution_count": 10,
Expand Down
6 changes: 3 additions & 3 deletions eo_tides/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,16 +28,16 @@

# Import commonly used functions for convenience
from .eo import pixel_tides, tag_tides
from .model import list_models, model_tides
from .stats import tide_stats
from .model import list_models, model_phases, model_tides
from .stats import pixel_stats, tide_stats
from .utils import idw
from .validation import eval_metrics, load_gauge_gesla

# Define what should be imported with "from eo_tides import *"
__all__ = [
"list_models",
"model_tides",
"phase_tides",
"model_phases",
"tag_tides",
"pixel_tides",
"tide_stats",
Expand Down
30 changes: 16 additions & 14 deletions eo_tides/eo.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,11 @@

# Only import if running type checking
if TYPE_CHECKING:
import datetime

from odc.geo import Shape2d

from .model import _standardise_time, model_tides
from .model import DatetimeLike, _standardise_time, model_tides


def _resample_chunks(
Expand Down Expand Up @@ -49,7 +51,7 @@ def _resample_chunks(

def _standardise_inputs(
data: xr.DataArray | xr.Dataset | GeoBox,
time: np.ndarray | pd.DatetimeIndex | pd.Timestamp | None,
time: DatetimeLike | None,
) -> tuple[GeoBox, np.ndarray | None]:
"""
Takes an xarray or GeoBox input and an optional custom times,
Expand Down Expand Up @@ -156,7 +158,7 @@ def _pixel_tides_resample(

def tag_tides(
data: xr.Dataset | xr.DataArray | GeoBox,
time: np.ndarray | pd.DatetimeIndex | pd.Timestamp | None = None,
time: DatetimeLike | None = None,
model: str | list[str] = "EOT20",
directory: str | os.PathLike | None = None,
tidepost_lat: float | None = None,
Expand Down Expand Up @@ -190,11 +192,11 @@ def tag_tides(
is an xarray object, it should include a "time" dimension.
If no "time" dimension exists or if `data` is a GeoBox,
then times must be passed using the `time` parameter.
time : pd.DatetimeIndex or list of pd.Timestamp, optional
By default, the function will model tides using the times
contained in the "time" dimension of `data`. Alternatively, this
param can be used to model tides for a custom set of times
instead. For example:
time : DatetimeLike, optional
By default, tides will be modelled using times from the
"time" dimension of `data`. Alternatively, this param can
be used to provide a custom set of times. Accepts any format
that can be converted by `pandas.to_datetime()`. For example:
`time=pd.date_range(start="2000", end="2001", freq="5h")`
model : str or list of str, optional
The tide model (or models) used to model tides. If a list is
Expand Down Expand Up @@ -272,7 +274,7 @@ def tag_tides(

def pixel_tides(
data: xr.Dataset | xr.DataArray | GeoBox,
time: np.ndarray | pd.DatetimeIndex | pd.Timestamp | None = None,
time: DatetimeLike | None = None,
model: str | list[str] = "EOT20",
directory: str | os.PathLike | None = None,
resample: bool = True,
Expand Down Expand Up @@ -319,11 +321,11 @@ def pixel_tides(
is an xarray object, it should include a "time" dimension.
If no "time" dimension exists or if `data` is a GeoBox,
then times must be passed using the `time` parameter.
time : pd.DatetimeIndex or list of pd.Timestamp, optional
By default, the function will model tides using the times
contained in the "time" dimension of `data`. Alternatively, this
param can be used to model tides for a custom set of times
instead. For example:
time : DatetimeLike, optional
By default, tides will be modelled using times from the
"time" dimension of `data`. Alternatively, this param can
be used to provide a custom set of times. Accepts any format
that can be converted by `pandas.to_datetime()`. For example:
`time=pd.date_range(start="2000", end="2001", freq="5h")`
model : str or list of str, optional
The tide model (or models) used to model tides. If a list is
Expand Down
48 changes: 28 additions & 20 deletions eo_tides/model.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
# Used to postpone evaluation of type annotations
from __future__ import annotations

import datetime
import os
import pathlib
import textwrap
import warnings
from concurrent.futures import ProcessPoolExecutor
from concurrent.futures.process import BrokenProcessPool
from functools import partial
from typing import TYPE_CHECKING
from typing import TYPE_CHECKING, List, Union

# Only import if running type checking
if TYPE_CHECKING:
Expand All @@ -25,6 +26,9 @@

from .utils import idw

# Type alias for all possible inputs to "time" params
DatetimeLike = Union[np.ndarray, pd.DatetimeIndex, pd.Timestamp, datetime.datetime, str, List[str]]


def _set_directory(
directory: str | os.PathLike | None = None,
Expand Down Expand Up @@ -53,20 +57,22 @@ def _set_directory(


def _standardise_time(
time: np.ndarray | pd.DatetimeIndex | pd.Timestamp | None,
time: DatetimeLike | None,
) -> np.ndarray | None:
"""
Accept a datetime64 ndarray, pandas.DatetimeIndex
or pandas.Timestamp, and return a datetime64 ndarray.
Accept any time format accepted by `pd.to_datetime`,
and return a datetime64 ndarray. Return None if None
passed.
"""
# Return time as-is if none
# Return time as-is if None
if time is None:
return time
return None

# Convert to a 1D datetime64 array
time = np.atleast_1d(time).astype("datetime64[ns]")
# Use pd.to_datetime for conversion, then convert to numpy array
time = pd.to_datetime(time).to_numpy().astype("datetime64[ns]")

return time
# Ensure that data has at least one dimension
return np.atleast_1d(time)


def list_models(
Expand Down Expand Up @@ -487,7 +493,7 @@ def _ensemble_model(
def model_tides(
x: float | list[float] | xr.DataArray,
y: float | list[float] | xr.DataArray,
time: np.ndarray | pd.DatetimeIndex,
time: DatetimeLike,
model: str | list[str] = "EOT20",
directory: str | os.PathLike | None = None,
crs: str = "EPSG:4326",
Expand Down Expand Up @@ -533,10 +539,11 @@ def model_tides(
the location at which to model tides. By default these
coordinates should be lat/lon; use "crs" if they
are in a custom coordinate reference system.
time : Numpy datetime array or pandas.DatetimeIndex
An array containing `datetime64[ns]` values or a
`pandas.DatetimeIndex` providing the times at which to
model tides in UTC time.
time : DatetimeLike
Times at which to model tide heights (in UTC). Accepts
any format that can be converted by `pandas.to_datetime()`;
e.g. np.ndarray[datetime64], pd.DatetimeIndex, pd.Timestamp,
datetime.datetime and strings (e.g. "2020-01-01 23:00").
model : str or list of str, optional
The tide model (or models) to use to model tides.
Defaults to "EOT20"; for a full list of available/supported
Expand Down Expand Up @@ -808,10 +815,10 @@ def model_tides(
return tide_df


def phase_tides(
def model_phases(
x: float | list[float] | xr.DataArray,
y: float | list[float] | xr.DataArray,
time: np.ndarray | pd.DatetimeIndex,
time: DatetimeLike,
model: str | list[str] = "EOT20",
directory: str | os.PathLike | None = None,
time_offset: str = "15 min",
Expand Down Expand Up @@ -842,10 +849,11 @@ def phase_tides(
the location at which to model tide phases. By default
these coordinates should be lat/lon; use "crs" if they
are in a custom coordinate reference system.
time : Numpy datetime array or pandas.DatetimeIndex
An array containing `datetime64[ns]` values or a
`pandas.DatetimeIndex` providing the times at which to
model tide phases in UTC time.
time : DatetimeLike
Times at which to model tide phases (in UTC). Accepts
any format that can be converted by `pandas.to_datetime()`;
e.g. np.ndarray[datetime64], pd.DatetimeIndex, pd.Timestamp,
datetime.datetime and strings (e.g. "2020-01-01 23:00").
model : str or list of str, optional
The tide model (or models) to use to compute tide phases.
Defaults to "EOT20"; for a full list of available/supported
Expand Down
Loading

0 comments on commit afeca6f

Please sign in to comment.