01234567890123456789012345678901234567890123456789012345678901234567890123456789
1780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807 18081809181018111812181318141815181618171818181918201821182218231824182518261827 413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159 4160 416141624163416441654166416741684169417041714172417341744175417641774178417941804181 41964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227 4228422942304231423242334234423542364237423842394240 42414242424342444245424642474248424942504251425242534254425542564257425842594260 42724273427442754276427742784279428042814282428342844285428642874288428942904291 429242934294429542964297429842994300430143024303430443054306 43074308430943104311431243134314431543164317431843194320432143224323 4324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351 43524353435443554356 4357435843594360 436143624363436443654366436743684369437043714372437343744375437643774378437943804381 44394440444144424443444444454446444744484449445044514452445344544455445644574458 445944604461446244634464 44654466446744684469447044714472447344744475447644774478447944804481448244834484 4638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689 |
<----SKIPPED LINES---->
Returns:
String identifying either the airline, or Unknown if not available.
"""
airline = flight.get('airline_short_name', flight.get('airline_full_name'))
# Some names are very similar to others and so appear identical on splitflap
replacement_names = (
('Delta Private Jets', 'DPJ'),
('United Parcel Service', 'UPS'))
for (old, new) in replacement_names:
if airline and old.upper() == airline.upper():
airline = new
break
if not airline:
airline = KEY_NOT_PRESENT_STRING
return airline
def AircraftLength(flight):
"""Returns length (in meters) of aircraft, or 0 if unknown."""
aircraft = flight.get('aircraft_type_friendly')
if not aircraft:
return 0
if aircraft not in AIRCRAFT_LENGTH:
return 0
return AIRCRAFT_LENGTH[aircraft]
def DisplayAircraft(flight):
"""Provides a display-ready string about the aircraft used.
Args:
flight: dictionary with key-value attributes about the flight.
Returns:
Aircraft string if available; empty string otherwise.
"""
aircraft = flight.get('aircraft_type_friendly')
if aircraft:
aircraft = aircraft.replace('(twin-jet)', '(twin)')
aircraft = aircraft.replace('(quad-jet)', '(quad)')
aircraft = aircraft.replace('Regional Jet ', '')
aircraft = aircraft[:SPLITFLAP_CHARS_PER_LINE]
else:
aircraft = ''
return aircraft
<----SKIPPED LINES---->
keyfunction,
sort_type,
truncate=truncate,
hours=hours,
max_distance_feet=max_distance_feet,
max_altitude_feet=max_altitude_feet,
normalize_factor=normalize_factor,
exhaustive=exhaustive)
if position:
matplotlib.pyplot.subplot(*position)
matplotlib.pyplot.figure(figsize=figsize_inches)
values_coordinates = numpy.arange(len(keys))
matplotlib.pyplot.bar(values_coordinates, values)
# The filtering may have removed any flight data, or there may be none to start
if not filtered_data:
return
earliest_flight_time = int(filtered_data[0]['now'])
last_flight_time = int(filtered_data[-1]['now'])
date_range_string = ' (%d flights over last %s hours)' % (
sum(values), SecondsToDdHh(last_flight_time - earliest_flight_time))
matplotlib.pyplot.title(title + date_range_string)
matplotlib.pyplot.subplots_adjust(bottom=0.15, left=0.09, right=0.99, top=0.92)
matplotlib.pyplot.xticks(
values_coordinates, keys, rotation='vertical', wrap=True,
horizontalalignment='right',
verticalalignment='center')
def HistogramSettingsHours(how_much_history):
"""Extracts the desired history (in hours) from the histogram configuration string.
Args:
how_much_history: string from the histogram config file.
Returns:
Number of hours of history to include in the histogram.
"""
if how_much_history == 'today':
hours = HoursSinceMidnight()
elif how_much_history == '24h':
hours = HOURS_IN_DAY
<----SKIPPED LINES---->
Args:
max_screens: string from the histogram config file.
Returns:
Number of maximum number of screens to display for a splitflap histogram.
"""
if max_screens == '_1':
screen_limit = 1
elif max_screens == '_2':
screen_limit = 2
elif max_screens == '_5':
screen_limit = 5
elif max_screens == 'all':
screen_limit = 0 # no limit on screens
else:
Log('Histogram form has invalid value for max_screens: %s' % max_screens)
screen_limit = 1
return screen_limit
def HistogramSettingsKeySortTitle(which, hours, max_altitude=45000):
"""Provides the arguments necessary to generate a histogram from the config string.
The same parameters are used to generate either a splitflap text or web-rendered
histogram in terms of the histogram title, the keyfunction, and how to sort the keys.
For a given histogram name (based on the names defined in the histogram config file),
this provides those parameters.
Args:
which: string from the histogram config file indicating the histogram to provide
settings for.
hours: how many hours of histogram data have been requested.
max_altitude: indicates the maximum altitude that should be included on the
altitude labels.
Returns:
A 4-tuple of the parameters used by either CreateSingleHistogramChart or
MessageboardHistogram, of the keyfunction, sort, title, and hours.
"""
def DivideAndFormat(dividend, divisor):
if dividend is None:
return KEY_NOT_PRESENT_STRING
if isinstance(dividend, numbers.Number):
return '%2d' % round(dividend / divisor)
return dividend[:2]
if which == 'destination':
key = lambda k: k.get('destination_iata', KEY_NOT_PRESENT_STRING)
sort = 'value'
title = 'Destination'
elif which == 'origin':
key = lambda k: k.get('origin_iata', KEY_NOT_PRESENT_STRING)
sort = 'value'
title = 'Origin'
elif which == 'hour':
key = lambda k: DisplayTime(k, '%H')
sort = 'key'
title = 'Hour'
elif which == 'airline':
key = DisplayAirline
sort = 'value'
title = 'Airline'
elif which == 'aircraft':
key = lambda k: k.get('aircraft_type_code', KEY_NOT_PRESENT_STRING)
sort = 'value'
<----SKIPPED LINES---->
key = lambda k: DivideAndFormat(k.get('min_feet', KEY_NOT_PRESENT_STRING), 100)
sort = ['%2d'%x for x in range(0, round((MIN_METERS*FEET_IN_METER)/100)+1)]
title = 'Min Dist (100ft)'
elif which == 'day_of_week':
key = lambda k: DisplayTime(k, '%a')
sort = DAYS_OF_WEEK
title = 'Day of Week'
# if less than one week, as requested; if more than one week, in full week multiples
hours_in_week = 7 * HOURS_IN_DAY
weeks = hours / hours_in_week
if weeks > 1:
hours = hours_in_week * int(hours / hours_in_week)
elif which == 'day_of_month':
key = lambda k: DisplayTime(k, '%-d').rjust(2)
today_day = datetime.datetime.now(TZ).day
days = list(range(today_day, 0, -1)) # today down to the first of the month
days.extend(range(31, today_day, -1)) # 31st of the month down to day after today
days = [str(d).rjust(2) for d in days]
sort = days
title = 'Day of Month'
else:
Log(
'Histogram form has invalid value for which_histograms: %s' % which)
return HistogramSettingsKeySortTitle(
'destination', hours, max_altitude=max_altitude)
return (key, sort, title, hours)
def ImageHistograms(
flights,
which_histograms,
how_much_history,
filename_prefix=HISTOGRAM_IMAGE_PREFIX,
filename_suffix=HISTOGRAM_IMAGE_SUFFIX):
"""Generates multiple split histogram images.
Args:
flights: the iterable of the raw data from which the histogram will be generated;
each element of the iterable is a dictionary, that contains at least the key
'now', and depending on other parameters, also potentially
'min_feet' amongst others.
which_histograms: string paramater indicating which histogram(s) to generate, which
can be either the special string 'all', or a string linked to a specific
histogram.
how_much_history: string parameter taking a value among ['today', '24h', '7d', '30d].
filename_prefix: this string indicates the file path and name prefix for the images
that are created. File names are created in the form [prefix]name.[suffix], i.e.:
if the prefix is histogram_ and the suffix is png, then the file name might be
histogram_aircraft.png.
filename_suffix: see above; also interpreted by savefig to generate the correct
format.
Returns:
List of the names of the histograms generated.
"""
hours = HistogramSettingsHours(how_much_history)
histograms_to_generate = []
if which_histograms in ['destination', 'all']:
histograms_to_generate.append({'generate': 'destination'})
if which_histograms in ['origin', 'all']:
histograms_to_generate.append({'generate': 'origin'})
if which_histograms in ['hour', 'all']:
histograms_to_generate.append({'generate': 'hour'})
if which_histograms in ['airline', 'all']:
histograms_to_generate.append({'generate': 'airline', 'truncate': int(TRUNCATE/2)})
if which_histograms in ['aircraft', 'all']:
histograms_to_generate.append({'generate': 'aircraft'})
if which_histograms in ['altitude', 'all']:
histograms_to_generate.append({'generate': 'altitude', 'exhaustive': True})
if which_histograms in ['bearing', 'all']:
histograms_to_generate.append({'generate': 'bearing'})
if which_histograms in ['distance', 'all']:
histograms_to_generate.append({'generate': 'distance', 'exhaustive': True})
if which_histograms in ['day_of_week', 'all']:
histograms_to_generate.append({'generate': 'day_of_week'})
if which_histograms in ['day_of_month', 'all']:
histograms_to_generate.append({'generate': 'day_of_month'})
for histogram in histograms_to_generate:
this_histogram = which_histograms
if this_histogram == 'all':
this_histogram = histogram['generate']
(key, sort, title, hours) = HistogramSettingsKeySortTitle(this_histogram, hours)
# if multiple histograms are getting generated, this might take a few seconds;
# logging a heartbeat with each histogram ensures that monitoring.py does not
# mistake this pause for a hang.
Heartbeat()
CreateSingleHistogramChart(
flights,
key,
sort,
title,
truncate=histogram.get('truncate', TRUNCATE),
hours=hours,
exhaustive=histogram.get('exhaustive', False))
filename = filename_prefix + histogram['generate'] + '.' + filename_suffix
matplotlib.pyplot.savefig(filename)
matplotlib.pyplot.close()
histograms_generated = [h['generate'] for h in histograms_to_generate]
return histograms_generated
def MessageboardHistograms(
flights,
which_histograms,
<----SKIPPED LINES---->
'suppress_percent_sign': True,
'columns': 3})
if which_histograms in ['distance', 'all']:
histograms_to_generate.append({
'generate': 'distance',
'columns': 3})
if ((which_histograms == 'all' and how_much_history == '7d')
or which_histograms == 'day_of_week'):
histograms_to_generate.append({
'generate': 'day_of_week',
'columns': 3,
'absolute': True})
if ((which_histograms == 'all' and how_much_history == '30d')
or which_histograms == 'day_of_month'):
histograms_to_generate.append({
'generate': 'day_of_month',
'columns': 3,
'suppress_percent_sign': True,
'column_divider': '|',
'absolute': True})
for histogram in histograms_to_generate:
this_histogram = which_histograms
if this_histogram == 'all':
this_histogram = histogram['generate']
(key, sort, title, hours) = HistogramSettingsKeySortTitle(this_histogram, hours)
# if multiple histograms are getting generated, this might take a few seconds;
# logging a heartbeat with each histogram ensures that monitoring.py does not
# mistake this pause for a hang.
Heartbeat()
histogram = MessageboardHistogram(
flights,
key,
sort,
title,
screen_limit=screen_limit,
columns=histogram.get('columns', 2),
suppress_percent_sign=histogram.get('suppress_percent_sign', False),
column_divider=histogram.get('column_divider', ' '),
data_summary=data_summary,
hours=hours,
absolute=histogram.get('absolute', False))
messages.extend(histogram)
messages = [(FLAG_MSG_HISTOGRAM, m) for m in messages]
<----SKIPPED LINES---->
created so that broken image links are not displayed in the webpage.
Args:
flights: List of flight attribute dictionaries.
histogram_settings: Dictionary of histogram parameters.
Returns:
List of histogram messages, if text-based histograms are selected; empty list
otherwise.
"""
histogram_messages = []
if histogram_settings['type'] in ('messageboard', 'both'):
histogram_messages = MessageboardHistograms(
flights,
histogram_settings['histogram'],
histogram_settings['histogram_history'],
histogram_settings['histogram_max_screens'],
histogram_settings.get('histogram_data_summary', False))
if histogram_settings['type'] in ('images', 'both'):
histograms_generated = ImageHistograms(
flights,
histogram_settings['histogram'],
histogram_settings['histogram_history'])
all_available_histograms = [
'destination', 'origin', 'hour', 'airline', 'aircraft', 'altitude',
'bearing', 'distance', 'day_of_week', 'day_of_month']
for histogram in all_available_histograms:
if histogram not in histograms_generated:
missing_filename = (
HISTOGRAM_IMAGE_PREFIX + histogram + '.' + HISTOGRAM_IMAGE_SUFFIX)
shutil.copyfile(HISTOGRAM_EMPTY_IMAGE_FILE, missing_filename)
return histogram_messages
def SaveFlightsByAltitudeDistanceCSV(
flights,
max_days=0,
filename='flights_by_alt_dist.csv',
precision=100):
"""Extracts hourly histogram into text file for a variety of altitudes and distances.
Generates a csv with 26 columns:
- col#1: altitude (in feet)
- col#2: distance (in feet)
- cols#3-26: hour of the day
The first row is a header row; subsequent rows list the number of flights that have
occurred in the last max_days with an altitude and min distance less than that identified
in the first two columns. Each row increments elevation or altitude by precision feet,
up to the max determined by the max altitude and max distance amongst all the flights.
<----SKIPPED LINES---->
|
01234567890123456789012345678901234567890123456789012345678901234567890123456789
178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845 415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204 4219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291 430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455 45134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571 472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748 47494750475147524753475447554756475747584759476047614762476347644765476647674768 |
<----SKIPPED LINES---->
Returns:
String identifying either the airline, or Unknown if not available.
"""
airline = flight.get('airline_short_name', flight.get('airline_full_name'))
# Some names are very similar to others and so appear identical on splitflap
replacement_names = (
('Delta Private Jets', 'DPJ'),
('United Parcel Service', 'UPS'))
for (old, new) in replacement_names:
if airline and old.upper() == airline.upper():
airline = new
break
if not airline:
airline = KEY_NOT_PRESENT_STRING
return airline
def AircraftLength(flight, default=0):
"""Returns length (in meters) of aircraft, or default if unknown."""
aircraft = flight.get('aircraft_type_friendly')
if not aircraft:
return default
if aircraft not in AIRCRAFT_LENGTH:
return default
return AIRCRAFT_LENGTH[aircraft]
def DisplayLength(flight):
"""Returns rounded length (in meters) of aircraft, or UNKNOWN if unknown."""
length = round(AircraftLength(flight, default=0))
if length:
return length
return KEY_NOT_PRESENT_STRING
def DisplaySpeed(flight):
"""Returns speed in knots or UNKNOWN if not known."""
return flight.get('speed', KEY_NOT_PRESENT_STRING)
def DisplayVertRate(flight):
"""Returns vertical rate in fpm or UNKNOWN if not known."""
return flight.get('vert_rate', KEY_NOT_PRESENT_STRING)
def DisplayAircraft(flight):
"""Provides a display-ready string about the aircraft used.
Args:
flight: dictionary with key-value attributes about the flight.
Returns:
Aircraft string if available; empty string otherwise.
"""
aircraft = flight.get('aircraft_type_friendly')
if aircraft:
aircraft = aircraft.replace('(twin-jet)', '(twin)')
aircraft = aircraft.replace('(quad-jet)', '(quad)')
aircraft = aircraft.replace('Regional Jet ', '')
aircraft = aircraft[:SPLITFLAP_CHARS_PER_LINE]
else:
aircraft = ''
return aircraft
<----SKIPPED LINES---->
keyfunction,
sort_type,
truncate=truncate,
hours=hours,
max_distance_feet=max_distance_feet,
max_altitude_feet=max_altitude_feet,
normalize_factor=normalize_factor,
exhaustive=exhaustive)
if position:
matplotlib.pyplot.subplot(*position)
matplotlib.pyplot.figure(figsize=figsize_inches)
values_coordinates = numpy.arange(len(keys))
matplotlib.pyplot.bar(values_coordinates, values)
# The filtering may have removed any flight data, or there may be none to start
if not filtered_data:
return
earliest_flight_time = int(filtered_data[0]['now'])
last_flight_time = int(filtered_data[-1]['now'])
date_range_string = ' %d flights over last %s hours' % (
sum(values), SecondsToDdHh(last_flight_time - earliest_flight_time))
timestamp_string = 'Last updated %s' % EpochDisplayTime(
time.time(), format_string='%b %-d %H:%M')
full_title = '\n'.join([title, date_range_string, timestamp_string])
matplotlib.pyplot.title(full_title)
matplotlib.pyplot.subplots_adjust(bottom=0.15, left=0.09, right=0.99, top=0.89)
matplotlib.pyplot.xticks(
values_coordinates, keys, rotation='vertical', wrap=True,
horizontalalignment='right',
verticalalignment='center')
def HistogramSettingsHours(how_much_history):
"""Extracts the desired history (in hours) from the histogram configuration string.
Args:
how_much_history: string from the histogram config file.
Returns:
Number of hours of history to include in the histogram.
"""
if how_much_history == 'today':
hours = HoursSinceMidnight()
elif how_much_history == '24h':
hours = HOURS_IN_DAY
<----SKIPPED LINES---->
Args:
max_screens: string from the histogram config file.
Returns:
Number of maximum number of screens to display for a splitflap histogram.
"""
if max_screens == '_1':
screen_limit = 1
elif max_screens == '_2':
screen_limit = 2
elif max_screens == '_5':
screen_limit = 5
elif max_screens == 'all':
screen_limit = 0 # no limit on screens
else:
Log('Histogram form has invalid value for max_screens: %s' % max_screens)
screen_limit = 1
return screen_limit
def HistogramSettingsKeySortTitle(which, hours, flights, max_altitude=45000):
"""Provides the arguments necessary to generate a histogram from the config string.
The same parameters are used to generate either a splitflap text or web-rendered
histogram in terms of the histogram title, the keyfunction, and how to sort the keys.
For a given histogram name (based on the names defined in the histogram config file),
this provides those parameters.
Args:
which: string from the histogram config file indicating the histogram to provide
settings for.
hours: how many hours of histogram data have been requested.
flights: list of the flights in the data set.
max_altitude: indicates the maximum altitude that should be included on the
altitude labels.
Returns:
A 4-tuple of the parameters used by either CreateSingleHistogramChart or
MessageboardHistogram, of the keyfunction, sort, title, and hours.
"""
def DivideAndFormat(dividend, divisor):
if dividend is None:
return KEY_NOT_PRESENT_STRING
if isinstance(dividend, numbers.Number):
return '%2d' % round(dividend / divisor)
return dividend[:2]
def RoundAndFormat(dividend, divisor, digits):
if dividend is None:
return KEY_NOT_PRESENT_STRING
if isinstance(dividend, numbers.Number):
return divisor*round(dividend / divisor)
return dividend[:digits]
if which == 'destination':
key = lambda k: k.get('destination_iata', KEY_NOT_PRESENT_STRING)
sort = 'value'
title = 'Destination'
elif which == 'origin':
key = lambda k: k.get('origin_iata', KEY_NOT_PRESENT_STRING)
sort = 'value'
title = 'Origin'
elif which == 'hour':
key = lambda k: DisplayTime(k, '%H')
sort = 'key'
title = 'Hour'
elif which == 'airline':
key = DisplayAirline
sort = 'value'
title = 'Airline'
elif which == 'aircraft':
key = lambda k: k.get('aircraft_type_code', KEY_NOT_PRESENT_STRING)
sort = 'value'
<----SKIPPED LINES---->
key = lambda k: DivideAndFormat(k.get('min_feet', KEY_NOT_PRESENT_STRING), 100)
sort = ['%2d'%x for x in range(0, round((MIN_METERS*FEET_IN_METER)/100)+1)]
title = 'Min Dist (100ft)'
elif which == 'day_of_week':
key = lambda k: DisplayTime(k, '%a')
sort = DAYS_OF_WEEK
title = 'Day of Week'
# if less than one week, as requested; if more than one week, in full week multiples
hours_in_week = 7 * HOURS_IN_DAY
weeks = hours / hours_in_week
if weeks > 1:
hours = hours_in_week * int(hours / hours_in_week)
elif which == 'day_of_month':
key = lambda k: DisplayTime(k, '%-d').rjust(2)
today_day = datetime.datetime.now(TZ).day
days = list(range(today_day, 0, -1)) # today down to the first of the month
days.extend(range(31, today_day, -1)) # 31st of the month down to day after today
days = [str(d).rjust(2) for d in days]
sort = days
title = 'Day of Month'
elif which == 'speed':
rounding = 25
field = 'speed'
min_value = min([f[field] for f in flights if f.get(field)])
max_value = max([f[field] for f in flights if f.get(field)])
digits = int(math.log10(max_value)) + 1
key = lambda k: RoundAndFormat(k.get(field, KEY_NOT_PRESENT_STRING), rounding, digits)
values = range(int(min_value), int(max_value) + 1)
sort = sorted(list({RoundAndFormat(v, rounding, digits) for v in values}))
title = 'Speed (kn)'
elif which == 'aircraft_length':
key = DisplayLength
min_value = min([AircraftLength(f, default=float('inf')) for f in flights])
max_value = max([AircraftLength(f, default=float('-inf')) for f in flights])
sort = list(range(round(min_value), round(max_value) + 1))
title = 'Plane Length (m)'
elif which == 'vert_rate':
rounding = 200
field = 'vert_rate'
min_value = min([f[field] for f in flights if f.get(field)])
max_value = max([f[field] for f in flights if f.get(field)])
digits = max(int(math.log10(max_value)), 1 + int(math.log10(abs(min_value)))) + 1
key = lambda k: RoundAndFormat(k.get(field, KEY_NOT_PRESENT_STRING), rounding, digits)
values = range(int(min_value), int(max_value) + 1)
sort = sorted(list({RoundAndFormat(v, rounding, digits) for v in values}))
title = 'Ascent Rate (%s)' % CLIMB_RATE_UNITS
else:
Log(
'Histogram form has invalid value for which_histograms: %s' % which)
return HistogramSettingsKeySortTitle(
'destination', hours, flights, max_altitude=max_altitude)
return (key, sort, title, hours)
def ImageHistograms(
flights,
which_histograms,
how_much_history,
filename_prefix=HISTOGRAM_IMAGE_PREFIX,
filename_suffix=HISTOGRAM_IMAGE_SUFFIX,
heartbeat=True):
"""Generates multiple split histogram images.
Args:
flights: the iterable of the raw data from which the histogram will be generated;
each element of the iterable is a dictionary, that contains at least the key
'now', and depending on other parameters, also potentially
'min_feet' amongst others.
which_histograms: string paramater indicating which histogram(s) to generate, which
can be either the special string 'all', or a string linked to a specific
histogram.
how_much_history: string parameter taking a value among ['today', '24h', '7d', '30d].
filename_prefix: this string indicates the file path and name prefix for the images
that are created. File names are created in the form [prefix]name.[suffix], i.e.:
if the prefix is histogram_ and the suffix is png, then the file name might be
histogram_aircraft.png.
filename_suffix: see above; also interpreted by savefig to generate the correct
format.
heartbeat: boolean indicating whether we should log heartbeats between each histogram
to make sure monitoring does not mistake this slow procedure for being hung; this
should be set to false if this is called from outside of messageboard.main.
Returns:
List of the names of the histograms generated.
"""
hours = HistogramSettingsHours(how_much_history)
histograms_to_generate = []
if which_histograms in ['destination', 'all']:
histograms_to_generate.append({'generate': 'destination'})
if which_histograms in ['origin', 'all']:
histograms_to_generate.append({'generate': 'origin'})
if which_histograms in ['hour', 'all']:
histograms_to_generate.append({'generate': 'hour'})
if which_histograms in ['airline', 'all']:
histograms_to_generate.append({'generate': 'airline', 'truncate': int(TRUNCATE/2)})
if which_histograms in ['aircraft', 'all']:
histograms_to_generate.append({'generate': 'aircraft'})
if which_histograms in ['altitude', 'all']:
histograms_to_generate.append({'generate': 'altitude', 'exhaustive': True})
if which_histograms in ['bearing', 'all']:
histograms_to_generate.append({'generate': 'bearing'})
if which_histograms in ['distance', 'all']:
histograms_to_generate.append({'generate': 'distance', 'exhaustive': True})
if which_histograms in ['day_of_week', 'all']:
histograms_to_generate.append({'generate': 'day_of_week'})
if which_histograms in ['day_of_month', 'all']:
histograms_to_generate.append({'generate': 'day_of_month'})
if which_histograms in ['speed', 'all']:
histograms_to_generate.append({'generate': 'speed', 'exhaustive': True})
if which_histograms in ['aircraft_length', 'all']:
histograms_to_generate.append({'generate': 'aircraft_length', 'exhaustive': True})
if which_histograms in ['vert_rate', 'all']:
histograms_to_generate.append({'generate': 'vert_rate', 'exhaustive': True})
for histogram in histograms_to_generate:
this_histogram = which_histograms
if this_histogram == 'all':
this_histogram = histogram['generate']
(key, sort, title, hours) = HistogramSettingsKeySortTitle(
this_histogram, hours, flights)
# if multiple histograms are getting generated, this might take a few seconds;
# logging a heartbeat with each histogram ensures that monitoring.py does not
# mistake this pause for a hang.
if heartbeat:
Heartbeat()
CreateSingleHistogramChart(
flights,
key,
sort,
title,
truncate=histogram.get('truncate', TRUNCATE),
hours=hours,
exhaustive=histogram.get('exhaustive', False))
filename = filename_prefix + histogram['generate'] + '.' + filename_suffix
matplotlib.pyplot.savefig(filename)
matplotlib.pyplot.close()
histograms_generated = [h['generate'] for h in histograms_to_generate]
return histograms_generated
def MessageboardHistograms(
flights,
which_histograms,
<----SKIPPED LINES---->
'suppress_percent_sign': True,
'columns': 3})
if which_histograms in ['distance', 'all']:
histograms_to_generate.append({
'generate': 'distance',
'columns': 3})
if ((which_histograms == 'all' and how_much_history == '7d')
or which_histograms == 'day_of_week'):
histograms_to_generate.append({
'generate': 'day_of_week',
'columns': 3,
'absolute': True})
if ((which_histograms == 'all' and how_much_history == '30d')
or which_histograms == 'day_of_month'):
histograms_to_generate.append({
'generate': 'day_of_month',
'columns': 3,
'suppress_percent_sign': True,
'column_divider': '|',
'absolute': True})
if which_histograms in ['speed', 'all']:
histograms_to_generate.append({
'generate': 'speed',
'columns': 2})
if which_histograms in ['aircraft_length', 'all']:
histograms_to_generate.append({
'generate': 'aircraft_length',
'columns': 3})
if which_histograms in ['vert_rate', 'all']:
histograms_to_generate.append({
'generate': 'vert_rate',
'columns': 2})
for histogram in histograms_to_generate:
this_histogram = which_histograms
if this_histogram == 'all':
this_histogram = histogram['generate']
(key, sort, title, hours) = HistogramSettingsKeySortTitle(
this_histogram, hours, flights)
# if multiple histograms are getting generated, this might take a few seconds;
# logging a heartbeat with each histogram ensures that monitoring.py does not
# mistake this pause for a hang.
Heartbeat()
histogram = MessageboardHistogram(
flights,
key,
sort,
title,
screen_limit=screen_limit,
columns=histogram.get('columns', 2),
suppress_percent_sign=histogram.get('suppress_percent_sign', False),
column_divider=histogram.get('column_divider', ' '),
data_summary=data_summary,
hours=hours,
absolute=histogram.get('absolute', False))
messages.extend(histogram)
messages = [(FLAG_MSG_HISTOGRAM, m) for m in messages]
<----SKIPPED LINES---->
created so that broken image links are not displayed in the webpage.
Args:
flights: List of flight attribute dictionaries.
histogram_settings: Dictionary of histogram parameters.
Returns:
List of histogram messages, if text-based histograms are selected; empty list
otherwise.
"""
histogram_messages = []
if histogram_settings['type'] in ('messageboard', 'both'):
histogram_messages = MessageboardHistograms(
flights,
histogram_settings['histogram'],
histogram_settings['histogram_history'],
histogram_settings['histogram_max_screens'],
histogram_settings.get('histogram_data_summary', False))
if histogram_settings['type'] in ('images', 'both'):
ImageHistograms(
flights,
histogram_settings['histogram'],
histogram_settings['histogram_history'])
return histogram_messages
def SaveFlightsByAltitudeDistanceCSV(
flights,
max_days=0,
filename='flights_by_alt_dist.csv',
precision=100):
"""Extracts hourly histogram into text file for a variety of altitudes and distances.
Generates a csv with 26 columns:
- col#1: altitude (in feet)
- col#2: distance (in feet)
- cols#3-26: hour of the day
The first row is a header row; subsequent rows list the number of flights that have
occurred in the last max_days with an altitude and min distance less than that identified
in the first two columns. Each row increments elevation or altitude by precision feet,
up to the max determined by the max altitude and max distance amongst all the flights.
<----SKIPPED LINES---->
|