API#
Top-level API#
|
Construct a CF-compliant trajectory dataset from a CSV file. |
|
Construct a CF-compliant trajectory dataset from a pd.DataFrame of positions. |
|
Create a CF-compatible trajectory file from dictionary of drifter positions |
Classes#
- class trajan.traj.orthogonal.Orthogonal(ds, trajectory_dim, obs_dim, time_varname)[source]#
A structured dataset, where each trajectory is always given at the same times. Typically the output from a model or from a gridded dataset.
- distance_to(other)[source]#
Distance between trajectories or a single point.
- Parameters:
other (
Dataset) – Other dataset to which distance is calculated- Returns:
Dataset–- Same dimensions as original dataset, containing three DataArrays from pyproj.geod.inv:
distance : distance [meters]
az_fwd : forward azimuth angle [degrees]
az_bwd : backward azimuth angle [degrees]
See also
distance_to_next
- filter(method='speed', max_speed=10.0, nsigma=5.0, side_half_width=2)[source]#
Filter outlier positions from trajectories.
- Parameters:
method (
str) – Outlier detection method:'speed': walk through non-NaN positions in order and compare each to the last accepted position. Any position whose speed from the last accepted position exceeds max_speed [m/s] is masked. Crucially, when a position is masked the “last accepted” pointer is not advanced, so entire consecutive runs of invalid positions (e.g. GPS no-fix sentinel values near (0, 0)) are cleared in a single O(N) pass without falsely masking the valid positions that bracket the bad run.'nsigma_sliding': mask positions whose latitude or longitude deviates more than nsigma standard deviations from the local mean computed over a sliding window of half-width side_half_width. Applied independently to latitude and longitude. Note: this method is designed for isolated single- point spikes; it is less effective for consecutive runs of outliers.
max_speed (
float) – Maximum allowed speed [m/s]. Used withmethod='speed'. Default: 10.nsigma (
float) – Outlier threshold in number of standard deviations. Used withmethod='nsigma_sliding'. Default: 5.side_half_width (
int) – Half-width of the sliding window (number of neighbours on each side). Used withmethod='nsigma_sliding'. Default: 2.
- Returns:
xarray.Dataset– Dataset with outlier lat/lon positions set to NaN. Time and other variables are left unchanged.
See also
speedCalculate the speed along trajectories.
Examples
>>> import xarray as xr >>> import trajan as ta >>> ds = xr.open_dataset(ta.DATA_DIR + 'barents.nc') >>> filtered = ds.traj.filter(method='speed', max_speed=3.) >>> filtered = ds.traj.filter(method='nsigma_sliding', nsigma=5., side_half_width=2)
- gridtime(times, time_varname=None, round=True)[source]#
Interpolate dataset to a regular time interval or a different grid.
- Parameters:
- Returns:
Dataset– A new dataset interpolated to the target times. The dataset will be Orthogonal (i.e. gridded) and the time dimension will be named time.
- is_orthogonal()[source]#
Returns True if dataset is orthogonal, i.e. time is a 1D coordinate variable.
- Returns:
- is_ragged()[source]#
Returns True if dataset is Ragged, i.e. time is a 2D variable and not a coordinate variable.
- Returns:
- iseltime(i)[source]#
Select observations by index (of non-nan, time, observation) across trajectories. For Orthogonal datasets prefer to use xarray.Dataset.isel.
- Parameters:
i (
index,listofindexesora slice.)- Returns:
ds (
Dataset) – A dataset with the selected indexes in each trajectory.
Example
Select the first and last element in each trajectory in a dataset of unstructured observations:
>>> import xarray as xr >>> import trajan as ta >>> ds = xr.open_dataset(ta.DATA_DIR + 'barents.nc') >>> print(ds) <xarray.Dataset> Size: 110kB Dimensions: (trajectory: 2, obs: 2287) Dimensions without coordinates: trajectory, obs Data variables: lon (trajectory, obs) float64 37kB ... lat (trajectory, obs) float64 37kB ... time (trajectory, obs) datetime64[ns] 37kB ... drifter_names (trajectory) <U16 128B ... 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
>>> ds = ds.traj.iseltime([0, -1]) >>> print(ds) <xarray.Dataset> Size: 224B Dimensions: (trajectory: 2, obs: 2) Dimensions without coordinates: trajectory, obs Data variables: lon (trajectory, obs) float64 32B 29.85 25.11 27.82 21.15 lat (trajectory, obs) float64 32B 77.3 76.57 77.11 74.58 time (trajectory, obs) datetime64[ns] 32B 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
- rotary_spectrum()[source]#
Calculate the rotary spectrum for a single trajectory.
Note
This method is not yet fully implemented.
- sel(*args, **kwargs)[source]#
Select on each trajectory. On Orthogonal datasets this is just a shortcut for Dataset.sel.
- Parameters:
Anything accepted by `Dataset.sel`.
- Returns:
ds (
Dataset) – A dataset with the selected range in each trajectory.
- seltime(t0=None, t1=None)[source]#
Select observations in time window between t0 and t1 (inclusive). For Orthogonal datasets prefer to use xarray.Dataset.sel.
- Parameters:
t0, t1 (
numpy.datetime64)- Returns:
ds (
Dataset) – A dataset with the selected indexes in each trajectory.
- skill(expected, method='liu-weissberg', **kwargs)[source]#
Compare the skill score between this trajectory and an expected trajectory.
- Parameters:
- Returns:
skill (
DataArray) – The skill-score in the combined dimensions of both datasets.
Notes
Both datasets must have the same number of trajectories (N:N), or at least one of the datasets (normally the expected) must have a single trajectory only (1:N, N:1, 1:1).
The datasets must be sampled (or have observations) at approximately the same timesteps. Consider using
gridtime()to interpolate one of the datasets to the other.Any additional dimensions will be broadcasted, so that the result include the combined dimensions of both datasets.
Some skillscore methods (e.g. liu-weissberg) are not symmetrical. This specific skillscore is normalized on the length of the expected / observed trajectories. Thus a.traj.skill(b) will provide different numerical results than b.traj.skill(a).
Examples
>>> import xarray as xr >>> import trajan as ta >>> ds = xr.open_dataset(ta.DATA_DIR + 'barents.nc') >>> expected = ds.copy() >>> ds = ds.traj.gridtime('1h') >>> expected = expected.traj.gridtime(ds.time) >>> skill = ds.traj.skill(expected)
>>> skill # Returns 1 since comparing to itself <xarray.DataArray 'Skillscore' (trajectory: 2)> Size: 16B array([1., 1.]) Coordinates: * trajectory (trajectory) int64 16B 0 1 Attributes: method: liu-weissberg
>>> expected = ds.isel(trajectory=0) >>> skill = ds.traj.skill(expected)
>>> skill <xarray.DataArray 'Skillscore' (trajectory: 2)> Size: 16B array([1. , 0.60805799]) Coordinates: * trajectory (trajectory) int64 16B 0 1 Attributes: method: liu-weissberg
- skill_along_trajectory(expected, **kwargs)[source]#
_Skill score is calculated for each trajectory versus the matcing part of the expected (single) trajectory.
- time_to_next()[source]#
Returns the time difference to the next observation.
- Returns:
xarray.DataArray– Scalar timedelta for Orthogonal datasets with fixed timestep, or DataArray of the same shape as the dataset for Ragged datasets. Attributes includeunits: seconds.
See also
distance_to_next,speed
- timestep()[source]#
Calculate the time step between observations.
- Parameters:
average (
callable(), optional) – Function to aggregate multiple time steps (e.g.np.nanmedian). Ignored for Orthogonal datasets where the time step is uniform (TODO: handle variable timestep also for Orthogonal datasets).- Returns:
pd.Timedelta– Time step between observations.
- to_orthogonal()[source]#
Convert dataset into Orthogonal dataset from. This is only possible if the dataset has a single trajectory.
- to_ragged(obs_dim='obs')[source]#
Convert the dataset to a Ragged representation.
- Parameters:
obs_dim (
str, optional) – Name of the observation dimension in the Ragged representation, by default ‘obs’.- Returns:
xarray.Dataset– Dataset with a Ragged representation of trajectories.
- trim()[source]#
Remove empty positions at start and end of trajectory.
- Returns:
xarray.Dataset– Trimmed dataset
- velocity_spectrum()[source]#
Calculate the velocity spectrum for a single trajectory.
- Returns:
xarray.DataArray– Velocity spectrum with dimensions (‘period’) andunits: powerattribute.
- class trajan.traj.ragged.Ragged(ds, trajectory_dim, obs_dim, time_varname)[source]#
A unstructured dataset, where each trajectory may have observations at different times. Typically from a collection of drifters.
- condense_obs(**kwargs)[source]#
Move all observations to the first index, so that the observation dimension is reduced to a minimum. When creating ragged arrays the observations from consecutive trajectories start at the observation index after the previous, causing a very long observation dimension.
Original:
………….. Observations —>
trajectory 1: | t01 | t02 | t03 | t04 | t05 | nan | nan | nan | nan | trajectory 2: | nan | nan | nan | nan | nan | t11 | t12 | t13 | t14 |
After condensing:
………….. Observations —>
trajectory 1: | t01 | t02 | t03 | t04 | t05 | trajectory 2: | t11 | t12 | t13 | t14 | nan |
Returns:
A new Dataset with observations condensed.
- drop_where(condition)[source]#
Remove positions where the condition is True, shifting the rest of the trajectory.
- Parameters:
condition (
xarray.DataArray) – Boolean condition indicating positions to drop.- Returns:
xarray.Dataset– Dataset with positions removed where the condition is True.
- filter(method='speed', **kwargs)[source]#
Filter outlier positions from trajectories.
- Parameters:
method (
str) – Outlier detection method:'speed': walk through non-NaN positions in order and compare each to the last accepted position. Any position whose speed from the last accepted position exceeds max_speed [m/s] is masked. Crucially, when a position is masked the “last accepted” pointer is not advanced, so entire consecutive runs of invalid positions (e.g. GPS no-fix sentinel values near (0, 0)) are cleared in a single O(N) pass without falsely masking the valid positions that bracket the bad run.'nsigma_sliding': mask positions whose latitude or longitude deviates more than nsigma standard deviations from the local mean computed over a sliding window of half-width side_half_width. Applied independently to latitude and longitude. Note: this method is designed for isolated single- point spikes; it is less effective for consecutive runs of outliers.
max_speed (
float) – Maximum allowed speed [m/s]. Used withmethod='speed'. Default: 10.nsigma (
float) – Outlier threshold in number of standard deviations. Used withmethod='nsigma_sliding'. Default: 5.side_half_width (
int) – Half-width of the sliding window (number of neighbours on each side). Used withmethod='nsigma_sliding'. Default: 2.
- Returns:
xarray.Dataset– Dataset with outlier lat/lon positions set to NaN. Time and other variables are left unchanged.
See also
speedCalculate the speed along trajectories.
Examples
>>> import xarray as xr >>> import trajan as ta >>> ds = xr.open_dataset(ta.DATA_DIR + 'barents.nc') >>> filtered = ds.traj.filter(method='speed', max_speed=3.) >>> filtered = ds.traj.filter(method='nsigma_sliding', nsigma=5., side_half_width=2)
- static from_contiguous(ds, trajectory_dim, obs_dim, time_varname, rowvar)[source]#
An unstructured dataset, where each trajectory may have observations at different times, and all the data for the different trajectories are stored in single arrays with one dimension, contiguously, one trajectory after the other. Typically from a collection of drifters.
This method converts ContinousRagged datasets into Ragged datasets.
- static from_ncparticles(ds, obs_dim='obs', time_varname='time', id_varname='id', count_varname='particle_count', data_dim='data')[source]#
An unstructured dataset following the nc_particles standard (https://noaa-orr-erd.github.io/nc_particles/nc_particle_standard.html).
nc_particles files are “ragged by time”: count_varname(time) gives the number of particles present at each time step, and all per-particle data (lat, lon, depth, mass, …) is stored contiguously in a single flattened data_dim array, one time step’s worth of particles after another. id_varname(data) gives the particle ID for each entry, allowing particles created/destroyed during the run to be tracked across time even though they don’t occupy a fixed row/index.
This method inverts that “ragged-by-time” layout into the “ragged-by-trajectory” representation used by trajan, where each row holds the time-ordered observations for a single particle ID.
- gridtime(**kwargs)[source]#
Interpolate dataset to a regular time interval or a different grid.
- Parameters:
- Returns:
Dataset– A new dataset interpolated to the target times. The dataset will be Orthogonal (i.e. gridded) and the time dimension will be named time.
- insert_nan_where(condition)[source]#
Insert NaN values in trajectories after given positions, shifting the rest of the trajectory.
- Parameters:
condition (
xarray.DataArray) – Boolean condition indicating where NaN values should be inserted.- Returns:
xarray.Dataset– Dataset with NaN values inserted at specified positions.
- is_orthogonal()[source]#
Returns True if dataset is orthogonal, i.e. time is a 1D coordinate variable.
- Returns:
- is_ragged()[source]#
Returns True if dataset is Ragged, i.e. time is a 2D variable and not a coordinate variable.
- Returns:
- iseltime(**kwargs)[source]#
Select observations by index (of non-nan, time, observation) across trajectories. For Orthogonal datasets prefer to use xarray.Dataset.isel.
- Parameters:
i (
index,listofindexesora slice.)- Returns:
ds (
Dataset) – A dataset with the selected indexes in each trajectory.
Example
Select the first and last element in each trajectory in a dataset of unstructured observations:
>>> import xarray as xr >>> import trajan as ta >>> ds = xr.open_dataset(ta.DATA_DIR + 'barents.nc') >>> print(ds) <xarray.Dataset> Size: 110kB Dimensions: (trajectory: 2, obs: 2287) Dimensions without coordinates: trajectory, obs Data variables: lon (trajectory, obs) float64 37kB ... lat (trajectory, obs) float64 37kB ... time (trajectory, obs) datetime64[ns] 37kB ... drifter_names (trajectory) <U16 128B ... 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
>>> ds = ds.traj.iseltime([0, -1]) >>> print(ds) <xarray.Dataset> Size: 224B Dimensions: (trajectory: 2, obs: 2) Dimensions without coordinates: trajectory, obs Data variables: lon (trajectory, obs) float64 32B 29.85 25.11 27.82 21.15 lat (trajectory, obs) float64 32B 77.3 76.57 77.11 74.58 time (trajectory, obs) datetime64[ns] 32B 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
- sel(*args, **kwargs)[source]#
Select on each trajectory. On Orthogonal datasets this is just a shortcut for Dataset.sel.
- Parameters:
Anything accepted by `Dataset.sel`.
- Returns:
ds (
Dataset) – A dataset with the selected range in each trajectory.
- seltime(t0=None, t1=None)[source]#
Select observations in time window between t0 and t1 (inclusive). For Orthogonal datasets prefer to use xarray.Dataset.sel.
- Parameters:
t0, t1 (
numpy.datetime64)- Returns:
ds (
Dataset) – A dataset with the selected indexes in each trajectory.
- skill()[source]#
Compare the skill score between this trajectory and an expected trajectory.
- Parameters:
- Returns:
skill (
DataArray) – The skill-score in the combined dimensions of both datasets.
Notes
Both datasets must have the same number of trajectories (N:N), or at least one of the datasets (normally the expected) must have a single trajectory only (1:N, N:1, 1:1).
The datasets must be sampled (or have observations) at approximately the same timesteps. Consider using
gridtime()to interpolate one of the datasets to the other.Any additional dimensions will be broadcasted, so that the result include the combined dimensions of both datasets.
Some skillscore methods (e.g. liu-weissberg) are not symmetrical. This specific skillscore is normalized on the length of the expected / observed trajectories. Thus a.traj.skill(b) will provide different numerical results than b.traj.skill(a).
Examples
>>> import xarray as xr >>> import trajan as ta >>> ds = xr.open_dataset(ta.DATA_DIR + 'barents.nc') >>> expected = ds.copy() >>> ds = ds.traj.gridtime('1h') >>> expected = expected.traj.gridtime(ds.time) >>> skill = ds.traj.skill(expected)
>>> skill # Returns 1 since comparing to itself <xarray.DataArray 'Skillscore' (trajectory: 2)> Size: 16B array([1., 1.]) Coordinates: * trajectory (trajectory) int64 16B 0 1 Attributes: method: liu-weissberg
>>> expected = ds.isel(trajectory=0) >>> skill = ds.traj.skill(expected)
>>> skill <xarray.DataArray 'Skillscore' (trajectory: 2)> Size: 16B array([1. , 0.60805799]) Coordinates: * trajectory (trajectory) int64 16B 0 1 Attributes: method: liu-weissberg
- time_to_next()[source]#
Returns the time difference to the next observation.
- Returns:
xarray.DataArray– Scalar timedelta for Orthogonal datasets with fixed timestep, or DataArray of the same shape as the dataset for Ragged datasets. Attributes includeunits: seconds.
See also
distance_to_next,speed
- timestep(average=<function nanmedian>)[source]#
Calculate the time step between observations.
- Parameters:
average (
callable(), optional) – Function to aggregate multiple time steps (e.g.np.nanmedian). Ignored for Orthogonal datasets where the time step is uniform (TODO: handle variable timestep also for Orthogonal datasets).- Returns:
pd.Timedelta– Time step between observations.
- to_orthogonal()[source]#
Convert dataset into Orthogonal dataset from. This is only possible if the dataset has a single trajectory.
- to_ragged(obs_dim='obs')[source]#
Convert the dataset to a Ragged representation.
- Parameters:
obs_dim (
str, optional) – Name of the observation dimension in the Ragged representation, by default ‘obs’.- Returns:
xarray.Dataset– Dataset with a Ragged representation of trajectories.
Dataset#
Attributes#
See |
|
Return an |
|
Trajectory x coordinates (usually longitude). |
|
Trajectory y coordinates (usually latitude). |
|
Retrieve the trajectories in geographic coordinates (longitudes). |
|
Retrieve the trajectories in geographic coordinates (latitudes). |
|
Retrieve the pyproj.crs.CRS object from the CF-defined grid-mapping in the dataset. |
|
Retrieve a cartopy CRS from the pyproj CRS. |
Methods#
|
Transform this datasets to to_crs coordinate system. |
|
Create a transformer useful for transforming other coordinates to the CRS of this dataset. |
|
Returns a new dataset with the CF-supported grid-mapping / projection set to crs. |
|
Return a new dataset with CF-standard and common attributes set. |
Find the index of the last valid position along each trajectory. |
|
Returns the speed [m/s] along trajectories. |
|
Returns the time difference to the next observation. |
|
|
Distance between trajectories or a single point. |
Returns distance in meters from one position to the next along trajectories. |
|
Returns azimution travel direction in degrees from one position to the next. |
|
Returns distance in meters of each trajectory. |
|
|
Compare the skill score between this trajectory and an expected trajectory. |
Calculate velocity components [m/s] from one position to the next. |
|
Calculate the velocity spectrum for a single trajectory. |
|
|
Return the concave hull for all particles, in geographical coordinates. |
Return the scipy convex hull for all particles, in geographical coordinates. |
|
|
Return True if given point is within the scipy convex hull for all particles. |
Calculate the area [m2] of the convex hull spanned by all positions. |
|
|
Interpolate dataset to a regular time interval or a different grid. |
|
Select on each trajectory. |
|
Select observations in time window between t0 and t1 (inclusive). |
Select observations by index (of non-nan, time, observation) across trajectories. |
|
|
Filter outlier positions from trajectories. |
|
Append trajectories from other dataset to this. |
|
Remove parts of trajectories outside of given geographical bounds. |
|
Return only trajectories fully within given geographical bounds. |
Returns True if dataset is orthogonal, i.e. time is a 1D coordinate variable. |
|
Returns True if dataset is Ragged, i.e. time is a 2D variable and not a coordinate variable. |
|
Convert dataset into Orthogonal dataset from. |
|
Convert dataset into Orthogonal dataset from. |
|
|
Convert the dataset to a Ragged representation. |
Iterate over each trajectory. |
|
Move all observations to the first index, so that the observation dimension is reduced to a minimum. |
|
|
Make a grid that covers all elements of dataset, with given spatial resolution. |
|
Calculate concentration of elements on a provided grid |
Plotting#
|
|
Builder for trajectory animations. |
Animation methods#
|
Color particles by a variable or a fixed matplotlib colour. |
|
Draw full trajectory lines as a static background. |
|
Set the playback speed. |
|
Set the particle marker size. |
|
Control the axes title. |
|
Overlay an animated gridded variable as a background field. |
|
Build the |
Display the animation. |
|
|
Save the animation to a file. |