def repeat_to_duration(self, duration):
        r'''Repeat start-positioned division payload expression to `duration`.

        ::

            >>> payload = [(6, 8), (6, 8), (3, 4)]
            >>> expression = musicexpressiontools.StartPositionedDivisionPayloadExpression(
            ...     payload, Offset(0))

        ::

            >>> result = expression.repeat_to_duration(Duration(13, 4))

        ::

            >>> print result.storage_format
            musicexpressiontools.StartPositionedDivisionPayloadExpression(
                payload=musicexpressiontools.DivisionList(
                    [Division('[6, 8]', start_offset=Offset(0, 1)),
                    Division('[6, 8]', start_offset=Offset(3, 4)),
                    Division('[3, 4]', start_offset=Offset(3, 2)),
                    Division('[6, 8]', start_offset=Offset(9, 4)),
                    Division('[2, 8]', start_offset=Offset(3, 1))],
                    start_offset=durationtools.Offset(0, 1)
                    ),
                start_offset=durationtools.Offset(0, 1)
                )

        Returns newly constructed start-positioned division payload expression.
        '''
        divisions = sequencetools.repeat_sequence_to_weight_exactly(self.payload, duration)
        result = type(self)(payload=divisions, voice_name=self.voice_name, start_offset=self.start_offset)
        return result
    def repeat_to_duration(self, duration):
        r'''Repeat payload expression to duration.

        ::

            >>> result = \
            ...     payload_expression.repeat_to_duration(Duration(13, 16))

        ::

            >>> print result.storage_format
            musicexpressiontools.IterablePayloadExpression(
                payload=(NonreducedFraction(4, 16),
                NonreducedFraction(2, 16),
                NonreducedFraction(4, 16),
                NonreducedFraction(2, 16),
                NonreducedFraction(1, 16))
                )

        Returns newly constructed payload expression.
        '''
        if not sequencetools.all_are_numbers(self.payload):
            payload = [mathtools.NonreducedFraction(x) for x in self.payload]
        else:
            payload = self.payload
        payload = sequencetools.repeat_sequence_to_weight_exactly(
            payload, duration)
        result = self.new(payload=payload)
        return result
def test_sequencetools_repeat_sequence_to_weight_exactly_02():
    r'''Works with nonreduced fractions.
    '''

    sequence = [NonreducedFraction(3, 16)]
    sequence = sequencetools.repeat_sequence_to_weight_exactly(sequence, NonreducedFraction(5, 4))

    assert sum(sequence) == NonreducedFraction(5, 4)
    assert [x.pair for x in sequence] == [(3, 16), (3, 16), (3, 16), (3, 16), (3, 16), (3, 16), (2, 16)]
    def evaluate(self):
        r'''Evaluate division region expression.

        Returns start-positioned division payload expression.
        '''
        from experimental.tools import musicexpressiontools
        divisions = self.source_expression[:]
        divisions = [musicexpressiontools.Division(x) for x in divisions]
        divisions = sequencetools.repeat_sequence_to_weight_exactly(
            divisions, self.total_duration)
        expression = musicexpressiontools.StartPositionedDivisionPayloadExpression(
            payload=divisions,
            start_offset=self.start_offset,
            voice_name=self.voice_name,
            )
        return expression
Exemplo n.º 5
0
 def _split(
     self,
     durations,
     cyclic=False,
     fracture_spanners=False,
     tie_split_notes=True,
     ):
     from abjad.tools import iterationtools
     from abjad.tools import pitchtools
     from abjad.tools import selectiontools
     from abjad.tools import spannertools
     durations = [durationtools.Duration(x) for x in durations]
     if cyclic:
         durations = sequencetools.repeat_sequence_to_weight_exactly(
             durations, self._get_duration())
     durations = [durationtools.Duration(x) for x in durations]
     if sum(durations) < self._get_duration():
         last_duration = self._get_duration() - sum(durations)
         durations.append(last_duration)
     sequencetools.truncate_sequence_to_weight(
         durations, self._get_duration())
     result = []
     leaf_prolation = self._get_parentage(include_self=False).prolation
     leaf_copy = copy.copy(self)
     for duration in durations:
         new_leaf = copy.copy(self)
         preprolated_duration = duration / leaf_prolation
         shard = new_leaf._set_duration(preprolated_duration)
         shard = [x._get_parentage().root for x in shard]
         result.append(shard)
     flattened_result = sequencetools.flatten_sequence(result)
     flattened_result = selectiontools.SliceSelection(flattened_result)
     spanner_classes = (spannertools.TieSpanner,)
     parentage = self._get_parentage()
     if parentage._get_spanners(spanner_classes=spanner_classes):
         selection = selectiontools.select(flattened_result)
         for component in selection:
             for mark in component._get_spanners(
                 spanner_classes=spanner_classes):
                 mark.detach()
     # replace leaf with flattened result
     selection = selectiontools.SliceSelection(self)
     parent, start, stop = selection._get_parent_and_start_stop_indices()
     if parent:
         parent.__setitem__(slice(start, stop + 1), flattened_result)
     else:
         selection._give_dominant_spanners(flattened_result)
         selection._withdraw_from_crossing_spanners()
     # fracture spanners
     if fracture_spanners:
         first_shard = result[0]
         for spanner in first_shard[-1]._get_spanners():
             index = spanner.index(first_shard[-1])
             spanner.fracture(index, direction=Right)
         last_shard = result[-1]
         for spanner in last_shard[0]._get_spanners():
             index = spanner.index(last_shard[0])
             spanner.fracture(index, direction=Left)
         for middle_shard in result[1:-1]:
             for spanner in middle_shard[0]._get_spanners():
                 index = spanner.index(middle_shard[0])
                 spanner.fracture(index, direction=Left)
             for spanner in middle_shard[-1]._get_spanners():
                 index = spanner.index(middle_shard[-1])
                 spanner.fracture(index, direction=Right)
     # adjust first leaf
     first_leaf = flattened_result[0]
     self._detach_grace_containers(kind='after')
     # adjust any middle leaves
     for middle_leaf in flattened_result[1:-1]:
         middle_leaf._detach_grace_containers(kind='grace')
         self._detach_grace_containers(kind='after')
         for mark in middle_leaf._get_marks():
             mark.detach()
     # adjust last leaf
     last_leaf = flattened_result[-1]
     last_leaf._detach_grace_containers(kind='grace')
     for mark in last_leaf._get_marks():
         mark.detach()
     # tie split notes, rests and chords as specified
     if pitchtools.Pitch.is_pitch_carrier(self) and tie_split_notes:
         flattened_result_leaves = iterationtools.iterate_leaves_in_expr(
             flattened_result)
         # TODO: implement SliceSelection._attach_tie_spanner_to_leaves()
         for leaf_pair in sequencetools.iterate_sequence_pairwise_strict(
             flattened_result_leaves):
             selection = selectiontools.ContiguousSelection(leaf_pair)
             selection._attach_tie_spanner_to_leaf_pair()
     # return result
     return result
