pycontrails.Fleet

class pycontrails.Fleet(data=None, *, longitude=None, latitude=None, altitude=None, altitude_ft=None, level=None, time=None, attrs=None, copy=True, fuel=None, fl_attrs=None, **attrs_kwargs)

Bases: Flight

Data structure for holding a sequence of Flight instances.

Flight waypoints are merged into a single Flight-like object.

__init__(data=None, *, longitude=None, latitude=None, altitude=None, altitude_ft=None, level=None, time=None, attrs=None, copy=True, fuel=None, fl_attrs=None, **attrs_kwargs)

Methods

T_isa()

Calculate the ICAO standard atmosphere temperature at each point.

__init__([data, longitude, latitude, ...])

broadcast_attrs(keys[, overwrite, raise_error])

Attach values from keys in attrs onto data.

broadcast_numeric_attrs([ignore_keys, overwrite])

Attach numeric values in attrs onto data.

clean_and_resample([freq, fill_method, ...])

Resample and (possibly) filter a flight trajectory.

coords_intersect_met(met)

Return boolean mask of data inside the bounding box defined by met.

copy(**kwargs)

Return a copy of this instance.

create_empty([keys, attrs])

Create instance with variables defined by keys and size 0.

distance_to_coords(distance)

Convert distance along flight path to geodesic coordinates.

downselect_met(met, *[, longitude_buffer, ...])

Downselect met to encompass a spatiotemporal region of the data.

ensure_vars(vars[, raise_error])

Ensure variables exist in column of data or attrs.

filter(mask[, copy])

Filter data according to a boolean array mask.

filter_altitude([kernel_size, cruise_threshold])

Filter noisy altitude on a single flight.

filter_by_first()

Keep first row of group of waypoints with identical coordinates.

from_dict(obj[, copy])

Create instance from dict representation containing data and attrs.

from_seq(seq[, broadcast_numeric, attrs])

Instantiate a Fleet instance from an iterable of Flight.

generate_splits(n_splits[, copy])

Split instance into n_split sub-vectors.

get(key[, default_value])

Get values from data with default_value if key not in data.

get_data_or_attr(key[, default])

Get value from data or attrs.

intersect_met(mda, *[, longitude, latitude, ...])

Intersect waypoints with MetDataArray.

length_met(key[, threshold])

Calculate total horizontal distance where column key exceeds threshold.

plot(**kwargs)

Plot flight trajectory longitude-latitude values.

plot_profile(**kwargs)

Plot flight trajectory time-altitude values.

proportion_met(key[, threshold])

Calculate proportion of flight with certain meteorological constraint.

resample_and_fill(*args, **kwargs)

Resample and fill flight trajectory with geodesics and linear interpolation.

segment_angle()

Calculate sine and cosine for the angle between each segment and the longitudinal axis.

segment_azimuth()

Calculate (forward) azimuth at each waypoint.

segment_duration([dtype])

Compute time elapsed between waypoints in seconds.

segment_groundspeed(*args, **kwargs)

Return groundspeed across segments.

segment_haversine()

Compute Haversine (great circle) distance between flight waypoints.

segment_length()

Compute spherical distance between flight waypoints.

segment_mach_number(true_airspeed, ...)

Calculate the mach number of each segment.

segment_phase([threshold_rocd, ...])

Identify the phase of flight (climb, cruise, descent) for each segment.

segment_rocd([air_temperature])

Calculate the rate of climb and descent (ROCD).

segment_true_airspeed([u_wind, v_wind, ...])

Calculate the true airspeed [\(m / s\)] from the ground speed and horizontal winds.

select(keys[, copy])

Return new class instance only containing specified keys.

setdefault(key[, default])

Shortcut to VectorDataDict.setdefault().

sort(by)

Sort data by key(s).

sum(vectors[, infer_attrs, fill_value])

Sum a list of VectorDataset instances.

to_dataframe([copy])

Create pd.DataFrame in which each key-value pair in data is a column.

to_dict()

Create dictionary with data and attrs.

to_flight_list([copy])

De-concatenate merged waypoints into a list of Flight instances.

to_geojson_linestring()

Return trajectory as geojson FeatureCollection containing single LineString.

to_geojson_multilinestring([key, ...])

Return trajectory as GeoJSON FeatureCollection of MultiLineStrings.

to_geojson_points()

Return dataset as GeoJSON FeatureCollection of Points.

to_lon_lat_grid(agg, *[, spatial_bbox, ...])

Convert vectors to a longitude-latitude grid.

to_traffic()

Convert to :class:`traffic.core.Flight`instance.

transform_crs(crs)

Transform trajectory data from one coordinate reference system (CRS) to another.

update([other])

Update values in data dict without warning if overwriting.

Attributes

final_waypoints

fl_attrs

air_pressure

Get air_pressure values for points.

altitude

Get altitude.

altitude_ft

Get altitude in feet.

attrs

Generic dataset attributes

constants

Return a dictionary of constant attributes and data values.

coords

Get geospatial coordinates for compatibility with MetDataArray.

data

Vector data with labels as keys and numpy.ndarray as values

dataframe

Shorthand property to access to_dataframe() with copy=False.

duration

Determine flight duration.

fuel

Fuel used in flight trajectory

hash

Generate a unique hash for this class instance.

length

Return flight length based on WGS84 geodesic.

level

Get pressure level values for points.

max_distance_gap

Return maximum distance gap between waypoints along flight trajectory.

max_time_gap

Return maximum time gap between waypoints along flight trajectory.

n_flights

Return number of distinct flights.

required_keys

Required keys for creating GeoVectorDataset

shape

Shape of each array in data.

size

Length of each array in data.

time_end

Last waypoint time.

time_start

First waypoint time.

vertical_keys

At least one of these vertical-coordinate keys must also be included

T_isa()

Calculate the ICAO standard atmosphere temperature at each point.

Returns:

npt.NDArray[np.floating] – ISA temperature, [\(K\)]

property air_pressure

Get air_pressure values for points.

Returns:

npt.NDArray[np.floating] – Point air pressure values, [\(Pa\)]

property altitude

Get altitude.

Automatically calculates altitude using units.pl_to_m() using level key.

Note that if altitude key exists in data, the data at the altitude key will be returned. This allows an override of the default calculation of altitude from pressure level.

Returns:

npt.NDArray[np.floating] – Altitude, [\(m\)]

property altitude_ft

Get altitude in feet.

Returns:

npt.NDArray[np.floating] – Altitude, [\(ft\)]

attrs

Generic dataset attributes

broadcast_attrs(keys, overwrite=False, raise_error=True)

Attach values from keys in attrs onto data.

If possible, use dtype = np.float32 when broadcasting. If not possible, use whatever dtype is inferred from the data by numpy.full().

Parameters:
  • keys (str | Iterable[str]) – Keys to broadcast

  • overwrite (bool, optional) – If True, overwrite existing values in data. By default False.

  • raise_error (bool, optional) – Raise KeyError if self.attrs does not contain some of keys.

Raises:

KeyError – Not all keys found in attrs.

broadcast_numeric_attrs(ignore_keys=None, overwrite=False)

Attach numeric values in attrs onto data.

Iterate through values in attrs and attach float and int values to data.

This method modifies object in place.

Parameters:
  • ignore_keys (str | Iterable[str], optional) – Do not broadcast selected keys. Defaults to None.

  • overwrite (bool, optional) – If True, overwrite existing values in data. By default False.

clean_and_resample(freq='1min', fill_method='geodesic', geodesic_threshold=100000.0, nominal_rocd=0.0, kernel_size=17, cruise_threshold=120, force_filter=False, drop=True, keep_original_index=False)

Resample and (possibly) filter a flight trajectory.

Waypoints are resampled according to the frequency freq. If the original flight data has a short sampling period, filter_altitude will also be called to clean the data. Large gaps in trajectories may be interpolated as step climbs through _altitude_interpolation.

Parameters:
  • freq (str, optional) – Resampling frequency, by default “1min”

  • fill_method ({"geodesic", "linear"}, optional) – Choose between "geodesic" and "linear", by default "geodesic". In geodesic mode, large gaps between waypoints are filled with geodesic interpolation and small gaps are filled with linear interpolation. In linear mode, all gaps are filled with linear interpolation.

  • geodesic_threshold (float, optional) – Threshold for geodesic interpolation, [\(m\)]. If the distance between consecutive waypoints is under this threshold, values are interpolated linearly.

  • nominal_rocd (float, optional) – Nominal rate of climb / descent for aircraft type. Defaults to constants.nominal_rocd.

  • kernel_size (int, optional) – Passed directly to scipy.signal.medfilt(), by default 11. Passed also to scipy.signal.medfilt()

  • cruise_theshold (float, optional) – Minimal length of time, in seconds, for a flight to be in cruise to apply median filter

  • force_filter (bool, optional) – If set to true, meth:filter_altitude will always be called. otherwise, it will only be called if the flight has a median sample period under 10 seconds

  • drop (bool, optional) – Drop any columns that are not resampled and filled. Defaults to True, dropping all keys outside of “time”, “latitude”, “longitude” and “altitude”. If set to False, the extra keys will be kept but filled with nan or None values, depending on the data type.

  • keep_original_index (bool, optional) – Keep the original index of the Flight in addition to the new resampled index. Defaults to False. .. versionadded:: 0.45.2

Returns:

Flight – Filled Flight

property constants

Return a dictionary of constant attributes and data values.

Includes attrs and values from columns in data with a unique value.

Returns:

dict[str, Any] – Properties and their constant values

property coords

Get geospatial coordinates for compatibility with MetDataArray.

Returns:

pandas.DataFramepd.DataFrame with columns longitude, latitude, level, and time.

coords_intersect_met(met)

Return boolean mask of data inside the bounding box defined by met.

Parameters:

met (MetDataset | MetDataArray) – MetDataset or MetDataArray to compare.

Returns:

npt.NDArray[np.bool_] – True if point is inside the bounding box defined by met.

copy(**kwargs)

Return a copy of this instance.

Parameters:

**kwargs (Any) – Additional keyword arguments passed into the constructor of the returned class.

Returns:

Self – Copy of class

classmethod create_empty(keys=None, attrs=None, **attrs_kwargs)

Create instance with variables defined by keys and size 0.

If instance requires additional variables to be defined, these keys will automatically be attached to returned instance.

