def test_year_00_uses_fallback_year(self): # Ensure that a timebase error is not raised due to old date! #Other than the year 2000 or possibly 2100, no date values # can be all 0's dt = datetime(2012,12,12,12,12,10, tzinfo=pytz.utc) # Test only without second and empty year hdf = {'Year': P('Year',np.ma.array([0, 0, 0, 0])), 'Month': P('Month',np.ma.array([11, 11, 11,11])), 'Day': P('Day',np.ma.array([11, 11, 11,11])), 'Hour': P('Hour',np.ma.array([11,11,11,11], mask=[True, False, False, False])), 'Minute':P('Minute',np.ma.array([11,11]), frequency=0.5), } # add a masked invalid value hdf['Year'].array[2] = 50 hdf['Year'].array[2] = np.ma.masked res = _calculate_start_datetime(hdf, dt) self.assertEqual(res, datetime(2012,11,11,11,11,9, tzinfo=pytz.utc))
def test_masked_values(self): alt_agl = P('Altitude AGL', array=np.ma.sin(np.linspace(0, np.pi, 500)) * 1000) alt_agl.array[200:240] = np.ma.masked node = AltitudeAGLForFlightPhases() node.derive(alt_agl) assert not node.array.mask.any()
def derive(self, toffs=KTI('Takeoff Acceleration Start'), lifts=KTI('Liftoff'), eng_np=P('Eng (*) Np Avg'), duration=A('HDF Duration'), eng_type=A('Engine Propulsion'), ac_type=A('Aircraft Type')): pass
def derive(self, mobiles=S('Mobile'), gspd=P('Groundspeed'), toffs=S('Takeoff'), lands=S('Landing'), rtos=S('Rejected Takeoff'), airs=S('Airborne')): pass
def test_adh_two_rigs(self): z = np.ma.arange(200) height = P( 'Altitude Radio', np.ma.concatenate([ z, z[:150:-1], z[50::-1], z[:50], z[150:], z[:150:-1], z[100::-1], z[:100], z[150:], z[::-1] ])) hdot = P( 'Vertical Speed', np.ma.concatenate( (np.ones(200) * 60, np.ones(100) * -60, np.ones(100) * 60, np.ones(150) * -60, np.ones(150) * 60, np.ones(200) * -60))) adh = AltitudeADH() adh.derive(height, hdot) self.assertEqual(height.array[210] - adh.array[210], 100.0) self.assertEqual(height.array[680] - adh.array[680], 50.0)
def derive(self, alt_agl=P('Altitude AGL'), airs=S('Airborne'), gspd=P('Groundspeed'), trans_hfs=S('Transition Hover To Flight'), trans_fhs=S('Transition Flight To Hover')): low_flights = [] hovers = [] for air in airs: lows = slices_below(alt_agl.array[air.slice], HOVER_HEIGHT_LIMIT)[1] for low in lows: if np.ma.min(alt_agl.array[shift_slice( low, air.slice.start)]) <= HOVER_MIN_HEIGHT: low_flights.extend([shift_slice(low, air.slice.start)]) repaired_gspd = repair_mask(gspd.array, frequency=gspd.hz, repair_duration=8, method='fill_start') slows = slices_below(repaired_gspd, HOVER_GROUNDSPEED_LIMIT)[1] low_flights = slices_and(low_flights, slows) # Remove periods identified already as transitions. for low_flight in low_flights: if trans_fhs: for trans_fh in trans_fhs: if slices_overlap(low_flight, trans_fh.slice): low_flight = slice(trans_fh.slice.stop, low_flight.stop) if trans_hfs: for trans_hf in trans_hfs: if slices_overlap(low_flight, trans_hf.slice): low_flight = slice(low_flight.start, trans_hf.slice.start) hovers.extend([low_flight]) # Exclude transition periods and trivial periods of operation. self.create_phases( filter_slices_duration(hovers, HOVER_MIN_DURATION, frequency=alt_agl.frequency))
def test_on_ground(self): alt_rad = P(name='Altitude Radio', array=np.ma.array([ -1, 0, 6, 0, -1, -1, 0, 6, 0, -1, -1, 0, 6, 0, -1, -1, 0, 6, 0, -1 ])) alt_baro = P(name='Altitude STD', array=np.ma.array([0] * 20)) gog = M(name='Gear On Ground', array=np.ma.array([1] * 20), values_mapping={ 0: 'Air', 1: 'Ground' }) alt_aal = AltitudeAGL() alt_aal.derive(alt_rad, None, alt_baro, gog) expected = [0] * 20 assert_array_equal(alt_aal.array, expected)
def test_derive(self): one = P('Nr (1)', np.ma.array([100, 200, 300]), frequency=0.5, offset=0.0) two = P('Nr (2)', np.ma.array([150, 250, 350]), frequency=0.5, offset=1.0) node = self.node_class() node.derive(one, two) # Note: end samples are not 100 & 350 due to method of merging. assert_array_equal(node.array[1:-1], np.array([150, 200, 250, 300])) self.assertEqual(node.frequency, 1.0) self.assertEqual(node.offset, 0.0)
def test_midnight_rollover(self): """ When a flight starts just before midnight, the majority of the flight will be in the next day so the fallback_dt needs to adjust throughout the data otherwise it will try to force the next day's flight to appear to that of the previous. """ # fallback is at start of the recording dt = datetime(2012, 12, 12, 23, 59, 58, tzinfo=pytz.utc) hdf = MockHDF({ 'Hour': P('Hour', np.ma.array([23, 23] + [0] * 18)), 'Minute': P('Minute', np.ma.array([59, 59] + [0] * 18)), 'Second': P('Minute', np.ma.array([58, 59] + range(18))), # last two seconds and start of next flight }, duration=20) res = _calculate_start_datetime(hdf, dt, dt) # result is the exact start of the data for the timestamp (not a day before!) self.assertEqual(res, datetime(2012, 12, 12, 23, 59, 58, tzinfo=pytz.utc))
def derive(self, cas=P('Airspeed'), vref=P('Vref (Recorded then Lookup)'), altitude=P('Altitude AAL'), touchdowns=KTI('Touchdown'), approaches=S('Approach And Landing')): for app in approaches: if vref is not None and vref.array is not None: cas_run = sustained_min(cas, _slice=app) cas_vref = cas_run.data - vref.array[app.slice] x = np.ma.zeros(len(cas.array)) x.data[app.slice] = cas_vref self.create_kpvs_within_slices( x, altitude.slices_from_to(500, 50), min_value) else: return
def test_derive(self): grounded = buildsections('Grounded', [0, 2], [8, 10]) airspeed = P('Airspeed True', array=np.ma.ones(10) * 3600., frequency=1., offset=0.) # middle Riemann sum mid_array = np.array([0., 0., .5, 1.5, 2.5, 3.5, 4.5, 5.5, 6., 6.]) expected = P(name='Distance Travelled In Air', array=mid_array, frequency=1., offset=0.) node = DistanceTravelledInAir() node.derive(airspeed, grounded) actual = node.array np.testing.assert_array_equal(actual, mid_array)
def test_nose_down_insufficient_pitch(self): node = NoseDownAttitudeAdoption() pitch = np.concatenate([np.ones(15) * 2, np.linspace(2, -6, num=15), np.ones(10) * -6]) node.derive(P('Pitch', pitch), self.climbs) self.assertEqual(len(node), 1) self.assertEqual(node[0], Section('Nose Down Attitude Adoption', slice(15, 29, None), 15, 29))
def test_calculate_start_datetime_multiple_valid_slices(self): aspd = load_array('airspeed_sample_masked_under_80.npz') duration = len(aspd) airspeed = P('Airspeed', array=aspd) year = P('Year', array=np.ma.array([2019]*duration)) month = P('Month', array=np.ma.array([2]*duration)) day = P('Day', array=np.ma.array([1]*duration)) hour = P('Hour', array=np.ma.array([0]*duration)) minute = P('Minute', array=np.ma.repeat(np.ma.arange(duration//60), 61)[:duration]) second = P('Second', array=np.ma.array(np.tile(np.arange(60), duration//59))[:duration]) values = {'Year': year, 'Month': month, 'Day': day, 'Hour': hour, 'Minute': minute, 'Second': second, 'Airspeed': airspeed} def hdf_get(arg): return values[arg] hdf = mock.Mock() hdf.duration = duration hdf.get = mock.Mock() hdf.get.side_effect = hdf_get start_dt = datetime(2019, 2, 1, 0, 0, tzinfo=pytz.utc) new_dt, _precise_timestamp, _conf = _calculate_start_datetime(hdf, datetime(2019, 2, 2, 0, 1, 1, tzinfo=pytz.utc), datetime(2012, 2, 2, 1, 2, 2, tzinfo=pytz.utc)) self.assertEqual(new_dt, start_dt)
def derive(self, airspeed=P('Airspeed True'), grounded=S('Grounded')): for section in grounded: # zero out travel on the ground airspeed.array[section.slice] = 0.0 # this is already a copy repaired_array = repair_mask( airspeed.array) # to avoid integration hiccups adist = integrate(repaired_array, airspeed.frequency, scale=1.0 / 3600.0) self.array = adist
def derive(self, pitch=P('Pitch'), climbs=S('Initial Climb')): for climb in climbs: masked_pitch = mask_outside_slices(pitch.array, [climb.slice]) pitch_index = np.ma.argmax( masked_pitch <= -10) or np.ma.argmin(masked_pitch) scaling_factor = abs(masked_pitch[pitch_index]) / 10 window_threshold = -10.00 * scaling_factor min_window_threshold = -8.00 * scaling_factor window_size = 32 window_threshold_step = 0.050 * scaling_factor diffs = np.ma.ediff1d(masked_pitch[climb.slice.start:pitch_index]) diffs_exist = diffs.data.size >= 2 big_diff_index = -1 while diffs_exist: sig_pitch_threshold = window_threshold / window_size for i, d in enumerate(diffs): # Look for the first big negative pitch spike if diffs[slices_int( i, i + window_size)].sum() < window_threshold: # Find the first significant negative value within the # spike and make that the starting point of the phase big_diff_index = np.ma.argmax( diffs[i:i + window_size] < sig_pitch_threshold) + i break # Bail on match or total failure if big_diff_index != -1 or window_size < 2: break # Shrink window size instead of looking for insignificant # spikes and scale window/pitch thresholds accordingly if window_threshold >= min_window_threshold: window_size //= 2 min_window_threshold /= 2 window_threshold /= 2 window_threshold_step /= 2 sig_pitch_threshold *= 2 else: window_threshold += window_threshold_step if big_diff_index != -1: self.create_section( slice(climb.slice.start + big_diff_index, pitch_index)) # Worst case fallback, this should happen extremely rarely # and would trigger all events related to this phase else: self.create_section(slice(climb.slice.start, climb.slice.stop))
def derive(self, afr_type=A('AFR Type'), fast=S('Fast'), liftoffs=KTI('Liftoff'), touchdowns=KTI('Touchdown'), touch_and_gos=S('Touch And Go'), groundspeed=P('Groundspeed')): ''' TODO: Detect MID_FLIGHT. ''' afr_type = afr_type.value if afr_type else None if liftoffs and not touchdowns: # In the air without having touched down. self.warning("'Liftoff' KTI exists without 'Touchdown'.") raise InvalidFlightType('LIFTOFF_ONLY') #self.set_flight_attr('LIFTOFF_ONLY') #return elif not liftoffs and touchdowns: # In the air without having lifted off. self.warning("'Touchdown' KTI exists without 'Liftoff'.") raise InvalidFlightType('TOUCHDOWN_ONLY') #self.set_flight_attr('TOUCHDOWN_ONLY') #return if liftoffs and touchdowns: first_touchdown = touchdowns.get_first() first_liftoff = liftoffs.get_first() if first_touchdown.index < first_liftoff.index: # Touchdown before having lifted off, data must be INCOMPLETE. self.warning("'Touchdown' KTI index before 'Liftoff'.") raise InvalidFlightType('TOUCHDOWN_BEFORE_LIFTOFF') #self.set_flight_attr('TOUCHDOWN_BEFORE_LIFTOFF') #return last_touchdown = touchdowns.get_last() # TODO: Delete line. if touch_and_gos: last_touchdown = touchdowns.get_last() last_touch_and_go = touch_and_gos.get_last() if last_touchdown.index <= last_touch_and_go.index: self.warning("A 'Touch And Go' KTI exists after the last " "'Touchdown'.") raise InvalidFlightType('LIFTOFF_ONLY') #self.set_flight_attr('LIFTOFF_ONLY') #return if afr_type in [FlightType.Type.FERRY, FlightType.Type.LINE_TRAINING, FlightType.Type.POSITIONING, FlightType.Type.TEST, FlightType.Type.TRAINING]: flight_type = afr_type else: flight_type = FlightType.Type.COMPLETE elif fast: flight_type = FlightType.Type.REJECTED_TAKEOFF elif groundspeed and groundspeed.array.ptp() > 10: # The aircraft moved on the ground. flight_type = FlightType.Type.GROUND_RUN else: flight_type = FlightType.Type.ENGINE_RUN_UP self.set_flight_attr(flight_type)
def derive(self, tcas_ctl = M('TCAS Combined Control'), tcas_up = M('TCAS Up Advisory'), tcas_down = M('TCAS Down Advisory'), tcas_vert = M('TCAS Vertical Control'), vertspd = P('Vertical Speed'), ra_sections = S('TCAS RA Sections'), raduration = KPV('TCAS RA Warning Duration'), ): standard_vert_accel = 8.0 * 60 # 8 ft/sec^2, converted to ft/min^2 standard_vert_accel_reversal = 11.2 * 60 # ft/sec^2 ==> ft/min^2 standard_response_lag = 5.0 # seconds standard_response_lag_reversal = 2.5 # seconds self.array = vertspd.array * 0 #make a copy, mask and zero out self.array.mask = True required_fpm_array = vertspd.array * 0 for ra in ra_sections: self.debug('TCAS RA Standard Response: in sections') #initialize response state ra_ctl_prev = tcas_ctl.array[ra.start_edge] # used to check if the command has changed up_prev = tcas_ctl.array[ra.start_edge] # used to check if the command has changed down_prev = tcas_ctl.array[ra.start_edge] # used to check if the command has changed initial_vert_spd = vertspd.array[ra.start_edge] std_vert_spd = initial_vert_spd # current standard response vert speed in fpm required_fpm = None # nominal vertical speed in fpm required by the RA lag_end = ra.start_edge + standard_response_lag # time pilot response lag ends acceleration = standard_vert_accel for t in range(int(ra.start_edge), int(ra.stop_edge)+1): # set required_fpm for initial ra or a change in command if ra_ctl_prev!=tcas_ctl.array[t] or up_prev!=tcas_up.array[t] or down_prev!=tcas_down.array[t]: if tcas_ctl.array[t] == 'Up Advisory Corrective' or tcas_up.array[t].lower()!='no up advisory': required_fpm = tcas_vert_spd_up(tcas_up.array[t], vertspd.array[t], tcas_vert.array[t]) elif tcas_ctl.array[t] == 'Down Advisory Corrective' or tcas_down.array[t].lower()!='no down advisory': required_fpm = tcas_vert_spd_down(tcas_down.array[t], vertspd.array[t], tcas_vert.array[t]) else: required_fpm = vertspd.array[t] if tcas_vert.array[t]=='Reversal': lag_end = t + standard_response_lag_reversal acceleration = standard_vert_accel_reversal initial_vert_spd = std_vert_spd if required_fpm is None: self.warning('TCAS RA Standard Response: No required_fpm found. Take a look! '+str(t)) std_vert_spd= update_std_vert_spd(t, lag_end, tcas_ctl.array[t], tcas_up.array[t], tcas_down.array[t], acceleration, required_fpm, std_vert_spd, initial_vert_spd, vertspd.array[t]) self.array.data[t] = std_vert_spd self.array.mask[t] = False required_fpm_array[t] = required_fpm ra_ctl_prev = tcas_ctl.array[t] up_prev = tcas_up.array[t] down_prev = tcas_down.array[t] #end of time loop within ra section return
def test_airborne_helicopter_radio_refinement(self): ''' Confirms that the beginning and end are trimmed to match the radio signal, not the (smoothed) AGL data. ''' gog = M(name='Gear On Ground', array=np.ma.array([0]*3+[1]*5+[0]*10+[1]*5, dtype=int), frequency=1, offset=0, values_mapping={1:'Ground', 0:'Air'}) agl = P(name='Altitude AGL', array=np.ma.array([0.0]*6+[20.0]*12+[0.0]*5, dtype=float)) rad = P(name='Altitude Radio', array=np.ma.array([0.0]*7+[10.0]*10+[0.0]*6, dtype=float)) rtr = buildsection('Rotors Turning', 0, 40) node = Airborne() node.derive(rad, agl, gog, rtr) self.assertEqual(node[0].start_edge, 6.1) self.assertEqual(node[0].stop_edge, 16.9)
def derive(self, tcas_sens=P('TCAS Sensitivity Level'), ra_sections=S('TCAS RA Sections') ): _change_points = change_indexes(tcas_sens.array.data) #returns array index for cp in _change_points: _value = tcas_sens.array.data[cp] if tcas_sens.array.mask[cp]: _name = 'TCAS Sensitivity|masked' else: _name = 'TCAS Sensitivity|' + tcas_sens.array[cp] kpv = KeyPointValue(index=cp, value=_value, name=_name) self.append(kpv)
def derive(self, alt_agl=P('Altitude AGL'), ias=P('Airspeed'), airs=S('Airborne'), pitch_rate=P('Pitch Rate')): for air in airs: trans_slices = slices_from_to(ias.array[air.slice], ROTOR_TRANSITION_SPEED_HIGH, ROTOR_TRANSITION_SPEED_LOW, threshold=1.0)[1] if trans_slices: for trans in shift_slices(trans_slices, air.slice.start): trans_end = index_at_value( ias.array, 0.0, _slice=slice(trans.stop, trans.stop + 20 * ias.frequency), endpoint='first_closing') self.create_phase(slice(trans.start, trans_end + 1))
def test_derive_masked(self): ''' ''' flight_number = FlightNumber() number_param = P( 'Flight Number', array=np.ma.array([0, 0, 0, 0, 36, 36, 0, 0, 0, 0], mask=[True] * 4 + [False] * 2 + [True] * 4)) flight_number.derive(number_param) self.assertEqual(flight_number.value, '36')
def test_airborne_helicopter_cant_fly_without_rotor_turning(self): gog = M(name='Gear On Ground', array=np.ma.array([1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1], dtype=int), values_mapping={1:'Ground', 0:'Air'}) agl = P(name='Altitude AGL', array=np.ma.array([0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 2, 0], dtype=float), frequency=0.2) rtr = buildsection('Rotors Turning', 0, 0) node = Airborne() node.derive(agl, agl, gog, rtr) self.assertEqual(len(node), 0)
def derive(self, ra_sections=S('TCAS RA Sections'), tcas_ctl=M('TCAS Combined Control'), tcas_up = M('TCAS Up Advisory'), tcas_down = M('TCAS Down Advisory'), std=P('TCAS RA Standard Response'), vertspd=P('Vertical Speed') ): for ra in ra_sections: exceedance=0 deviation=0 for t in range(int(ra.start_edge), int(ra.stop_edge)): if tcas_ctl.array[t] == 'Down Advisory Corrective' or tcas_down.array[t].lower()!='no down advisory': deviation = max(vertspd.array[t] - std.array[t], 0) elif tcas_ctl.array[t] == 'Up Advisory Corrective' or tcas_up.array[t].lower()!='no up advisory': deviation = max(std.array[t] - vertspd.array[t], 0) else: deviation = abs(vertspd.array[t] - std.array[t]) deviation = max( deviation-250, 0 ) # allow 250 fpm buffer #print 't vert std DEV', t, vertspd.array[t], std.array[t], deviation if deviation and deviation!=0: exceedance += deviation #print 'Alt Exceed', exceedance exceedance = exceedance / 60.0 # min to sec self.create_kpv(ra.start_edge, exceedance)
def test_nose_down_multiple_climbs(self): node = NoseDownAttitudeAdoption() pitch = np.concatenate([np.ones(15) * 2, np.linspace(2, -11, num=15), np.linspace(-11, 2, num=10), np.ones(20) * 2, np.linspace(2, -11, num=15), np.ones(10) * -11]) climbs = buildsections('Initial Climb', [10, 40], [60, 85]) node.derive(P('Pitch', pitch), climbs) self.assertEqual(len(node), 2) self.assertEqual(node[0], Section('Nose Down Attitude Adoption', slice(15, 28, None), 15, 28)) self.assertEqual(node[1], Section('Nose Down Attitude Adoption', slice(60, 73, None), 60, 73))
def test_airborne_helicopter_short(self): gog = M(name='Gear On Ground', array=np.ma.array([0]*3+[1]*5+[0]*10+[1]*5, dtype=int), frequency=1, offset=0, values_mapping={1:'Ground', 0:'Air'}) agl = P(name='Altitude AGL', array=np.ma.array([2.0, 0.0, 0.0]+[0.0]*4+[20.0]*10+[0.0]*6, dtype=float)) rtr = buildsection('Rotors Turning', 0, 40) node = Airborne() node.derive(agl, agl, gog, rtr) self.assertEqual(len(node), 1)
def derive(self, alt_aal=P('Altitude AAL'), lat=P('Latitude Smoothed'), lon=P('Longitude Smoothed'), tdwns=KTI('Touchdown')): app_range = np_ma_masked_zeros_like(alt_aal.array) #Helicopter compuation does not rely on runways! stop_delay = 10 # To make sure the helicopter has stopped moving for tdwn in tdwns: end = tdwn.index endpoint = {'latitude': lat.array[int(end)], 'longitude': lon.array[int(end)]} prev_tdwn = tdwns.get_previous(end) begin = prev_tdwn.index + stop_delay if prev_tdwn else 0 this_leg = slices_int(begin, end+stop_delay) _, app_range[this_leg] = bearings_and_distances(lat.array[this_leg], lon.array[this_leg], endpoint) self.array = app_range
def test_2_sources(self): lat1 = P('Latitude (1)', array=np.ma.arange(-10, 10), frequency=0.5, offset=0.25) lat1.array[5:8] = np.ma.masked lat2 = P('Latitude (2)', array=np.ma.arange(-9.5, 10), frequency=0.5, offset=0.75) lat2.array[5:8] = np.ma.masked latitude = Latitude() latitude.get_derived((lat1, lat2, None)) expected = np.ma.arange(-9.75, 10, 0.5) expected[-1] = np.ma.masked np.testing.assert_array_equal(latitude.array, expected) np.testing.assert_array_equal(latitude.array.mask, expected.mask) assert latitude.offset == 0.5 assert latitude.frequency == 1
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')): #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[lift.index] == 'Engaged' ap2 = ap2_eng.array[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, 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 test_derive_most_common_positive_float(self): flight_number = FlightNumber() neg_number_param = P( 'Flight Number', array=np.ma.array([-1,2,-4,10,20,40,11])) flight_number.derive(neg_number_param) self.assertEqual(flight_number.value, None) # TODO: Implement variance checks as below ##high_variance_number_param = P( ##'Flight Number', ##array=np.ma.array([2,2,4,4,4,7,7,7,4,5,4,7,910])) ##self.assertRaises(ValueError, flight_number.derive, high_variance_number_param) flight_number_param= P( 'Flight Number', array=np.ma.array([2,555.6,444,444,444,444,444,444,888,444,444, 444,444,444,444,444,444,7777,9100])) flight_number.set_flight_attr = Mock() flight_number.derive(flight_number_param) flight_number.set_flight_attr.assert_called_with('444')