Exemplo n.º 6
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 partition_sequence_by_counts(sequence, counts, cyclic=False, overhang=False, copy_elements=False):
    r"""Partition sequence by counts.
    
    ..  container:: example

        **Example 1a.** Partition sequence once by counts without overhang:

        ::

            >>> sequencetools.partition_sequence_by_counts(
            ...     range(10), 
            ...     [3], 
            ...     cyclic=False, 
            ...     overhang=False,
            ...     )
            [[0, 1, 2]]

    ..  container:: example

        **Example 1b.** Partition sequence once by counts without overhang:

        ::

            >>> sequencetools.partition_sequence_by_counts(
            ...     range(16), 
            ...     [4, 3], 
            ...     cyclic=False, 
            ...     overhang=False,
            ...     )
            [[0, 1, 2, 3], [4, 5, 6]]

    ..  container:: example

        **Example 2a.** Partition sequence cyclically by counts without 
        overhang:

        ::

            >>> sequencetools.partition_sequence_by_counts(
            ...     range(10), 
            ...     [3], 
            ...     cyclic=True, 
            ...     overhang=False,
            ...     )
            [[0, 1, 2], [3, 4, 5], [6, 7, 8]]

    ..  container:: example

        **Example 2b.** Partition sequence cyclically by counts without 
        overhang:

        ::

            >>> sequencetools.partition_sequence_by_counts(
            ...     range(16), 
            ...     [4, 3], 
            ...     cyclic=True, 
            ...     overhang=False,
            ...     )
            [[0, 1, 2, 3], [4, 5, 6], [7, 8, 9, 10], [11, 12, 13]]

    ..  container:: example

        **Example 3a.** Partition sequence once by counts with overhang:

        ::

            >>> sequencetools.partition_sequence_by_counts(
            ...     range(10), 
            ...     [3], 
            ...     cyclic=False, 
            ...     overhang=True,
            ...     )
            [[0, 1, 2], [3, 4, 5, 6, 7, 8, 9]]

    ..  container:: example

        **Example 3b.** Partition sequence once by counts with overhang:

        ::

            >>> sequencetools.partition_sequence_by_counts(
            ...     range(16), 
            ...     [4, 3], 
            ...     cyclic=False, 
            ...     overhang=True,
            ...     )
            [[0, 1, 2, 3], [4, 5, 6], [7, 8, 9, 10, 11, 12, 13, 14, 15]]

    ..  container:: example

        **Example 4a.** Partition sequence cyclically by counts with overhang:

        ::

            >>> sequencetools.partition_sequence_by_counts(
            ...     range(10), 
            ...     [3], 
            ...     cyclic=True, 
            ...     overhang=True,
            ...     )
            [[0, 1, 2], [3, 4, 5], [6, 7, 8], [9]]

    ..  container:: example

        **Example 4b.** Partition sequence cyclically by counts with overhang:

        ::

            >>> sequencetools.partition_sequence_by_counts(
            ...     range(16), 
            ...     [4, 3], 
            ...     cyclic=True, 
            ...     overhang=True,
            ...     )
            [[0, 1, 2, 3], [4, 5, 6], [7, 8, 9, 10], [11, 12, 13], [14, 15]]

    Returns list of sequence objects.
    """
    from abjad.tools import sequencetools

    result = []

    if cyclic:
        if overhang:
            counts = sequencetools.repeat_sequence_to_weight_exactly(counts, len(sequence))
        else:
            counts = sequencetools.repeat_sequence_to_weight_at_most(counts, len(sequence))
    elif overhang:
        weight_counts = mathtools.weight(counts)
        len_sequence = len(sequence)
        if weight_counts < len_sequence:
            counts = list(counts)
            counts.append(len(sequence) - weight_counts)

    for start, stop in mathtools.cumulative_sums_pairwise(counts):
        result.append(type(sequence)(sequence[start:stop]))

    return result
def test_sequencetools_repeat_sequence_to_weight_exactly_01():

    assert sequencetools.repeat_sequence_to_weight_exactly((5, -5, -5), 23) == (5, -5, -5, 5, -3)