Parameters:
  • keys (Iterable[str]) – Keys to include in empty VectorDataset instance.

  • attrs (dict[str, Any] | None, optional) – Attributes to attach instance.

  • **kwargs (Any) – Additional keyword arguments passed into the constructor of the returned class.

Returns:

Self – Empty VectorDataset instance.

data

Vector data with labels as keys and numpy.ndarray as values

property dataframe

Shorthand property to access to_dataframe() with copy=False.

Returns:

pandas.DataFrame – Equivalent to the output from to_dataframe()

distance_to_coords(distance)

Convert distance along flight path to geodesic coordinates.

Will return a tuple containing (lat, lon, index), where index indicates which flight segment contains the returned coordinate.

Parameters:

distance (ArrayOrFloat) – Distance along flight path, [\(m\)]

Returns:

(ArrayOrFloat, ArrayOrFloat, int | npt.NDArray[int]) – latitude, longitude, and segment index cooresponding to distance.

downselect_met(met, *, longitude_buffer=(0.0, 0.0), latitude_buffer=(0.0, 0.0), level_buffer=(0.0, 0.0), time_buffer=(np.timedelta64(0, 'h'), np.timedelta64(0, 'h')))

Downselect met to encompass a spatiotemporal region of the data.

Changed in version 0.54.5: Returned object is no longer copied.

Parameters:
  • met (MetDataset | MetDataArray) – MetDataset or MetDataArray to downselect.

  • longitude_buffer (tuple[float, float], optional) – Extend longitude domain past by longitude_buffer[0] on the low side and longitude_buffer[1] on the high side. Units must be the same as class coordinates. Defaults to (0, 0) degrees.

  • latitude_buffer (tuple[float, float], optional) – Extend latitude domain past by latitude_buffer[0] on the low side and latitude_buffer[1] on the high side. Units must be the same as class coordinates. Defaults to (0, 0) degrees.

  • level_buffer (tuple[float, float], optional) – Extend level domain past by level_buffer[0] on the low side and level_buffer[1] on the high side. Units must be the same as class coordinates. Defaults to (0, 0) [\(hPa\)].

  • time_buffer (tuple[np.timedelta64, np.timedelta64], optional) – Extend time domain past by time_buffer[0] on the low side and time_buffer[1] on the high side. Units must be the same as class coordinates. Defaults to (np.timedelta64(0, "h"), np.timedelta64(0, "h")).

Returns:

MetDataset | MetDataArray – Copy of downselected MetDataset or MetDataArray.

property duration

Determine flight duration.

Returns:

pd.Timedelta – Difference between terminal and initial time

ensure_vars(vars, raise_error=True)

Ensure variables exist in column of data or attrs.

Parameters:
  • vars (str | Iterable[str]) – A single string variable name or a sequence of string variable names.

  • raise_error (bool, optional) – Raise KeyError if data does not contain variables. Defaults to True.

Returns:

bool – True if all variables exist. False otherwise.

Raises:

KeyError – Raises when dataset does not contain variable in vars

filter(mask, copy=True, **kwargs)

Filter data according to a boolean array mask.

Entries corresponding to mask == True are kept.

Parameters:
  • mask (npt.NDArray[np.bool_]) – Boolean array with compatible shape.

  • copy (bool, optional) – Copy data on filter. Defaults to True. See numpy best practices for insight into whether copy is appropriate.

  • **kwargs (Any) – Additional keyword arguments passed into the constructor of the returned class.

Returns:

Self – Containing filtered data

Raises:

TypeError – If mask is not a boolean array.

filter_altitude(kernel_size=17, cruise_threshold=120.0)

Filter noisy altitude on a single flight.

Currently runs altitude through a median filter using scipy.signal.medfilt() with kernel_size, then a Savitzky-Golay filter to filter noise. The median filter is only applied during cruise segments that are longer than cruise_threshold.

Parameters:
Returns:

Flight – Filtered Flight

Notes

Algorithm is derived from traffic.core.Flight.filter().

The traffic algorithm also computes thresholds on sliding windows and replaces unacceptable values with NaNs.

Errors may raised if the kernel_size is too large.

See also

traffic.core.flight.Flight.filter(), scipy.signal.medfilt()

filter_by_first()

Keep first row of group of waypoints with identical coordinates.

Chaining this method with resample_and_fill often gives a cleaner trajectory when using noisy flight waypoints.

Returns:

Flight – Filtered Flight instance

Examples

>>> from datetime import datetime
>>> import pandas as pd
>>> df = pd.DataFrame()
>>> df['longitude'] = [0, 0, 50]
>>> df['latitude'] = 0
>>> df['altitude'] = 0
>>> df['time'] = [datetime(2020, 1, 1, h) for h in range(3)]
>>> fl = Flight(df)
>>> fl.filter_by_first().dataframe
   longitude  latitude  altitude                time
0        0.0       0.0       0.0 2020-01-01 00:00:00
1       50.0       0.0       0.0 2020-01-01 02:00:00
final_waypoints
fl_attrs
classmethod from_dict(obj, copy=True, **obj_kwargs)

Create instance from dict representation containing data and attrs.

Parameters:
  • obj (dict[str, Any]) – Dict representation of VectorDataset (e.g. to_dict())

  • copy (bool, optional) – Passed to VectorDataset constructor. Defaults to True.

  • **obj_kwargs (Any) – Additional properties passed as keyword arguments.

