pyfvcom2.tide module

class pyfvcom2.tide.HarmonicAnalysisWriter(filename, dimensions, global_attributes=None, **kwargs)[source]

Bases: FVCOMWriter

Write tidal harmonic analysis results to a NetCDF file.

Subclasses FVCOMWriter to provide methods for writing the grid, sigma coordinates, constituent names, harmonic amplitudes/phases, and optionally raw or predicted time series.

Typical usage:

dims = {
    'node': nx, 'nele': ne, 'siglay': nz, 'siglev': nzlev,
    'three': 3, 'nconsts': len(consts),
    'NameStrLen': 4, 'DateStrLen': 26,
}
global_atts = {'title': 'FVCOM harmonic analysis', ...}
with HarmonicAnalysisWriter('harmonics.nc', dims, global_atts) as nc:
    nc.add_grid(lon, lat, lonc, latc, h, h_center, nv, siglay, siglev, consts)
    nc.write_fvcom_time(times)   # only needed when writing time series
    nc.add_harmonics('zeta', z_amp, z_phase)
    nc.add_harmonics('ua', ua_amp, ua_phase)
    nc.add_harmonics('u', u_amp, u_phase)

Notes

Dimensions must be passed to __init__ before calling add_grid() or add_harmonics(). The ‘time’ dimension should be set to 0 (unlimited) when writing raw or predicted time series, and omitted otherwise.

The ncopts compression settings default to zlib level 7, matching the original PyFVCOM HarmonicOutput behaviour.

add_grid(lon, lat, lonc, latc, h, h_center, nv, siglay, siglev, consts)[source]

Write grid coordinates, bathymetry, connectivity and constituent names.

Parameters:
  • lon (array-like) – Node longitudes and latitudes.

  • lat (array-like) – Node longitudes and latitudes.

  • lonc (array-like) – Element centre longitudes and latitudes.

  • latc (array-like) – Element centre longitudes and latitudes.

  • h (array-like) – Node bathymetry (m, positive down).

  • h_center (array-like) – Element centre bathymetry (m, positive down).

  • nv (array-like) – Node-to-element connectivity table, shape (3, nele).

  • siglay (array-like) – Sigma layer coordinates, shape (siglay, node).

  • siglev (array-like) – Sigma level coordinates, shape (siglev, node).

  • consts (list of str) – Tidal constituent names, padded to 4 characters (e.g. ‘M2 ‘).

add_harmonics(variable, amplitude, phase)[source]

Write harmonic amplitude and phase for a given variable.

Parameters:
  • variable (str) – One of ‘zeta’, ‘ua’, ‘va’, ‘u’, ‘v’.

  • amplitude (array-like) – Harmonic amplitudes (m or m/s). Shape is (nconsts, node) for ‘zeta’, (nconsts, nele) for depth-averaged velocity, or (nconsts, siglay, nele) for depth-resolved velocity.

  • phase (array-like) – Harmonic phases (degrees), same shape as amplitude.

add_predicted(variable, data)[source]

Write a predicted time series reconstructed from the harmonics.

Requires a ‘time’ dimension to have been created and write_fvcom_time() to have been called first.

Parameters:
  • variable (str) – One of ‘zeta’, ‘ua’, ‘va’, ‘u’, ‘v’.

  • data (array-like) – Predicted time series. Same shape conventions as add_raw().

add_raw(variable, data)[source]

Write the raw (input) time series used in the harmonic analysis.

Requires a ‘time’ dimension to have been created and write_fvcom_time() to have been called first.

Parameters:
  • variable (str) – One of ‘zeta’, ‘ua’, ‘va’, ‘u’, ‘v’.

  • data (array-like) – Time series data. Shape is (time, node) for ‘zeta’, (time, nele) for depth-averaged, or (time, siglay, nele) for depth-resolved.

class pyfvcom2.tide.HarmonicsAnalyser(reader: FVCOMReader, output_file: str, constit: tuple = ('M2', 'S2', 'N2', 'K2', 'K1', 'O1', 'P1', 'Q1', 'M4', 'MS4', 'MN4'), predict: bool = False, dump_raw: bool = False, node_indices: ndarray = None, element_indices: ndarray = None, verbose: bool = False, pool_size: int = 1, show_progress: bool = True)[source]

Bases: object

Orchestrate tidal harmonic analysis from FVCOM output.

