- Introduction
- Installation
- Basic Usage
- Flight Analysis
- Dumping Flight Data
- Working with Tasks
- Command-line Usage
- API Reference
- Changelog
- Contributing
- License
- Additional Information
- Original Author
libigc is a Python library designed to parse and analyze IGC (International Gliding Commission) flight recorder logs. It provides functionality to detect thermals, analyze flight patterns, and extract valuable information from glider flight data.
- Parses IGC files and extracts flight data
- Detects takeoff and landing
- Identifies thermals and glides
- Calculates various flight statistics
- Supports task validation
- Provides data export in various formats (WPT, CUP, KML, CSV)
libigc requires Python 3.12 or newer. You can install it using pip:
pip install libigcHere's a simple example of how to use libigc to parse an IGC file and extract basic flight information:
from libigc import Flight
# Parse an IGC file
flight = Flight.create_from_file("path/to/your/file.igc")
# Check if the flight is valid
if flight.valid:
print("Flight is valid")
print(f"Takeoff time: {flight.takeoff_fix.timestamp}")
print(f"Landing time: {flight.landing_fix.timestamp}")
print(f"Number of thermals: {len(flight.thermals)}")
else:
print("Flight is invalid")
print("Reasons:", flight.notes)libigc provides various methods to analyze flight data:
# Iterate through thermals
for i, thermal in enumerate(flight.thermals):
print(f"Thermal {i + 1}:")
print(f" Start time: {thermal.enter_fix.timestamp}")
print(f" End time: {thermal.exit_fix.timestamp}")
print(f" Duration: {thermal.time_change()} seconds")
print(f" Altitude gain: {thermal.alt_change()} meters")
print(f" Average vertical velocity: {thermal.vertical_velocity():.2f} m/s")
# Analyze glides
for i, glide in enumerate(flight.glides):
print(f"Glide {i + 1}:")
print(f" Start time: {glide.enter_fix.timestamp}")
print(f" End time: {glide.exit_fix.timestamp}")
print(f" Duration: {glide.time_change()} seconds")
print(f" Distance: {glide.track_length:.2f} km")
print(f" Average speed: {glide.speed():.2f} km/h")
print(f" Glide ratio: {glide.glide_ratio():.2f}")
# Access individual fixes
for fix in flight.fixes:
print(f"Time: {fix.timestamp}, Lat: {fix.lat}, Lon: {fix.lon}, Alt: {fix.alt}")libigc provides functions to export flight data in various formats:
from libigc.lib.dumpers import (
dump_thermals_to_wpt_file,
dump_thermals_to_cup_file,
dump_flight_to_kml,
dump_flight_to_csv,
)
# Dump thermals to a .wpt file
dump_thermals_to_wpt_file(flight, "thermals.wpt")
# Dump thermals to a .cup file (SeeYou format)
dump_thermals_to_cup_file(flight, "thermals.cup")
# Dump flight to KML format
dump_flight_to_kml(flight, "flight.kml")
# Dump flight data to CSV files
dump_flight_to_csv(flight, "track.csv", "thermals.csv")libigc supports parsing and validating flight tasks:
from libigc import Task, Turnpoint
# Create a task from an LK8000 task file
task = Task.create_from_lkt_file("task.lkt")
# Or create a task manually
turnpoints = [
Turnpoint(lat=50.0, lon=14.0, radius=3.0, kind="start_exit"),
Turnpoint(lat=51.0, lon=15.0, radius=0.5, kind="cylinder"),
Turnpoint(lat=52.0, lon=16.0, radius=3.0, kind="goal_cylinder"),
]
task = Task(turnpoints, start_time=36000, end_time=64800) # 10:00 to 18:00
# Check if the flight completed the task
reached_turnpoints = task.check_flight(flight)
if len(reached_turnpoints) == len(task.turnpoints):
print("Task completed!")
else:
print(f"Reached {len(reached_turnpoints)} out of {len(task.turnpoints)} turnpoints")libigc comes with a demo script that can be run from the command line:
python examples/libigc_demo.py path/to/your/file.igcThis will print a summary of the flight and save thermal and track data to CSV files. Pass
-o <dir> to write the dumped files somewhere other than the current directory.
The Flight class is the main entry point for working with IGC files.
create_from_file(filename): Creates a Flight object from an IGC file._check_altitudes(): Validates altitude data._compute_ground_speeds(): Calculates ground speeds._compute_flight(): Determines flying status for each fix._compute_circling(): Detects circling (thermalling) behavior._find_thermals(): Identifies thermal segments in the flight.
fixes: List of GNSSFix objects.thermals: List of Thermal objects.glides: List of Glide objects.takeoff_fix: GNSSFix object representing takeoff.landing_fix: GNSSFix object representing landing.alt_source: Altitude data source ("PRESS" or "GNSS").valid: Boolean indicating if the flight data is valid.notes: List of notes about the flight data validity.
Represents a single fix in the IGC file.
timestamp: Unix timestamp of the fix.lat: Latitude in degrees.lon: Longitude in degrees.alt: Altitude in meters.ground_speed: Ground speed in km/h. (gspis kept as a deprecated alias.)bearing: Aircraft bearing in degrees.bearing_change_rate: Rate of bearing change in degrees/second.flying: Boolean indicating if the aircraft is flying at this fix.circling: Boolean indicating if the aircraft is circling at this fix.
Represents a thermal detected in the flight.
time_change(): Duration of the thermal in seconds.alt_change(): Altitude gained in the thermal in meters.vertical_velocity(): Average vertical velocity in m/s.
enter_fix: GNSSFix object at the start of the thermal.exit_fix: GNSSFix object at the end of the thermal.
Represents a glide between thermals.
time_change(): Duration of the glide in seconds.speed(): Average ground speed during the glide in km/h.alt_change(): Altitude change during the glide in meters.glide_ratio(): Glide ratio (distance traveled / altitude lost).
enter_fix: GNSSFix object at the start of the glide.exit_fix: GNSSFix object at the end of the glide.track_length: Total track length of the glide in kilometers.
Represents a flight task.
create_from_lkt_file(filename): Creates a Task object from an LK8000 task file.check_flight(flight): Checks if a Flight object has completed the task.
turnpoints: List of Turnpoint objects.start_time: Task start time (seconds past midnight).end_time: Task end time (seconds past midnight).
Represents a single turnpoint in a task.
in_radius(fix): Checks if a GNSSFix is within the turnpoint's radius.
lat: Latitude of the turnpoint in degrees.lon: Longitude of the turnpoint in degrees.radius: Radius of the turnpoint cylinder in kilometers.kind: Type of turnpoint (e.g., "start_exit", "cylinder", "goal_cylinder").
See CHANGELOG.md. Note that 1.2.0 raises the minimum Python to
3.12 and changes what str() returns for AltitudeSource and FixValidity.
If you find an IGC file that libigc doesn't handle correctly, please open an issue on the GitHub repository. Include the problematic IGC file and a description of the expected behavior.
To contribute code:
- Fork the repository.
- Create a new branch for your feature or bug fix.
- Write tests for your changes.
- Implement your changes.
- Run
make testto format-check, lint and run the test suite. - Submit a pull request with a clear description of your changes.
Formatting and linting are both handled by ruff, configured in
pyproject.toml. The enabled rule sets are E (pycodestyle), F (pyflakes), I (import
sorting), UP (pyupgrade) and B (bugbear), on top of the default ruff format style: 88
columns, double quotes.
make format # apply the formatter and every autofixable lint rule
make lint # check only, no writeslibigc is released under the MIT License. See the LICENSE file in the repository for full details.
Whatever is on master is what is published. There is no release to cut and nothing to
approve: merging a pull request builds, tests and uploads to PyPI.
To ship a new version, bump it in the pull request:
make bump-patch # or bump-minor / bump-majorMerge it, and the Publish workflow uploads that version and tags the commit. Merges that
do not change the version are safe; that version is already on PyPI, so the upload is
skipped and the run stays green.
Publishing uses trusted publishing (OpenID Connect). There is no API token: PyPI verifies a
short-lived identity token minted by GitHub for this repository, the publish.yml workflow
and the release environment.
To rehearse against test.pypi.org, run the Publish workflow
manually with the testpypi option. That needs its own trusted publisher registered there,
since the two indexes do not share configuration.
The make publish and make test-publish targets still work for a local upload with
twine, but the workflow is the supported path.