Tools for working with X-Plane airport data
============================================================================================================================================================
[![CircleCI](https://circleci.com/gh/X-Plane/xplane_airports/tree/master.svg?style=svg)](https://circleci.com/gh/X-Plane/xplane_airports/tree/master)
`xplane_airports` is a Python package for interacting with [X-Plane](https://www.x-plane.com)'s airport data ([`apt.dat`](https://developer.x-plane.com/article/airport-data-apt-dat-file-format-specification/)) files.
This includes the following major components:
1. [The `AptDat` module](#the-aptdat-module): Used to parse & query raw `apt.dat` files (e.g., the files stored on disk in your X-Plane installation)
- The [`AptDat`](#aptdataptdat) class itself: A parser for X-Plane's airport data files (which may contain more than 35,000 airports); a collection of [`Airport`](#aptdatairport) objects
- The [`Airport`](#aptdatairport) class: Represents an individual airport from an `apt.dat` file.
2. [The `gateway` module](#the-gateway-module): Used to interact with [the X-Plane Scenery Gateway](https://gateway.x-plane.com) to get information about what airports are available, and to download individual scenery packs contributed by the community.
- [`airports()`](#xplane_airportsgatewayairports---dict): Queries for metadata on all 35,000+ airports on the Gateway.
- [`airport()`](#xplane_airportsgatewayairportairport_id---dict): Queries the Gateway for information about the specified airport itself, as well as metadata on all scenery packs submitted for it. Unlike [`scenery_pack()`](#xplane_airportsgatewayscenery_packpack_to_download---gatewayapt), though, this does *not* include actual `apt.dat` or DSF data.
- [`scenery_pack()`](#xplane_airportsgatewayscenery_packpack_to_download---gatewayapt): Downloads either the recommended pack for the specified airport, or the scenery pack with the specified `int` ID. Includes both the `apt.dat` data and DSF, where applicable.
- [`recommended_scenery_packs()`](#xplane_airportsgatewayrecommended_scenery_packsselective_apt_idsnone---collectionsiterablegatewayapt): A generator equivalent to calling [`scenery_pack()`](#xplane_airportsgatewayscenery_packpack_to_download---gatewayapt) to download the recommended scenery pack for every airport (or only a preselected list of airports, at your discretion).
## Installation instructions
`xplane_airports` requires Python 3.6 or newer.
Install via pip with:
`$ pip install xplane_airports`
## Sample code
### Parsing the default apt.dat file in your local X-Plane installation
```python
from xplane_airports.AptDat import AptDat, Airport
from pathlib import Path
xplane_installation = Path(input("Path to your X-Plane installation: "))
assert xplane_installation.is_dir(), f"{xplane_installation} does not exist or is not a directory"
print("Reading 35,000+ airports from disk (this will take awhile)")
default_xplane_apt_dat = AptDat(xplane_installation / 'Resources/default scenery/default apt dat/Earth nav data/apt.dat')
print(f"{len(default_xplane_apt_dat)} airports found in your default apt.dat\n")
ksea = default_xplane_apt_dat['KSEA']
""":type ksea: Airport"""
print("KSEA's airport data on disk begins:")
print(ksea.head())
```
### Getting metadata on airports from the Gateway
```python
from xplane_airports.gateway import airports
all_apts = airports()
print("There are %d airports on the X-Plane Scenery Gateway" % len(all_apts))
print("KSEA has the following metadata on the Gateway:")
for key, value in all_apts['KSEA'].items():
print('\t' + key + ':', value)
```
### Downloaded the recommended scenery pack for an airport from the Gateway
```python
from xplane_airports.gateway import scenery_pack, GatewayApt
ksea_recommended_pack = scenery_pack('KSEA')
""":type ksea_recommended_pack: GatewayApt"""
print("KSEA downloaded from the Gateway begins:")
print(ksea_recommended_pack.apt.head())
```
More sample code is available in the doctests in [the `gateway` module](#the-gateway-module) docs below.
## The `AptDat` module
Tools for reading, inspecting, and manipulating X-Plane’s airport (apt.dat) files.
### AptDat.AptDat
_class_ `AptDat.AptDat`(_path\_to\_file=None_)
A container class for [`Airport`](#aptdatairport) objects. Parses X-Plane’s gigantic `apt.dat` files, which may have data on tens of thousands of airports.
**Fields**
- `airports` (List\[Airport\])
- `xplane_version` (int): The version of the apt.dat spec used by the airports in this collection
**Static method** `from_file_text`(_apt\_dat\_file\_text_, _from\_file_) -> [`AptDat`](#aptdataptdat)\
Parameters:
- **apt\_dat\_file\_text** (_str_): The contents of an apt.dat (or ICAO.dat) file
- **from\_file** (_os.PathLike_): Path to the file from which this was read
**Property** `ids`\
A generator containing the X-Plane IDs of all airports in the collection. Note that these IDs may or may not correspond to the airports’ ICAO identifiers.\
Type: collection.Iterable\[str\]
**Property** `names`\
A generator containing the names of all airports in the collection\
Type: collection.Iterable\[str\]
**Method** `search_by_id`(_apt\_id_)\
Parameter: **apt\_id** (_str_) – The X-Plane ID of the airport you want to query\
Returns: The airport with the specified ID, or `None` if no matching airport exists in this collection.\
Return type: Optional\[[Airport](#aptdatairport)\]
**Method** `search_by_name`(_apt\_name_)\
Parameter: **apt\_name** (_str_) – The name of the airport you want to query\
Returns: All airports that match the specified name, case-insensitive (an empty list if no airports match)
Return type: list\[[Airport](#aptdatairport)\]
**Method** `search_by_predicate`(_predicate\_fn_)\
Parameter: **predicate\_fn** (_(_[_Airport_](#aptdatairport)_)_ _\-> bool_) – We will collect all airports for which this function returns `True`\
Return type: list\[[Airport](#aptdatairport)\]
**Method** `sort`(_key='name'_)\
By default, we store the airport data in whatever order we read it from the apt.dat file. When you call sort, though, we’ll ensure that it’s in order (default to name order, just like it’s always been in the shipping versions of X-Plane).\
Parameter: **key** (_str_) – The [Airport](#aptdatairport) key to sort on
**Method** `write_to_disk`(_path_to_write_to_)\
Writes a complete apt.dat file containing this entire collection of airports.\
Parameter: **path_to_write_to** (_Optional_\[_os.PathLike_\]) – A complete file path (ending in .dat); if `None`, we'll use the path we read this apt.dat in from.
### AptDat.Airport
A single airport from an apt.dat file.
_class_ `xplane_airports.AptDat.Airport`(_name: str_, _id: str_, _from\_file: str = ''_, _has\_atc: bool = False_, _elevation\_ft\_amsl: float = 0_, _text: List\[[AptDat.AptDatLine](#aptdataptdatline)\]=\[\]_)\
Dataclass members:
- _name_ (str): The name of the airport, like "Seattle-Tacoma Intl"
- _id_ (str): The X-Plane identifier for the airport, which may or may not correspond to its ICAO ID
- _from_file_ (_pathlib.Path_; default empty): Path to the `apt.dat` file from which this airport was read
- _has_atc_ (bool; default `False`): True if the airport header indicates the airport has air traffic control
- _elevation_ft_amsl_ (float; default 0): The elevation, in feat above mean sea level, indicated in the airport header line
- _text_ (List\[[AptDatLine](#aptdataptdatline)\]; default empty): The complete text of the portion of the apt.dat file pertaining to this airport
- _xplane_version_ (int; default 1100): The version of the X-Plane apt.dat spec this airport uses (e.g., 1050, 1100, 1130)
**Static method** `from_lines`(_apt\_dat\_lines_, _from\_file\_name_) -> [Airport](#aptdatairport)\
Parameters:\
- **from\_file\_name** (_str_) – The name of the apt.dat file you read this airport in from
- **apt\_dat\_lines** (_collections.Iterable\[[AptDatLine]