Loads data from a FVCOMReader, runs UTide harmonic analysis for each requested variable, and writes results to a HarmonicAnalysisWriter NetCDF file.

Parameters:
  • reader (FVCOMReader) – Open reader for the FVCOM model output to analyse.

  • output_file (str) – Path to the NetCDF output file to create.

  • constit (tuple, optional) – Tidal constituent names. Defaults to DEFAULT_CONSTIT.

  • predict (bool, optional) – If True, also write a predicted (reconstructed) time series for each variable. Defaults to False.

  • dump_raw (bool, optional) – If True, also write the raw (input) time series for each variable. Defaults to False.

  • node_indices (array-like of int, optional) –

    Integer indices into the full node array selecting the subset of nodes to analyse. If None (default), all nodes are analysed. Useful for restricting the analysis to a spatial region of interest and avoiding the cost of analysing the full mesh. Typically constructed as:

    mask = (lon >= lon_min) & (lon <= lon_max) & (lat >= lat_min) & (lat <= lat_max)
    node_indices = np.where(mask)[0]
    

  • element_indices (array-like of int, optional) – Integer indices into the full element array selecting the subset of elements to analyse. If None (default), all elements are analysed. Constructed analogously to node_indices using element-centred coordinates (reader.lon_elements, reader.lat_elements).

  • verbose (bool, optional) – If True, print UTide’s per-solve progress messages ("solve: matrix prep solution done."). Defaults to False.

  • pool_size (int, optional) – Number of worker processes for parallel analysis. 1 (default) runs serially. Set to the number of physical cores (e.g. multiprocessing.cpu_count()) for maximum throughput. Passed directly to analyse_harmonics().

  • show_progress (bool, optional) – If True (default), print a live progress line to stdout for each variable (and each sigma layer for 3-D variables) showing the count of completed positions, elapsed time, and estimated time remaining. Set to False to suppress all progress output.

Examples

reader = FVCOMReader(['output_0001.nc', 'output_0002.nc'])
analyser = HarmonicsAnalyser(reader, 'harmonics.nc', predict=True)
analyser.run(['zeta', 'u', 'v'])
run(variables: list = None)[source]

Run harmonic analysis for the specified variables.

Opens the output file, writes the grid and (when applicable) time, then runs the analysis variable by variable.

Parameters:

variables (list of str, optional) – FVCOM variable names to analyse. Valid values are 'zeta', 'u', 'v', 'ua', 'va'. Defaults to all five.

class pyfvcom2.tide.TideManager(constituents: list[str], parallel: bool = True, pool_size: int | None = None)[source]

Bases: object

Manages tidal harmonics interpolation and prediction.

Orchestrates the pipeline from TPXO tidal harmonic data through interpolation onto target positions to tidal time series prediction via UTide.

Typical usage:
  1. Create a TideManager with the desired constituents.

  2. Register TPXOInterpolator instances for each variable (zeta, u, v) via add_interpolator.

  3. Pass the TideManager to NestManager.add_tidal_data(), which calls predict() for each variable with the appropriate target positions.

Args:

constituents: List of tidal constituent names (e.g. [‘M2’, ‘S2’]). parallel: Whether to run UTide predictions in parallel. Default True. pool_size: Number of parallel processes. Default None (use all CPUs).

add_interpolator(variable: str, interpolator) None[source]

Register a TPXOInterpolator for a tidal variable.

Args:

variable: Tidal variable name (‘zeta’, ‘u’, or ‘v’). interpolator: TPXOInterpolator loaded with harmonics data

for this variable.

property constituents: list[str]

List of tidal constituent names.

predict(variable: str, datetimes: ndarray, longitudes: ndarray, latitudes: ndarray) ndarray[source]

Interpolate harmonics onto target positions and predict tides.

Args:

variable: Variable name (‘zeta’, ‘u’, or ‘v’). datetimes: Array of datetime objects for prediction times. longitudes: Target longitude positions. latitudes: Target latitude positions.

Returns:

Predicted tidal time series, shape (n_times, n_points).

pyfvcom2.tide.analyse_harmonics(times: ndarray, elevations: ndarray, latitudes: ndarray, predict: bool = False, constit: tuple = ('M2', 'S2', 'N2', 'K2', 'K1', 'O1', 'P1', 'Q1', 'M4', 'MS4', 'MN4'), pool_size: int = 1, label: str = '', **kwargs) ndarray[source]