Returns:

Self – VectorDataset instance.

See also

to_dict()

classmethod from_seq(seq, broadcast_numeric=True, attrs=None)

Instantiate a Fleet instance from an iterable of Flight.

Changed in version 0.49.3: Empty flights are now filtered out before concatenation.

Parameters:
  • seq (Iterable[Flight]) – An iterable of Flight instances.

  • broadcast_numeric (bool, optional) – If True, broadcast numeric attributes to data variables.

  • attrs (dict[str, Any] | None, optional) – Global attribute to attach to instance.

Returns:

Fleet – A Fleet instance made from concatenating the Flight instances in seq. The fuel type is taken from the first Flight in seq.

fuel

Fuel used in flight trajectory

generate_splits(n_splits, copy=True)

Split instance into n_split sub-vectors.

Parameters:
Returns:

Generator[Self, None, None] – Generator of split vectors.

get(key, default_value=None)

Get values from data with default_value if key not in data.

Parameters:
  • key (str) – Key to get from data

  • default_value (Any, optional) – Return default_value if key not in data, by default None

Returns:

Any – Values at data[key] or default_value

get_data_or_attr(key, default=<object object>)

Get value from data or attrs.

This method first checks if key is in data and returns the value if so. If key is not in data, then this method checks if key is in attrs and returns the value if so. If key is not in data or attrs, then the default value is returned if provided. Otherwise a KeyError is raised.

Parameters:
  • key (str) – Key to get from data or attrs

  • default (Any, optional) – Default value to return if key is not in data or attrs.

Returns:

Any – Value at data[key] or attrs[key]

Raises:

KeyError – If key is not in data or attrs and default is not provided.

Examples

>>> vector = VectorDataset({"a": [1, 2, 3]}, attrs={"b": 4})
>>> vector.get_data_or_attr("a")
array([1, 2, 3])
>>> vector.get_data_or_attr("b")
4
>>> vector.get_data_or_attr("c")
Traceback (most recent call last):
...
KeyError: "Key 'c' not found in data or attrs."
>>> vector.get_data_or_attr("c", default=5)
5
property hash

Generate a unique hash for this class instance.

Returns:

str – Unique hash for flight instance (sha1)

intersect_met(mda, *, longitude=None, latitude=None, level=None, time=None, use_indices=False, **interp_kwargs)

Intersect waypoints with MetDataArray.

Parameters:
  • mda (MetDataArray) – MetDataArray containing a meteorological variable at spatio-temporal coordinates.

  • longitude (npt.NDArray[np.floating], optional) – Override existing coordinates for met interpolation

  • latitude (npt.NDArray[np.floating], optional) – Override existing coordinates for met interpolation

  • level (npt.NDArray[np.floating], optional) – Override existing coordinates for met interpolation

  • time (npt.NDArray[np.datetime64], optional) – Override existing coordinates for met interpolation

  • use_indices (bool, optional) – Experimental.

  • **interp_kwargs (Any) – Additional keyword arguments to pass to MetDataArray.intersect_met(). Examples include method, bounds_error, and fill_value. If an error such as

    ValueError: One of the requested xi is out of bounds in dimension 2
    

    occurs, try calling this function with bounds_error=False. In addition, setting fill_value=0.0 will replace NaN values with 0.0.

Returns:

npt.NDArray[np.floating] – Interpolated values

Examples

>>> from datetime import datetime
>>> import pandas as pd
>>> import numpy as np
>>> from pycontrails.datalib.ecmwf import ERA5
>>> from pycontrails import Flight
>>> # Get met data
>>> times = (datetime(2022, 3, 1, 0),  datetime(2022, 3, 1, 3))
>>> variables = ["air_temperature", "specific_humidity"]
>>> levels = [300, 250, 200]
>>> era5 = ERA5(time=times, variables=variables, pressure_levels=levels)
>>> met = era5.open_metdataset()
>>> # Example flight
>>> df = pd.DataFrame()
>>> df['longitude'] = np.linspace(0, 50, 10)
>>> df['latitude'] = np.linspace(0, 10, 10)
>>> df['altitude'] = 11000
>>> df['time'] = pd.date_range("2022-03-01T00", "2022-03-01T02", periods=10)
>>> fl = Flight(df)
>>> # Intersect
>>> fl.intersect_met(met['air_temperature'], method='nearest')
array([231.62969892, 230.72604651, 232.24318771, 231.88338483,
       231.06429438, 231.59073409, 231.65125393, 231.93064004,
       232.03344087, 231.65954432])
>>> fl.intersect_met(met['air_temperature'], method='linear')
array([225.77794552, 225.13908414, 226.231218  , 226.31831528,
       225.56102321, 225.81192149, 226.03192642, 226.22056121,
       226.03770174, 225.63226188])
>>> # Interpolate and attach to `Flight` instance
>>> for key in met:
...     fl[key] = fl.intersect_met(met[key])
>>> # Show the final three columns of the dataframe
>>> fl.dataframe.iloc[:, -3:].head()
                 time  air_temperature  specific_humidity
0 2022-03-01 00:00:00       225.777946           0.000132
1 2022-03-01 00:13:20       225.139084           0.000132
2 2022-03-01 00:26:40       226.231218           0.000107
3 2022-03-01 00:40:00       226.318315           0.000171
4 2022-03-01 00:53:20       225.561022           0.000109
property length

