Source code for act.utils.ship_utils

"""
Module containing utilities for ship data

"""

import dask
import numpy as np
import pyproj
import xarray as xr


[docs]def calc_cog_sog(ds): """ This function calculates the course and speed over ground of a moving platform using the lat/lon. Note,data are resampled to 1 minute in order to provide a better estimate of speed/course compared with 1 second. Function is set up to use dask for the calculations in order to improve efficiency. Data are then resampled to 1 second to match native format. This assumes that the input data are 1 second. See this `example <https://ARM-DOE.github.io/ACT/source/auto_examples/correct_ship_wind_data.html #sphx-glr-source-auto-examples-correct-ship-wind-data-py>`_. Parameters ---------- ds : xarray.Dataset ACT xarray dataset to calculate COG/SOG from. Assumes lat/lon are variables and that it's 1-second data. Returns ------- ds : xarray.Dataset Returns dataset with course_over_ground and speed_over_ground variables. """ # Convert data to 1 minute in order to get proper values new_ds = ds.resample(time='1min').nearest() # Get lat and lon data if 'lat' in new_ds: lat = new_ds['lat'] elif 'latitude' in new_ds: lat = new_ds['latitude'] else: return new_ds if 'lon' in new_ds: lon = new_ds['lon'] elif 'longitude' in new_ds: lon = new_ds['longitude'] else: return new_ds # Set pyproj Geod _GEOD = pyproj.Geod(ellps='WGS84') # Set up delayed tasks for dask task = [] time = new_ds['time'].values for i in range(len(lat) - 1): task.append( dask.delayed(proc_scog)( _GEOD, lon[i + 1], lat[i + 1], lon[i], lat[i], time[i], time[i + 1] ) ) # Compute and process results Adding 2 values # to the end to make up for the missing times results = dask.compute(*task) sog = [r[0] for r in results] sog.append(sog[-1]) sog.append(sog[-1]) cog = [r[1] for r in results] cog.append(cog[-1]) cog.append(cog[-1]) time = np.append(time, time[-1] + np.timedelta64(1, 'm')) atts = {'long_name': 'Speed over ground', 'units': 'm/s'} sog_da = xr.DataArray(sog, coords={'time': time}, dims=['time'], attrs=atts) sog_da = sog_da.resample(time='1s').nearest() atts = {'long_name': 'Course over ground', 'units': 'deg'} cog_da = xr.DataArray(cog, coords={'time': time}, dims=['time'], attrs=atts) cog_da = cog_da.resample(time='1s').nearest() ds['course_over_ground'] = cog_da ds['speed_over_ground'] = sog_da return ds
[docs]def proc_scog(_GEOD, lon2, lat2, lon1, lat1, time1, time2): """ This procedure is to only be used by the calc_cog_sog function for dask delayed processing. """ cog, baz, dist = _GEOD.inv(lon1, lat1, lon2, lat2) tdiff = (time2 - time1) / np.timedelta64(1, 's') sog = dist / tdiff if cog < 0: cog = 360.0 + cog if sog < 0.5: cog = np.nan return sog, cog, dist