Tides

The Tides class fetches water-level data from NOAA CO-OPS tide gauge stations and derives tidal indices such as time since last high tide and tidal phase. No registration is required.

class ecosound.environment.tides.Tides(verbose: bool = True)[source]

Bases: object

Class for fetching NOAA CO-OPS water level and computing tidal indices.

Data is fetched at 6-minute resolution from the nearest NOAA tide gauge station to the requested location. Results are returned as xr.Dataset compatible with NECOFS, ERA5, and HMD outputs.

By default, tidal index variables (time_since_high_tide_h, tidal_phase) are computed automatically and included in the returned dataset. Detected high- and low-tide event times are stored as class attributes.

Parameters:

verbose – Print progress messages (default: True).

water_level

Most recent water level time series from get_water_level(). Dimension: time. Coordinates: time, lat, lon. Includes tidal index variables when compute_tidal_index=True. None until first call.

Type:

xr.Dataset | None

high_tide_times

datetime64 array of detected high-tide peak times. None until get_water_level() is called with compute_tidal_index=True.

Type:

np.ndarray | None

high_tide_levels

Water level (m) at each high-tide peak (same order as high_tide_times).

Type:

np.ndarray | None

low_tide_times

datetime64 array of detected low-tide trough times.

Type:

np.ndarray | None

low_tide_levels

Water level (m) at each low-tide trough (same order as low_tide_times).

Type:

np.ndarray | None

Examples

>>> from ecosound.environment import Tides
>>> tides = Tides()

# Fetch by explicit time range (tidal index included by default) >>> ds = tides.get_water_level(lat=42.5, lon=-70.0, … start_dt=”2015-08-01”, end_dt=”2015-08-31”) >>> print(ds) # contains water_level_m, time_since_high_tide_h, tidal_phase >>> print(tides.high_tide_times) # numpy array of high-tide datetimes >>> tides.plot_water_level()

# Fetch using another xr.Dataset’s time axis (e.g. from HMD or NECOFS) >>> tides.get_water_level(lat=42.5, lon=-70.0, time_ref=hmd.ds)

# Merge with HMD acoustic data (reindex to 1-minute HMD time axis) >>> ds_aligned = tides.water_level.reindex( … time=hmd.ds.time, method=”nearest”, tolerance=”10min”) >>> ds_combined = xr.merge([hmd.ds, ds_aligned])

COOPS_API_URL = 'https://api.tidesandcurrents.noaa.gov/api/prod/datagetter'
COOPS_MDAPI_URL = 'https://api.tidesandcurrents.noaa.gov/mdapi/prod/webapi'
TIDAL_PERIOD_H = 12.42
find_nearest_station(lat: float, lon: float) tuple[str, str, float, float][source]

Find the nearest NOAA water-level gauge to a given location.

Parameters:
  • lat – Latitude (decimal degrees).

  • lon – Longitude (decimal degrees, negative west).

Returns:

Tuple (station_id, station_name, station_lat, station_lon).

get_water_level(lat: float, lon: float, start_dt: datetime | Timestamp | str | None = None, end_dt: datetime | Timestamp | str | None = None, time_ref: Dataset | None = None, product: str = 'predictions', datum: str = 'MLLW', compute_tidal_index: bool = True) Dataset[source]

Fetch NOAA CO-OPS water level at the nearest tide gauge.

The time range can be specified either explicitly with start_dt/end_dt, or implicitly by passing another xr.Dataset via time_ref (its first and last time coordinate values are used as the range).

Data is fetched in ≤31-day chunks (NOAA API limit for 6-minute data) and concatenated automatically.

When compute_tidal_index=True (default), the tidal index variables time_since_high_tide_h and tidal_phase are computed and added directly to the returned dataset. Detected high- and low-tide event times and levels are stored in self.high_tide_times, self.high_tide_levels, self.low_tide_times, and self.low_tide_levels.

The result is always stored in self.water_level and always returned:

tides.get_water_level(lat, lon, start_dt=”2015-08-01”, end_dt=”2015-08-31”) ds = tides.get_water_level(lat, lon, time_ref=hmd.ds)

Parameters:
  • lat – Latitude (decimal degrees, WGS84).

  • lon – Longitude (decimal degrees, WGS84, negative west).

  • start_dt – Start of the time range (inclusive). Accepts datetime, pd.Timestamp, or ISO 8601 string. Ignored if time_ref is provided.

  • end_dt – End of the time range (inclusive). Ignored if time_ref is provided.

  • time_ref – Optional xr.Dataset whose time coordinate defines the fetch range. When provided, start_dt and end_dt are derived from time_ref.time.values[0] and [-1].

  • product – NOAA product — “predictions” (default, astronomical tides) or “water_level” (observed, includes surge).

  • datum – Vertical datum (default “MLLW”). Other options: “MSL”, “MHW”, “NAVD”, etc.

  • compute_tidal_index – If True (default), compute and merge tidal index variables into the returned dataset. Requires scipy. Set to False to skip.

Returns:

Data variables (always present):
  • water_level_m (time): Water level (m above datum)

Data variables (when compute_tidal_index=True):
  • time_since_high_tide_h (time): Hours since last high tide. NaN before the first detected high tide in the record.

  • tidal_phase (time): Fractional tidal cycle [0,1). 0 = high tide, ~0.5 = low tide. NaN before first peak.

Coordinates:
  • time : datetime64 UTC, 6-minute resolution

  • lat : station latitude (scalar)

  • lon : station longitude (scalar)

Dataset.attrs:
  • requested_lat/lon, station_id, station_name, station_lat, station_lon, product, datum, source, temporal_resolution, tidal_period_h (if tidal index), n_high_tides, n_low_tides (if tidal index)

Return type:

xr.Dataset with dimension time, also stored in self.water_level

Side effects (when compute_tidal_index=True):
  • self.high_tide_times set to numpy datetime64 array of high-tide peaks

  • self.high_tide_levels set to numpy float array of water levels at peaks

  • self.low_tide_times set to numpy datetime64 array of low-tide troughs

  • self.low_tide_levels set to numpy float array of water levels at troughs

Raises:
  • ValueError – If neither time_ref nor both start_dt/end_dt are given.

  • ImportError – If scipy is not installed and compute_tidal_index=True.

  • RuntimeError – If the NOAA API returns an error.

plot_water_level(figsize: tuple = (12, 4), display: bool = True, filename: str | None = None) None[source]

Plot the water level time series with high and low tide markers.

If get_water_level() was called with compute_tidal_index=True, the already-detected high/low tide times stored in self.high_tide_times and self.low_tide_times are used directly. Otherwise, peak detection is run on the fly (requires scipy).

Parameters:
  • figsize – Figure size as (width, height) in inches (default: (12, 4)).

  • display – Show the figure on screen (default: True).

  • filename – If provided, save the figure to this path. Default: None.

Raises:
  • ImportError – If scipy is not installed and peaks were not pre-detected.

  • RuntimeError – If get_water_level() has not been called yet.