Note
Go to the end to download the full example code.
Analysing a drifter dataset
import numpy as np
import lzma
import matplotlib.pyplot as plt
import cartopy.crs as ccrs
import xarray as xr
import trajan as ta
Importing a dataset with two drifters in the Barents Sea
2024-09-02 11:27:37 fv-az1272-597 h5py._conv[3440] DEBUG Creating converter from 3 to 5
This follows the CF convention for trajectories https://cfconventions.org/Data/cf-conventions/cf-conventions-1.10/cf-conventions.html#_multidimensional_array_representation_of_trajectories
print(ds)
<xarray.Dataset> Size: 110kB
Dimensions: (trajectory: 2, obs: 2287)
Dimensions without coordinates: trajectory, obs
Data variables:
lon (trajectory, obs) float64 37kB 29.85 29.83 ... 21.14 21.15
lat (trajectory, obs) float64 37kB 77.3 77.31 ... 74.58 74.58
time (trajectory, obs) datetime64[ns] 37kB 2022-10-07T00:00:38 ...
drifter_names (trajectory) <U16 128B 'UIB-2022-TILL-01' 'UIB-2022-TILL-02'
Attributes: (12/13)
Conventions: CF-1.10
featureType: trajectory
geospatial_lat_min: 74.5454462
geospatial_lat_max: 77.4774768
geospatial_lon_min: 17.2058074
geospatial_lon_max: 29.8523485
... ...
time_coverage_end: 2022-11-23T13:30:28
creator_email: gauteh@met.no, knutfd@met.no
creator_name: Gaute Hope and Knut Frode Dagestad
creator_url: https://github.com/OpenDrift/opendrift
summary: Two drifters in the Barents Sea. One stranded at Ho...
title: Barents Sea drifters
A basic plot can be made very simply with Trajan
ds.traj.plot()
plt.show()
![example drifters](../_images/sphx_glr_example_drifters_001.png)
2024-09-02 11:27:37 fv-az1272-597 trajan.trajectory_accessor[3440] DEBUG Detecting time-dimension for "obs"..
2024-09-02 11:27:37 fv-az1272-597 trajan.trajectory_accessor[3440] DEBUG Detected obs-dim: obs, detected time-dim: time.
2024-09-02 11:27:37 fv-az1272-597 trajan.trajectory_accessor[3440] DEBUG Detected un-structured (2D) trajectory dataset
2024-09-02 11:27:37 fv-az1272-597 trajan.trajectory_accessor[3440] DEBUG Setting up new plot object.
2024-09-02 11:27:37 fv-az1272-597 trajan.plot[3440] DEBUG Plotting lines
2024-09-02 11:27:37 fv-az1272-597 trajan.traj[3440] DEBUG No grid-mapping specified, checking if coordinates are lon/lat..
2024-09-02 11:27:37 fv-az1272-597 trajan.plot[3440] DEBUG Creating new figure and axes..
2024-09-02 11:27:37 fv-az1272-597 trajan.traj[3440] DEBUG No grid-mapping specified, checking if coordinates are lon/lat..
2024-09-02 11:27:37 fv-az1272-597 trajan.traj[3440] DEBUG No grid-mapping specified, checking if coordinates are lon/lat..
2024-09-02 11:27:37 fv-az1272-597 trajan.traj[3440] DEBUG No grid-mapping specified, checking if coordinates are lon/lat..
2024-09-02 11:27:37 fv-az1272-597 trajan.traj[3440] DEBUG No grid-mapping specified, checking if coordinates are lon/lat..
/home/runner/micromamba-root/envs/trajan/lib/python3.10/site-packages/shapely/creation.py:119: RuntimeWarning: invalid value encountered in linestrings
return lib.linestrings(coords, out=out, **kwargs)
The figure can be customized, combining functionality from Trajan, Xarray and Matplotlib
ds.isel(trajectory=1).traj.plot(color='b', label=ds.trajectory[1].values,
land='mask', margin=3)
ds.isel(trajectory=0).traj.plot(color='r', label=ds.trajectory[0].values)
plt.legend()
plt.title('Two drifters in the Barents Sea')
plt.show()
![Two drifters in the Barents Sea](../_images/sphx_glr_example_drifters_002.png)
2024-09-02 11:27:39 fv-az1272-597 trajan.trajectory_accessor[3440] DEBUG Detecting time-dimension for "obs"..
2024-09-02 11:27:39 fv-az1272-597 trajan.trajectory_accessor[3440] DEBUG Detected obs-dim: obs, detected time-dim: time.
2024-09-02 11:27:39 fv-az1272-597 trajan.trajectory_accessor[3440] DEBUG Detected un-structured (2D) trajectory dataset
2024-09-02 11:27:39 fv-az1272-597 trajan.trajectory_accessor[3440] DEBUG Setting up new plot object.
2024-09-02 11:27:39 fv-az1272-597 trajan.plot[3440] DEBUG Plotting lines
2024-09-02 11:27:39 fv-az1272-597 trajan.trajectory_accessor[3440] DEBUG Detecting time-dimension for "obs"..
2024-09-02 11:27:39 fv-az1272-597 trajan.trajectory_accessor[3440] DEBUG Detected obs-dim: obs, detected time-dim: time.
2024-09-02 11:27:39 fv-az1272-597 trajan.trajectory_accessor[3440] DEBUG Detected un-structured (2D) trajectory dataset
2024-09-02 11:27:39 fv-az1272-597 trajan.traj[3440] DEBUG No grid-mapping specified, checking if coordinates are lon/lat..
2024-09-02 11:27:39 fv-az1272-597 trajan.plot[3440] DEBUG Creating new figure and axes..
2024-09-02 11:27:40 fv-az1272-597 trajan.traj[3440] DEBUG No grid-mapping specified, checking if coordinates are lon/lat..
2024-09-02 11:27:40 fv-az1272-597 trajan.traj[3440] DEBUG No grid-mapping specified, checking if coordinates are lon/lat..
2024-09-02 11:27:40 fv-az1272-597 trajan.traj[3440] DEBUG No grid-mapping specified, checking if coordinates are lon/lat..
2024-09-02 11:27:40 fv-az1272-597 trajan.traj[3440] DEBUG No grid-mapping specified, checking if coordinates are lon/lat..
2024-09-02 11:27:40 fv-az1272-597 trajan.trajectory_accessor[3440] DEBUG Detecting time-dimension for "obs"..
2024-09-02 11:27:40 fv-az1272-597 trajan.trajectory_accessor[3440] DEBUG Detected obs-dim: obs, detected time-dim: time.
2024-09-02 11:27:40 fv-az1272-597 trajan.trajectory_accessor[3440] DEBUG Detected un-structured (2D) trajectory dataset
2024-09-02 11:27:40 fv-az1272-597 trajan.trajectory_accessor[3440] DEBUG Setting up new plot object.
2024-09-02 11:27:40 fv-az1272-597 trajan.plot[3440] DEBUG Plotting lines
2024-09-02 11:27:40 fv-az1272-597 trajan.trajectory_accessor[3440] DEBUG Detecting time-dimension for "obs"..
2024-09-02 11:27:40 fv-az1272-597 trajan.trajectory_accessor[3440] DEBUG Detected obs-dim: obs, detected time-dim: time.
2024-09-02 11:27:40 fv-az1272-597 trajan.trajectory_accessor[3440] DEBUG Detected un-structured (2D) trajectory dataset
2024-09-02 11:27:40 fv-az1272-597 trajan.traj[3440] DEBUG No grid-mapping specified, checking if coordinates are lon/lat..
2024-09-02 11:27:40 fv-az1272-597 trajan.plot[3440] DEBUG Axes already exist on existing figure.
2024-09-02 11:27:40 fv-az1272-597 trajan.traj[3440] DEBUG No grid-mapping specified, checking if coordinates are lon/lat..
2024-09-02 11:27:40 fv-az1272-597 trajan.traj[3440] DEBUG No grid-mapping specified, checking if coordinates are lon/lat..
2024-09-02 11:27:40 fv-az1272-597 trajan.traj[3440] DEBUG No grid-mapping specified, checking if coordinates are lon/lat..
2024-09-02 11:27:40 fv-az1272-597 trajan.traj[3440] DEBUG No grid-mapping specified, checking if coordinates are lon/lat..
/home/runner/micromamba-root/envs/trajan/lib/python3.10/site-packages/shapely/creation.py:119: RuntimeWarning: invalid value encountered in linestrings
return lib.linestrings(coords, out=out, **kwargs)
Trajan includes methods to e.g. calculate the speed of the drifters
speed = ds.traj.speed()
print(f'Max speed {speed.max().values} m/s')
Max speed 1008.360274201437 m/s
We see that the max speed > 1000 m/s, which is a numerical error due to some cases with GPS positions reported with very small time interval. By removing all positions where time interval < 5 min, we avoid this problem.
ds = ds.traj.drop_where(ds.traj.time_to_next() < np.timedelta64(5, 'm'))
speed = ds.traj.speed()
print(f'Max speed {speed.max().values} m/s')
2024-09-02 11:27:40 fv-az1272-597 trajan.trajectory_accessor[3440] DEBUG Detecting time-dimension for "obs"..
2024-09-02 11:27:40 fv-az1272-597 trajan.trajectory_accessor[3440] DEBUG Detected obs-dim: obs, detected time-dim: time.
2024-09-02 11:27:40 fv-az1272-597 trajan.trajectory_accessor[3440] DEBUG Detected un-structured (2D) trajectory dataset
Max speed 1.2873047098224348 m/s
Likewise, one can insert breaks (NaN) in the trajectories whenever the time between points exceed a desired threshold, e.g. 3 hours
ds = ds.traj.insert_nan_where(ds.traj.time_to_next()>np.timedelta64(3, 'h'))
Plotting trajectories colored by drifter speed
mappable = ds.traj.plot(color=speed)
cb = plt.gcf().colorbar(mappable,
orientation='horizontal', pad=.05, aspect=30, shrink=.8, drawedges=False)
cb.set_label('Speed [m/s]')
plt.title('Trajectories colored by drift speed')
plt.show()
![Trajectories colored by drift speed](../_images/sphx_glr_example_drifters_003.png)
2024-09-02 11:27:40 fv-az1272-597 trajan.trajectory_accessor[3440] DEBUG Detecting time-dimension for "obs"..
2024-09-02 11:27:40 fv-az1272-597 trajan.trajectory_accessor[3440] DEBUG Detected obs-dim: obs, detected time-dim: time.
2024-09-02 11:27:40 fv-az1272-597 trajan.trajectory_accessor[3440] DEBUG Detected un-structured (2D) trajectory dataset
2024-09-02 11:27:40 fv-az1272-597 trajan.trajectory_accessor[3440] DEBUG Setting up new plot object.
2024-09-02 11:27:40 fv-az1272-597 trajan.plot[3440] DEBUG Plotting lines
2024-09-02 11:27:40 fv-az1272-597 trajan.traj[3440] DEBUG No grid-mapping specified, checking if coordinates are lon/lat..
2024-09-02 11:27:40 fv-az1272-597 trajan.plot[3440] DEBUG Creating new figure and axes..
2024-09-02 11:27:40 fv-az1272-597 trajan.traj[3440] DEBUG No grid-mapping specified, checking if coordinates are lon/lat..
2024-09-02 11:27:40 fv-az1272-597 trajan.traj[3440] DEBUG No grid-mapping specified, checking if coordinates are lon/lat..
2024-09-02 11:27:40 fv-az1272-597 trajan.traj[3440] DEBUG No grid-mapping specified, checking if coordinates are lon/lat..
2024-09-02 11:27:40 fv-az1272-597 trajan.plot[3440] DEBUG Plotting trajectory 0 of 2 with color
2024-09-02 11:27:40 fv-az1272-597 trajan.traj[3440] DEBUG No grid-mapping specified, checking if coordinates are lon/lat..
/home/runner/micromamba-root/envs/trajan/lib/python3.10/site-packages/shapely/creation.py:119: RuntimeWarning: invalid value encountered in linestrings
return lib.linestrings(coords, out=out, **kwargs)
2024-09-02 11:27:41 fv-az1272-597 trajan.plot[3440] DEBUG Plotting trajectory 1 of 2 with color
2024-09-02 11:27:41 fv-az1272-597 trajan.traj[3440] DEBUG No grid-mapping specified, checking if coordinates are lon/lat..
2024-09-02 11:27:42 fv-az1272-597 matplotlib.colorbar[3440] DEBUG locator: <matplotlib.ticker.AutoLocator object at 0x7f80873f8b50>
Histogram of drifter speeds.
speed = ds.traj.speed()
plt.hist(speed.values[~np.isnan(speed.values)], 100)
plt.xlabel('Drifter speed [m/s]')
plt.ylabel('Number')
plt.show()
![example drifters](../_images/sphx_glr_example_drifters_004.png)
The peak at speed=0m/s is from the period where one of the drifters are on land (Hopen island). This can be removed simply:
speed = speed.where(speed>0.01)
plt.hist(speed.values[~np.isnan(speed.values)], 100)
plt.xlabel('Drifter speed [m/s]')
plt.ylabel('Number')
plt.show()
![example drifters](../_images/sphx_glr_example_drifters_005.png)
The positions of GPS based drifters are normally given at slightly irregular time intervals, as drifters may be without GPS coverage for periods, and may get GPX fixes irregularly. TrajAn contains the method gridtime to interpolate positions to a regular time intervel, e.g. hourly:
dh = ds.traj.gridtime('1h')
ds.traj.plot(color='r', label='raw data', land='mask')
dh.traj.plot(color='b', label='hourly')
plt.gca().set_extent([23.8, 25.0, 76.8, 77], crs=ccrs.PlateCarree()) # Zooming in to highliht differences
plt.legend()
plt.show()
![example drifters](../_images/sphx_glr_example_drifters_006.png)
2024-09-02 11:27:44 fv-az1272-597 trajan.plot[3440] DEBUG Plotting lines
2024-09-02 11:27:44 fv-az1272-597 trajan.traj[3440] DEBUG No grid-mapping specified, checking if coordinates are lon/lat..
2024-09-02 11:27:44 fv-az1272-597 trajan.plot[3440] DEBUG Creating new figure and axes..
2024-09-02 11:27:44 fv-az1272-597 trajan.traj[3440] DEBUG No grid-mapping specified, checking if coordinates are lon/lat..
2024-09-02 11:27:44 fv-az1272-597 trajan.traj[3440] DEBUG No grid-mapping specified, checking if coordinates are lon/lat..
2024-09-02 11:27:44 fv-az1272-597 trajan.traj[3440] DEBUG No grid-mapping specified, checking if coordinates are lon/lat..
2024-09-02 11:27:44 fv-az1272-597 trajan.traj[3440] DEBUG No grid-mapping specified, checking if coordinates are lon/lat..
/home/runner/micromamba-root/envs/trajan/lib/python3.10/site-packages/shapely/creation.py:119: RuntimeWarning: invalid value encountered in linestrings
return lib.linestrings(coords, out=out, **kwargs)
/home/runner/micromamba-root/envs/trajan/lib/python3.10/site-packages/shapely/creation.py:119: RuntimeWarning: invalid value encountered in linestrings
return lib.linestrings(coords, out=out, **kwargs)
2024-09-02 11:27:44 fv-az1272-597 trajan.trajectory_accessor[3440] DEBUG Detected obs-dim: time, detected time-dim: time.
2024-09-02 11:27:44 fv-az1272-597 trajan.trajectory_accessor[3440] DEBUG Detected structured (1D) trajectory dataset
2024-09-02 11:27:44 fv-az1272-597 trajan.trajectory_accessor[3440] DEBUG Setting up new plot object.
2024-09-02 11:27:44 fv-az1272-597 trajan.plot[3440] DEBUG Plotting lines
2024-09-02 11:27:44 fv-az1272-597 trajan.traj[3440] DEBUG No grid-mapping specified, checking if coordinates are lon/lat..
2024-09-02 11:27:44 fv-az1272-597 trajan.plot[3440] DEBUG Axes already exist on existing figure.
2024-09-02 11:27:44 fv-az1272-597 trajan.traj[3440] DEBUG No grid-mapping specified, checking if coordinates are lon/lat..
2024-09-02 11:27:44 fv-az1272-597 trajan.traj[3440] DEBUG No grid-mapping specified, checking if coordinates are lon/lat..
2024-09-02 11:27:44 fv-az1272-597 trajan.traj[3440] DEBUG No grid-mapping specified, checking if coordinates are lon/lat..
2024-09-02 11:27:44 fv-az1272-597 trajan.traj[3440] DEBUG No grid-mapping specified, checking if coordinates are lon/lat..
/home/runner/micromamba-root/envs/trajan/lib/python3.10/site-packages/shapely/creation.py:119: RuntimeWarning: invalid value encountered in linestrings
return lib.linestrings(coords, out=out, **kwargs)
/home/runner/micromamba-root/envs/trajan/lib/python3.10/site-packages/shapely/creation.py:119: RuntimeWarning: invalid value encountered in linestrings
return lib.linestrings(coords, out=out, **kwargs)
Having the dataset on a regular time interval makes it simpler to compare with e.g. drift models, and also makes some analyses simpler
dh.isel(trajectory=0).traj.plot(color='r', label='Full trajectory')
dh.isel(trajectory=0).sel(time=slice('2022-10-10', '2022-10-12')).traj.plot(
color='k', linewidth=2, label='10-12 Oct 2022')
plt.legend()
plt.show()
![example drifters](../_images/sphx_glr_example_drifters_007.png)
2024-09-02 11:27:45 fv-az1272-597 trajan.trajectory_accessor[3440] DEBUG Detected obs-dim: time, detected time-dim: time.
2024-09-02 11:27:45 fv-az1272-597 trajan.trajectory_accessor[3440] DEBUG Detected structured (1D) trajectory dataset
2024-09-02 11:27:45 fv-az1272-597 trajan.trajectory_accessor[3440] DEBUG Setting up new plot object.
2024-09-02 11:27:45 fv-az1272-597 trajan.plot[3440] DEBUG Plotting lines
2024-09-02 11:27:45 fv-az1272-597 trajan.trajectory_accessor[3440] DEBUG Detected obs-dim: time, detected time-dim: time.
2024-09-02 11:27:45 fv-az1272-597 trajan.trajectory_accessor[3440] DEBUG Detected structured (1D) trajectory dataset
2024-09-02 11:27:45 fv-az1272-597 trajan.traj[3440] DEBUG No grid-mapping specified, checking if coordinates are lon/lat..
2024-09-02 11:27:45 fv-az1272-597 trajan.plot[3440] DEBUG Creating new figure and axes..
2024-09-02 11:27:45 fv-az1272-597 trajan.traj[3440] DEBUG No grid-mapping specified, checking if coordinates are lon/lat..
2024-09-02 11:27:45 fv-az1272-597 trajan.traj[3440] DEBUG No grid-mapping specified, checking if coordinates are lon/lat..
2024-09-02 11:27:45 fv-az1272-597 trajan.traj[3440] DEBUG No grid-mapping specified, checking if coordinates are lon/lat..
2024-09-02 11:27:45 fv-az1272-597 trajan.traj[3440] DEBUG No grid-mapping specified, checking if coordinates are lon/lat..
/home/runner/micromamba-root/envs/trajan/lib/python3.10/site-packages/shapely/creation.py:119: RuntimeWarning: invalid value encountered in linestrings
return lib.linestrings(coords, out=out, **kwargs)
2024-09-02 11:27:45 fv-az1272-597 trajan.trajectory_accessor[3440] DEBUG Detected obs-dim: time, detected time-dim: time.
2024-09-02 11:27:45 fv-az1272-597 trajan.trajectory_accessor[3440] DEBUG Detected structured (1D) trajectory dataset
2024-09-02 11:27:45 fv-az1272-597 trajan.trajectory_accessor[3440] DEBUG Setting up new plot object.
2024-09-02 11:27:45 fv-az1272-597 trajan.plot[3440] DEBUG Plotting lines
2024-09-02 11:27:45 fv-az1272-597 trajan.trajectory_accessor[3440] DEBUG Detected obs-dim: time, detected time-dim: time.
2024-09-02 11:27:45 fv-az1272-597 trajan.trajectory_accessor[3440] DEBUG Detected structured (1D) trajectory dataset
2024-09-02 11:27:45 fv-az1272-597 trajan.traj[3440] DEBUG No grid-mapping specified, checking if coordinates are lon/lat..
2024-09-02 11:27:45 fv-az1272-597 trajan.plot[3440] DEBUG Axes already exist on existing figure.
2024-09-02 11:27:45 fv-az1272-597 trajan.traj[3440] DEBUG No grid-mapping specified, checking if coordinates are lon/lat..
2024-09-02 11:27:45 fv-az1272-597 trajan.traj[3440] DEBUG No grid-mapping specified, checking if coordinates are lon/lat..
2024-09-02 11:27:45 fv-az1272-597 trajan.traj[3440] DEBUG No grid-mapping specified, checking if coordinates are lon/lat..
2024-09-02 11:27:45 fv-az1272-597 trajan.traj[3440] DEBUG No grid-mapping specified, checking if coordinates are lon/lat..
The original dataset had two dimensions (trajectory, obs) (see top of page), and time is a 2D variable. For the gridded dataset (as with datasets imported from some trajectory models), dimensions are (trajectory, time) and time is a 1D Xarray dimension coordinate
print(dh)
<xarray.Dataset> Size: 46kB
Dimensions: (trajectory: 2, time: 1142)
Coordinates:
* time (time) datetime64[ns] 9kB 2022-10-07 ... 2022-11-23T13:00:00
* trajectory (trajectory) int64 16B 0 1
Data variables:
lon (trajectory, time) float64 18kB nan 29.82 29.77 ... 21.13 nan
lat (trajectory, time) float64 18kB nan 77.31 77.31 ... 74.58 nan
drifter_names (trajectory) <U16 128B 'UIB-2022-TILL-01' 'UIB-2022-TILL-02'
Attributes: (12/13)
Conventions: CF-1.10
featureType: trajectory
geospatial_lat_min: 74.5454462
geospatial_lat_max: 77.4774768
geospatial_lon_min: 17.2058074
geospatial_lon_max: 29.8523485
... ...
time_coverage_end: 2022-11-23T13:30:28
creator_email: gauteh@met.no, knutfd@met.no
creator_name: Gaute Hope and Knut Frode Dagestad
creator_url: https://github.com/OpenDrift/opendrift
summary: Two drifters in the Barents Sea. One stranded at Ho...
title: Barents Sea drifters
Plotting the velocity spectrum for one drifter
dh.isel(trajectory=1).traj.velocity_spectrum().plot()
plt.xlim([0, 30])
plt.show()
![example drifters](../_images/sphx_glr_example_drifters_008.png)
2024-09-02 11:27:47 fv-az1272-597 trajan.trajectory_accessor[3440] DEBUG Detected obs-dim: time, detected time-dim: time.
2024-09-02 11:27:47 fv-az1272-597 trajan.trajectory_accessor[3440] DEBUG Detected structured (1D) trajectory dataset
/home/runner/work/trajan/trajan/trajan/traj.py:359: FutureWarning: The return type of `Dataset.dims` will be changed to return a set of dimension names in future, in order to be more consistent with `DataArray.dims`. To access a mapping from dimension names to lengths, please use `Dataset.sizes`.
lenobs = self.ds.dims[self.obsdim]
Do a basic animation of the drift of the drifters
ds.traj.animate()
plt.show()
![example drifters](../_images/sphx_glr_example_drifters_009.png)
2024-09-02 11:27:47 fv-az1272-597 trajan.trajectory_accessor[3440] DEBUG Setting up new animation object.
2024-09-02 11:27:47 fv-az1272-597 trajan.animation[3440] DEBUG Animating trajectories..
2024-09-02 11:27:47 fv-az1272-597 trajan.traj[3440] DEBUG No grid-mapping specified, checking if coordinates are lon/lat..
2024-09-02 11:27:47 fv-az1272-597 trajan.plot[3440] DEBUG Creating new figure and axes..
2024-09-02 11:27:47 fv-az1272-597 trajan.animation[3440] DEBUG Running animation.. frames: 1142
Total running time of the script: (0 minutes 10.566 seconds)