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()
Exemple #3
0
 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
Exemple #4
0
 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))
Exemple #10
0
    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
Exemple #11
0
    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)
Exemple #12
0
    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)
Exemple #17
0
    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
Exemple #18
0
 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)
Exemple #19
0
 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))
Exemple #21
0
 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')
Exemple #22
0
 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)
Exemple #23
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)
Exemple #24
0
    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))
Exemple #25
0
 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)
Exemple #26
0
    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
Exemple #27
0
    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
Exemple #28
0
    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))
Exemple #30
0
    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')