Return flight length based on WGS84 geodesic.

Returns:

float – Total flight length, [\(m\)]

Examples

>>> import numpy as np
>>> fl = Flight(
...     longitude=np.linspace(20, 30, 200),
...     latitude=np.linspace(40, 30, 200),
...     altitude=11000 * np.ones(200),
...     time=pd.date_range('2021-01-01T12', '2021-01-01T14', periods=200),
... )
>>> fl.length
np.float64(1436924.67...)
length_met(key, threshold=1.0)

Calculate total horizontal distance where column key exceeds threshold.

Parameters:
  • key (str) – Column key in data

  • threshold (float) – Consider trajectory waypoints whose associated key value exceeds threshold, by default 1.0

Returns:

float – Total distance, [\(m\)]

Raises:

KeyErrordata does not contain column key

Examples

>>> from datetime import datetime
>>> import pandas as pd
>>> import numpy as np
>>> from pycontrails.datalib.ecmwf import ERA5
>>> from pycontrails import Flight
>>> # Get met data
>>> times = (datetime(2022, 3, 1, 0),  datetime(2022, 3, 1, 3))
>>> variables = ["air_temperature", "specific_humidity"]
>>> levels = [300, 250, 200]
>>> era5 = ERA5(time=times, variables=variables, pressure_levels=levels)
>>> met = era5.open_metdataset()
>>> # Build flight
>>> df = pd.DataFrame()
>>> df["time"] = pd.date_range("2022-03-01T00", "2022-03-01T03", periods=11)
>>> df["longitude"] = np.linspace(-20, 20, 11)
>>> df["latitude"] = np.linspace(-20, 20, 11)
>>> df["altitude"] = np.linspace(9500, 10000, 11)
>>> fl = Flight(df).resample_and_fill("10s")
>>> # Intersect and attach
>>> fl["air_temperature"] = fl.intersect_met(met["air_temperature"])
>>> fl["air_temperature"]
array([235.94657007, 235.55745645, 235.56709768, ..., 234.59917962,
       234.60387402, 234.60845312], shape=(1081,))
>>> # Length (in meters) of waypoints whose temperature exceeds 236K
>>> fl.length_met("air_temperature", threshold=236)
np.float64(3589705.998...)
>>> # Proportion (with respect to distance) of waypoints whose temperature exceeds 236K
>>> fl.proportion_met("air_temperature", threshold=236)
np.float64(0.576...)
property level

Get pressure level values for points.

Automatically calculates pressure level using units.m_to_pl() using altitude key.

Note that if level key exists in data, the data at the level key will be returned. This allows an override of the default calculation of pressure level from altitude.

Returns:

npt.NDArray[np.floating] – Point pressure level values, [\(hPa\)]

property max_distance_gap

Return maximum distance gap between waypoints along flight trajectory.

Distance is calculated based on WGS84 geodesic.

Returns:

float – Maximum distance between waypoints, [\(m\)]

Examples

>>> import numpy as np
>>> fl = Flight(
...     longitude=np.linspace(20, 30, 200),
...     latitude=np.linspace(40, 30, 200),
...     altitude=11000 * np.ones(200),
...     time=pd.date_range('2021-01-01T12', '2021-01-01T14', periods=200),
... )
>>> fl.max_distance_gap
np.float64(7391.27...)
property max_time_gap

Return maximum time gap between waypoints along flight trajectory.

Returns:

pd.Timedelta – Gap size

Examples

>>> import numpy as np
>>> fl = Flight(
...     longitude=np.linspace(20, 30, 200),
...     latitude=np.linspace(40, 30, 200),
...     altitude=11000 * np.ones(200),
...     time=pd.date_range('2021-01-01T12', '2021-01-01T14', periods=200),
... )
>>> fl.max_time_gap
Timedelta('0 days 00:00:36.180...')
property n_flights

Return number of distinct flights.

Returns:

int – Number of flights

plot(**kwargs)

Plot flight trajectory longitude-latitude values.

Parameters:

**kwargs (Any) – Additional plot properties to passed to pd.DataFrame.plot

Returns:

matplotlib.axes.Axes – Plot

plot_profile(**kwargs)

Plot flight trajectory time-altitude values.

Parameters:

**kwargs (Any) – Additional plot properties to passed to pd.DataFrame.plot

Returns:

matplotlib.axes.Axes – Plot

proportion_met(key, threshold=1.0)

Calculate proportion of flight with certain meteorological constraint.

Parameters:
  • key (str) – Column key in data

  • threshold (float) – Consider trajectory waypoints whose associated key value exceeds threshold, Defaults to 1.0

Returns:

float – Ratio

required_keys = ('longitude', 'latitude', 'time')

Required keys for creating GeoVectorDataset

resample_and_fill(*args, **kwargs)

Resample and fill flight trajectory with geodesics and linear interpolation.

Waypoints are resampled according to the frequency freq. Values for data columns longitude, latitude, and altitude are interpolated.

Resampled waypoints will include all multiples of freq between the flight start and end time. For example, when resampling to a frequency of 1 minute, a flight that starts at 2020/1/1 00:00:59 and ends at 2020/1/1 00:01:01 will return a single waypoint at 2020/1/1 00:01:00, whereas a flight that starts at 2020/1/1 00:01:01 and ends at 2020/1/1 00:01:59 will return an empty flight.

