def can_operate(cls, available, ac_type=A('Aircraft Type')): aircraft = ac_type == helicopter gearbox = any_of( ('MGB Oil Press', 'MGB (Fwd) Oil Press', 'MGB (Aft) Oil Press'), available) airborne = 'Airborne' in available return aircraft and gearbox and airborne
def derive(self, liftoff=KTI('Liftoff'), rto=S('Rejected Takeoff'), off_blocks=KTI('Off Blocks'), start_dt=A('Start Datetime')): if liftoff: # Flight - use first liftoff index first_liftoff = liftoff.get_first() liftoff_index = first_liftoff.index frequency = liftoff.frequency elif rto: # RTO - use start index of first RTO first_rto = rto.get_first() liftoff_index = first_rto.slice.start frequency = rto.frequency elif off_blocks: # Ground Only - use first off blocks index first_off_blocks = off_blocks.get_first() liftoff_index = first_off_blocks.index frequency = off_blocks.frequency else: # Incomplete - use start of data liftoff_index = 0 frequency = 1 takeoff_dt = datetime_of_index(start_dt.value, liftoff_index, frequency=frequency) self.set_flight_attr(takeoff_dt)
def derive(self, start_datetime=A('Start Datetime')): ''' Every derive method requires at least one dependency. Since this class should always derive a flight attribute, 'Start Datetime' is its only dependency as it will always be present, though it is unused. ''' self.set_flight_attr(datetime.utcnow().replace(tzinfo=pytz.utc))
def derive(self, pilot_flying=M('Pilot Flying'), pitch_capt=P('Pitch (Capt)'), pitch_fo=P('Pitch (FO)'), roll_capt=P('Roll (Capt)'), roll_fo=P('Roll (FO)'), cc_capt=P('Control Column Force (Capt)'), cc_fo=P('Control Column Force (FO)'), ap1_eng=M('AP (1) Engaged'), ap2_eng=M('AP (2) Engaged'), takeoffs=S('Takeoff'), liftoffs=KTI('Liftoff'), rejected_toffs=S('Rejected Takeoff'), afr_takeoff_pilot=A('AFR Takeoff Pilot')): if afr_takeoff_pilot and afr_takeoff_pilot.value: self.set_flight_attr(afr_takeoff_pilot.value.replace('_', ' ').title()) return #TODO: Tidy phase = takeoffs or rejected_toffs or None if phase is None: # Nothing to do as no attempt to takeoff return lift = liftoffs.get_first() if liftoffs else None if lift and ap1_eng and ap2_eng: # check AP state at the floored index (just before lift) ap1 = ap1_eng.array[int(lift.index)] == 'Engaged' ap2 = ap2_eng.array[int(lift.index)] == 'Engaged' else: ap1 = ap2 = None args = (pilot_flying, pitch_capt, pitch_fo, roll_capt, roll_fo, cc_capt, cc_fo, phase.get_first(), ap1, ap2) self.set_flight_attr(self._determine_pilot(*args))
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 derive(self, approaches=App('Approach Information'), land_afr_apt=A('AFR Landing Airport')): ''' ''' # 1. If we have Approach Information use this as hardwork already done. if approaches and approaches.get_last(_type='LANDING'): landing_approach = approaches.get_last(_type='LANDING') airport = landing_approach.airport if airport: self.set_flight_attr(airport) return # We found an airport, so finish here. elif landing_approach: self.warning('No landing airport found.') else: self.warning('No Landing Approach for looking up landing airport.') # 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, takeoffs=S('Takeoff'), climb_starts=KTI('Climb Start'), tocs=KTI('Top Of Climb'), alt=P('Altitude STD'), ac_type=A('Aircraft Type')): pass
def test_derive_without_turning(self): # Empty 'Turning'. turning = S('Turning On Ground') start_datetime = A(name='Start Datetime', value=datetime.now()) off_blocks_datetime = OnBlocksDatetime() off_blocks_datetime.set_flight_attr = Mock() off_blocks_datetime.derive(turning, start_datetime) off_blocks_datetime.set_flight_attr.assert_called_once_with(None) # 'Turning On Ground'. turning = S('Turning On Ground', items=[KeyPointValue(name='Turning On Ground', slice=slice(20, 60))]) off_blocks_datetime.set_flight_attr = Mock() off_blocks_datetime.derive(turning, start_datetime) off_blocks_datetime.set_flight_attr.assert_called_once_with( start_datetime.value + timedelta(seconds=60)) turning = S('Turning', items=[KeyPointValue(name='Turning On Ground', slice=slice(10, 20)), KeyPointValue(name='Turning In Air', slice=slice(20, 60)), KeyPointValue(name='Turning On Ground', slice=slice(70, 90))]) off_blocks_datetime.set_flight_attr = Mock() off_blocks_datetime.derive(turning, start_datetime) off_blocks_datetime.set_flight_attr.assert_called_once_with( start_datetime.value + timedelta(seconds=90))
def test_derive_afr_fallback(self, get_nearest_airport): info = {'id': '50'} get_nearest_airport.return_value = info lat = KPV(name='Latitude At Liftoff', items=[ KeyPointValue(index=12, value=4.0), KeyPointValue(index=32, value=6.0), ]) lon = KPV(name='Longitude At Liftoff', items=[ KeyPointValue(index=12, value=3.0), KeyPointValue(index=32, value=9.0), ]) afr_apt = A(name='AFR Takeoff Airport', value={'id': 25}) apt = self.node_class() apt.set_flight_attr = Mock() # Check that the AFR airport was used and the API wasn't called: apt.derive(None, None, afr_apt) apt.set_flight_attr.assert_called_once_with(afr_apt.value) apt.set_flight_attr.reset_mock() assert not get_nearest_airport.called, 'method should not have been called' apt.derive(lat, None, afr_apt) apt.set_flight_attr.assert_called_once_with(afr_apt.value) apt.set_flight_attr.reset_mock() assert not get_nearest_airport.called, 'method should not have been called' apt.derive(None, lon, afr_apt) apt.set_flight_attr.assert_called_once_with(afr_apt.value) apt.set_flight_attr.reset_mock() assert not get_nearest_airport.called, 'method should not have been called'
def derive(self, approaches=KPV('Approach Information'), land_afr_apt=App('AFR Landing Airport'), precise_pos=A('Precise Positioning')): ''' ''' precise_pos = bool(getattr(precise_pos, 'value', False)) if not precise_pos and land_afr_apt: self.use_afr(land_afr_apt) return if approaches and approaches.get_last(_type='LANDING'): landing_approach = approaches.get_last(_type='LANDING') airport = landing_approach.airport if airport: self.set_flight_attr(airport) return elif landing_approach: self.warning('No landing airport found.') else: self.warning('No Landing Approach for looking up landing airport.') if land_afr_apt: self.use_afr(land_afr_apt) return self.error('Unable to determine airport at landing!') self.set_flight_attr(None)
def derive( self, # align to longitude to avoid wrap around artifacts lon=P('Longitude'), lat=P('Latitude'), ac_type=A('Aircraft Type')): self.array = self._smooth_coordinates(lat, lon, ac_type)
def derive( self, toff_lat=KPV('Latitude At Liftoff'), toff_lon=KPV('Longitude At Liftoff'), toff_afr_apt=A('AFR Takeoff Airport'), off_block_lat=KPV('Latitude Off Blocks'), off_block_lon=KPV('Longitude Off Blocks'), ): ''' ''' # 1. If we have latitude and longitude, look for the nearest airport: if toff_lat and toff_lon: success = self.lookup_airport(toff_lat, toff_lon) if success: return # 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. If we have coordinates of Aircraft moving off Blocks look for the nearest airport: if off_block_lat and off_block_lon: success = self.lookup_airport(off_block_lat, off_block_lon) if success: return # 4. 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, pilot_flying=M('Pilot Flying'), pitch_capt=P('Pitch (Capt)'), pitch_fo=P('Pitch (FO)'), roll_capt=P('Roll (Capt)'), roll_fo=P('Roll (FO)'), cc_capt=P('Control Column Force (Capt)'), cc_fo=P('Control Column Force (FO)'), ap1_eng=M('AP (1) Engaged'), ap2_eng=M('AP (2) Engaged'), landings=S('Landing'), touchdowns=KTI('Touchdown'), afr_landing_pilot=A('AFR Landing Pilot')): if afr_landing_pilot and afr_landing_pilot.value: self.set_flight_attr(afr_landing_pilot.value.replace('_', ' ').title()) return phase = landings.get_last() if landings else None tdwn = touchdowns.get_last() if touchdowns else None if tdwn and ap1_eng and ap2_eng: # check AP state at the floored index (just before tdwn) ap1 = ap1_eng.array[int(tdwn.index)] == 'Engaged' ap2 = ap2_eng.array[int(tdwn.index)] == 'Engaged' else: ap1 = ap2 = None args = (pilot_flying, pitch_capt, pitch_fo, roll_capt, roll_fo, cc_capt, cc_fo, phase, ap1, ap2) self.set_flight_attr(self._determine_pilot(*args))
def derive( self, approaches=App('Approach Information'), land_afr_rwy=A('AFR Landing Runway'), ): ''' ''' # 1. If we have Approach Information use this as hardwork already done. if approaches: landing_approach = approaches.get_last(_type='LANDING') runway = landing_approach.landing_runway if runway: self.set_flight_attr(runway) return # We found an airport, so finish here. elif landing_approach: self.warning('No landing runway found.') else: self.warning( 'No Landing Approach for looking up landing airport.') # 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, 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 handler = api.get_handler(settings.API_HANDLER) try: airport = handler.get_airport(value) except api.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, ac_type=A('Aircraft Type'), alt_aal=P('Altitude AAL For Flight Phases'), level_flights=S('Level Flight'), apps=S('Approach'), landings=S('Landing')): pass
def test_derive_airport_found(self, get_nearest_airport): ''' Attribute is set when airport is found. ''' info = {'id': 123, 'distance':2} get_nearest_airport.return_value = [info] lat = KPV(name='Latitude At Liftoff', items=[ KeyPointValue(index=12, value=4.0), KeyPointValue(index=32, value=6.0), ]) lon = KPV(name='Longitude At Liftoff', items=[ KeyPointValue(index=12, value=3.0), KeyPointValue(index=32, value=9.0), ]) afr_apt = A(name='AFR Takeoff Airport', value={'id': 25, 'distance':2}) apt = self.node_class() apt.set_flight_attr = Mock() # Check that the airport returned via API is used for the attribute: apt.derive(lat, lon, afr_apt) apt.set_flight_attr.assert_called_once_with(info) apt.set_flight_attr.reset_mock() get_nearest_airport.assert_called_once_with(4.0, 3.0) get_nearest_airport.reset_mock() # Check that the airport returned via API is used for the attribute: apt.derive(None, None, None, lat, lon) apt.set_flight_attr.assert_called_once_with(info) apt.set_flight_attr.reset_mock() get_nearest_airport.assert_called_once_with(4.0, 3.0) get_nearest_airport.reset_mock()
def derive(self, ils_localizer=P('ILS Localizer'), alt_aal=P('Altitude AAL For Flight Phases'), approaches=S('Approach And Landing'), runway=A('FDR Landing Runway')): if 'glideslope' in runway.value: for app in approaches: if ils_localizer: alt_bands = alt_aal.slices_from_to(1000, 500) ils_run = sustained_max_abs(ils_localizer, window=5, _slice=app) x = np.ma.zeros(len(ils_localizer.array)) x.data[app.slice] = ils_run self.create_kpvs_within_slices( abs(x), alt_bands, max_abs_value, ) else: self.warning("ILS Localizer not measured on approach") return else: self.warning("Runway not equipped with ILS Localizer") return
def test_derive_airport_not_found(self, get_nearest_airport): ''' Attribute is not set when airport is not found. ''' get_nearest_airport.side_effect = api.NotFoundError('Not Found.') lat = KPV(name='Latitude At Liftoff', items=[ KeyPointValue(index=12, value=4.0), KeyPointValue(index=32, value=6.0), ]) lon = KPV(name='Longitude At Liftoff', items=[ KeyPointValue(index=12, value=3.0), KeyPointValue(index=32, value=9.0), ]) afr_apt = A(name='AFR Takeoff Airport', value={'id': 25}) apt = self.node_class() apt.set_flight_attr = Mock() # Check that no attribute is created if not found via API: apt.derive(lat, lon, None) apt.set_flight_attr.assert_called_once_with(None) apt.set_flight_attr.reset_mock() get_nearest_airport.assert_called_once_with(4.0, 3.0) get_nearest_airport.reset_mock() # Check that the AFR airport was used if not found via API: apt.derive(lat, lon, afr_apt) apt.set_flight_attr.assert_called_once_with(afr_apt.value) apt.set_flight_attr.reset_mock() get_nearest_airport.assert_called_once_with(4.0, 3.0) get_nearest_airport.reset_mock()
def test_derive__columbia234(self): vert_spd = load( os.path.join(test_data_path, "gear_on_ground__columbia234_vert_spd.nod")) torque = load( os.path.join(test_data_path, "gear_on_ground__columbia234_torque.nod")) collective = load( os.path.join(test_data_path, "gear_on_ground__columbia234_collective.nod")) ac_series = A("Series", value="Columbia 234") wow = GearOnGround() wow.derive(None, None, vert_spd, torque, ac_series, collective) self.assertTrue(np.ma.all(wow.array[:252] == 'Ground')) self.assertTrue(np.ma.all(wow.array[254:540] == 'Air')) self.assertTrue(np.ma.all(wow.array[1040:1200] == 'Air')) self.assertTrue(np.ma.all(wow.array[1420:1440] == 'Air')) self.assertTrue(np.ma.all(wow.array[1533:1550] == 'Ground')) self.assertTrue(np.ma.all(wow.array[1615:1622] == 'Air')) #self.assertTrue(np.ma.all(wow.array[1696:1730] == 'Ground')) self.assertTrue(np.ma.all(wow.array[1900:2150] == 'Air')) self.assertTrue(np.ma.all(wow.array[2350:2385] == 'Air')) self.assertTrue(np.ma.all(wow.array[2550:2750] == 'Air')) self.assertTrue(np.ma.all(wow.array[2900:3020] == 'Air')) self.assertTrue(np.ma.all(wow.array[3366:3376] == 'Air')) self.assertTrue(np.ma.all(wow.array[3425:] == 'Ground'))
def setUp(self): dest_array = np.ma.array( [b'FDSL', b'FDSL', b'FDSL', b'FDSL', b'ABCD', b'ABCD'], mask=[True, False, False, False, False, True]) self.dest = P('Destination', array=dest_array) self.afr_dest = A('AFR Destination Airport', value={'id': 2000}) self.node = DestinationAirport()
def derive(self, afr_landing_fuel=A('AFR Landing Fuel'), touchdown_fuel_qty=KPV('Fuel Qty At Touchdown')): if afr_landing_fuel: self.set_flight_attr(afr_landing_fuel.value) else: fuel_qty_kpv = touchdown_fuel_qty.get_last() if fuel_qty_kpv: self.set_flight_attr(fuel_qty_kpv.value)
def derive(self, gl=M('Gear (L) On Ground'), gr=M('Gear (R) On Ground'), vert_spd=P('Vertical Speed'), torque=P('Eng (*) Torque Avg'), ac_series=A('Series'), collective=P('Collective')): pass
def derive(self, ac_type=A('Aircraft Type'), alt_aal=P('Altitude AAL For Flight Phases'), level_flights=S('Level Flight'), landings=S('Landing'), alt_agl=P('Altitude AGL'), alt_std=P('Altitude STD')): pass
def can_operate(cls, available, ac_type=A('Aircraft Type')): required = ['Approach And Landing'] required.append('Altitude AGL' if ac_type == helicopter else 'Altitude AAL') # Force both Latitude and Longitude to be available if one is available if 'Latitude Prepared' in available and not 'Longitude Prepared' in available: return False elif 'Longitude Prepared' in available and not 'Latitude Prepared' in available: return False return all_of(required, available)
def derive(self, off_blocks=KTI('Off Blocks'), start_datetime=A('Start Datetime')): first_off_blocks = off_blocks.get_first() if first_off_blocks: off_blocks_datetime = datetime_of_index(start_datetime.value, first_off_blocks.index) self.set_flight_attr(off_blocks_datetime) else: self.set_flight_attr(None)
def derive(self, on_blocks=KTI('On Blocks'), start_datetime=A('Start Datetime')): last_on_blocks = on_blocks.get_last() if last_on_blocks: on_blocks_datetime = datetime_of_index(start_datetime.value, last_on_blocks.index) self.set_flight_attr(on_blocks_datetime) else: self.set_flight_attr(None)
def derive(self, # align to longitude to avoid wrap around artifacts lon=P('Longitude'), lat=P('Latitude'), ac_type=A('Aircraft Type')): """ This removes the jumps in longitude arising from the poor resolution of the recorded signal. """ self.array = self._smooth_coordinates(lon, lat, ac_type)
def can_operate(cls, available, ac_type=A('Aircraft Type')): gog_available = any_of(('Gear (L) On Ground', 'Gear (R) On Ground'), available) if gog_available: return True elif all_of(('Vertical Speed', 'Eng (*) Torque Avg'), available): return True else: return False
def test_derive_afr_fallback(self): afr_apt = A(name='AFR Landing Airport', value={'id': 25}) apt = self.node_class() apt.set_flight_attr = Mock() approach = App() approach.create_approach('LANDING', slice(None)) apt.derive(approach, afr_apt) apt.set_flight_attr.assert_called_once_with(afr_apt.value) apt.set_flight_attr.reset_mock()