def split_sequence_extended_to_weights(sequence, weights, overhang=True):
    '''Split sequence extended to weights.

    ..  container:: example

        **Example 1.** Split sequence extended to weights with overhang:

        ::

            >>> sequencetools.split_sequence_extended_to_weights(
            ...     [1, 2, 3, 4, 5], [7, 7, 7], overhang=True)
            [[1, 2, 3, 1], [3, 4], [1, 1, 2, 3], [4, 5]]

    ..  container:: example

        **Example 2.** Split sequence extended to weights without overhang:

        ::

            >>> sequencetools.split_sequence_extended_to_weights(
            ...     [1, 2, 3, 4, 5], [7, 7, 7], overhang=False)
            [[1, 2, 3, 1], [3, 4], [1, 1, 2, 3]]

    Returns sequence of sequence objects.
    '''
    from abjad.tools import sequencetools

    n = int(math.ceil(float(mathtools.weight(weights)) / mathtools.weight(sequence)))

    sequence = sequencetools.repeat_sequence_n_times(sequence, n)

    return sequencetools.split_sequence_by_weights(sequence, weights, cyclic=False, overhang=overhang)
 def _fracture_right(self, i):
     self, left, right = ComplexBeamSpanner._fracture_right(self, i)
     weights = [left.get_duration(), right.get_duration()]
     assert sum(self.durations) == sum(weights)
     split_durations = sequencetools.split_sequence_by_weights(
         self.durations, weights, cyclic=False, overhang=False)
     left_durations, right_durations = split_durations
     left._durations = left_durations
     right._durations = right_durations
     return self, left, right
Esempio n. 3
0
 def _make_secondary_duration_pairs(
     self, duration_pairs, secondary_divisions):
     if not secondary_divisions:
         return duration_pairs[:]
     numerators = [duration_pair.numerator 
         for duration_pair in duration_pairs]
     secondary_numerators = sequencetools.split_sequence_by_weights(
         numerators, secondary_divisions, cyclic=True, overhang=True)
     secondary_numerators = \
         sequencetools.flatten_sequence(secondary_numerators)
     denominator = duration_pairs[0].denominator
     secondary_duration_pairs = \
         [(n, denominator) for n in secondary_numerators]
     return secondary_duration_pairs
 def _split_payload_at_offsets(self, offsets):
     from experimental.tools import musicexpressiontools
     divisions = self.payload.divisions
     self._payload = musicexpressiontools.DivisionList(
         [], voice_name=self.voice_name, start_offset=self.start_offset)
     shards = sequencetools.split_sequence_by_weights(
         divisions, offsets, cyclic=False, overhang=True)
     result, total_duration = [], durationtools.Duration(0)
     for shard in shards:
         shard = musicexpressiontools.DivisionList(
             shard, voice_name=self.voice_name, start_offset=total_duration)
         result.append(shard)
         total_duration += shard.duration
     return result
Esempio n. 5
0
 def _make_numeric_map_part(
     self,
     numerator,
     prefix,
     suffix,
     is_note_filled=True,
     ):
     prefix_weight = mathtools.weight(prefix)
     suffix_weight = mathtools.weight(suffix)
     middle = numerator - prefix_weight - suffix_weight
     if numerator < prefix_weight:
         weights = [numerator]
         prefix = sequencetools.split_sequence_by_weights(
             prefix, weights, cyclic=False, overhang=False)[0]
     middle = self._make_middle_of_numeric_map_part(middle)
     suffix_space = numerator - prefix_weight
     if suffix_space <= 0:
         suffix = ()
     elif suffix_space < suffix_weight:
         weights = [suffix_space]
         suffix = sequencetools.split_sequence_by_weights(
             suffix, weights, cyclic=False, overhang=False)[0]
     numeric_map_part = prefix + middle + suffix
     return numeric_map_part
