Skip to content
scipython.com

P6.2.2Airport distances

The file busiest_airports.txt provides details of the 30 busiest airports in the world in 2014. The tab-delimited fields are: three-letter IATA code, airport name, airport location, latitude and longitude (both in degrees).

Write a program to determine the distance between two airports identified by their three-letter IATA code, using the Haversine formula (see, for example, Exercise 4.4.2) and assuming a spherical Earth of radius 6378.1 km).

Show solution

This solution uses a structured array. Note that the strings in this array are bytestrings and so for comparison and output we must encode and decode appropriately.

airportdistances
import sys
import numpy as np

haversin = lambda alpha: np.sin(alpha / 2) ** 2


def gc_distance(airport_coords1, airport_coords2):
    """
    Return the great-circle distance between two coordinates on the Earth
    provided as two (latitude, longitude) tuples in radians.

    """

    # Earth's radius, km
    R = 6378.1
    (phi1, lambda1), (phi2, lambda2) = airport_coords1, airport_coords2
    d = (
        2
        * R
        * np.arcsin(
            np.sqrt(
                haversin(phi2 - phi1)
                + np.cos(phi1) * np.cos(phi2) * haversin(lambda2 - lambda1)
            )
        )
    )
    return d


iata1, iata2 = sys.argv[1:]

dt = np.dtype(
    [
        ("IATA", "S50"),
        ("Name", "S50"),
        ("Location", "S50"),
        ("Latitude", "f8"),
        ("Longitude", "f8"),
    ]
)

to_radians = lambda alpha: np.radians(float(alpha))
airports = np.loadtxt(
    "busiest_airports.txt",
    dtype=dt,
    delimiter="\t",
    converters={3: to_radians, 4: to_radians},
)


def get_airport(iata):
    """
    Return the airport with IATA code iata from the airports array or
    raise an Exception if it isn't recognised.

    """

    b_iata = bytes(iata, encoding="ascii")
    airport = airports[airports["IATA"] == b_iata]
    # check we retrieved an airport: NB we can't use assert airport, ...
    # because of a bug in numpy versions older than 1.8
    assert len(airport) == 1, "Airport not recognised: {:s}".format(iata)
    return airport


airport1 = get_airport(iata1)
airport2 = get_airport(iata2)
airport_coords1 = airport1[["Latitude", "Longitude"]][0]
airport_coords2 = airport2[["Latitude", "Longitude"]][0]
airport_name1 = airport1["Name"][0].decode()
airport_name2 = airport2["Name"][0].decode()
d = gc_distance(airport_coords1, airport_coords2)

print(
    f"Distance from {airport_name1:s} ({iata1:3s}) to {airport_name2:s}"
    f" ({iata2:3s}) is {int(d):d} km"
)

For example:

$ python airport-distances.py SFO LHR
Distance from San Francisco International Airport (SFO) to London Heathrow
Airport (LHR) is 8625 km