def to_fixed_multiplier(self):
        r'''Change fixed-duration tuplet to (unqualified) tuplet.

        ..  container:: example

            **Example:**

            ::

                >>> tuplet = tuplettools.FixedDurationTuplet((2, 8), [])
                >>> tuplet.extend("c'8 d'8 e'8")
                >>> show(tuplet) # doctest: +SKIP

            ::

                >>> tuplet
                FixedDurationTuplet(1/4, [c'8, d'8, e'8])

            ::

                >>> new_tuplet = tuplet.to_fixed_multiplier()
                >>> show(new_tuplet) # doctest: +SKIP

            ::

                >>> new_tuplet
                Tuplet(2/3, [c'8, d'8, e'8])

        Returns new tuplet.
        '''
        from abjad.tools import tuplettools
        new_tuplet = tuplettools.Tuplet(self.multiplier, [])
        mutationtools.mutate(self).swap(new_tuplet)
        return new_tuplet
 def _fuse_tuplets(self):
     from abjad.tools import containertools
     from abjad.tools import tuplettools
     assert self._all_are_contiguous_components_in_same_parent(
         self, component_classes=(tuplettools.Tuplet,))
     if len(self) == 0:
         return None
     first = self[0]
     first_multiplier = first.multiplier
     first_type = type(first)
     for tuplet in self[1:]:
         if tuplet.multiplier != first_multiplier:
             raise TupletFuseError('tuplets must carry same multiplier.')
         if type(tuplet) != first_type:
             raise TupletFuseError('tuplets must be same type.')
     if isinstance(first, tuplettools.FixedDurationTuplet):
         total_contents_duration = sum(
             [x._contents_duration for x in self])
         new_target_duration = first_multiplier * total_contents_duration
         new_tuplet = tuplettools.FixedDurationTuplet(
             new_target_duration, [])
     elif isinstance(first, tuplettools.Tuplet):
         new_tuplet = tuplettools.Tuplet(first_multiplier, [])
     else:
         raise TypeError('unknown tuplet type.')
     wrapped = False
     if self[0]._get_parentage().root is not \
         self[-1]._get_parentage().root:
         dummy_container = containertools.Container(self)
         wrapped = True
     mutationtools.mutate(self).swap(new_tuplet)
     if wrapped:
         del(dummy_container[:])
     return new_tuplet
    def __or__(self, expr):
        r'''Logical OR of two payload expressions.

        Payload expression must be able to fuse.

        Returns timespan inventory.
        '''
        assert self._can_fuse(expr)
        if isinstance(self.payload, containertools.Container):
            selection = select(self.payload[0], contiguous=True)
            left = mutationtools.mutate(selection).copy()[0]
            selection = select(expr.payload[0], contiguous=True)
            right = mutationtools.mutate(selection).copy()[0]
            payload = containertools.Container([left, right])
            for component in payload[:]:
                component._extract()
            payload = containertools.Container([payload])
        else:
            payload = self.payload + expr.payload
        result = type(self)(
            [],
            start_offset=self.timespan.start_offset,
            voice_name=self.voice_name,
            )
        result._payload = payload
        return timespantools.TimespanInventory([result])
 def __call__(self, expr):
     for i, note in enumerate(iterationtools.iterate_notes_in_expr(expr)):
         cluster_width = self.cluster_widths[i]
         start = note.written_pitch.diatonic_pitch_number
         diatonic_numbers = range(start, start + cluster_width)
         chromatic_numbers = [
             (12 * (x // 7)) +
             pitchtools.PitchClass._diatonic_pitch_class_number_to_pitch_class_number[
                 x % 7]
             for x in diatonic_numbers 
             ] 
         chord_pitches = [pitchtools.NamedPitch(x) 
             for x in chromatic_numbers]
         chord = scoretools.Chord(note)
         chord[:] = []
         chord.extend(chord_pitches)
         mutationtools.mutate(note).replace(chord)
 def _split_payload_at_offsets(self, offsets):
     assert isinstance(self.payload, containertools.Container)
     music = self.payload
     self._payload = containertools.Container()
     shards = mutationtools.mutate([music]).split(
         offsets, 
         cyclic=False, 
         fracture_spanners=True,
         )
     shards = [shard[0] for shard in shards]
     for shard in shards:
         if not inspect(shard).is_well_formed():
             wellformednesstools.tabulate_well_formedness_violations_in_expr(shard)
     return shards
 def _copy_and_include_enclosing_containers(self):
     from abjad.tools import scoretools
     from abjad.tools import iterationtools
     from abjad.tools import leaftools
     from abjad.tools.mutationtools import mutate
     # get governor
     parentage = self[0]._get_parentage(include_self=True)
     governor = parentage._get_governor()
     # find start and stop indices in governor
     governor_leaves = list(governor.select_leaves())
     for i, x in enumerate(governor_leaves):
         if x is self[0]:
             start_index_in_governor = i
     for i, x in enumerate(governor_leaves):
         if x is self[-1]:
             stop_index_in_governor = i
     # copy governor
     governor_copy = mutate(governor).copy()
     copied_leaves = governor_copy.select_leaves()
     # find start and stop leaves in copy of governor
     start_leaf = copied_leaves[start_index_in_governor]
     stop_leaf = copied_leaves[stop_index_in_governor]
     # trim governor copy forwards from first leaf
     found_start_leaf = False
     while not found_start_leaf:
         leaf = iterationtools.iterate_leaves_in_expr(governor_copy).next()
         if leaf is start_leaf:
             found_start_leaf = True
         else:
             leaf._remove_and_shrink_durated_parent_containers()
     # trim governor copy backwards from last leaf
     found_stop_leaf = False
     while not found_stop_leaf:
         reverse_iterator = iterationtools.iterate_leaves_in_expr(
             governor_copy, reverse=True)
         leaf = reverse_iterator.next()
         if leaf is stop_leaf:
             found_stop_leaf = True
         else:
             leaf._remove_and_shrink_durated_parent_containers()
     # return trimmed governor copy
     return governor_copy
Example #7
0
    def to_tuplet(self, proportions, dotted=False, is_diminution=True):
        r"""Change tie chain to tuplet.

        ..  container:: example

            **Example 1.** Change tie chain to diminished tuplet:

            ::

                >>> staff = Staff(r"c'8 ~ c'16 cqs''4")
                >>> crescendo = spannertools.HairpinSpanner(descriptor='p < f')
                >>> attach(crescendo, staff[:])
                >>> staff.override.dynamic_line_spanner.staff_padding = 3
                >>> time_signature = contexttools.TimeSignatureMark((7, 16))
                >>> attach(time_signature, staff)
                TimeSignatureMark((7, 16))(Staff{3})
                
            ..  doctest::

                >>> f(staff)
                \new Staff \with {
                    \override DynamicLineSpanner #'staff-padding = #3
                } {
                    \time 7/16
                    c'8 \< \p ~
                    c'16
                    cqs''4 \f
                }

            ::

                >>> show(staff) # doctest: +SKIP

            ::

                >>> tie_chain = inspect(staff[0]).get_tie_chain()
                >>> tie_chain.to_tuplet([2, 1, 1, 1], is_diminution=True)
                FixedDurationTuplet(3/16, [c'8, c'16, c'16, c'16])

            ..  doctest::

                >>> f(staff)
                \new Staff \with {
                    \override DynamicLineSpanner #'staff-padding = #3
                } {
                    \time 7/16
                    \tweak #'text #tuplet-number::calc-fraction-text
                    \times 3/5 {
                        c'8 \< \p
                        c'16
                        c'16
                        c'16
                    }
                    cqs''4 \f
                }

            ::

                >>> show(staff) # doctest: +SKIP

        ..  container:: example

            **Example 2.** Change tie chain to augmented tuplet:

            ::

                >>> staff = Staff(r"c'8 ~ c'16 cqs''4")
                >>> crescendo = spannertools.HairpinSpanner(descriptor='p < f')
                >>> attach(crescendo, staff[:])
                >>> staff.override.dynamic_line_spanner.staff_padding = 3
                >>> time_signature = contexttools.TimeSignatureMark((7, 16))
                >>> attach(time_signature, staff)
                TimeSignatureMark((7, 16))(Staff{3})
                
            ..  doctest::

                >>> f(staff)
                \new Staff \with {
                    \override DynamicLineSpanner #'staff-padding = #3
                } {
                    \time 7/16
                    c'8 \< \p ~
                    c'16
                    cqs''4 \f
                }

            ::

                >>> show(staff) # doctest: +SKIP

            ::

                >>> tie_chain = inspect(staff[0]).get_tie_chain()
                >>> tie_chain.to_tuplet([2, 1, 1, 1], is_diminution=False)
                FixedDurationTuplet(3/16, [c'16, c'32, c'32, c'32])

            ..  doctest::

                >>> f(staff)
                \new Staff \with {
                    \override DynamicLineSpanner #'staff-padding = #3
                } {
                    \time 7/16
                    \tweak #'text #tuplet-number::calc-fraction-text
                    \times 6/5 {
                        c'16 \< \p
                        c'32
                        c'32
                        c'32
                    }
                    cqs''4 \f
                }

            ::

                >>> show(staff) # doctest: +SKIP

        Returns tuplet.
        """
        from abjad.tools import scoretools
        from abjad.tools import mathtools
        from abjad.tools import mutationtools
        from abjad.tools import notetools
        from abjad.tools import spannertools
        from abjad.tools import tuplettools

        # coerce input
        proportions = mathtools.Ratio(proportions)

        # find target duration of fixed-duration tuplet
        target_duration = self._preprolated_duration

        # find prolated duration of each note in tuplet
        prolated_duration = target_duration / sum(proportions)

        # find written duration of each notes in tuplet
        if is_diminution:
            if dotted:
                basic_written_duration = prolated_duration.equal_or_greater_assignable
            else:
                basic_written_duration = prolated_duration.equal_or_greater_power_of_two
        else:
            if dotted:
                basic_written_duration = prolated_duration.equal_or_lesser_assignable
            else:
                basic_written_duration = prolated_duration.equal_or_lesser_power_of_two

        # find written duration of each note in tuplet
        written_durations = [x * basic_written_duration for x in proportions]

        # make tuplet notes
        try:
            notes = [notetools.Note(0, x) for x in written_durations]
        except AssignabilityError:
            denominator = target_duration._denominator
            note_durations = [durationtools.Duration(x, denominator) for x in proportions]
            notes = notetools.make_notes(0, note_durations)

        # make tuplet
        tuplet = tuplettools.FixedDurationTuplet(target_duration, notes)

        # replace tie chain with tuplet
        mutationtools.mutate(self).replace(tuplet)

        # untie tuplet
        for spanner in tuplet._get_spanners(spannertools.TieSpanner):
            spanner.detach()

        # return tuplet
        return tuplet
    def recurse(tie_chain, depth=0):
        offsets = get_offsets_at_depth(depth)
        #print 'DEPTH:', depth

        tie_chain_duration = tie_chain._preprolated_duration
        tie_chain_start_offset = tie_chain.get_timespan().start_offset
        tie_chain_stop_offset = tie_chain.get_timespan().stop_offset
        tie_chain_starts_in_offsets = tie_chain_start_offset in offsets
        tie_chain_stops_in_offsets = tie_chain_stop_offset in offsets

        if not is_acceptable_tie_chain(
            tie_chain_duration,
            tie_chain_starts_in_offsets,
            tie_chain_stops_in_offsets):

            #print 'UNACCEPTABLE:', tie_chain, tie_chain_start_offset, tie_chain_stop_offset
            #print '\t', ' '.join([str(x) for x in offsets])
            split_offset = None
            offsets = get_offsets_at_depth(depth)

            # If the tie chain's start aligns, take the latest possible offset.
            if tie_chain_starts_in_offsets:
                offsets = reversed(offsets)

            for offset in offsets:
                if tie_chain_start_offset < offset < tie_chain_stop_offset:
                    split_offset = offset
                    break

            #print '\tABS:', split_offset
            if split_offset is not None:
                split_offset -= tie_chain_start_offset
                #print '\tREL:', split_offset
                #print ''
                shards = \
                    mutationtools.mutate(tie_chain[:]).split([split_offset])
                tie_chains = \
                    [selectiontools.TieChain(shard) for shard in shards]
                for tie_chain in tie_chains:
                    recurse(tie_chain, depth=depth)
            else:
                #print ''
                recurse(tie_chain, depth=depth+1)

        elif is_boundary_crossing_tie_chain(
            tie_chain_start_offset,
            tie_chain_stop_offset):

            #print 'BOUNDARY CROSSING', tie_chain, tie_chain_start_offset, tie_chain_stop_offset
            offsets = boundary_offsets
            if tie_chain_start_offset in boundary_offsets:
                offsets = reversed(boundary_offsets)
            split_offset = None
            for offset in offsets:
                if tie_chain_start_offset < offset < tie_chain_stop_offset:
                    split_offset = offset
                    break
            assert split_offset is not None
            #print '\tABS:', split_offset
            split_offset -= tie_chain_start_offset
            #print '\tREL:', split_offset
            #print ''
            shards = \
                mutationtools.mutate(tie_chain[:]).split([split_offset])
            tie_chains = \
                [selectiontools.TieChain(shard) for shard in shards]
            for tie_chain in tie_chains:
                recurse(tie_chain, depth=depth)

        else:
            #print 'ACCEPTABLE:', tie_chain, tie_chain_start_offset, tie_chain_stop_offset
            #print '\t', ' '.join([str(x) for x in offsets])
            #print ''
            tie_chain[:]._fuse()
    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
Example #10
0
    def from_score(score, populate=True):
        r'''Make pitch array from `score`.

        ..  container:: example

            **Example 1.** Make empty pitch array from score:

            ::

                >>> score = Score([])
                >>> score.append(Staff("c'8 d'8 e'8 f'8"))
                >>> score.append(Staff("c'4 d'4"))
                >>> score.append(
                ...     Staff(
                ...     tuplettools.FixedDurationTuplet(
                ...     Duration(2, 8), "c'8 d'8 e'8") * 2))

            ..  doctest::

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

            ::

                >>> show(score) # doctest: +SKIP

            ::

                >>> array = pitcharraytools.PitchArray.from_score(
                ...     score, populate=False)

            ::

                >>> print array
                [     ] [     ] [     ] [     ]
                [                 ] [                 ]
                [ ] [     ] [ ] [ ] [     ] [ ]

        ..  container:: example

            **Example 2.** Make populated pitch array from `score`:

            ::

                >>> score = Score([])
                >>> score.append(Staff("c'8 d'8 e'8 f'8"))
                >>> score.append(Staff("c'4 d'4"))
                >>> score.append(
                ...     Staff(
                ...     tuplettools.FixedDurationTuplet(
                ...     Duration(2, 8), "c'8 d'8 e'8") * 2))

            ..  doctest::

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

            ::

                >>> show(score) # doctest: +SKIP
                
            ::

                >>> array = pitcharraytools.PitchArray.from_score(
                ...     score, populate=True)

            ::

                >>> print array
                [c'     ] [d'     ] [e'     ] [f'     ]
                [c'                   ] [d'                   ]
                [c'] [d'     ] [e'] [c'] [d'     ] [e']
    
        Returns pitch array.
        '''
        time_intervals = \
            PitchArray._get_composite_offset_difference_series_from_leaves_in_expr(
            score)
        array_width = len(time_intervals)
        array_depth = len(score)
        pitch_array = PitchArray(array_depth, array_width)
        tokens = notetools.make_quarter_notes_with_lilypond_duration_multiplier(
            [0], time_intervals)
        for leaf_iterable, pitch_array_row in \
            zip(score, pitch_array.rows):
            durations = []
            for leaf in iterationtools.iterate_leaves_in_expr(leaf_iterable):
                durations.append(leaf._get_duration())
            parts = mutationtools.mutate(tokens).split(
                durations,
                cyclic=False,
                fracture_spanners=False,
                )
            part_lengths = [len(part) for part in parts]
            cells = pitch_array_row.cells
            grouped_cells = sequencetools.partition_sequence_by_counts(
                cells,
                part_lengths,
                cyclic=False,
                overhang=False,
                )
            for group in grouped_cells:
                pitch_array_row.merge(group)
            leaves = iterationtools.iterate_leaves_in_expr(leaf_iterable)
            if populate:
                for cell, leaf in zip(pitch_array_row.cells, leaves):
                    cell.pitches.extend(
                        pitchtools.list_named_pitches_in_expr(leaf))
        return pitch_array