aerofiles.igc

The IGC file format is used by glide computers to record flights.

class aerofiles.igc.Reader

A reader for the IGC flight log file format.

Example:

>>> with open('track.igc', 'r') as f:
...     parsed = Reader().read(f)
read(file_obj)

Read the specified file object and return a dictionary with the parsed data.

Parameters:

file_obj – a Python file object

class aerofiles.igc.Writer(fp=None)

A writer for the IGC flight log file format.

write_club(club)

Write the optional club declaration header:

writer.write_club('LV Aachen')
# -> HFCLBCLUB:LV Aachen
Parameters:

club – club or organisation for which this flight should be scored

write_comment(code, text)

Write a comment record:

writer.write_comment('PLT', 'Arrived at the first turnpoint')
# -> LPLTArrived at the first turnpoint
Parameters:
  • code – a three-letter-code describing the source of the comment (e.g. PLT for pilot)

  • text – the text that should be added to the comment

write_competition_class(competition_class)

Write the optional competition class declaration header:

writer.write_competition_class('Club')
# -> HFCCLCOMPETITIONCLASS:Club
Parameters:

competition_class – competition class of the glider

write_competition_id(competition_id)

Write the optional competition id declaration header:

writer.write_competition_id('TH')
# -> HFCIDCOMPETITIONID:TH
Parameters:

competition_id – competition id of the glider

write_copilot(copilot)

Write the copilot declaration header:

writer.write_copilot('John Doe')
# -> HFCM2CREW2:John Doe
Parameters:

copilot – name of the copilot

write_date(date)

Write the date header:

writer.write_date(datetime.date(2014, 5, 2))
# -> HFDTE140502
Parameters:

date – a datetime.date instance

write_event(*args)

Write an event record:

writer.write_event(datetime.time(12, 34, 56), 'PEV')
# -> B123456PEV

writer.write_event(datetime.time(12, 34, 56), 'PEV', 'Some Text')
# -> B123456PEVSome Text

writer.write_event('PEV')  # uses utcnow()
# -> B121503PEV
Parameters:
  • time – UTC time of the fix record (default: utcnow())

  • code – event type as three-letter-code

  • text – additional text describing the event (optional)

write_firmware_version(firmware_version)

Write the firmware version header:

writer.write_firmware_version('6.4')
# -> HFRFWFIRMWAREVERSION:6.4
Parameters:

firmware_version – the firmware version of the flight recorder

write_fix(time=None, latitude=None, longitude=None, valid=False, pressure_alt=None, gps_alt=None, extensions=None)

Write a fix record:

writer.write_fix(
    datetime.time(12, 34, 56),
    latitude=51.40375,
    longitude=6.41275,
    valid=True,
    pressure_alt=1234,
    gps_alt=1432,
)
# -> B1234565124225N00624765EA0123401432
Parameters:
  • time – UTC time of the fix record (default: utcnow())

  • latitude – longitude of the last GPS fix

  • longitude – latitude of the last GPS fix

  • validTrue if the current GPS fix is 3D

  • pressure_alt – altitude to the ICAO ISA above the 1013.25 hPa sea level datum

  • gps_alt – altitude above the WGS84 ellipsoid

  • extensions – a list of extension values according to previous declaration through write_fix_extensions()

write_fix_accuracy(accuracy=None)

Write the GPS fix accuracy header:

writer.write_fix_accuracy()
# -> HFFXA500

writer.write_fix_accuracy(25)
# -> HFFXA025
Parameters:

accuracy – the estimated GPS fix accuracy in meters (optional)

write_fix_extensions(extensions)

Write the fix extensions description header:

writer.write_fix_extensions([('FXA', 3), ('SIU', 2), ('ENL', 3)])
# -> I033638FXA3940SIU4143ENL
Parameters:

extensions – a list of (extension, length) tuples

write_glider_id(glider_id)

Write the glider id declaration header:

writer.write_glider_id('D-4449')
# -> HFGIDGLIDERID:D-4449

The glider id is usually the official registration number of the airplane. For example:D-4449 or N116EL.

Parameters:

glider_id – the glider registration number

write_glider_type(glider_type)

Write the glider type declaration header:

writer.write_glider_type('Hornet')
# -> HFGTYGLIDERTYPE:Hornet
Parameters:

glider_type – the glider type (e.g. Hornet)

write_gps_datum(code=None, gps_datum=None)

Write the mandatory GPS datum header:

writer.write_gps_datum()
# -> HFDTM100GPSDATUM:WGS-1984

writer.write_gps_datum(33, 'Guam-1963')
# -> HFDTM033GPSDATUM:Guam-1963

Note that the default GPS datum is WGS-1984 and you should use that unless you have very good reasons against it.

Parameters:
  • code – the GPS datum code as defined in the IGC file specification, section A8

  • gps_datum – the GPS datum in written form

write_gps_receiver(gps_receiver)

Write the GPS receiver header:

writer.write_gps_receiver('uBLOX LEA-4S-2,16,max9000m')
# -> HFGPSuBLOX LEA-4S-2,16,max9000m
Parameters:

gps_receiver – the GPS receiver information

write_hardware_version(hardware_version)

Write the hardware version header:

writer.write_hardware_version('1.2')
# -> HFRHWHARDWAREVERSION:1.2
Parameters:

hardware_version – the hardware version of the flight recorder

write_headers(headers)

Write all the necessary headers in the correct order:

writer.write_headers({
    'manufacturer_code': 'XCS',
    'logger_id': 'TBX',
    'date': datetime.date(1987, 2, 24),
    'fix_accuracy': 50,
    'pilot': 'Tobias Bieniek',
    'copilot': 'John Doe',
    'glider_type': 'Duo Discus',
    'glider_id': 'D-KKHH',
    'firmware_version': '2.2',
    'hardware_version': '2',
    'logger_type': 'LXNAVIGATION,LX8000F',
    'gps_receiver': 'uBLOX LEA-4S-2,16,max9000m',
    'pressure_sensor': 'INTERSEMA,MS5534A,max10000m',
    'competition_id': '2H',
    'competition_class': 'Doubleseater',
})

# -> AXCSTBX
# -> HFDTE870224
# -> HFFXA050
# -> HFPLTPILOTINCHARGE:Tobias Bieniek
# -> HFCM2CREW2:John Doe
# -> HFGTYGLIDERTYPE:Duo Discus
# -> HFGIDGLIDERID:D-KKHH
# -> HFDTM100GPSDATUM:WGS-1984
# -> HFRFWFIRMWAREVERSION:2.2
# -> HFRHWHARDWAREVERSION:2
# -> HFFTYFRTYPE:LXNAVIGATION,LX8000F
# -> HFGPSRECEIVER:uBLOX LEA-4S-2,16,max9000m
# -> HFPRSPRESSALTSENSOR:INTERSEMA,MS5534A,max10000m
# -> HFCIDCOMPETITIONID:2H
# -> HFCCLCOMPETITIONCLASS:Doubleseater

This method will throw a ValueError if a mandatory header is missing and will fill others up with empty strings if no value was given. The optional headers are only written if they are part of the specified dict.

Note

The use of this method is encouraged compared to calling all the other header-writing methods manually!

Parameters:

headers – a dict of all the headers that should be written.

write_k_record(*args)

Write a K record:

writer.write_k_record_extensions([
    ('FXA', 3), ('SIU', 2), ('ENL', 3),
])

writer.write_k_record(datetime.time(2, 3, 4), ['023', 13, 2])

# -> J030810FXA1112SIU1315ENL
# -> K02030402313002
Parameters:
  • time – UTC time of the k record (default: utcnow())

  • extensions – a list of extension values according to previous declaration through write_k_record_extensions()

write_k_record_extensions(extensions)

Write the K record extensions description header:

writer.write_k_record_extensions([('HDT', 5)])
# -> J010812HDT

Use write_k_record() to write the associated records.

Parameters:

extensions – a list of (extension, length) tuples

write_logger_id(manufacturer, logger_id, extension=None, validate=True)

Write the manufacturer and logger id header line:

writer.write_logger_id('XXX', 'ABC', extension='FLIGHT:1')
# -> AXXXABCFLIGHT:1

Some older loggers have decimal logger ids which can be written like this:

writer.write_logger_id('FIL', '13961', validate=False)
# -> AFIL13961
Parameters:
  • manufacturer – the three-letter-code of the manufacturer

  • logger_id – the logger id as three-letter-code

  • extension – anything else that should be appended to this header (e.g. FLIGHT:1)

  • validate – whether to validate the manufacturer and logger_id three-letter-codes

write_logger_type(logger_type)

Write the extended logger type header:

writer.write_logger_type('Flarm-IGC')
# -> HFFTYFRTYPE:Flarm-IGC
Parameters:

logger_type – the extended type information of the flight recorder

write_pilot(pilot)

Write the pilot declaration header:

writer.write_pilot('Tobias Bieniek')
# -> HFPLTPILOTINCHARGE:Tobias Bieniek
Parameters:

pilot – name of the pilot

write_pressure_sensor(pressure_sensor)

Write the pressure sensor header:

writer.write_pressure_sensor('Intersema MS5534B,8191')
# -> HFPRSPRESSALTSENSOR:Intersema MS5534B,8191
Parameters:

pressure_sensor – the pressure sensor information

write_satellites(*args)

Write a satellite constellation record:

writer.write_satellites(datetime.time(12, 34, 56), [1, 2, 5, 22])
# -> F12345601020522
Parameters:
  • time – UTC time of the satellite constellation record (default: utcnow())

  • satellites – a list of satellite IDs as either two-character strings or integers below 100

write_security(security, bytes_per_line=75)

Write the security signature:

writer.write_security('ABCDEF')
# -> GABCDEF

If a signature of more than 75 bytes is used the G record will be broken into multiple lines according to the IGC file specification. This rule can be configured with the bytes_per_line parameter if necessary.

Parameters:
  • security – the security signature

  • bytes_per_line – the maximum number of bytes per line (default: 75)

write_task_metadata(declaration_datetime=None, flight_date=None, task_number=None, turnpoints=None, text=None)

Write the task declaration metadata record:

writer.write_task_metadata(
    datetime.datetime(2014, 4, 13, 12, 53, 02),
    task_number=42,
    turnpoints=3,
)
# -> C140413125302000000004203

There are sensible defaults in place for all parameters except for the turnpoints parameter. If you don’t pass that parameter the method will raise a ValueError. The other parameter defaults are mentioned in the list below.

Parameters:
  • declaration_datetime – a datetime.datetime instance of the UTC date and time at the time of declaration (default: current date and time)

  • flight_date – a datetime.date instance of the intended date of the flight (default: 000000, which means “use declaration date”)

  • task_number – task number for the flight date or an integer-based identifier (default: 0001)

  • turnpoints – the number of turnpoints in the task (not counting start and finish points!)

  • text – optional text to append to the metadata record

write_task_point(latitude=None, longitude=None, text='', distance_min=None, distance_max=None, bearing1=None, bearing2=None)

Write a task declaration point:

writer.write_task_point(
    latitude=(51 + 7.345 / 60.),
    longitude=(6 + 24.765 / 60.),
    text='Meiersberg',
)
# -> C5107345N00624765EMeiersberg

If no latitude or longitude is passed, the fields will be filled with zeros (i.e. unknown coordinates). This however should only be used for TAKEOFF and LANDING points.

For area tasks there are some additional parameters that can be used to specify the relevant areas:

writer.write_task_point(
    -(12 + 32.112 / 60.),
    -(178 + .001 / 60.),
    'TURN AREA',
    distance_min=12.0,
    distance_max=32.0,
    bearing1=122.0,
    bearing2=182.0,
)
# -> C1232112S17800001W00120000032000122000182000TURN AREA
Parameters:
  • latitude – latitude of the point (between -90 and 90 degrees)

  • longitude – longitude of the point (between -180 and 180 degrees)

  • text – type and/or name of the waypoint (e.g. TAKEOFF, START, TURN 1, TURN 2, FINISH or LANDING)

write_task_points(points)

Write multiple task declaration points with one call:

writer.write_task_points([
    (None, None, 'TAKEOFF'),
    (51.40375, 6.41275, 'START'),
    (50.38210, 8.82105, 'TURN 1'),
    (50.59045, 7.03555, 'TURN 2', 0, 32.5, 0, 180),
    (51.40375, 6.41275, 'FINISH'),
    (None, None, 'LANDING'),
])
# -> C0000000N00000000ETAKEOFF
# -> C5124225N00624765ESTART
# -> C5022926N00849263ETURN 1
# -> C5035427N00702133E00000000032500000000180000TURN 2
# -> C5124225N00624765EFINISH
# -> C0000000N00000000ELANDING

see the write_task_point() method for more information.

Parameters:

points – a list of (latitude, longitude, text) tuples. use (latitude, longitude, text, distance_min, distance_max, bearing1, bearing2) tuples for area task points.