def get_aircraft_info(tail_number): ''' Fetch aircraft info from settings.API_HANDLER or from LOCAL_API_HANDLER if there is an API_ERROR raised. :param tail_number: Aircraft tail registration :type tail_number: string :returns: Aircraft information key:value pairs :rtype: dict ''' # Fetch aircraft info through the API. api_handler = get_api_handler(settings.API_HANDLER) try: aircraft_info = api_handler.get_aircraft(tail_number) except APIError: if settings.API_HANDLER == settings.LOCAL_API_HANDLER: raise # Fallback to the local API handler. logger.info( "Aircraft '%s' could not be found with '%s' API handler. " "Falling back to '%s'.", tail_number, settings.API_HANDLER, settings.LOCAL_API_HANDLER) api_handler = get_api_handler(settings.LOCAL_API_HANDLER) aircraft_info = api_handler.get_aircraft(tail_number) logger.info("Using aircraft_info provided by '%s' '%s'.", api_handler.__class__.__name__, aircraft_info) return aircraft_info
def derive(self, dest=P('Destination'), afr_dest=A('AFR Destination Airport')): ''' Requires an ASCII destination parameter recording either the airport's ICAO or IATA code. ''' if not dest or dest.array.dtype.type is not np.string_: if afr_dest: self.set_flight_attr(afr_dest.value) return value = most_common_value(dest.array, threshold=0.45) if value is None or not value.isalpha(): return api = get_api_handler(settings.API_HANDLER) try: airport = api.get_airport(value) except NotFoundError: self.warning('No destination airport found for %s.', value) return self.debug('Detected destination airport: %s', airport) self.set_flight_attr(airport)
def derive(self, dest=P('Destination'), afr_dest=A('AFR Destination Airport')): ''' Requires an ASCII destination parameter recording either the airport's ICAO or IATA code. ''' if not dest or dest.array.dtype.type is not np.string_: if afr_dest: self.set_flight_attr(afr_dest.value) return # XXX: Slow, but Destination should be sampled infrequently. value, count = next(reversed(sorted(Counter(dest.array).items(), key=itemgetter(1)))) # Q: Should we validate that the value is 3-4 characters long? if value is np.ma.masked or count < len(dest.array) * 0.45: return api = get_api_handler(settings.API_HANDLER) try: airport = api.get_airport(value) except NotFoundError: self.warning('No destination airport found for %s.', value) return self.debug('Detected destination airport: %s', airport) self.set_flight_attr(airport)
def lookup_airport(self, lat_source, lon_source): lat = lat_source.get_first() lon = lon_source.get_first() if lat and lon: api = get_api_handler(settings.API_HANDLER) try: airport = api.get_nearest_airport(lat.value, lon.value) except NotFoundError: msg = 'No takeoff airport found near coordinates (%f, %f).' self.warning(msg, lat.value, lon.value) # No airport was found, so fall through and try AFR. else: self.info('Detected takeoff airport: %s from coordinates (%f, %f)', airport.get('code'), lat.value, lon.value) self.set_flight_attr(airport) return True # We found an airport, so finish here. else: self.warning('No coordinates for looking up takeoff airport.')
def lookup_airport(self, lat_source, lon_source): lat = lat_source.get_first() lon = lon_source.get_first() if lat and lon: api = get_api_handler(settings.API_HANDLER) try: airport = api.get_nearest_airport(lat.value, lon.value) except NotFoundError: msg = 'No takeoff airport found near coordinates (%f, %f).' self.warning(msg, lat.value, lon.value) # No airport was found, so fall through and try AFR. else: self.info( 'Detected takeoff airport: %s from coordinates (%f, %f)', airport.get('code'), lat.value, lon.value) self.set_flight_attr(airport) return True # We found an airport, so finish here. else: self.warning('No coordinates for looking up takeoff airport.')
def derive(self, land_lat=KPV('Latitude At Touchdown'), land_lon=KPV('Longitude At Touchdown'), land_afr_apt=A('AFR Landing Airport')): ''' ''' # 1. If we have latitude and longitude, look for the nearest airport: if land_lat and land_lon: lat = land_lat.get_last() lon = land_lon.get_last() if lat and lon: api = get_api_handler(settings.API_HANDLER) try: airport = api.get_nearest_airport(lat.value, lon.value) except NotFoundError: msg = 'No landing airport found near coordinates (%f, %f).' self.warning(msg, lat.value, lon.value) # No airport was found, so fall through and try AFR. else: self.info( 'Detected landing airport: %s from coordinates (%f, %f)', airport.get('code'), lat.value, lon.value) self.set_flight_attr(airport) return # We found an airport, so finish here. else: self.warning('No coordinates for looking up landing airport.') # No suitable coordinates, so fall through and try AFR. # 2. If we have an airport provided in achieved flight record, use it: if land_afr_apt: airport = land_afr_apt.value self.debug('Using landing airport from AFR: %s', airport) self.set_flight_attr(airport) return # We found an airport in the AFR, so finish here. # 3. After all that, we still couldn't determine an airport... self.error('Unable to determine airport at landing!') self.set_flight_attr(None)
def derive(self, toff_lat=KPV('Latitude At Liftoff'), toff_lon=KPV('Longitude At Liftoff'), toff_afr_apt=A('AFR Takeoff Airport')): ''' ''' # 1. If we have latitude and longitude, look for the nearest airport: if toff_lat and toff_lon: lat = toff_lat.get_first() lon = toff_lon.get_first() if lat and lon: api = get_api_handler(settings.API_HANDLER) try: airport = api.get_nearest_airport(lat.value, lon.value) except NotFoundError: msg = 'No takeoff airport found near coordinates (%f, %f).' self.warning(msg, lat.value, lon.value) # No airport was found, so fall through and try AFR. else: self.debug('Detected takeoff airport: %s', airport) self.set_flight_attr(airport) return # We found an airport, so finish here. else: self.warning('No coordinates for looking up takeoff airport.') # No suitable coordinates, so fall through and try AFR. # 2. If we have an airport provided in achieved flight record, use it: if toff_afr_apt: airport = toff_afr_apt.value self.debug('Using takeoff airport from AFR: %s', airport) self.set_flight_attr(airport) return # We found an airport in the AFR, so finish here. # 3. After all that, we still couldn't determine an airport... self.error('Unable to determine airport at takeoff!') self.set_flight_attr(None)
def derive(self, toff_fdr_apt=A('FDR Takeoff Airport'), toff_afr_rwy=A('AFR Takeoff Runway'), toff_hdg=KPV('Heading During Takeoff'), toff_lat=KPV('Latitude At Liftoff'), toff_lon=KPV('Longitude At Liftoff'), precision=A('Precise Positioning')): ''' ''' fallback = False precise = bool(getattr(precision, 'value', False)) try: airport = int(toff_fdr_apt.value['id']) except (AttributeError, KeyError, TypeError, ValueError): self.warning('Invalid airport... Fallback to AFR Takeoff Runway.') fallback = True try: heading = toff_hdg.get_first().value if heading is None: raise ValueError except (AttributeError, ValueError): self.warning('Invalid heading... Fallback to AFR Takeoff Runway.') fallback = True # 1. If we have airport and heading, look for the nearest runway: if not fallback: kwargs = {} # Even if we do not have precise latitude and longitude # information, we still use this for the takeoff runway detection # as it is often accurate at the start of a flight, and in the # absence of an ILS tuned frequency we have no better option. (We # did consider using the last direction of turn onto the runway, # but this would require an airport database with terminal and # taxiway details that was not felt justified). if toff_lat and toff_lon: lat = toff_lat.get_first() lon = toff_lon.get_first() if lat and lon: kwargs.update( latitude=lat.value, longitude=lon.value, ) else: self.warning('No coordinates for takeoff runway lookup.') if not precise: kwargs.update(hint='takeoff') api = get_api_handler(settings.API_HANDLER) try: runway = api.get_nearest_runway(airport, heading, **kwargs) except NotFoundError: msg = 'No runway found for airport #%d @ %03.1f deg with %s.' self.warning(msg, airport, heading, kwargs) # No runway was found, so fall through and try AFR. else: self.info( 'Detected takeoff runway: %s for airport #%d @ %03.1f deg with %s', runway['identifier'], airport, heading, kwargs) self.set_flight_attr(runway) return # We found a runway, so finish here. # 2. If we have a runway provided in achieved flight record, use it: if toff_afr_rwy: runway = toff_afr_rwy.value self.debug('Using takeoff runway from AFR: %s', runway) self.set_flight_attr(runway) return # We found a runway in the AFR, so finish here. # 3. After all that, we still couldn't determine a runway... self.error('Unable to determine runway at takeoff!') self.set_flight_attr(None)
def derive(self, land_fdr_apt=A('FDR Landing Airport'), land_afr_rwy=A('AFR Landing Runway'), land_hdg=KPV('Heading During Landing'), land_lat=KPV('Latitude At Touchdown'), land_lon=KPV('Longitude At Touchdown'), precision=A('Precise Positioning'), approaches=S('Approach And Landing'), ils_freq_on_app=KPV('ILS Frequency During Approach')): ''' ''' fallback = False precise = bool(getattr(precision, 'value', False)) try: airport = int(land_fdr_apt.value['id']) except (AttributeError, KeyError, TypeError, ValueError): self.warning('Invalid airport... Fallback to AFR Landing Runway.') fallback = True try: heading = land_hdg.get_last().value if heading is None: raise ValueError except (AttributeError, ValueError): self.warning('Invalid heading... Fallback to AFR Landing Runway.') fallback = True try: landing = approaches.get_last() if landing is None: raise ValueError except (AttributeError, ValueError): self.warning('No approaches... Fallback to AFR Landing Runway.') # Don't set fallback - can still attempt to use heading only... # 1. If we have airport and heading, look for the nearest runway: if not fallback: kwargs = {} # The last approach is assumed to be the landing. # XXX: Last approach may not be landing for partial data?! if ils_freq_on_app: if landing.start_edge: ils_app_slice = slice(landing.start_edge, landing.slice.stop) else: ils_app_slice = landing.slice ils_freq = ils_freq_on_app.get_last(within_slice=ils_app_slice) if ils_freq: kwargs.update(ils_freq=ils_freq.value) ''' Original comment: # We only provide coordinates when looking up a landing runway if # the recording of latitude and longitude on the aircraft is # precise. Inertial recordings are too inaccurate to pinpoint the # correct runway and we use ILS frequencies if possible to get a # more exact match. Revised comment: In the absence of an ILS frequency, the recorded latitude and longitude is better than nothing and reduces the chance of identifying the wrong runway. ''' if (precise or not ils_freq_on_app) and landing and land_lat and land_lon: lat = land_lat.get_last(within_slice=landing.slice) lon = land_lon.get_last(within_slice=landing.slice) if lat and lon: kwargs.update( latitude=lat.value, longitude=lon.value, ) else: self.warning('No coordinates for landing runway lookup.') else: kwargs.update(hint='landing') api = get_api_handler(settings.API_HANDLER) try: runway = api.get_nearest_runway(airport, heading, **kwargs) except NotFoundError: msg = 'No runway found for airport #%d @ %03.1f deg with %s.' self.warning(msg, airport, heading, kwargs) # No runway was found, so fall through and try AFR. if 'ils_freq' in kwargs: # This is a trap for airports where the ILS data is not # available, but the aircraft approached with the ILS # tuned. A good prompt for an omission in the database. self.warning('Fix database? No runway but ILS was tuned.') else: self.info( 'Detected landing runway: %s for airport #%d @ %03.1f deg with %s', runway['identifier'], airport, heading, kwargs) self.set_flight_attr(runway) return # We found a runway, so finish here. # 2. If we have a runway provided in achieved flight record, use it: if land_afr_rwy: runway = land_afr_rwy.value self.debug('Using landing runway from AFR: %s', runway) self.set_flight_attr(runway) return # We found a runway in the AFR, so finish here. # 3. After all that, we still couldn't determine a runway... self.error('Unable to determine runway at landing!') self.set_flight_attr(None)
def derive(self, toff_fdr_apt=A('FDR Takeoff Airport'), toff_afr_rwy=A('AFR Takeoff Runway'), toff_hdg=KPV('Heading During Takeoff'), toff_lat=KPV('Latitude At Liftoff'), toff_lon=KPV('Longitude At Liftoff'), precision=A('Precise Positioning')): ''' ''' fallback = False precise = bool(getattr(precision, 'value', False)) try: airport = int(toff_fdr_apt.value['id']) except (AttributeError, KeyError, TypeError, ValueError): self.warning('Invalid airport... Fallback to AFR Takeoff Runway.') fallback = True try: heading = toff_hdg.get_first().value if heading is None: raise ValueError except (AttributeError, ValueError): self.warning('Invalid heading... Fallback to AFR Takeoff Runway.') fallback = True # 1. If we have airport and heading, look for the nearest runway: if not fallback: kwargs = {} # Even if we do not have precise latitude and longitude # information, we still use this for the takeoff runway detection # as it is often accurate at the start of a flight, and in the # absence of an ILS tuned frequency we have no better option. (We # did consider using the last direction of turn onto the runway, # but this would require an airport database with terminal and # taxiway details that was not felt justified). if toff_lat and toff_lon: lat = toff_lat.get_first() lon = toff_lon.get_first() if lat and lon: kwargs.update( latitude=lat.value, longitude=lon.value, ) else: self.warning('No coordinates for takeoff runway lookup.') if not precise: kwargs.update(hint='takeoff') api = get_api_handler(settings.API_HANDLER) try: runway = api.get_nearest_runway(airport, heading, **kwargs) except NotFoundError: msg = 'No runway found for airport #%d @ %03.1f deg with %s.' self.warning(msg, airport, heading, kwargs) # No runway was found, so fall through and try AFR. else: self.debug('Detected takeoff runway: %s', runway) self.set_flight_attr(runway) return # We found a runway, so finish here. # 2. If we have a runway provided in achieved flight record, use it: if toff_afr_rwy: runway = toff_afr_rwy.value self.debug('Using takeoff runway from AFR: %s', runway) self.set_flight_attr(runway) return # We found a runway in the AFR, so finish here. # 3. After all that, we still couldn't determine a runway... self.error('Unable to determine runway at takeoff!') self.set_flight_attr(None)
def derive(self, land_fdr_apt=A('FDR Landing Airport'), land_afr_rwy=A('AFR Landing Runway'), land_hdg=KPV('Heading During Landing'), land_lat=KPV('Latitude At Touchdown'), land_lon=KPV('Longitude At Touchdown'), precision=A('Precise Positioning'), approaches=S('Approach And Landing'), ils_freq_on_app=KPV('ILS Frequency During Approach')): ''' ''' fallback = False precise = bool(getattr(precision, 'value', False)) try: airport = int(land_fdr_apt.value['id']) except (AttributeError, KeyError, TypeError, ValueError): self.warning('Invalid airport... Fallback to AFR Landing Runway.') fallback = True try: heading = land_hdg.get_last().value if heading is None: raise ValueError except (AttributeError, ValueError): self.warning('Invalid heading... Fallback to AFR Landing Runway.') fallback = True try: landing = approaches.get_last() if landing is None: raise ValueError except (AttributeError, ValueError): self.warning('No approaches... Fallback to AFR Landing Runway.') # Don't set fallback - can still attempt to use heading only... # 1. If we have airport and heading, look for the nearest runway: if not fallback: kwargs = {} # The last approach is assumed to be the landing. # XXX: Last approach may not be landing for partial data?! if ils_freq_on_app: ils_freq = ils_freq_on_app.get_last(within_slice=landing.slice) if ils_freq: kwargs.update(ils_freq=ils_freq.value) # We only provide coordinates when looking up a landing runway if # the recording of latitude and longitude on the aircraft is # precise. Inertial recordings are too inaccurate to pinpoint the # correct runway and we use ILS frequencies if possible to get a # more exact match. if precise and landing and land_lat and land_lon: lat = land_lat.get_last(within_slice=landing.slice) lon = land_lon.get_last(within_slice=landing.slice) if lat and lon: kwargs.update( latitude=lat.value, longitude=lon.value, ) else: self.warning('No coordinates for landing runway lookup.') else: kwargs.update(hint='landing') api = get_api_handler(settings.API_HANDLER) try: runway = api.get_nearest_runway(airport, heading, **kwargs) except NotFoundError: msg = 'No runway found for airport #%d @ %03.1f deg with %s.' self.warning(msg, airport, heading, kwargs) # No runway was found, so fall through and try AFR. if 'ils_freq' in kwargs: # This is a trap for airports where the ILS data is not # available, but the aircraft approached with the ILS # tuned. A good prompt for an omission in the database. self.warning('Fix database? No runway but ILS was tuned.') else: self.debug('Detected landing runway: %s', runway) self.set_flight_attr(runway) return # We found a runway, so finish here. # 2. If we have a runway provided in achieved flight record, use it: if land_afr_rwy: runway = land_afr_rwy.value self.debug('Using landing runway from AFR: %s', runway) self.set_flight_attr(runway) return # We found a runway in the AFR, so finish here. # 3. After all that, we still couldn't determine a runway... self.error('Unable to determine runway at landing!') self.set_flight_attr(None)
def _lookup_airport_and_runway(self, _slice, precise, lowest_lat, lowest_lon, lowest_hdg, appr_ils_freq, land_afr_apt=None, land_afr_rwy=None, hint='approach'): ''' ''' api = get_api_handler(settings.API_HANDLER) kwargs = {} airport = None runway = None # A1. If we have latitude and longitude, look for the nearest airport: if lowest_lat != None and lowest_lon != None: kwargs.update(latitude=lowest_lat, longitude=lowest_lon) try: airport = api.get_nearest_airport(**kwargs) except NotFoundError: msg = 'No approach airport found near coordinates (%f, %f).' self.warning(msg, lowest_lat, lowest_lon) # No airport was found, so fall through and try AFR. else: self.debug('Detected approach airport: %s', airport) else: # No suitable coordinates, so fall through and try AFR. self.warning('No coordinates for looking up approach airport.') return None, None # A2. If and we have an airport in achieved flight record, use it: # NOTE: AFR data is only provided if this approach is a landing. if not airport and land_afr_apt: airport = land_afr_apt.value self.debug('Using approach airport from AFR: %s', airport) # A3. After all that, we still couldn't determine an airport... if not airport: self.error('Unable to determine airport on approach!') return None, None airport_id = int(airport['id']) if lowest_hdg is not None: #if heading is None: #self.warning('Invalid heading... Fallback to AFR.') #fallback = True # R1. If we have airport and heading, look for the nearest runway: if appr_ils_freq: kwargs['ils_freq'] = appr_ils_freq # We already have latitude and longitude in kwargs from looking up # the airport. If the measurments are not precise, remove them. if not precise: kwargs['hint'] = hint del kwargs['latitude'] del kwargs['longitude'] try: runway = api.get_nearest_runway(airport_id, lowest_hdg, **kwargs) except NotFoundError: msg = 'No runway found for airport #%d @ %03.1f deg with %s.' self.warning(msg, airport_id, lowest_hdg, kwargs) # No runway was found, so fall through and try AFR. if 'ils_freq' in kwargs: # This is a trap for airports where the ILS data is not # available, but the aircraft approached with the ILS # tuned. A good prompt for an omission in the database. self.warning('Fix database? No runway but ILS was tuned.') else: self.debug('Detected approach runway: %s', runway) runway = runway # R2. If we have a runway provided in achieved flight record, use it: if not runway and land_afr_rwy: runway = land_afr_rwy.value self.debug('Using approach runway from AFR: %s', runway) # R3. After all that, we still couldn't determine a runway... if not runway: self.error('Unable to determine runway on approach!') return airport, runway
def _lookup_airport_and_runway(self, _slice, precise, lowest_lat, lowest_lon, lowest_hdg, appr_ils_freq, land_afr_apt=None, land_afr_rwy=None, hint='approach'): ''' ''' api = get_api_handler(settings.API_HANDLER) kwargs = {} airport = None runway = None # A1. If we have latitude and longitude, look for the nearest airport: if lowest_lat!=None and lowest_lon!=None: kwargs.update(latitude=lowest_lat, longitude=lowest_lon) try: airport = api.get_nearest_airport(**kwargs) except NotFoundError: msg = 'No approach airport found near coordinates (%f, %f).' self.warning(msg, lowest_lat, lowest_lon) # No airport was found, so fall through and try AFR. else: self.debug('Detected approach airport: %s', airport) else: # No suitable coordinates, so fall through and try AFR. self.warning('No coordinates for looking up approach airport.') return None, None # A2. If and we have an airport in achieved flight record, use it: # NOTE: AFR data is only provided if this approach is a landing. if not airport and land_afr_apt: airport = land_afr_apt.value self.debug('Using approach airport from AFR: %s', airport) # A3. After all that, we still couldn't determine an airport... if not airport: self.error('Unable to determine airport on approach!') return None, None airport_id = int(airport['id']) if lowest_hdg is not None: #if heading is None: #self.warning('Invalid heading... Fallback to AFR.') #fallback = True # R1. If we have airport and heading, look for the nearest runway: if appr_ils_freq: ils_freq = appr_ils_freq.get_first(within_slice=_slice) if ils_freq: kwargs['ils_freq'] = ils_freq.value # We already have latitude and longitude in kwargs from looking up # the airport. If the measurments are not precise, remove them. if not precise: kwargs['hint'] = hint del kwargs['latitude'] del kwargs['longitude'] try: runway = api.get_nearest_runway(airport_id, lowest_hdg, **kwargs) except NotFoundError: msg = 'No runway found for airport #%d @ %03.1f deg with %s.' self.warning(msg, airport_id, lowest_hdg, kwargs) # No runway was found, so fall through and try AFR. if 'ils_freq' in kwargs: # This is a trap for airports where the ILS data is not # available, but the aircraft approached with the ILS # tuned. A good prompt for an omission in the database. self.warning('Fix database? No runway but ILS was tuned.') else: self.debug('Detected approach runway: %s', runway) runway = runway # R2. If we have a runway provided in achieved flight record, use it: if not runway and land_afr_rwy: runway = land_afr_rwy.value self.debug('Using approach runway from AFR: %s', runway) # R3. After all that, we still couldn't determine a runway... if not runway: self.error('Unable to determine runway on approach!') return airport, runway
def process_flight(hdf_path, tail_number, aircraft_info={}, start_datetime=datetime.now(), achieved_flight_record={}, requested=[], required=[], include_flight_attributes=True, additional_modules=[]): ''' Processes the HDF file (hdf_path) to derive the required_params (Nodes) within python modules (settings.NODE_MODULES). Note: For Flight Data Services, the definitive API is located here: "PolarisTaskManagement.test.tasks_mask.process_flight" :param hdf_path: Path to HDF File :type hdf_path: String :param aircraft: Aircraft specific attributes :type aircraft: dict :param start_datetime: Datetime of the origin of the data (at index 0) :type start_datetime: Datetime :param achieved_flight_record: See API Below :type achieved_flight_record: Dict :param requested: Derived nodes to process (dependencies will also be evaluated). :type requested: List of Strings :param required: Nodes which are required, otherwise an exception will be raised. :type required: List of Strings :param include_flight_attributes: Whether to include all flight attributes :type include_flight_attributes: Boolean :param additional_modules: List of module paths to import. :type additional_modules: List of Strings :returns: See below: :rtype: Dict Sample aircraft_info -------------------- { 'Tail Number': # Aircraft Registration 'Identifier': # Aircraft Ident 'Manufacturer': # e.g. Boeing 'Manufacturer Serial Number': #MSN 'Model': # e.g. 737-808-ER 'Series': # e.g. 737-800 'Family': # e.g. 737 'Frame': # e.g. 737-3C 'Main Gear To Altitude Radio': # Distance in metres 'Wing Span': # Distance in metres } Sample achieved_flight_record ----------------------------- { # Simple values first, e.g. string, int, float, etc. 'AFR Flight ID': # e.g. 1 'AFR Flight Number': # e.g. 1234 'AFR Type': # 'POSITIONING' 'AFR Off Blocks Datetime': # datetime(2015,01,01,13,00) 'AFR Takeoff Datetime': # datetime(2015,01,01,13,15) 'AFR Takeoff Pilot': # 'Joe Bloggs' 'AFR Takeoff Gross Weight': # weight in kg 'AFR Takeoff Fuel': # fuel in kg 'AFR Landing Datetime': # datetime(2015,01,01,18,45) 'AFR Landing Pilot': # 'Joe Bloggs' 'AFR Landing Gross Weight': # weight in kg 'AFR Landing Fuel': # weight in kg 'AFR On Blocks Datetime': # datetime(2015,01,01,19,00) 'AFR V2': # V2 used at takeoff in kts 'AFR Vapp': # Vapp used in kts 'AFR Vref': # Vref used in kts # More complex data that needs to be looked up next: 'AFR Takeoff Airport': { 'id': 4904, # unique id 'name': 'Athens Intl Airport Elefterios Venizel', 'code': {'iata': 'ATH', 'icao': 'LGAV'}, 'latitude': 37.9364, 'longitude': 23.9445, 'location': {'city': u'Athens', 'country': u'Greece'}, 'elevation': 266, # ft 'magnetic_variation': 'E003186 0106', } }, 'AFR Landing Aiport': { 'id': 1, # unique id 'name': 'Athens Intl Airport Elefterios Venizel', 'code': {'iata': 'ATH', 'icao': 'LGAV'}, 'latitude': 37.9364, 'longitude': 23.9445, 'location': {'city': u'Athens', 'country': u'Greece'}, 'elevation': 266, # ft 'magnetic_variation': 'E003186 0106', } }, 'AFR Destination Airport': None, # if not required, or exclude this key 'AFR Takeoff Runway': { 'id': 1, 'identifier': '21L', 'magnetic_heading': 212.6, 'strip': { 'id': 1, 'length': 13123, 'surface': 'ASP', 'width': 147}, 'start': { 'elevation': 308, 'latitude': 37.952425, 'longitude': 23.970422}, 'end': { 'elevation': 279, 'latitude': 37.923511, 'longitude': 23.943261}, 'glideslope': { 'angle': 3.0, 'elevation': 282, 'latitude': 37.9473, 'longitude': 23.9676, 'threshold_distance': 999}, 'localizer': { 'beam_width': 4.5, 'elevation': 256, 'frequency': 111100, 'heading': 213, 'latitude': 37.919281, 'longitude': 23.939294}, }, 'AFR Landing Runway': { 'id': 1, 'identifier': '21L', 'magnetic_heading': 212.6, 'strip': { 'id': 1, 'length': 13123, 'surface': 'ASP', 'width': 147}, 'start': { 'elevation': 308, 'latitude': 37.952425, 'longitude': 23.970422}, 'end': { 'elevation': 279, 'latitude': 37.923511, 'longitude': 23.943261}, 'glideslope': { 'angle': 3.0, 'elevation': 282, 'latitude': 37.9473, 'longitude': 23.9676, 'threshold_distance': 999}, 'localizer': { 'beam_width': 4.5, 'elevation': 256, 'frequency': 111100, 'heading': 213, 'latitude': 37.919281, 'longitude': 23.939294}, }, } Sample Return ------------- { 'flight':[Attribute('name value')] # sample: [Attribute('Takeoff Airport', {'id':1234, 'name':'Int. Airport'}, Attribute('Approaches', [4567,7890]), ...], 'kti':[GeoKeyTimeInstance('index name latitude longitude')] if lat/long available else [KeyTimeInstance('index name')] 'kpv':[KeyPointValue('index value name slice')] } ''' logger.info("Processing: %s", hdf_path) if aircraft_info: # Aircraft info has already been provided. logger.info( "Using aircraft_info dictionary passed into process_flight '%s'." % aircraft_info) else: # Fetch aircraft info through the API. api_handler = get_api_handler(settings.API_HANDLER) try: aircraft_info = api_handler.get_aircraft(tail_number) except APIError: if settings.API_HANDLER == settings.LOCAL_API_HANDLER: raise # Fallback to the local API handler. logger.info( "Aircraft '%s' could not be found with '%s' API handler. " "Falling back to '%s'.", tail_number, settings.API_HANDLER, settings.LOCAL_API_HANDLER) api_handler = get_api_handler(settings.LOCAL_API_HANDLER) aircraft_info = api_handler.get_aircraft(tail_number) logger.info("Using aircraft_info provided by '%s' '%s'.", api_handler.__class__.__name__, aircraft_info) aircraft_info['Tail Number'] = tail_number # go through modules to get derived nodes node_modules = additional_modules + settings.NODE_MODULES derived_nodes = get_derived_nodes(node_modules) if requested: requested = \ list(set(requested).intersection(set(derived_nodes))) else: # if requested isn't set, try using ALL derived_nodes! logger.info("No requested nodes declared, using all derived nodes") requested = derived_nodes.keys() # include all flight attributes as requested if include_flight_attributes: requested = list(set( requested + get_derived_nodes( ['analysis_engine.flight_attribute']).keys())) # open HDF for reading with hdf_file(hdf_path) as hdf: if hooks.PRE_FLIGHT_ANALYSIS: logger.info("Performing PRE_FLIGHT_ANALYSIS actions: %s", hooks.PRE_FLIGHT_ANALYSIS.func_name) hooks.PRE_FLIGHT_ANALYSIS(hdf, aircraft_info) else: logger.info("No PRE_FLIGHT_ANALYSIS actions to perform") # Track nodes. Assume that all params in HDF are from LFL(!) node_mgr = NodeManager( start_datetime, hdf.duration, hdf.valid_param_names(), requested, required, derived_nodes, aircraft_info, achieved_flight_record) # calculate dependency tree process_order, gr_st = dependency_order(node_mgr, draw=False) if settings.CACHE_PARAMETER_MIN_USAGE: # find params used more than for node in gr_st.nodes(): if node in node_mgr.derived_nodes: # this includes KPV/KTIs but they'll be ignored by HDF qty = len(gr_st.predecessors(node)) if qty > settings.CACHE_PARAMETER_MIN_USAGE: hdf.cache_param_list.append(node) logging.info("HDF set to cache parameters: %s", hdf.cache_param_list) # derive parameters kti_list, kpv_list, section_list, approach_list, flight_attrs = \ derive_parameters(hdf, node_mgr, process_order) # geo locate KTIs kti_list = geo_locate(hdf, kti_list) kti_list = _timestamp(start_datetime, kti_list) # geo locate KPVs kpv_list = geo_locate(hdf, kpv_list) kpv_list = _timestamp(start_datetime, kpv_list) # Store version of FlightDataAnalyser hdf.analysis_version = __version__ # Store dependency tree hdf.dependency_tree = json_graph.dumps(gr_st) # Store aircraft info hdf.set_attr('aircraft_info', aircraft_info) hdf.set_attr('achieved_flight_record', achieved_flight_record) return { 'flight' : flight_attrs, 'kti' : kti_list, 'kpv' : kpv_list, 'approach': approach_list, 'phases' : section_list, }