From 896f6e98d98c737d4587386845effb6bd4b25d07 Mon Sep 17 00:00:00 2001 From: Robbi Bishop-Taylor Date: Mon, 14 Oct 2024 23:31:50 +0000 Subject: [PATCH] Better error handling --- eo_tides/model.py | 163 +++++++++++++++++++++++--------------------- tests/testing.ipynb | 45 ++++++++++-- 2 files changed, 128 insertions(+), 80 deletions(-) diff --git a/eo_tides/model.py b/eo_tides/model.py index 32e27d7..8d0e2b6 100644 --- a/eo_tides/model.py +++ b/eo_tides/model.py @@ -199,88 +199,99 @@ def _model_tides( lat.max() + buffer, ] - # Read tidal constants and interpolate to grid points - if pytmd_model.format in ("OTIS", "ATLAS-compact", "TMD3"): - amp, ph, D, c = pyTMD.io.OTIS.extract_constants( - lon, - lat, - pytmd_model.grid_file, - pytmd_model.model_file, - pytmd_model.projection, - type=pytmd_model.type, - grid=pytmd_model.file_format, - crop=crop, - bounds=bounds, - method=method, - extrapolate=extrapolate, - cutoff=cutoff, - ) + try: + # Read tidal constants and interpolate to grid points + if pytmd_model.format in ("OTIS", "ATLAS-compact", "TMD3"): + amp, ph, D, c = pyTMD.io.OTIS.extract_constants( + lon, + lat, + pytmd_model.grid_file, + pytmd_model.model_file, + pytmd_model.projection, + type=pytmd_model.type, + grid=pytmd_model.file_format, + crop=crop, + bounds=bounds, + method=method, + extrapolate=extrapolate, + cutoff=cutoff, + ) - # Use delta time at 2000.0 to match TMD outputs - deltat = np.zeros((len(timescale)), dtype=np.float64) - - elif pytmd_model.format in ("ATLAS-netcdf",): - amp, ph, D, c = pyTMD.io.ATLAS.extract_constants( - lon, - lat, - pytmd_model.grid_file, - pytmd_model.model_file, - type=pytmd_model.type, - crop=crop, - bounds=bounds, - method=method, - extrapolate=extrapolate, - cutoff=cutoff, - scale=pytmd_model.scale, - compressed=pytmd_model.compressed, - ) + # Use delta time at 2000.0 to match TMD outputs + deltat = np.zeros((len(timescale)), dtype=np.float64) + + elif pytmd_model.format in ("ATLAS-netcdf",): + amp, ph, D, c = pyTMD.io.ATLAS.extract_constants( + lon, + lat, + pytmd_model.grid_file, + pytmd_model.model_file, + type=pytmd_model.type, + crop=crop, + bounds=bounds, + method=method, + extrapolate=extrapolate, + cutoff=cutoff, + scale=pytmd_model.scale, + compressed=pytmd_model.compressed, + ) - # Use delta time at 2000.0 to match TMD outputs - deltat = np.zeros((len(timescale)), dtype=np.float64) - - elif pytmd_model.format in ("GOT-ascii", "GOT-netcdf"): - amp, ph, c = pyTMD.io.GOT.extract_constants( - lon, - lat, - pytmd_model.model_file, - grid=pytmd_model.file_format, - crop=crop, - bounds=bounds, - method=method, - extrapolate=extrapolate, - cutoff=cutoff, - scale=pytmd_model.scale, - compressed=pytmd_model.compressed, - ) + # Use delta time at 2000.0 to match TMD outputs + deltat = np.zeros((len(timescale)), dtype=np.float64) + + elif pytmd_model.format in ("GOT-ascii", "GOT-netcdf"): + amp, ph, c = pyTMD.io.GOT.extract_constants( + lon, + lat, + pytmd_model.model_file, + grid=pytmd_model.file_format, + crop=crop, + bounds=bounds, + method=method, + extrapolate=extrapolate, + cutoff=cutoff, + scale=pytmd_model.scale, + compressed=pytmd_model.compressed, + ) - # Delta time (TT - UT1) - deltat = timescale.tt_ut1 - - elif pytmd_model.format in ("FES-ascii", "FES-netcdf"): - amp, ph = pyTMD.io.FES.extract_constants( - lon, - lat, - pytmd_model.model_file, - type=pytmd_model.type, - version=pytmd_model.version, - crop=crop, - bounds=bounds, - method=method, - extrapolate=extrapolate, - cutoff=cutoff, - scale=pytmd_model.scale, - compressed=pytmd_model.compressed, - ) + # Delta time (TT - UT1) + deltat = timescale.tt_ut1 + + elif pytmd_model.format in ("FES-ascii", "FES-netcdf"): + amp, ph = pyTMD.io.FES.extract_constants( + lon, + lat, + pytmd_model.model_file, + type=pytmd_model.type, + version=pytmd_model.version, + crop=crop, + bounds=bounds, + method=method, + extrapolate=extrapolate, + cutoff=cutoff, + scale=pytmd_model.scale, + compressed=pytmd_model.compressed, + ) - # Available model constituents - c = pytmd_model.constituents + # Available model constituents + c = pytmd_model.constituents - # Delta time (TT - UT1) - deltat = timescale.tt_ut1 - else: - raise Exception( - f"Unsupported model format ({pytmd_model.format}). This may be due to an incompatible version of `pyTMD`." + # Delta time (TT - UT1) + deltat = timescale.tt_ut1 + else: + raise Exception( + f"Unsupported model format ({pytmd_model.format}). This may be due to an incompatible version of `pyTMD`." + ) + + # Raise error if constituent files no not cover analysis extent + except IndexError: + error_msg = ( + f"The {model} tide model constituent files do not cover the requested analysis extent. " + "This can occur if you are using clipped model files to improve run times. " + "Consider using model files that cover your analysis area, or set `crop=False` " + "to reduce the extent of tide model constituent files that is loaded." ) + raise Exception(error_msg) # Calculate complex phase in radians for Euler's cph = -1j * ph * np.pi / 180.0 diff --git a/tests/testing.ipynb b/tests/testing.ipynb index 78a2809..7ccf8da 100644 --- a/tests/testing.ipynb +++ b/tests/testing.ipynb @@ -2,14 +2,16 @@ "cells": [ { "cell_type": "code", - "execution_count": 11, + "execution_count": 1, "metadata": {}, "outputs": [], "source": [ + "%load_ext autoreload\n", + "%autoreload 2\n", + "\n", "import odc.stac\n", "import pandas as pd\n", "import pystac_client\n", - "import pytest\n", "\n", "from pyTMD.compute import tide_elevations\n", "import pandas as pd\n", @@ -30,7 +32,7 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": 2, "metadata": {}, "outputs": [], "source": [ @@ -171,6 +173,41 @@ "\n", "np.allclose(modelled_tides_df.tide_height.values, pytmd_tides.data)" ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Error for out of bounds" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [], + "source": [ + "from eo_tides import model_tides\n", + "\n", + "x, y = 180, -50\n", + "\n", + "\n", + "# Run EOT20 tidal model for locations and timesteps in tide gauge data\n", + "modelled_tides_df = model_tides(\n", + " x=[x],\n", + " y=[y],\n", + " model=[\"EOT20\", \"GOT5.5\"],\n", + " time=measured_tides_ds.time,\n", + " directory=\"../tests/data/tide_models\",\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] } ], "metadata": { @@ -189,7 +226,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.11.10" + "version": "3.12.0" } }, "nbformat": 4,