def partition_sequence_by_weights_exactly(
    sequence, 
    weights, 
    cyclic=False, 
    overhang=False,
    ):
    r'''Partition `sequence` by `weights` exactly.

    ::

        >>> sequence = [3, 3, 3, 3, 4, 4, 4, 4, 5]

    ..  container:: example

        **Example 1.** Partition sequence once by weights exactly without 
        overhang:

        ::

            >>> sequencetools.partition_sequence_by_weights_exactly(
            ...     sequence, 
            ...     [3, 9], 
            ...     cyclic=False, 
            ...     overhang=False,
            ...     )
            [[3], [3, 3, 3]]

    ..  container:: example

        **Example 2.** Partition sequence once by weights exactly with 
        overhang:

        ::

            >>> sequencetools.partition_sequence_by_weights_exactly(
            ...     sequence, 
            ...     [3, 9], 
            ...     cyclic=False, 
            ...     overhang=True,
            ...     )
            [[3], [3, 3, 3], [4, 4, 4, 4, 5]]

    ..  container:: example

        **Example 3.** Partition sequence cyclically by weights exactly 
        without overhang:

        ::

            >>> sequencetools.partition_sequence_by_weights_exactly(
            ...     sequence, 
            ...     [12], 
            ...     cyclic=True, 
            ...     overhang=False,
            ...     )
            [[3, 3, 3, 3], [4, 4, 4]]

    ..  container:: example

        **Example 4.** Partition sequence cyclically by weights exactly with 
        overhang:

        ::

            >>> sequencetools.partition_sequence_by_weights_exactly(
            ...     sequence, 
            ...     [12], 
            ...     cyclic=True, 
            ...     overhang=True,
            ...     )
            [[3, 3, 3, 3], [4, 4, 4], [4, 5]]

    Returns list sequence objects.
    '''
    from abjad.tools import sequencetools

    candidate = sequencetools.split_sequence_by_weights(
        sequence, 
        weights, 
        cyclic=cyclic, 
        overhang=overhang,
        )
    flattened_candidate = sequencetools.flatten_sequence(candidate)
    if flattened_candidate == sequence[:len(flattened_candidate)]:
        return candidate
    else:
        raise PartitionError('can not partition exactly.')