Parameters:
  • freq (str, optional) – Resampling frequency, by default “1min”

  • fill_method ({"geodesic", "linear"}, optional) – Choose between "geodesic" and "linear", by default "geodesic". In geodesic mode, large gaps between waypoints are filled with geodesic interpolation and small gaps are filled with linear interpolation. In linear mode, all gaps are filled with linear interpolation.

  • geodesic_threshold (float, optional) – Threshold for geodesic interpolation, [\(m\)]. If the distance between consecutive waypoints is under this threshold, values are interpolated linearly.

  • nominal_rocd (float | None, optional) – Nominal rate of climb / descent for aircraft type. Defaults to constants.nominal_rocd.

  • drop (bool, optional) – Drop any columns that are not resampled and filled. Defaults to True, dropping all keys outside of “time”, “latitude”, “longitude” and “altitude”. If set to False, the extra keys will be kept but filled with nan or None values, depending on the data type.

  • keep_original_index (bool, optional) – Keep the original index of the Flight in addition to the new resampled index. Defaults to False. .. versionadded:: 0.45.2

Returns:

Flight – Filled Flight

Raises:

ValueError – Unknown fill_method

Examples

>>> from datetime import datetime
>>> import pandas as pd
>>> df = pd.DataFrame()
>>> df['longitude'] = [0, 0, 50]
>>> df['latitude'] = 0
>>> df['altitude'] = 0
>>> df['time'] = [datetime(2020, 1, 1, h) for h in range(3)]
>>> fl = Flight(df)
>>> fl.dataframe
   longitude  latitude  altitude                time
           0        0.0       0.0       0.0 2020-01-01 00:00:00
           1        0.0       0.0       0.0 2020-01-01 01:00:00
           2       50.0       0.0       0.0 2020-01-01 02:00:00
>>> fl.resample_and_fill('10min').dataframe  # resample with 10 minute frequency
    longitude  latitude  altitude                time
0    0.000000       0.0       0.0 2020-01-01 00:00:00
1    0.000000       0.0       0.0 2020-01-01 00:10:00
2    0.000000       0.0       0.0 2020-01-01 00:20:00
3    0.000000       0.0       0.0 2020-01-01 00:30:00
4    0.000000       0.0       0.0 2020-01-01 00:40:00
5    0.000000       0.0       0.0 2020-01-01 00:50:00
6    0.000000       0.0       0.0 2020-01-01 01:00:00
7    8.333333       0.0       0.0 2020-01-01 01:10:00
8   16.666667       0.0       0.0 2020-01-01 01:20:00
9   25.000000       0.0       0.0 2020-01-01 01:30:00
10  33.333333       0.0       0.0 2020-01-01 01:40:00
11  41.666667       0.0       0.0 2020-01-01 01:50:00
12  50.000000       0.0       0.0 2020-01-01 02:00:00
segment_angle()

Calculate sine and cosine for the angle between each segment and the longitudinal axis.

This is different from the usual navigational angle between two points known as bearing.

Bearing in 3D spherical coordinates is referred to as azimuth.

        (lon_2, lat_2)  X
                       /|
                      / |
                     /  |
                    /   |
                   /    |
                  /     |
                 /      |
(lon_1, lat_1)  X -------> longitude (x-axis)
Returns:

npt.NDArray[np.floating], npt.NDArray[np.floating] – Returns sin(a), cos(a), where a is the angle between the segment and the longitudinal axis. The final values are of both arrays are np.nan.

See also

geo.segment_angle(), units.heading_to_longitudinal_angle(), segment_azimuth(), geo.forward_azimuth()

Examples

>>> from pycontrails import Flight
>>> fl = Flight(
... longitude=np.array([1, 2, 3, 5, 8]),
... latitude=np.arange(5),
... altitude=np.full(shape=(5,), fill_value=11000),
... time=pd.date_range('2021-01-01T12', '2021-01-01T14', periods=5),
... )
>>> sin, cos = fl.segment_angle()
>>> sin
array([0.70716063, 0.70737598, 0.44819424, 0.31820671,        nan])
>>> cos
array([0.70705293, 0.70683748, 0.8939362 , 0.94802136,        nan])
segment_azimuth()

Calculate (forward) azimuth at each waypoint.

Method calls pyproj.Geod.inv, which is slow. See geo.forward_azimuth for an outline of a faster implementation.

Changed in version 0.33.7: The dtype of the output now matches the dtype of self["longitude"].

Returns:

npt.NDArray[np.floating] – Array of azimuths.

See also

segment_angle(), geo.forward_azimuth()

segment_duration(dtype=<class 'numpy.float32'>)

Compute time elapsed between waypoints in seconds.

np.nan appended so the length of the output is the same as number of waypoints.

Parameters:

dtype (np.dtype) – Numpy dtype for time difference. Defaults to np.float64

Returns:

npt.NDArray[np.floating] – Time difference between waypoints, [\(s\)]. Returns an array with dtype specified by``dtype``

segment_groundspeed(*args, **kwargs)

Return groundspeed across segments.

Calculate by dividing the horizontal segment length by the difference in waypoint times.

Parameters:
Returns:

