pycontrails.Flight¶
- class pycontrails.Flight(data=None, *, longitude=None, latitude=None, altitude=None, altitude_ft=None, level=None, time=None, attrs=None, copy=True, fuel=None, drop_duplicated_times=False, **attrs_kwargs)¶
Bases:
GeoVectorDatasetA single flight trajectory.
Expect latitude-longitude coordinates in WGS 84. Expect altitude in [\(m\)]. Expect pressure level (level) in [\(hPa\)].
- Parameters:
data (
dict[str,npt.ArrayLike] | pd.DataFrame | VectorDataDict | VectorDataset | None) – Flight trajectory waypoints as data dictionary orpandas.DataFrame. Must include columnstime,latitude,longitude,altitudeorlevel. Keyword arguments fortime,latitude,longitude,altitudeorlevelwill overridedatainputs. Expectsaltitudein meters andtimeas a DatetimeLike (or array that can processed withpd.to_datetime()). Additional waypoint-specific data can be included as additional keys/columns.longitude (
npt.ArrayLike | None, optional) – Flight trajectory waypoint longitude. Defaults to None.latitude (
npt.ArrayLike | None, optional) – Flight trajectory waypoint latitude. Defaults to None.altitude (
npt.ArrayLike | None, optional) – Flight trajectory waypoint altitude, [\(m\)]. Defaults to None.altitude_ft (
npt.ArrayLike | None, optional) – Flight trajectory waypoint altitude, [\(ft\)].level (
npt.ArrayLike | None, optional) – Flight trajectory waypoint pressure level, [\(hPa\)]. Defaults to None.time (
npt.ArrayLike | None, optional) – Flight trajectory waypoint time. Defaults to None.attrs (
dict[str,Any] | None, optional) – Additional flight properties as a dictionary. While different models may utilize Flight attributes differently, pycontrails applies the following conventions:flight_id: An internal flight identifier. Used internally forFleetinteroperability.aircraft_type: Aircraft type ICAO, e.g."A320".wingspan: Aircraft wingspan, [\(m\)].n_engine: Number of aircraft engines.engine_uid: Aircraft engine unique identifier. Used for emissions calculations with the ICAO Aircraft Emissions Databank (EDB).max_mach_number: Maximum Mach number at cruise altitude. Used by some aircraft performance models to clip true airspeed.load_factor: The load factor used in determining the aircraft’s take-off weight. Used by some aircraft performance models.
Numeric quantities that are constant over the entire flight trajectory should be included as attributes.
copy (
bool, optional) – Copy data on Flight creation. Defaults to True.fuel (
Fuel | None, optional) – Fuel used in flight trajectory. Defaults toJetA.drop_duplicated_times (
bool, optional) – Drop duplicate times in flight trajectory. Defaults to False.**attrs_kwargs (
Any) – Additional flight properties passed as keyword arguments.
- Raises:
KeyError – Raises if
datainput does not contain at leasttime,latitude,longitude, (altitudeorlevel).
Notes
The Traffic library has many helpful flight processing utilities.
See
traffic.core.Flightfor more information.Examples
>>> import numpy as np >>> import pandas as pd >>> from pycontrails import Flight
>>> # Create `Flight` from a DataFrame. >>> df = pd.DataFrame({ ... "longitude": np.linspace(20, 30, 500), ... "latitude": np.linspace(40, 10, 500), ... "altitude": 10500, ... "time": pd.date_range('2021-01-01T10', '2021-01-01T15', periods=500), ... }) >>> fl = Flight(data=df, flight_id=123) # specify a flight_id by keyword >>> fl Flight [4 keys x 500 length, 1 attributes] Keys: longitude, latitude, altitude, time Attributes: time [2021-01-01 10:00:00, 2021-01-01 15:00:00] longitude [20.0, 30.0] latitude [10.0, 40.0] altitude [10500.0, 10500.0] flight_id 123
>>> # Create `Flight` from keywords >>> 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 Flight [4 keys x 200 length, 0 attributes] Keys: longitude, latitude, time, altitude Attributes: time [2021-01-01 12:00:00, 2021-01-01 14:00:00] longitude [20.0, 30.0] latitude [30.0, 40.0] altitude [11000.0, 11000.0]
>>> # Access the underlying data as DataFrame >>> fl.dataframe.head() longitude latitude time altitude 0 20.000000 40.000000 2021-01-01 12:00:00.000000000 11000.0 1 20.050251 39.949749 2021-01-01 12:00:36.180904522 11000.0 2 20.100503 39.899497 2021-01-01 12:01:12.361809045 11000.0 3 20.150754 39.849246 2021-01-01 12:01:48.542713567 11000.0 4 20.201005 39.798995 2021-01-01 12:02:24.723618090 11000.0
- __init__(data=None, *, longitude=None, latitude=None, altitude=None, altitude_ft=None, level=None, time=None, attrs=None, copy=True, fuel=None, drop_duplicated_times=False, **attrs_kwargs)¶
Methods
T_isa()Calculate the ICAO standard atmosphere temperature at each point.
__init__([data, longitude, latitude, ...])broadcast_attrs(keys[, overwrite, raise_error])broadcast_numeric_attrs([ignore_keys, overwrite])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
keysand size 0.distance_to_coords(distance)Convert distance along flight path to geodesic coordinates.
downselect_met(met, *[, longitude_buffer, ...])Downselect
metto encompass a spatiotemporal region of the data.ensure_vars(vars[, raise_error])filter(mask[, copy])Filter
dataaccording to a boolean arraymask.filter_altitude([kernel_size, cruise_threshold])Filter noisy altitude on a single flight.
Keep first row of group of waypoints with identical coordinates.
from_dict(obj[, copy])Create instance from dict representation containing data and attrs.
generate_splits(n_splits[, copy])Split instance into
n_splitsub-vectors.get(key[, default_value])get_constant(key[, default])get_data_or_attr(key[, default])intersect_met(mda, *[, longitude, latitude, ...])Intersect waypoints with MetDataArray.
length_met(key[, threshold])Calculate total horizontal distance where column
keyexceedsthreshold.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([freq, fill_method, ...])Resample and fill flight trajectory with geodesics and linear interpolation.
Calculate sine and cosine for the angle between each segment and the longitudinal axis.
Calculate (forward) azimuth at each waypoint.
segment_duration([dtype])Compute time elapsed between waypoints in seconds.
segment_groundspeed([smooth, window_length, ...])Return groundspeed across segments.
Compute Haversine (great circle) distance between flight waypoints.
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
VectorDatasetinstances.to_dataframe([copy])Create
pd.DataFramein which each key-value pair indatais a column.to_dict()Return trajectory as geojson FeatureCollection containing single LineString.
to_geojson_multilinestring([key, ...])Return trajectory as GeoJSON FeatureCollection of MultiLineStrings.
Return dataset as GeoJSON FeatureCollection of Points.
to_lon_lat_grid(agg, *[, spatial_bbox, ...])Convert vectors to a longitude-latitude grid.
Convert to
traffic.core.Flightinstance.transform_crs(crs)Transform trajectory data from one coordinate reference system (CRS) to another.
update([other])Update values in
datadict without warning if overwriting.Attributes
Fuel used in flight trajectory
Get
air_pressurevalues for points.Get altitude.
Get altitude in feet.
Generic dataset attributes
Return a dictionary of constant attributes and data values.
Get geospatial coordinates for compatibility with MetDataArray.
Vector data with labels as keys and
numpy.ndarrayas valuesShorthand property to access
to_dataframe()withcopy=False.Determine flight duration.
Generate a unique hash for this class instance.
Return flight length based on WGS84 geodesic.
Get pressure
levelvalues for points.Return maximum distance gap between waypoints along flight trajectory.
Return maximum time gap between waypoints along flight trajectory.
Required keys for creating GeoVectorDataset
Shape of each array in
data.Length of each array in
data.Last waypoint time.
First waypoint time.
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_pressurevalues for points.- Returns:
npt.NDArray[np.floating]– Point air pressure values, [\(Pa\)]
- property altitude¶
Get altitude.
Automatically calculates altitude using
units.pl_to_m()usinglevelkey.Note that if
altitudekey exists indata, the data at thealtitudekey 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
keysinattrsontodata.If possible, use
dtype = np.float32when broadcasting. If not possible, use whateverdtypeis inferred from the data bynumpy.full().
- broadcast_numeric_attrs(ignore_keys=None, overwrite=False)¶
Attach numeric values in
attrsontodata.Iterate through values in
attrsand attachfloatandintvalues todata.This method modifies object in place.
- clean_and_resample(freq='1min', fill_method='geodesic', geodesic_threshold=100000.0, nominal_rocd=12.7, kernel_size=17, cruise_threshold=120.0, 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 (
str, 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 toconstants.nominal_rocd.kernel_size (
int, optional) – Passed directly toscipy.signal.medfilt(), by default 11. Passed also toscipy.signal.medfilt()cruise_threshold (
float, optional) – Minimal length of time, in seconds, for a flight to be in cruise to apply median filterforce_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 secondsdrop (
bool, optional) – Drop any columns that are not resampled and filled. Defaults toTrue, dropping all keys outside of “time”, “latitude”, “longitude” and “altitude”. If set to False, the extra keys will be kept but filled withnanorNonevalues, depending on the data type.keep_original_index (
bool, optional) – Keep the original index of theFlightin addition to the new resampled index. Defaults toFalse. .. versionadded:: 0.45.2
- Returns:
Self– Filled Flight
- property constants¶
Return a dictionary of constant attributes and data values.
Includes
attrsand values from columns indatawith a unique value.- Returns:
dict[str,Any]– Properties and their constant values
- property coords¶
Get geospatial coordinates for compatibility with MetDataArray.
- Returns:
dict[str,np.ndarray]– A dictionary with fields longitude, latitude, level, and time.
- coords_intersect_met(met)¶
Return boolean mask of data inside the bounding box defined by
met.- Parameters:
met (
met_module.MetDataset | met_module.MetDataArray) – MetDataset or MetDataArray to compare.- Returns:
npt.NDArray[np.bool_]– True if point is inside the bounding box defined bymet.
- 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
keysand 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.ndarrayas values
- property dataframe¶
Shorthand property to access
to_dataframe()withcopy=False.- Returns:
pandas.DataFrame– Equivalent to the output fromto_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:
tuple[ArrayOrFloat,ArrayOrFloat,np.intp | npt.NDArray[np.intp]]– latitude, longitude, and segment index corresponding 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
metto encompass a spatiotemporal region of the data.Changed in version 0.54.5: Returned object is no longer copied.
- Parameters:
met (
met_module.MetDataType) – MetDataset or MetDataArray to downselect.longitude_buffer (
tuple[float,float], optional) – Extend longitude domain past bylongitude_buffer[0]on the low side andlongitude_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 bylatitude_buffer[0]on the low side andlatitude_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 bylevel_buffer[0]on the low side andlevel_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 bytime_buffer[0]on the low side andtime_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:
met_module.MetDataType– 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
dataorattrs.- 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
dataaccording to a boolean arraymask.Entries corresponding to
mask == Trueare 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
maskis 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()withkernel_size, then a Savitzky-Golay filter to filter noise. The median filter is only applied during cruise segments that are longer thancruise_threshold.- Parameters:
kernel_size (
int, optional) – Passed directly toscipy.signal.medfilt(), by default 11. Passed also toscipy.signal.medfilt()cruise_threshold (
float, optional) – Minimal length of time, in seconds, for a flight to be in cruise to apply median filter
- Returns:
Self– 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_sizeis 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:
Self– 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
- 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 toVectorDatasetconstructor. Defaults to True.**obj_kwargs (
Any) – Additional properties passed as keyword arguments.
- Returns:
Self– VectorDataset instance.
See also
- fuel¶
Fuel used in flight trajectory
- generate_splits(n_splits, copy=True)¶
Split instance into
n_splitsub-vectors.- Parameters:
n_splits (
int) – Number of splits.copy (
bool, optional) – Passed intofilter(). Defaults to True. Recommend to keep as True based on numpy best practices.
- Yields:
Self– Generator of split vectors.
See also
- get(key, default_value=None)¶
- get_constant(key, default=<object object>)¶
Get a constant value from
attrsordata.If
keyis found inattrs, the value is returned.If
keyis found indata, the common value is returned if all values are equal.If
keyis not found inattrsordataand adefaultis provided, thedefaultis returned.Otherwise, a KeyError is raised.
- Parameters:
- Returns:
Any– The constant value forkey.- Raises:
KeyError – If
keyis not found inattrsor the values indataare not equal anddefaultis not provided.
Examples
>>> vector = VectorDataset({"a": [1, 1, 1], "b": [2, 2, 3]}) >>> vector.get_constant("a") np.int64(1) >>> vector.get_constant("b") Traceback (most recent call last): ... KeyError: "A constant key 'b' not found in attrs or data" >>> vector.get_constant("b", 3) 3
See also
- get_data_or_attr(key, default=<object object>)¶
-
This method first checks if
keyis indataand returns the value if so. Ifkeyis not indata, then this method checks ifkeyis inattrsand returns the value if so. Ifkeyis not indataorattrs, then thedefaultvalue is returned if provided. Otherwise aKeyErroris raised.- Parameters:
- Returns:
Any– Value atdata[key]orattrs[key]- Raises:
KeyError – If
keyis not indataorattrsanddefaultis 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
See also
- 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 (
met_module.MetDataArray) – MetDataArray containing a meteorological variable at spatio-temporal coordinates.longitude (
npt.NDArray[np.floating] | None, optional) – Override existing coordinates for met interpolationlatitude (
npt.NDArray[np.floating] | None, optional) – Override existing coordinates for met interpolationlevel (
npt.NDArray[np.floating] | None, optional) – Override existing coordinates for met interpolationtime (
npt.NDArray[np.datetime64] | None, optional) – Override existing coordinates for met interpolationuse_indices (
bool, optional) – Experimental.**interp_kwargs (
Any) – Additional keyword arguments to pass toMetDataArray.intersect_met(). Examples includemethod,bounds_error, andfill_value. If an error such asValueError: One of the requested xi is out of bounds in dimension 2
occurs, try calling this function with
bounds_error=False. In addition, settingfill_value=0.0will 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
keyexceedsthreshold.- Parameters:
- Returns:
float– Total distance, [\(m\)]- Raises:
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
levelvalues for points.Automatically calculates pressure level using
units.m_to_pl()usingaltitudekey.Note that if
levelkey exists indata, the data at thelevelkey 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...')
- 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.
- required_keys = ('longitude', 'latitude', 'time')¶
Required keys for creating GeoVectorDataset
- resample_and_fill(freq='1min', fill_method='geodesic', geodesic_threshold=100000.0, nominal_rocd=12.7, drop=True, keep_original_index=False, time=None)¶
Resample and fill flight trajectory with geodesics and linear interpolation.
Waypoints are resampled according to the frequency
freqor to the times intime. Values fordatacolumnslongitude,latitude, andaltitudeare interpolated.When resampled based on
freq, waypoints will include all multiples offreqbetween 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.When resampled based on
time, waypoints will include all times between the flight start and end time.- Parameters:
freq (
str, optional) – Resampling frequency, by default “1min”fill_method (
str, 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 toconstants.nominal_rocd.drop (
bool, optional) – Drop any columns that are not resampled and filled. Defaults toTrue, dropping all keys outside of “time”, “latitude”, “longitude” and “altitude”. If set to False, the extra keys will be kept but filled withnanorNonevalues, depending on the data type.keep_original_index (
bool, optional) – Keep the original index of theFlightin addition to the new resampled index. Defaults toFalse. .. versionadded:: 0.45.2time (
npt.NDArray[np.datetime64] | None, optional) – Times to resample to. Will overridefreqif provided. .. versionadded:: 0.54.11
- Returns:
Self– 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:
tuple[npt.NDArray[np.floating],npt.NDArray[np.floating]]– Returnssin(a), cos(a), whereais the angle between the segment and the longitudinal axis. The final values are of both arrays arenp.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.nanappended so the length of the output is the same as number of waypoints.- Parameters:
dtype (
npt.DTypeLike, optional) – Numpy dtype for time difference. Defaults tonp.float32- Returns:
npt.NDArray[np.floating]– Time difference between waypoints, [\(s\)]. Returns an array with dtype specified by``dtype``
- segment_groundspeed(smooth=False, window_length=7, polyorder=1)¶
Return groundspeed across segments.
Calculate by dividing the horizontal segment length by the difference in waypoint times.
- Parameters:
smooth (
bool, optional) – Smooth airspeed with Savitzky-Golay filter. Defaults to False.window_length (
int, optional) – Passed directly toscipy.signal.savgol_filter(), by default 7.polyorder (
int, optional) – Passed directly toscipy.signal.savgol_filter(), by default 1.
- 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])
See also
- segment_length()¶
Compute spherical distance between flight waypoints.
Helper function used in
length()andlength_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_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}\)]. Seesegment_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. Seeflight.FlightPhasefor enumeration.
See also
- 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_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.
The calculated ground speed will first be smoothed with a Savitzky-Golay filter if enabled.
- Parameters:
u_wind (
npt.NDArray[np.floating] | float) – U wind speed, [\(m \ s^{-1}\)]. Defaults to 0 for all waypoints.v_wind (
npt.NDArray[np.floating] | float) – V wind speed, [\(m \ s^{-1}\)]. Defaults to 0 for all waypoints.smooth (
bool, optional) – Smooth airspeed with Savitzky-Golay filter. Defaults to True.window_length (
int, optional) – Passed directly toscipy.signal.savgol_filter(), by default 7.polyorder (
int, optional) – Passed directly toscipy.signal.savgol_filter(), by default 1.
- Returns:
npt.NDArray[np.floating]– True wind speed of each segment, [\(m \ s^{-1}\)]
- 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 tokeys. Note that this method always returns aVectorDataset, even if the calling class is a proper subclass ofVectorDataset.
- setdefault(key, default=None)¶
Shortcut to
VectorDataDict.setdefault().- Parameters:
- Returns:
numpy.ndarray– Values atkey
- 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
VectorDatasetinstances.- Parameters:
vectors (
Sequence[VectorDataset]) – List ofVectorDatasetinstances to concatenate.infer_attrs (
bool, optional) – If True, infer attributes from the first element in the sequence.fill_value (
float | None, optional) – Fill value to use when concatenating arrays. By default None, which raises an error if incompatible keys are found.
- Returns:
Self– Sum of all instances invectors.- Raises:
KeyError – If incompatible
datakeys are found amongvectors.
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.DataFramein which each key-value pair indatais a column.DataFrame does not copy data by default. Use the
copyparameter 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
dataandattrs.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 aGeoVectorDataset, disregard any"altitude"or"level"coordinate and only include"altitude_ft"in the output.See also
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_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
datais grouped according to values ofkey. Each group gives rise to a Feature containing a MultiLineString geometry. Each MultiLineString can optionally be split over the antimeridian.
- to_geojson_points()¶
Return dataset as GeoJSON FeatureCollection of Points.
Each Feature has a properties attribute that includes
timeand other data besideslatitude,longitude, andaltitudeindata.- 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
traffic.core.Flightinstance.- Returns:
traffic.core.Flight– traffic flight instance- Raises:
ModuleNotFoundError – traffic package not installed
See also
- transform_crs(crs)¶
Transform trajectory data from one coordinate reference system (CRS) to another.
- Parameters:
crs (
str) – Target CRS. Passed into topyproj.Transformer. The source CRS is assumed to be EPSG:4326.- 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
datadict 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