Source code for tracktable.info.airports

# -*- coding: utf-8 -*-

# Copyright (c) 2014-2023 National Technology and Engineering
# Solutions of Sandia, LLC. Under the terms of Contract DE-NA0003525
# with National Technology and Engineering Solutions of Sandia, LLC,
# the U.S. Government retains certain rights in this software.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# 1. Redistributions of source code must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright
#    notice, this list of conditions and the following disclaimer in the
#    documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLA IMED. IN NO EVENT SHALL THE COPYRIGHT
# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.


from __future__ import absolute_import, division, print_function

import operator
import os
import os.path
from csv import DictReader
from tracktable_data.data import retrieve

from tracktable.core.geomath import intersects
from tracktable.domain.terrestrial import TrajectoryPoint

[docs] class Airport(object): """Information about a single airport Attributes: iata_code (str): 3-letter IATA airport identifier icao_code (str): 4-leter ICAO airport identifier name (str): Human-readable airport name city (str): City where airport is located country (str): Country where airport is located position (tuple): (longitude, latitude, altitude) position of airport size_rank (int): Approximate rank among all the world's airports utc_offset (int): Local time zone as an offset from UTC """ def __init__(self): """Initialize an empty airport""" self.iata_code = None self.icao_code = None self.name = None self.city = None self.country = None self.position = None # latitude, longitude, altitude self.utc_offset = None self.size_rank = 1000000 def __str__(self): """Return human-readable representation of airport object""" return '<AIRPORT: %s (ICAO %s / IATA %s)>' % ( self.name, self.iata_code, self.icao_code )
[docs] def build_airport_dict(): """Assemble the airport dictionary on first access This function is called whenever the user tries to look up an airport. It checks to make sure the table has been populated and, if not, loads it from disk. Returns: None Side Effects: Airport data will be loaded if not already in memory """ global AIRPORT_DICT if len(AIRPORT_DICT) > 0: return # we've already built it else: AIRPORT_DICT = dict() openflight_field_names = [ 'numeric_id', 'name', 'city', 'country', 'iata', 'icao', 'latitude', 'longitude', 'altitude', 'utc_offset', 'daylight_savings' ] with open(retrieve('airports.csv'), mode='r', encoding='utf-8') as infile: # with open(data_filename, mode='r') as infile: csvreader = DictReader( infile, delimiter=',', quotechar='"', fieldnames=openflight_field_names ) for row in csvreader: airport = Airport() airport.name = row['name'] airport.city = row['city'] airport.country = row['country'] airport.iata_code = row['iata'] airport.icao_code = row['icao'] airport.position = ( float(row['longitude']), float(row['latitude']), float(row['altitude']) ) airport.utc_offset = float(row['utc_offset']) airport.daylight_savings = row['daylight_savings'] if len(airport.iata_code) == 0: airport.iata_code = None else: AIRPORT_DICT[airport.iata_code] = airport if len(airport.icao_code) == 0: airport.icao_code = None else: AIRPORT_DICT[airport.icao_code] = airport # now we add traffic information - rank each airport by # the amount of traffic it sees in some arbitrary period from tracktable_data.python_info_data.airport_traffic import AIRPORTS_BY_TRAFFIC airports_with_traffic = sorted(AIRPORTS_BY_TRAFFIC.items(), key=operator.itemgetter(1), reverse=True) ranked_airports_with_traffic = enumerate(airports_with_traffic) for (i, info) in ranked_airports_with_traffic: apt = info[0] if apt in AIRPORT_DICT: AIRPORT_DICT[apt].size_rank = i
# ----------------------------------------------------------------------
[docs] def airport_information(airport_code): """Look up information about an airport Args: airport_code (str): ICAO or IATA code for an airport Returns: Airport object containing requested information. Raises: KeyError: no such airport """ global AIRPORT_DICT if len(AIRPORT_DICT) == 0: build_airport_dict() return AIRPORT_DICT.get(airport_code, None)
# ----------------------------------------------------------------------
[docs] def airport_size_rank(airport_code): """Return an airport's global rank by size Args: airport_code (str): IATA or ICAO airport identifier Returns: Integer ranking. 1 is the largest, higher values are smaller. """ try: ap_info = airport_information(airport_code) return ap_info.size_rank except KeyError: return 1000000
# ----------------------------------------------------------------------
[docs] def all_airports(): """Return all the airport records we have Returns: Unsorted list of airport objects. """ global AIRPORT_DICT if len(AIRPORT_DICT) == 0: build_airport_dict() return list(set(AIRPORT_DICT.values()))
# ----------------------------------------------------------------------
[docs] def all_airports_within_bounding_box(bounding_box): """Return all the airport records we have from a given bounding box. Args: bounding_box (str): Bounding box to return all airports from. Returns: Dictionary of airports from the given bounding box. """ global AIRPORT_DICT if len(AIRPORT_DICT) == 0: build_airport_dict() airports = {} for airport_name, airport in AIRPORT_DICT.items(): if intersects(TrajectoryPoint(airport.position[0], airport.position[1]), bounding_box): airports[airport_name] = airport return airports
# ---------------------------------------------------------------------- AIRPORT_DICT = {} # This information comes from Wikipedia: # # http://en.wikipedia.org/wiki/World's_busiest_airports_by_passenger_traffic TIER1_AIRPORTS = [ 'ATL', 'PEK', 'LHR', 'HND', 'ORD', 'LAX', 'CDG', 'DFW', 'CGK', 'DXB', 'FRA', 'HKG', 'DEN', 'BKK', 'SIN', 'AMS', 'JFK', 'CAN', 'MAD', 'IST', 'PVG', 'SFO', 'LAS', 'CLT', 'PHX', 'IAH', 'KUL', 'MIA', 'ICN', 'MUC', 'SYD', 'FCO', 'MCO', 'BCN', 'YYZ', 'LGW' ] TIER2_AIRPORTS = [ 'DEL', 'EWR', 'SHA', 'SEA', 'MSP', 'NRT', 'GRU', 'DTW', 'MNL', 'CTU', 'PHL', 'BOM', 'SZX', 'MEL', 'BOS', 'LGA', 'FLL', 'BWI', 'IAD', 'SLC', 'MDW', 'DCA', 'HNL', 'SAN', 'TPA' ] TIER3_AIRPORTS = [ 'PDX', 'STL', 'MCI', 'HOU', 'BNA', 'MKE', 'OAK', 'RDU', 'AUS', 'CLE', 'SMF', 'MEM', 'MSY', 'SNA', 'SJC', 'PIT', 'SAT', 'SJU', 'DAL', 'RSW', 'IND', 'CVG', 'CMH', 'PBI', 'BDL', 'ABQ', 'JAX', 'OGG', 'BUF', 'ANC', 'ONT', 'BUR', 'OMA', 'PVD', 'RNO' ] # This information comes from Wikipedia: # http://en.wikipedia.org/wiki/List_of_the_busiest_airports_in_the_United_States BUSIEST_US_AIRPORTS_BY_PASSENGER_BOARDINGS = [ 'ATL', 'ORD', 'LAX', 'DFW', 'DEN', 'JFK', 'SFO', 'LAS', 'PHX', 'IAH', 'CLT', 'MIA', 'MCO', 'EWR', 'SEA', 'MSP', 'DTW', 'PHL', 'BOS', 'LGA', 'FLL', 'BWI', 'IAD', 'SLC', 'MDW', 'DCA', 'HNL', 'SAN', 'TPA' ] # This information comes from Wikipedia: # http://en.wikipedia.org/wiki/List_of_the_busiest_airports_in_the_United_States US_SECONDARY_HUBS = [ 'PDX', 'STL', 'MCI', 'HOU', 'BNA', 'MKE', 'OAK', 'RDU', 'AUS', 'CLE', 'SMF', 'MEM', 'MSY', 'SNA', 'SJC', 'PIT', 'SAT', 'SJU', 'DAL', 'RSW', 'IND', 'CVG', 'CMH', 'PBI', 'BDL', 'ABQ', 'JAX', 'OGG', 'BUF', 'ANC', 'ONT', 'BUR', 'OMA', 'PVD', 'RNO' ] AIRPORTS_BY_TIER = dict()
[docs] def airport_tier(airport_code): """Return an estimated tier for an airport We divide airports roughly into 4 tiers (chosen purely by hand) for a classification task. This function lets us retrieve the tier assigned to any given airport. Args: airport_code (str): IATA/ICAO airport identifier Returns: String: tier1, tier2, tier3 or tier4 Raises: KeyError: no such airport """ global AIRPORTS_BY_TIER, TIER1_AIRPORTS, TIER2_AIRPORTS, TIER3_AIRPORTS if len(AIRPORTS_BY_TIER) == 0: for airport in TIER1_AIRPORTS: info = airport_information(airport) AIRPORTS_BY_TIER[info.iata_code] = 'tier1' AIRPORTS_BY_TIER[info.icao_code] = 'tier1' for airport in TIER2_AIRPORTS: info = airport_information(airport) AIRPORTS_BY_TIER[info.iata_code] = 'tier2' AIRPORTS_BY_TIER[info.icao_code] = 'tier2' for airport in TIER3_AIRPORTS: info = airport_information(airport) AIRPORTS_BY_TIER[info.iata_code] = 'tier3' AIRPORTS_BY_TIER[info.icao_code] = 'tier3' return AIRPORTS_BY_TIER.get(airport_code, 'tier4')