npt.NDArray[np.floating] – Groundspeed of the segment, [\(m s^{-1}\)]

segment_haversine()

Compute Haversine (great circle) distance between flight waypoints.

Helper function used in resample_and_fill(). np.nan appended so the length of the output is the same as number of waypoints.

To account for vertical displacements when computing segment lengths, use segment_length().

Returns:

npt.NDArray[np.floating] – Array of great circle distances in [\(m\)] between waypoints

Examples

>>> from pycontrails import Flight
>>> fl = Flight(
... longitude=np.array([1, 2, 3, 5, 8]),
... latitude=np.arange(5),
... altitude=np.full(shape=(5,), fill_value=11000),
... time=pd.date_range('2021-01-01T12', '2021-01-01T14', periods=5),
... )
>>> fl.segment_haversine()
array([157255.03346286, 157231.08336815, 248456.48781503, 351047.44358851,
                   nan])
segment_length()

Compute spherical distance between flight waypoints.

Helper function used in length() and length_met(). np.nan appended so the length of the output is the same as number of waypoints.

Returns:

npt.NDArray[np.floating] – Array of distances in [\(m\)] between waypoints

Examples

>>> from pycontrails import Flight
>>> fl = Flight(
... longitude=np.array([1, 2, 3, 5, 8]),
... latitude=np.arange(5),
... altitude=np.full(shape=(5,), fill_value=11000),
... time=pd.date_range('2021-01-01T12', '2021-01-01T14', periods=5),
... )
>>> fl.segment_length()
array([157255.03346286, 157231.08336815, 248456.48781503, 351047.44358851,
                   nan])

See also

segment_length()

segment_mach_number(true_airspeed, air_temperature)

Calculate the mach number of each segment.

Parameters:
  • true_airspeed (npt.NDArray[np.floating]) – True airspeed of the segment, [\(m \ s^{-1}\)]. See segment_true_airspeed().

  • air_temperature (npt.NDArray[np.floating]) – Average air temperature of each segment, [\(K\)]

Returns:

npt.NDArray[np.floating] – Mach number of each segment

segment_phase(threshold_rocd=250.0, min_cruise_altitude_ft=20000.0, air_temperature=None)

Identify the phase of flight (climb, cruise, descent) for each segment.

Parameters:
  • threshold_rocd (float, optional) – ROCD threshold to identify climb and descent, [\(ft min^{-1}\)]. Currently set to 250 ft/min.

  • min_cruise_altitude_ft (float, optional) – Minimum altitude for cruise, [\(ft\)] This is specific for each aircraft type, and can be approximated as 50% of the altitude ceiling. Defaults to 20000 ft.

  • air_temperature (None | npt.NDArray[np.floating]) – Air temperature of each flight waypoint, [\(K\)]

Returns:

npt.NDArray[np.uint8] – Array of values enumerating the flight phase. See flight.FlightPhase for enumeration.

segment_rocd(air_temperature=None)

Calculate the rate of climb and descent (ROCD).

Parameters:

air_temperature (None | npt.NDArray[np.floating]) – Air temperature of each flight waypoint, [\(K\)]

Returns:

npt.NDArray[np.floating] – Rate of climb and descent over segment, [\(ft min^{-1}\)]

See also

segment_rocd()

segment_true_airspeed(u_wind=0.0, v_wind=0.0, smooth=True, window_length=7, polyorder=1)

Calculate the true airspeed [\(m / s\)] from the ground speed and horizontal winds.

Because Flight.segment_true_airspeed uses a smoothing pattern, waypoints in data are not independent. Moreover, we expect the final waypoint of each flight to have a nan value associated to any segment property. Consequently, we need to define a custom method here to deal with these issues when applying this method on a fleet of flights.

See docstring for Flight.segment_true_airspeed().

Raises:

RuntimeError – Unexpected key __u_wind or __v_wind found in data.

select(keys, copy=True)

Return new class instance only containing specified keys.

Parameters:
  • keys (Iterable[str]) – An iterable of keys to filter by.

  • copy (bool, optional) – Copy data on selection. Defaults to True.

Returns:

VectorDataset – VectorDataset containing only data associated to keys. Note that this method always returns a VectorDataset, even if the calling class is a proper subclass of VectorDataset.

setdefault(key, default=None)

Shortcut to VectorDataDict.setdefault().

Parameters:
  • key (str) – Key in data dict.

  • default (npt.ArrayLike, optional) – Values to use as default, if key is not defined

Returns:

numpy.ndarray – Values at key

property shape

Shape of each array in data.

Returns:

tuple[int] – Shape of each array in data.

property size

Length of each array in data.

Returns:

int – Length of each array in data.

sort(by)

Sort data by key(s).

This method always creates a copy of the data by calling pandas.DataFrame.sort_values().

Parameters:

by (str | list[str]) – Key or list of keys to sort by.

Returns:

Self – Instance with sorted data.

classmethod sum(vectors, infer_attrs=True, fill_value=None)

Sum a list of VectorDataset instances.

Parameters:
  • vectors (Sequence[VectorDataset]) – List of VectorDataset instances to concatenate.

  • infer_attrs (bool, optional) – If True, infer attributes from the first element in the sequence.

  • fill_value (float, optional) – Fill value to use when concatenating arrays. By default None, which raises an error if incompatible keys are found.

