Open-source library to predict aircraft fuel flow from trajectory data using machine learning models
Project description
Acropole — Predict aircraft fuel flow from trajectory data
acropole predicts the fuel flow of aircraft (kg/s, kg/h and cumulative kg) from
trajectory data — groundspeed, altitude and vertical rate — using a portable ONNX
model trained on Quick Access Recorder (QAR) data. It accepts a pandas or polars
DataFrame, dispatches per aircraft typecode, and returns the same frame enriched with
fuel-flow columns. The runtime depends only on numpy + polars + onnxruntime — no heavy
ML framework.
Features
- ⛽ Fuel-flow prediction — per-sample
fuel_flow(kg/s),fuel_flow_kgh(kg/h) andfuel_cumsum(kg) from a flight trajectory - ✈️ Multi-aircraft — frames mixing several typecodes are scored per typecode, each row with its own aircraft parameters
- 🐼 pandas and polars —
estimate()accepts either and returns the same type; the engine runs on polars internally - 🚀 Fast ONNX runtime — migrated from TensorFlow, 2–4.8× faster depending on batch size, numerical parity validated to 1e-6; no TensorFlow dependency
- 📈 Temporal derivatives — supply a
secondcolumn to compute accelerations (andfuel_cumsum), or pass pre-computed derivatives directly - 🎯 Column mapping — map your own column names with keyword arguments, no renaming required
- ⚡ Typecode-bound fast path —
AircraftFuelEstimatoroffers numpy-only I/O with pre-computed parameters for hot loops - 🧪 Fully typed — ships
py.typed, strict mypy on source and tests, 98% coverage
Installation
acropole is published on PyPI:
uv add acropole # or: pip install acropole
The core library runs on numpy + polars + onnxruntime. To pass and receive pandas
DataFrames, install the optional pandas extra:
uv add "acropole[pandas]" # or: pip install "acropole[pandas]"
To work from source, this project uses uv:
git clone https://github.com/DGAC/Acropole.git
cd Acropole
uv sync
Quick Start
import pandas as pd
from acropole import FuelEstimator
fe = FuelEstimator()
flight = pd.DataFrame({
"typecode": ["A320", "A320", "A320", "A320"],
"groundspeed": [400, 410, 420, 430], # kt
"altitude": [10000, 11000, 12000, 13000], # ft
"vertical_rate": [2000, 1500, 1000, 500], # ft/min
# optional features:
"second": [0.0, 4.0, 8.0, 12.0],
"airspeed": [400, 410, 420, 430],
"mass": [60000, 60000, 60000, 60000],
})
flight_fuel = fe.estimate(flight)
# adds fuel_flow (kg/s), fuel_flow_kgh (kg/h), fuel_cumsum (kg)
Notes:
- Providing the
secondcolumn makes the estimation more accurate (it derives accelerations of the speeds) and enablesfuel_cumsum. airspeedis optional; if absent it defaults togroundspeed. Accurate airspeed improves the estimate.- The expected sampling rate is 4 seconds. A higher or lower rate produces noisier fuel flow — resample before estimating.
For a full notebook, see examples/fuel_estimation.ipynb.
Advanced Usage
Mapping your own column names
estimate() accepts keyword arguments mapping each logical feature to the column
name in your frame. The example flight (QAR columns) maps like this:
import pandas as pd
from acropole import FuelEstimator
flight = pd.read_csv("examples/example_flight.csv")
flight = flight.iloc[::4] # resample to ~4 s
fe = FuelEstimator()
flight_fuel = fe.estimate(
flight,
typecode="FLPL_AIRC_TYPE",
groundspeed="GRND_SPD_KT",
altitude="ALTI_STD_FT",
vertical_rate="VERT_SPD_FTMN",
second="FLIGHT_TIME",
airspeed="TRUE_AIR_SPD_KT",
mass="MASS_KG",
)
Required logical columns: typecode, groundspeed (kt), altitude (ft),
vertical_rate (ft/min). Optional: second, airspeed, mass, and the
pre-computed derivatives d_altitude / d_groundspeed / d_airspeed.
Multi-aircraft frames
A single frame can mix typecodes; each row is scored with its own aircraft
parameters. Unsupported typecodes emit a warning and leave fuel_flow as NaN:
flight = pd.DataFrame({
"typecode": ["A320", "A320", "B738", "B738"],
"groundspeed": [400, 410, 420, 430],
"altitude": [10000, 11000, 12000, 13000],
"vertical_rate": [2000, 1500, 1000, 500],
})
fe.estimate(flight) # A320 rows and B738 rows each use their own params
Typecode-bound fast path
For hot loops on a single aircraft, AircraftFuelEstimator works directly on numpy
arrays (no per-call params lookup) and returns fuel flow in kg/s:
import numpy as np
from acropole import FuelEstimator
# share the already-loaded ONNX session and parameters
afe = FuelEstimator().for_aircraft("A320")
fuel_flow = afe.estimate(
groundspeed=np.array([400.0, 410.0, 420.0]),
altitude=np.array([10000.0, 11000.0, 12000.0]),
vertical_rate=np.array([2000.0, 1500.0, 1000.0]),
) # kg/s (multiply by 3600 for kg/h)
Custom aircraft parameters and model
fe = FuelEstimator(
aircraft_params_path="path/to/your/aircraft_params.csv",
model_path="path/to/your/model.onnx",
)
Aircraft parameters from open data are bundled in src/acropole/data/aircraft_params.csv
and the ONNX model in src/acropole/models/; both are loaded by default.
Command-Line
Installing acropole also installs the acropole command (entry point
acropole.cli:main). It reads a flight from a CSV or parquet file, estimates fuel flow,
and writes the enriched table back to disk — adding fuel_flow (kg/s),
fuel_flow_kgh (kg/h) and, with --second, fuel_cumsum (kg):
acropole estimate examples/example_flight.csv \
--typecode FLPL_AIRC_TYPE --groundspeed GRND_SPD_KT --altitude ALTI_STD_FT \
--vertical-rate VERT_SPD_FTMN --airspeed TRUE_AIR_SPD_KT --mass MASS_KG \
--second FLIGHT_TIME --out result.csv
# wrote 7796 rows with fuel columns to result.csv
If your file already uses the standard column names, no mapping is needed and the output
defaults to <flight>_fuel.<ext> next to the input:
acropole estimate flight.csv # writes flight_fuel.csv
Each --typecode, --groundspeed, --altitude, --vertical-rate, --airspeed,
--mass and --second flag maps a logical feature to the matching column in your file
(defaults are the standard names). See the
CLI reference for all options.
Comparison of Different Model Performances
Comparison of different model performances per phase for 1000 test flights of A320-214 aircraft using real mass and true airspeed.
| Phase | Samples # | Metric | ACROPOLE | OpenAP | OpenAP V2 | BADA | Poll-Schumann |
|---|---|---|---|---|---|---|---|
| MAPE (%) | 2.13 | 30.35 | 8.84 | 6.53 | 6.85 | ||
| CLIMB | 1,403,850 | MAE (kg/min) | 1.66 | 25.81 | 6.92 | 5.53 | 5.65 |
| ME (kg/min) | 0.85 | -25.66 | -2.48 | -5.27 | -4.62 | ||
| MAPE (%) | 4.41 | 18.59 | 10.69 | 7.01 | 4.84 | ||
| LEVEL | 4,017,801 | MAE (kg/min) | 1.82 | 7.82 | 3.48 | 2.65 | 2.03 |
| ME (kg/min) | 1.22 | -7.47 | 2.64 | -1.43 | -0.73 | ||
| MAPE (%) | 12.63 | 51.69 | 32.4 | 21.50 | 21.55 | ||
| DESCENT | 1,684,117 | MAE (kg/min) | 2.71 | 8.62 | 5.58 | 3.71 | 4.71 |
| ME (kg/min) | 1.88 | -1.75 | -1.16 | -0.64 | -3.67 | ||
| MAPE (%) | 5.91 | 27.60 | 14.71 | 9.84 | 8.61 | ||
| ALL | 7,105,768 | MAE (kg/min) | 1.99 | 11.55 | 4.58 | 3.44 | 3.29 |
| ME (kg/min) | 1.30 | -9.92 | 0.84 | -2.03 | -2.09 | ||
| Processing time (s) | 3 | 284 | 255 | 474 | 28 |
The Acropole model is a neural network trained on Quick Access Recorder (QAR) data from several aircraft types. Evaluation and the list of supported aircraft are available at evaluation/Dense_Acropole_FuelFlow_Scaling.
Development
Set up a full development environment (runtime, dev, and docs groups):
uv sync --all-groups
Common tasks:
uv run pytest # run the test suite (98% coverage)
make lint # ruff + mypy strict on src AND tests
pre-commit install # enable the pre-commit hooks
License
Acropole is licensed under the GNU Affero General Public License v3.0 (AGPL-3.0). See the LICENSE file for the full text.
Credits
@inproceedings{jarry2024towards,
title={Towards aircraft generic Quick Access Recorder fuel flow regression models for ADS-B data},
author={Jarry, Gabriel and Delahaye, Daniel and Hurter, Christophe},
booktitle={International Conference on Research in Air Transportation},
year={2024}
}
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file acropole-0.1.2.tar.gz.
File metadata
- Download URL: acropole-0.1.2.tar.gz
- Upload date:
- Size: 541.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e297c70354539df5d24a6316e662105cd4972d3b579d93d66bbe46daf922fee1
|
|
| MD5 |
a766663f62581ad2fd262dba9119db9e
|
|
| BLAKE2b-256 |
45bf5347f571d0a9007951035bcbf003a3461c03ebd18bbb9cca739bd966df61
|
Provenance
The following attestation bundles were made for acropole-0.1.2.tar.gz:
Publisher:
publish.yml on DGAC/Acropole
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
acropole-0.1.2.tar.gz -
Subject digest:
e297c70354539df5d24a6316e662105cd4972d3b579d93d66bbe46daf922fee1 - Sigstore transparency entry: 1800967996
- Sigstore integration time:
-
Permalink:
DGAC/Acropole@2fafe3c2c2f7d5945463c1391e73654df6e64e07 -
Branch / Tag:
refs/tags/v0.1.2 - Owner: https://github.com/DGAC
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@2fafe3c2c2f7d5945463c1391e73654df6e64e07 -
Trigger Event:
push
-
Statement type:
File details
Details for the file acropole-0.1.2-py3-none-any.whl.
File metadata
- Download URL: acropole-0.1.2-py3-none-any.whl
- Upload date:
- Size: 60.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4d39ee8d0f26ef1426f628b7b8faa631dd16ab0bf214761a9c609ca7e631bbcc
|
|
| MD5 |
bae4e09443ce135c8eaf6505bb412fb2
|
|
| BLAKE2b-256 |
8a0e63de53371fb314df3b010d3c2a358b9d48498d86a5b1e0a6709f115a210d
|
Provenance
The following attestation bundles were made for acropole-0.1.2-py3-none-any.whl:
Publisher:
publish.yml on DGAC/Acropole
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
acropole-0.1.2-py3-none-any.whl -
Subject digest:
4d39ee8d0f26ef1426f628b7b8faa631dd16ab0bf214761a9c609ca7e631bbcc - Sigstore transparency entry: 1800968162
- Sigstore integration time:
-
Permalink:
DGAC/Acropole@2fafe3c2c2f7d5945463c1391e73654df6e64e07 -
Branch / Tag:
refs/tags/v0.1.2 - Owner: https://github.com/DGAC
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@2fafe3c2c2f7d5945463c1391e73654df6e64e07 -
Trigger Event:
push
-
Statement type: