def derive(self,
               alt_agl=P('Altitude AGL'),
               airs=S('Airborne'),
               hovers=S('Hover'),
               trans_hfs=S('Transition Hover To Flight'),
               trans_fhs=S('Transition Flight To Hover')):

        air_taxis = []
        taxis = []

        if airs:
            for air in airs:
                lows = slices_below(alt_agl.array[air.slice],
                                    HOVER_TAXI_HEIGHT)[1]
                taxis = shift_slices(lows, air.slice.start)
        # Remove periods identified already as transitions.
        if taxis:
            for taxi in slices_and_not(taxis, [h.slice for h in hovers]):
                if trans_fhs:
                    for trans_fh in trans_fhs:
                        if slices_overlap(taxi, trans_fh.slice):
                            taxi = slice(trans_fh.slice.stop, taxi.stop)

                if trans_hfs:
                    for trans_hf in trans_hfs:
                        if slices_overlap(taxi, trans_hf.slice):
                            taxi = slice(taxi.start, trans_hf.slice.start)

                air_taxis.extend([taxi])

        self.create_phases(air_taxis)
    def derive(self, alt_agl=P('Altitude AGL'),
               airs=S('Airborne'),
               hovers=S('Hover'),
               trans_hfs=S('Transition Hover To Flight'),
               trans_fhs=S('Transition Flight To Hover')):

        air_taxis = []
        taxis = []

        if airs:
            for air in airs:
                lows = slices_below(alt_agl.array[air.slice], HOVER_TAXI_HEIGHT)[1]
                taxis = shift_slices(lows, air.slice.start)
        # Remove periods identified already as transitions.
        if taxis:
            for taxi in slices_and_not(taxis, [h.slice for h in hovers]):
                if trans_fhs:
                    for trans_fh in trans_fhs:
                        if slices_overlap(taxi, trans_fh.slice):
                            taxi = slice(trans_fh.slice.stop, taxi.stop)

                if trans_hfs:
                    for trans_hf in trans_hfs:
                        if slices_overlap(taxi, trans_hf.slice):
                            taxi = slice(taxi.start, trans_hf.slice.start)

                air_taxis.extend([taxi])

        self.create_phases(air_taxis)
    def derive(self,
               alt_rad=P('Altitude Radio'),
               alt_agl=P('Altitude AGL'),
               gog=M('Gear On Ground'),
               rtr=S('Rotors Turning')):
        # When was the gear in the air?
        gear_off_grounds = runs_of_ones(gog.array == 'Air')

        if alt_rad and alt_agl and rtr:
            # We can do a full analysis.
            # First, confirm that the rotors were turning at this time:
            gear_off_grounds = slices_and(gear_off_grounds, rtr.get_slices())

            # When did the radio altimeters indicate airborne?
            airs = slices_remove_small_gaps(
                np.ma.clump_unmasked(
                    np.ma.masked_less_equal(alt_agl.array, 1.0)),
                time_limit=AIRBORNE_THRESHOLD_TIME_RW,
                hz=alt_agl.frequency)
            # Both is a reliable indication of being in the air.
            for air in airs:
                for goff in gear_off_grounds:
                    # Providing they relate to each other :o)
                    if slices_overlap(air, goff):
                        start_index = max(air.start, goff.start)
                        end_index = min(air.stop, goff.stop)

                        better_begin = index_at_value(
                            alt_rad.array,
                            1.0,
                            _slice=slice(
                                max(start_index - 5 * alt_rad.frequency, 0),
                                start_index + 5 * alt_rad.frequency))
                        if better_begin:
                            begin = better_begin
                        else:
                            begin = start_index

                        better_end = index_at_value(
                            alt_rad.array,
                            1.0,
                            _slice=slice(
                                max(end_index + 5 * alt_rad.frequency, 0),
                                end_index - 5 * alt_rad.frequency, -1))
                        if better_end:
                            end = better_end
                        else:
                            end = end_index

                        duration = end - begin
                        if (duration /
                                alt_rad.hz) > AIRBORNE_THRESHOLD_TIME_RW:
                            self.create_phase(slice(begin, end))
        else:
            # During data validation we can select just sensible flights;
            # short hops make parameter validation tricky!
            self.create_phases(
                slices_remove_small_gaps(
                    slices_remove_small_slices(gear_off_grounds,
                                               time_limit=30)))
    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 derive(self,
               alt_rad=P('Altitude Radio'),
               alt_agl=P('Altitude AGL'),
               gog=M('Gear On Ground'),
               rtr=S('Rotors Turning')):
        # When was the gear in the air?
        gear_off_grounds = runs_of_ones(gog.array == 'Air')

        if alt_rad and alt_agl and rtr:
            # We can do a full analysis.
            # First, confirm that the rotors were turning at this time:
            gear_off_grounds = slices_and(gear_off_grounds, rtr.get_slices())

            # When did the radio altimeters indicate airborne?
            airs = slices_remove_small_gaps(
                np.ma.clump_unmasked(np.ma.masked_less_equal(alt_agl.array, 1.0)),
                time_limit=AIRBORNE_THRESHOLD_TIME_RW, hz=alt_agl.frequency)
            # Both is a reliable indication of being in the air.
            for air in airs:
                for goff in gear_off_grounds:
                    # Providing they relate to each other :o)
                    if slices_overlap(air, goff):
                        start_index = max(air.start, goff.start)
                        end_index = min(air.stop, goff.stop)

                        better_begin = index_at_value(
                            alt_rad.array, 1.0,
                            _slice=slice(max(start_index-5*alt_rad.frequency, 0),
                                         start_index+5*alt_rad.frequency)
                        )
                        if better_begin:
                            begin = better_begin
                        else:
                            begin = start_index

                        better_end = index_at_value(
                            alt_rad.array, 1.0,
                            _slice=slice(max(end_index+5*alt_rad.frequency, 0),
                                         end_index-5*alt_rad.frequency, -1))
                        if better_end:
                            end = better_end
                        else:
                            end = end_index

                        duration = end - begin
                        if (duration / alt_rad.hz) > AIRBORNE_THRESHOLD_TIME_RW:
                            self.create_phase(slice(begin, end))
        else:
            # During data validation we can select just sensible flights;
            # short hops make parameter validation tricky!
            self.create_phases(
                slices_remove_small_gaps(
                    slices_remove_small_slices(gear_off_grounds, time_limit=30)))
    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))