pycontrails.core.flight#
Flight Data Handling.
Module Attributes
Max airport elevation, [\(ft\)] See Daocheng_Yading_Airport |
|
Min estimated cruise altitude, [\(ft\)] |
|
Short haul duration cutoff, [\(s\)] |
|
Set maximum speed compatible with "on_ground" indicator, [\(mph\)] Thresholds assessed based on scatter plot (150 knots = 278 km/h) |
Functions
|
Filter noisy altitude on a single flight. |
|
Use piecewise linear fitting to smooth a flight profile. |
|
Calculate the time difference between waypoints. |
|
Identify the phase of flight (climb, cruise, descent) for each segment. |
|
Calculate the rate of climb and descent (ROCD). |
Classes
|
A single flight trajectory. |
|
Flight phase enumeration. |
- class pycontrails.core.flight.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:
GeoVectorDataset
A single flight trajectory.
Expect latitude-longitude coordinates in WGS 84. Expect altitude in [\(m\)]. Expect pressure level (level) in [\(hPa\)].
Use the attribute
attrs["crs"]
to specify coordinate reference system using PROJ or EPSG syntax.- Parameters:
data (
dict[str
,np.ndarray] | pd.DataFrame | VectorDataDict | VectorDataset | None
) – Flight trajectory waypoints as data dictionary orpandas.DataFrame
. Must include columnstime
,latitude
,longitude
,altitude
orlevel
. Keyword arguments fortime
,latitude
,longitude
,altitude
orlevel
will overridedata
inputs. Expectsaltitude
in meters andtime
as a DatetimeLike (or array that can processed withpd.to_datetime()
). Additional waypoint-specific data can be included as additional keys/columns.longitude (
npt.ArrayLike
, optional) – Flight trajectory waypoint longitude. Defaults to None.latitude (
npt.ArrayLike
, optional) – Flight trajectory waypoint latitude. Defaults to None.altitude (
npt.ArrayLike
, optional) – Flight trajectory waypoint altitude, [\(m\)]. Defaults to None.altitude_ft (
npt.ArrayLike
, optional) – Flight trajectory waypoint altitude, [\(ft\)].level (
npt.ArrayLike
, optional) – Flight trajectory waypoint pressure level, [\(hPa\)]. Defaults to None.time (
npt.ArrayLike
, optional) – Flight trajectory waypoint time. Defaults to None.attrs (
dict[str
,Any]
, 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 forFleet
interoperability.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.
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
, 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
data
input does not contain at leasttime
,latitude
,longitude
, (altitude
orlevel
).
Notes
The Traffic library has many helpful flight processing utilities.
See
traffic.core.Flight
for 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, 2 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 crs EPSG:4326
>>> # 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, 1 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] crs EPSG:4326
>>> # 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
- copy()#
Return a copy of this VectorDatasetType class.
- Returns:
VectorDatasetType
– Copy of class
- property duration#
Determine flight duration.
- Returns:
pd.Timedelta
– Difference between terminal and initial time
- 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
- fit_altitude(max_segments=30, pop=3, r2_target=0.999, max_cruise_rocd=10.0, sg_window=7, sg_polyorder=1)#
Use piecewise linear fitting to smooth a flight profile.
Fit a flight profile to a series of line segments. Segments that have a small rocd will be set to have a slope of zero and snapped to the nearest thousand foot level. A Savitzky-Golay filter will then be applied to the profile to smooth the climbs and descents. This filter works best for high frequency flight data, sampled at a 1-3 second sampling period.
- Parameters:
max_segments (
int
, optional) – The maximum number of line segements to fit to the flight profile.pop (
int
, optional) – Population parameter used for the stocastic optimization routine used to fit the flight profile.r2_target (
float
, optional) – Target r^2 value for solver. Solver will continue to add line segments until the resulting r^2 value is greater than this.max_cruise_rocd (
float
, optional) – The maximum ROCD for a segment that will be forced to a slope of zero, [\(ft s^{-1}\)]sg_window (
int
, optional) – Parameter forscipy.signal.savgol_filter()
sg_polyorder (
int
, optional) – Parameter forscipy.signal.savgol_filter()
- Returns:
Flight
– Smoothed flight
- fuel#
Fuel used in flight trajectory
- property length#
Return flight length based on WGS84 geodesic.
- Returns:
float
– Total flight length, [\(m\)]- Raises:
NotImplementedError – Raises when attr:attrs[“crs”] is not EPSG:4326
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 1436924.67...
- length_met(key, threshold=1.0)#
Calculate total horizontal distance where column
key
exceedsthreshold
.- Parameters:
- Returns:
float
– Total distance, [\(m\)]- Raises:
KeyError –
data
does not contain columnkey
NotImplementedError – Raised when
attrs["crs"]
is not EPSG:4326
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.94658, 235.95767, 235.96873, ..., 234.59918, 234.60388, 234.60846], dtype=float32)
>>> # Length (in meters) of waypoints whose temperature exceeds 236K >>> fl.length_met("air_temperature", threshold=236) 4132178.159...
>>> # Proportion (with respect to distance) of waypoints whose temperature exceeds 236K >>> fl.proportion_met("air_temperature", threshold=236) 0.663552...
- 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\)]- Raises:
NotImplementedError – Raises when attr:attrs[“crs”] is not EPSG:4326
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 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
- proportion_met(key, threshold=1.0)#
Calculate proportion of flight with certain meteorological constraint.
- resample_and_fill(freq='1T', fill_method='geodesic', geodesic_threshold=100000.0, nominal_rocd=12.7, drop=True, keep_original_index=False, climb_descend_at_end=False)#
Resample and fill flight trajectory with geodesics and linear interpolation.
Waypoints are resampled according to the frequency
freq
. Values fordata
columnslongitude
,latitude
, andaltitude
are interpolated.- Parameters:
freq (
str
, optional) – Resampling frequency, by default “1T”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 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 withnan
orNone
values, depending on the data type.keep_original_index (
bool
, optional) – Keep the original index of theFlight
in addition to the new resampled index. Defaults toFalse
. .. versionadded:: 0.45.2climb_or_descend_at_end (
bool
) – If true, the climb or descent will be placed at the end of each segment rather than the start. Default is false (climb or descent immediately).
- 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('10T').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.float_]
,npt.NDArray[np.float_]
– Returnssin(a), cos(a)
, wherea
is 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.float_]
– 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 tonp.float64
- Returns:
npt.NDArray[np.float_]
– 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.float_]
– Groundspeed of the segment, [\(m s^{-1}\)]
- 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.float_]
– Array of distances in [\(m\)] between waypoints- Raises:
NotImplementedError – Raises when attr:attrs[“crs”] is not EPSG:4326
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.float_]
) – True airspeed of the segment, [\(m \ s^{-1}\)]. Seesegment_true_airspeed()
.air_temperature (
npt.NDArray[np.float_]
) – Average air temperature of each segment, [\(K\)]
- Returns:
npt.NDArray[np.float_]
– Mach number of each segment
- segment_phase(threshold_rocd=250.0, min_cruise_altitude_ft=20000.0)#
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.
- Returns:
npt.NDArray[np.uint8]
– Array of values enumerating the flight phase. Seeflight.FlightPhase
for enumeration.
See also
- segment_rocd()#
Calculate the rate of climb and descent (ROCD).
- Returns:
npt.NDArray[np.float_]
– 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.float_] | float
) – U wind speed, [\(m \ s^{-1}\)]. Defaults to 0 for all waypoints.v_wind (
npt.NDArray[np.float_] | 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.float_]
– True wind speed of each segment, [\(m \ s^{-1}\)]
- 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_geojson_linestring()#
Return trajectory as geojson FeatureCollection containing single LineString.
- Returns:
dict[str
,Any]
– Python representation of geojson FeatureCollection
- to_geojson_multilinestring(key, split_antimeridian=True)#
Return trajectory as GeoJSON FeatureCollection of MultiLineStrings.
Flight
data
is grouped according to values ofkey
. Each group gives rise to a Feature containing a MultiLineString geometry. LineStrings can be split over the antimeridian.- Parameters:
- Returns:
dict[str
,Any]
– Python representation of GeoJSON FeatureCollection of MultiLinestring Features- Raises:
KeyError –
data
does not contain columnkey
- to_traffic()#
Convert Flight instance to
traffic.core.Flight
instance.See https://traffic-viz.github.io/traffic.core.flight.html#traffic.core.Flight
- Returns:
traffic.core.Flight
– traffic.core.Flight instance- Raises:
ModuleNotFoundError – traffic package not installed
- class pycontrails.core.flight.FlightPhase(value, names=None, *values, module=None, qualname=None, type=None, start=1, boundary=None)#
Bases:
IntEnum
Flight phase enumeration.
Use
segment_phase()
orFlight.segment_phase()
to determine flight phase.- CLIMB = 1#
Waypoints at which the flight is in a climb phase
- CRUISE = 2#
Waypoints at which the flight is in a cruise phase
- DESCENT = 3#
Waypoints at which the flight is in a descent phase
- LEVEL_FLIGHT = 4#
Waypoints at which the flight is not in a climb, cruise, or descent phase. In practice, this category is used for waypoints at which the ROCD resembles that of a cruise phase, but the altitude is below the minimum cruise altitude.
- NAN = 5#
Waypoints at which the ROCD is not defined.
- pycontrails.core.flight.MAX_AIRPORT_ELEVATION = 15000.0#
Max airport elevation, [\(ft\)] See Daocheng_Yading_Airport
- pycontrails.core.flight.MAX_ON_GROUND_SPEED = 150.0#
Set maximum speed compatible with “on_ground” indicator, [\(mph\)] Thresholds assessed based on scatter plot (150 knots = 278 km/h)
- pycontrails.core.flight.MIN_CRUISE_ALTITUDE = 20000.0#
Min estimated cruise altitude, [\(ft\)]
- pycontrails.core.flight.SHORT_HAUL_DURATION = 3600.0#
Short haul duration cutoff, [\(s\)]
- pycontrails.core.flight.filter_altitude(altitude, *, kernel_size=17)#
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.Todo
This method assumes that the time interval between altitude points (
segment_duration()
) is moderately small (e.g. minutes). This filter may not work as well when waypoints are close (seconds) or farther apart in time (e.g. 30 minutes).The optimal altitude filter is a work in a progress and may change in the future.
- Parameters:
altitude (
npt.NDArray[np.float_]
) – Altitude signalkernel_size (
int
, optional) – Passed directly toscipy.signal.medfilt()
, by default 11. Passed also toscipy.signal.medfilt()
- Returns:
npt.NDArray[np.float_]
– Filtered altitude
Notes
Algorithm is derived from
traffic.core.flight.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()
- pycontrails.core.flight.fit_altitude(elapsed_time, altitude_ft, *, max_segments=30, pop=3, r2_target=0.999, max_cruise_rocd=10.0, sg_window=7, sg_polyorder=1)#
Use piecewise linear fitting to smooth a flight profile.
Fit a flight profile to a series of line segments. Segments that have a small rocd will be set to have a slope of zero and snapped to the nearest thousand foot level. A Savitzky-Golay filter will then be applied to the profile to smooth the climbs and descents. This filter works best for high frequency flight data, sampled at a 1-3 second sampling period.
- Parameters:
elapsed_time (
npt.NDArray[np.float_]
) – Cumulative time of flight between waypoints, [\(s\)]altitude_ft (
npt.NDArray[np.float_]
) – Altitude of each waypoint, [\(ft\)max_segments (
int
, optional) – The maximum number of line segements to fit to the flight profile.pop (
int
, optional) – Population parameter used for the stocastic optimization routine used to fit the flight profile.r2_target (
float
, optional) – Target r^2 value for solver. Solver will continue to add line segments until the resulting r^2 value is greater than this.max_cruise_rocd (
float
, optional) – The maximum ROCD for a segment that will be forced to a slope of zero, [\(ft s^{-1}\)]sg_window (
int
, optional) – Parameter forscipy.signal.savgol_filter()
sg_polyorder (
int
, optional) – Parameter forscipy.signal.savgol_filter()
- Returns:
npt.NDArray[np.float_]
– Smoothed flight altitudes
- pycontrails.core.flight.segment_duration(time, dtype=<class 'numpy.float32'>)#
Calculate the time difference between waypoints.
np.nan
appended so the length of the output is the same as number of waypoints.- Parameters:
time (
npt.NDArray[np.datetime64]
) – Waypoint time innp.datetime64
format.dtype (
np.dtype
) – Numpy dtype for time difference. Defaults tonp.float64
- Returns:
npt.NDArray[np.float_]
– Time difference between waypoints, [\(s\)]. This returns an array with dtype specified by``dtype``.
- pycontrails.core.flight.segment_phase(rocd, altitude_ft, *, threshold_rocd=250.0, min_cruise_altitude_ft=20000.0)#
Identify the phase of flight (climb, cruise, descent) for each segment.
- Parameters:
rocd (
pt.NDArray[np.float_]
) – Rate of climb and descent across segment, [\(ft min^{-1}\)]. See output fromsegment_rocd()
.altitude_ft (
npt.NDArray[np.float_]
) – Altitude, [\(ft\)]threshold_rocd (
float
, optional) – ROCD threshold to identify climb and descent, [\(ft min^{-1}\)]. Defaults to 250 ft/min.min_cruise_altitude_ft (
float
, optional) – Minimum threshold altitude for cruise, [\(ft\)] This is specific for each aircraft type, and can be approximated as 50% of the altitude ceiling. Defaults toMIN_CRUISE_ALTITUDE
.
- Returns:
npt.NDArray[np.uint8]
– Array of values enumerating the flight phase. Seeflight.FlightPhase
for enumeration.
Notes
Flight data derived from ADS-B and radar sources could contain noise leading to small changes in altitude and ROCD. Hence, an arbitrary
threshold_rocd
is specified to identify the different phases of flight.The flight phase “level-flight” is when an aircraft is holding at lower altitudes. The cruise phase of flight only occurs above a certain threshold altitude.
See also
- pycontrails.core.flight.segment_rocd(segment_duration, altitude_ft)#
Calculate the rate of climb and descent (ROCD).
- Parameters:
segment_duration (
npt.NDArray[np.float_]
) – Time difference between waypoints, [\(s\)]. Expected to have numeric dtype, not “timedelta64”. See output fromsegment_duration()
.altitude_ft (
npt.NDArray[np.float_]
) – Altitude of each waypoint, [\(ft\)]
- Returns:
npt.NDArray[np.float_]
– Rate of climb and descent over segment, [\(ft min^{-1}\)]
See also