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----> |