Run UTide harmonic analysis on a set of time series.

Parameters:
  • times (np.ndarray) – Modified Julian Day times, shape (ntimes,).

  • elevations (np.ndarray) – Time series data, shape (npositions, ntimes).

  • latitudes (np.ndarray) – Latitude for each position, shape (npositions,). Positions with a NaN latitude are skipped and left as NaN in the output.

  • predict (bool, optional) – If True, also return a reconstructed predicted time series alongside the harmonics. Defaults to False.

  • constit (tuple, optional) – Tidal constituent names to include in the analysis. Defaults to DEFAULT_CONSTIT.

  • pool_size (int, optional) – Number of worker processes to use. 1 (default) runs a simple serial loop. Values greater than 1 dispatch positions across a multiprocessing.Pool via imap, producing near-linear speedup on multi-core machines. Use multiprocessing.cpu_count() to utilise all available cores. Tasks are yielded lazily so that memory use scales with pool_size, not with npositions — important for long records (hourly or sub-hourly over months).

  • label (str, optional) – If non-empty, a live progress line is printed to stdout showing completed positions, elapsed time, and estimated time remaining. HarmonicsAnalyser sets this automatically when show_progress=True; it can also be set directly when calling analyse_harmonics() standalone. Defaults to '' (no output).

  • **kwargs – Additional keyword arguments forwarded to utide.solve(). The verbose key is also forwarded to utide.reconstruct() when predict is True.

Returns:

  • harmonics (np.ndarray) – Shape (npositions, 2, len(constit)). Index 0 along the second axis is phase (degrees), index 1 is amplitude (m or m/s). Positions with a NaN latitude are left as NaN.

  • predicted (np.ndarray) – Only returned when predict is True. Shape (npositions, ntimes). Positions with a NaN latitude are left as NaN.

Notes

UTide returns constituents in an order that may differ from constit. The output arrays are always re-sorted to match the order given in constit.

pyfvcom2.tide.extend_datetime_array(datetimes: ndarray, extension_length_in_days: float = 1.0) ndarray[source]

Extend a datetime array by a given number of days at both ends.

TODO This was in the original PyFVCOM, although in a different form. Unsure whether it is actually needed for UTide. A simpler approach would be to just add one day at each end, but this might create unevenly spaced time arrays. Would this matter? Need to test it.

Args:

datetimes (np.ndarray): Original array of datetime objects. extension_length_in_days (float): Number of days to extend at both ends.

Returns:

np.ndarray: Extended array of datetime objects.

pyfvcom2.tide.predict_tide(datetimes: ndarray, constituents: list[str], amplitudes: ndarray, phases: ndarray, latitudes: ndarray, parallel: bool = True, pool_size: int | None = None)[source]

Reconstruct tidal variations in zeta, u, v etc at the provided datetimes and latitudes using the provided tidal constituent amplitudes and phases.

Args: datetimes : np.ndarray

Array of datetime objects for prediction times.

intervalfloat

Time interval between datetimes in days.

constituentslist[str]

List of tidal constituent names to read.

amplitudesnp.ndarray

Amplitude of the relevant constituents shaped [nlocs, nconst].

phasesnp.ndarray

Array of the phase of the relevant constituents shaped [nlocs, nconst].

latitudesnp.ndarray

Latitudes of the positions to predict.

parallelbool, optional

Whether to run the predictions in parallel using multiprocessing. Default is True.

pool_sizeint, optional

Number of parallel processes to use. If 1, runs serially. Default is 1.

Returns: results : list[np.ndarray]

List of predicted zeta time series arrays for each location.

pyfvcom2.tide.reconstruct_wrapper(args: tuple) ndarray[source]

For the given time and coefficients (in coef) reconstruct the tidal elevation or current component time series at the given latitude.

Args: args : tuple

Tuple of (lats, times, coef, amplitudes, phases) where: - lats: Latitude of the position to predict. - times: Array of datenums (days since MJD zero point). - coef: UTide coefficients Bunch. - amplitudes: Amplitude of the relevant constituents shaped [nconst]. - phases: Phase of the relevant constituents shaped [nconst].

Returns: zeta : np.ndarray

Time series of surface elevations.

Notes

Uses utide.reconstruct() for the predicted tide. Accepts a single tuple argument for compatibility with multiprocessing.Pool.map.