Returns:

VectorDataset – Sum of all instances in vectors.

Raises:

KeyError – If incompatible data keys are found among vectors.

Examples

>>> from pycontrails import VectorDataset
>>> v1 = VectorDataset({"a": [1, 2, 3], "b": [4, 5, 6]})
>>> v2 = VectorDataset({"a": [7, 8, 9], "b": [10, 11, 12]})
>>> v3 = VectorDataset({"a": [13, 14, 15], "b": [16, 17, 18]})
>>> v = VectorDataset.sum([v1, v2, v3])
>>> v.dataframe
    a   b
0   1   4
1   2   5
2   3   6
3   7  10
4   8  11
5   9  12
6  13  16
7  14  17
8  15  18
property time_end

Last waypoint time.

Returns:

pandas.Timestamp – Last waypoint time

property time_start

First waypoint time.

Returns:

pandas.Timestamp – First waypoint time

to_dataframe(copy=True)

Create pd.DataFrame in which each key-value pair in data is a column.

DataFrame does not copy data by default. Use the copy parameter to copy data values on creation.

Parameters:

copy (bool, optional) – Copy data on DataFrame creation.

Returns:

pandas.DataFrame – DataFrame holding key-values as columns.

to_dict()

Create dictionary with data and attrs.

If geo-spatial coordinates (e.g. "latitude", "longitude", "altitude") are present, round to a reasonable precision. If a "time" variable is present, round to unix seconds. When the instance is a GeoVectorDataset, disregard any "altitude" or "level" coordinate and only include "altitude_ft" in the output.

Returns:

dict[str, Any] – Dictionary with data and attrs.

See also

from_dict()

Examples

>>> import pprint
>>> from pycontrails import Flight
>>> fl = Flight(
...     longitude=[-100, -110],
...     latitude=[40, 50],
...     level=[200, 200],
...     time=[np.datetime64("2020-01-01T09"), np.datetime64("2020-01-01T09:30")],
...     aircraft_type="B737",
... )
>>> fl = fl.resample_and_fill("5min")
>>> pprint.pprint(fl.to_dict())
{'aircraft_type': 'B737',
 'altitude_ft': [38661.0, 38661.0, 38661.0, 38661.0, 38661.0, 38661.0, 38661.0],
 'latitude': [40.0, 41.724, 43.428, 45.111, 46.769, 48.399, 50.0],
 'longitude': [-100.0,
               -101.441,
               -102.959,
               -104.563,
               -106.267,
               -108.076,
               -110.0],
 'time': [1577869200,
          1577869500,
          1577869800,
          1577870100,
          1577870400,
          1577870700,
          1577871000]}
to_flight_list(copy=True)

De-concatenate merged waypoints into a list of Flight instances.

Any global attrs are lost.

Parameters:

copy (bool, optional) – If True, make copy of each Flight instance.

Returns:

list[Flight] – List of Flights in the same order as was passed into the Fleet instance.

to_geojson_linestring()

Return trajectory as geojson FeatureCollection containing single LineString.

Returns:

dict[str, Any] – Python representation of geojson FeatureCollection

to_geojson_multilinestring(key=None, split_antimeridian=True)

Return trajectory as GeoJSON FeatureCollection of MultiLineStrings.

If key is provided, Flight data is grouped according to values of key. Each group gives rise to a Feature containing a MultiLineString geometry. Each MultiLineString can optionally be split over the antimeridian.

Parameters:
  • key (str, optional) – If provided, name of data column to group by.

  • split_antimeridian (bool, optional) – Split linestrings that cross the antimeridian. Defaults to True.

Returns:

dict[str, Any] – Python representation of GeoJSON FeatureCollection of MultiLinestring Features

Raises:

KeyErrorkey is provided but data does not contain column key

to_geojson_points()

Return dataset as GeoJSON FeatureCollection of Points.

Each Feature has a properties attribute that includes time and other data besides latitude, longitude, and altitude in data.

Returns:

dict[str, Any] – Python representation of GeoJSON FeatureCollection

to_lon_lat_grid(agg, *, spatial_bbox=(-180.0, -90.0, 180.0, 90.0), spatial_grid_res=0.5)

Convert vectors to a longitude-latitude grid.

See also

vector_to_lon_lat_grid

to_traffic()

Convert to :class:`traffic.core.Flight`instance.

Returns:

traffic.core.Flight – traffic flight instance

Raises:

ModuleNotFoundErrortraffic package not installed

transform_crs(crs)

Transform trajectory data from one coordinate reference system (CRS) to another.

Parameters:
  • crs (str) – Target CRS. Passed into to pyproj.Transformer. The source CRS is assumed to be EPSG:4326.

  • copy (bool, optional) – Copy data on transformation. Defaults to True.

Returns:

tuple[npt.NDArray[np.floating], npt.NDArray[np.floating]] – New x and y coordinates in the target CRS.

update(other=None, **kwargs)

Update values in data dict without warning if overwriting.

Parameters:
  • other (dict[str, npt.ArrayLike] | None, optional) – Fields to update as dict

  • **kwargs (npt.ArrayLike) – Fields to update as kwargs

vertical_keys = ('altitude', 'level', 'altitude_ft')

At least one of these vertical-coordinate keys must also be included