Esempio n. 7
0
    def split(
        self, 
        durations,
        fracture_spanners=False, 
        cyclic=False, 
        tie_split_notes=True, 
        ):
        r'''Splits component or selection by `durations`.
        
        ..  container:: example

            **Example 1.** Split leaves:

            ::

                >>> staff = Staff("c'8 e' d' f' c' e' d' f'")
                >>> leaves = staff.select_leaves()
                >>> hairpin = spannertools.HairpinSpanner(descriptor='p < f')
                >>> attach(hairpin, leaves)
                >>> staff.override.dynamic_line_spanner.staff_padding = 3
                >>> show(staff) # doctest: +SKIP

            ..  doctest::

                >>> f(staff)
                \new Staff \with {
                    \override DynamicLineSpanner #'staff-padding = #3
                } {
                    c'8 \< \p
                    e'8
                    d'8
                    f'8
                    c'8
                    e'8
                    d'8
                    f'8 \f
                }

            ::

                >>> durations = [Duration(3, 16), Duration(7, 32)]
                >>> result = mutate(leaves).split(
                ...     durations, 
                ...     tie_split_notes=False,
                ...     )
                >>> show(staff) # doctest: +SKIP

            ..  doctest::

                >>> f(staff)
                \new Staff \with {
                    \override DynamicLineSpanner #'staff-padding = #3
                } {
                    c'8 \< \p
                    e'16 
                    e'16
                    d'8
                    f'32 
                    f'16.
                    c'8
                    e'8
                    d'8
                    f'8 \f
                }

        ..  container:: example

            **Example 2.** Split leaves and fracture crossing spanners:

            ::

                >>> staff = Staff("c'8 e' d' f' c' e' d' f'")
                >>> leaves = staff.select_leaves()
                >>> hairpin = spannertools.HairpinSpanner(descriptor='p < f')
                >>> attach(hairpin, leaves)
                >>> staff.override.dynamic_line_spanner.staff_padding = 3
                >>> show(staff) # doctest: +SKIP

            ..  doctest::

                >>> f(staff)
                \new Staff \with {
                    \override DynamicLineSpanner #'staff-padding = #3
                } {
                    c'8 \< \p
                    e'8
                    d'8
                    f'8
                    c'8
                    e'8
                    d'8
                    f'8 \f
                }

            ::

                >>> durations = [Duration(3, 16), Duration(7, 32)]
                >>> result = mutate(leaves).split(
                ...     durations, 
                ...     fracture_spanners=True, 
                ...     tie_split_notes=False,
                ...     )
                >>> show(staff) # doctest: +SKIP

            ..  doctest::

                >>> f(staff)
                \new Staff \with {
                    \override DynamicLineSpanner #'staff-padding = #3
                } {
                    c'8 \< \p
                    e'16 \f 
                    e'16 \< \p
                    d'8
                    f'32 \f 
                    f'16. \< \p
                    c'8
                    e'8
                    d'8
                    f'8 \f
                }

        ..  container:: example

            **Example 3.** Split leaves cyclically:

            ::

                >>> staff = Staff("c'8 e' d' f' c' e' d' f'")
                >>> leaves = staff.select_leaves()
                >>> hairpin = spannertools.HairpinSpanner(descriptor='p < f')
                >>> attach(hairpin, leaves)
                >>> staff.override.dynamic_line_spanner.staff_padding = 3
                >>> show(staff) # doctest: +SKIP

            ..  doctest::

                >>> f(staff)
                \new Staff \with {
                    \override DynamicLineSpanner #'staff-padding = #3
                } {
                    c'8 \< \p
                    e'8
                    d'8
                    f'8
                    c'8
                    e'8
                    d'8
                    f'8 \f
                }

            ::

                >>> durations = [Duration(3, 16), Duration(7, 32)]
                >>> result = mutate(leaves).split(
                ...     durations,
                ...     cyclic=True,
                ...     tie_split_notes=False,
                ...     )
                >>> show(staff) # doctest: +SKIP

            ..  doctest::

                >>> f(staff)
                \new Staff \with {
                    \override DynamicLineSpanner #'staff-padding = #3
                } {
                    c'8 \< \p
                    e'16 
                    e'16
                    d'8
                    f'32 
                    f'16.
                    c'16. 
                    c'32
                    e'8
                    d'16 
                    d'16
                    f'8 \f
                }

        ..  container:: example

            **Example 4.** Split leaves cyclically and fracture spanners:

            ::

                >>> staff = Staff("c'8 e' d' f' c' e' d' f'")
                >>> leaves = staff.select_leaves()
                >>> hairpin = spannertools.HairpinSpanner(descriptor='p < f')
                >>> attach(hairpin, leaves)
                >>> staff.override.dynamic_line_spanner.staff_padding = 3
                >>> show(staff) # doctest: +SKIP

            ..  doctest::

                >>> f(staff)
                \new Staff \with {
                    \override DynamicLineSpanner #'staff-padding = #3
                } {
                    c'8 \< \p
                    e'8
                    d'8
                    f'8
                    c'8
                    e'8
                    d'8
                    f'8 \f
                }

            ::

                >>> durations = [Duration(3, 16), Duration(7, 32)]
                >>> result = mutate(leaves).split(
                ...     durations,
                ...     cyclic=True, 
                ...     fracture_spanners=True,
                ...     tie_split_notes=False,
                ...     )
                >>> show(staff) # doctest: +SKIP

            ..  doctest::

                >>> f(staff)
                \new Staff \with {
                    \override DynamicLineSpanner #'staff-padding = #3
                } {
                    c'8 \< \p
                    e'16 \f 
                    e'16 \< \p
                    d'8
                    f'32 \f 
                    f'16. \< \p
                    c'16. \f 
                    c'32 \< \p
                    e'8
                    d'16 \f 
                    d'16 \< \p
                    f'8 \f
                }

        ..  container:: example

            **Example 5.** Split tupletted leaves and fracture 
                crossing spanners:

            ::

                >>> staff = Staff()
                >>> staff.append(Tuplet((2, 3), "c'4 d' e'"))
                >>> staff.append(Tuplet((2, 3), "c'4 d' e'"))
                >>> leaves = staff.select_leaves()
                >>> slur = spannertools.SlurSpanner()
                >>> attach(slur, leaves)
                >>> show(staff) # doctest: +SKIP

            ..  doctest::

                >>> f(staff)
                \new Staff {
                    \times 2/3 {
                        c'4 (
                        d'4
                        e'4
                    }
                    \times 2/3 {
                        c'4
                        d'4
                        e'4 )
                    }
                }

            ::

                >>> durations = [Duration(1, 4)]
                >>> result = mutate(leaves).split(
                ...     durations, 
                ...     fracture_spanners=True, 
                ...     tie_split_notes=False,
                ...     )
                >>> show(staff) # doctest: +SKIP

            ..  doctest::

                >>> f(staff)
                \new Staff {
                    \times 2/3 {
                        c'4 (
                        d'8 ) 
                        d'8 (
                        e'4
                    }
                    \times 2/3 {
                        c'4
                        d'4
                        e'4 )
                    }
                }

        Returns list of selections.
        '''
        from abjad.tools import scoretools
        from abjad.tools import leaftools
        from abjad.tools import selectiontools
        # check input
        components = self._client
        single_component_input = False
        if isinstance(components, scoretools.Component):
            single_component_input = True
            components = selectiontools.Selection(components)
        assert all(
            isinstance(x, scoretools.Component) for x in components)
        if not isinstance(components, selectiontools.Selection):
            components = selectiontools.Selection(components)
        durations = [durationtools.Duration(x) for x in durations]
        # return if no split to be done
        if not durations:
            if single_component_input:
                return components
            else:
                return [], components
        # calculate total component duration
        total_component_duration = components.get_duration()
        total_split_duration = sum(durations)
        # calculate durations
        if cyclic:
            durations = sequencetools.repeat_sequence_to_weight_exactly(
                durations, total_component_duration)
        elif total_split_duration < total_component_duration:
            final_offset = total_component_duration - sum(durations)
            durations.append(final_offset)
        elif total_component_duration < total_split_duration:
            durations = sequencetools.truncate_sequence_to_weight(
                durations, total_component_duration)
        # keep copy of durations to partition result components
        durations_copy = durations[:]
        # calculate total split duration
        total_split_duration = sum(durations)
        assert total_split_duration == total_component_duration
        # initialize loop variables
        result, shard = [], []
        offset_index, offset_count = 0, len(durations)
        current_shard_duration = durationtools.Duration(0)
        remaining_components = list(components[:])
        advance_to_next_offset = True
        # loop and build shards by grabbing next component 
        # and next duration each time through loop
        while True:
            # grab next split point
            if advance_to_next_offset:
                if durations:
                    next_split_point = durations.pop(0)
                else:
                    break
            advance_to_next_offset = True
            # grab next component from input stack of components
            if remaining_components:
                current_component = remaining_components.pop(0)
            else:
                break
            # find where current component endpoint will position us
            candidate_shard_duration = current_shard_duration + \
                current_component._get_duration()
            # if current component would fill current shard exactly
            if candidate_shard_duration == next_split_point:
                shard.append(current_component)
                result.append(shard)
                shard = []
                current_shard_duration = durationtools.Duration(0)
                offset_index += 1
            # if current component would exceed current shard
            elif next_split_point < candidate_shard_duration:
                local_split_duration = \
                    next_split_point - current_shard_duration
                if isinstance(current_component, leaftools.Leaf):
                    leaf_split_durations = [local_split_duration]
                    current_duration = current_component._get_duration()
                    additional_required_duration = \
                        current_duration - local_split_duration
                    split_durations = sequencetools.split_sequence_by_weights(
                        durations, 
                        [additional_required_duration], 
                        cyclic=False, 
                        overhang=True,
                        )
                    additional_durations = split_durations[0]
                    leaf_split_durations.extend(additional_durations)
                    durations = split_durations[-1]
                    leaf_shards = current_component._split(
                        leaf_split_durations,
                        cyclic=False, 
                        fracture_spanners=fracture_spanners,
                        tie_split_notes=tie_split_notes,
                        )
                    shard.extend(leaf_shards)
                    result.append(shard)
                    offset_index += len(additional_durations)
                else:
                    left_list, right_list = \
                        current_component._split_by_duration(
                        local_split_duration, 
                        fracture_spanners=fracture_spanners,
                        tie_split_notes=tie_split_notes, 
                        )
                    shard.extend(left_list)
                    result.append(shard)
                    remaining_components.__setitem__(slice(0, 0), right_list)
                shard = []
                offset_index += 1
                current_shard_duration = durationtools.Duration(0)
            # if current component would not fill current shard
            elif candidate_shard_duration < next_split_point:
                shard.append(current_component)
                current_shard_duration += current_component._get_duration()
                advance_to_next_offset = False
            else:
                raise ValueError
        # append any stub shard
        if len(shard):
            result.append(shard)
        # append any unexamined components
        if len(remaining_components):
            result.append(remaining_components)
        # partition split components according to input durations
        result = sequencetools.flatten_sequence(result)
        result = selectiontools.ContiguousSelection(result)
        result = result.partition_by_durations_exactly(durations_copy)
        # return list of shards
        result = [selectiontools.Selection(x) for x in result]
        return result
    def rotate(self, n, fracture_spanners=True):
        r'''Rotate start-positioned rhythm payload expression.

        Example 1. Rotate by count:

        ::

            >>> payload = [Container("c'8 d'8 e'8 f'8")]
            >>> expression = \
            ...     musicexpressiontools.StartPositionedRhythmPayloadExpression(
            ...     payload, Offset(0))

        ::

            >>> result = expression.rotate(-1)

        ::

            >>> print expression.storage_format
            musicexpressiontools.StartPositionedRhythmPayloadExpression(
                payload=containertools.Container(
                    music=[{d'8, e'8, f'8}, {c'8}]
                    ),
                start_offset=durationtools.Offset(0, 1)
                )

        Example 2. Rotate by duration:

        ::

            >>> payload = [Container("c'8 d'8 e'8 f'8")]
            >>> expression = \
            ...     musicexpressiontools.StartPositionedRhythmPayloadExpression(
            ...     payload, Offset(0))

        ::

            >>> result = expression.rotate(-Duration(3, 16))

        ::

            >>> print expression.storage_format
            musicexpressiontools.StartPositionedRhythmPayloadExpression(
                payload=containertools.Container(
                    music=[{d'16, e'8, f'8}, {c'8, d'16}]
                    ),
                start_offset=durationtools.Offset(0, 1)
                )

        Operates in place and returns start-positioned rhythm 
        payload expression.
        '''
        from experimental.tools import musicexpressiontools
        if isinstance(n, int):
            leaves = datastructuretools.CyclicTuple(self.payload.select_leaves())
            if 0 < n:
                split_offset = leaves[-n]._get_timespan().start_offset
            elif n == 0:
                return self
            else:
                split_offset = leaves[-(n+1)]._get_timespan().stop_offset
        elif isinstance(n, musicexpressiontools.RotationIndicator):
            rotation_indicator = n
            if rotation_indicator.level is None:
                components_at_level = self.payload.select_leaves()
            else:
                components_at_level = []
                for component in \
                    iterationtools.iterate_components_in_expr(self.payload):
                    score_index = component._get_parentage().score_index
                    if len(score_index) == rotation_indicator.level:
                        components_at_level.append(component)
            components_at_level = datastructuretools.CyclicTuple(components_at_level)
            if isinstance(rotation_indicator.index, int):
                if 0 < rotation_indicator.index:
                    split_offset = components_at_level[
                        -rotation_indicator.index]._get_timespan().start_offset
                elif n == 0:
                    return self
                else:
                    split_offset = components_at_level[
                        -(rotation_indicator.index+1)]._get_timespan().stop_offset
            else:
                index = durationtools.Duration(rotation_indicator.index)
                if 0 <= index:
                    split_offset = self.payload._get_duration() - index
                else:
                    split_offset = abs(index)
            if rotation_indicator.fracture_spanners is not None:
                fracture_spanners = rotation_indicator.fracture_spanners
        else:
            n = durationtools.Duration(n)
            if 0 <= n:
                split_offset = self.payload._get_duration() - n
            else:
                split_offset = abs(n)
        #self._debug(split_offset, 'split offset')
        try:
            payload_duration = getattr(self, 'payload')
        except AttributeError:
            payload_duration = self.payload._get_duration()
        if split_offset == payload_duration:
            return self
        if fracture_spanners:
            result = mutationtools.mutate([self.payload]).split(
                [split_offset],
                cyclic=False,
                fracture_spanners=True,
                tie_split_notes=False,
                )
            left_half, right_half = result[0][0], result[-1][0]
            payload = containertools.Container()
            payload.extend(right_half)
            payload.extend(left_half)
            assert inspect(payload).is_well_formed()
            self._payload = payload
        else:
            result = mutationtools.mutate(self.payload[:]).split(
                [split_offset],
                cyclic=False,
                fracture_spanners=False,
                tie_split_notes=False,
                )
            left_half, right_half = result[0], result[-1]
            spanner_classes = (spannertools.DuratedComplexBeamSpanner, )
            descendants = self.payload._get_descendants()
            for spanner in descendants.get_spanners(spanner_classes):
                if left_half[-1] in spanner and right_half[0] in spanner:
                    leaf_right_of_split = right_half[0]
                    split_offset_in_beam = spanner._duration_offset_in_me(
                        leaf_right_of_split)
                    left_durations, right_durations = \
                        sequencetools.split_sequence_by_weights(
                        spanner.durations,
                        [split_offset_in_beam],
                        cyclic=False,
                        overhang=True,
                        )
                    new_durations = right_durations + left_durations
                    spanner._durations = new_durations
            new_payload = right_half + left_half
            self.payload._music = new_payload
            for component in new_payload:
                component._update_later(offsets=True)
            for spanner in self.payload._get_descendants().get_spanners():
                spanner._components.sort(
                    lambda x, y: cmp(x._get_parentage().score_index, y._get_parentage().score_index))
            assert inspect(self.payload).is_well_formed()
        return self