Example #1
0
 def _update_all_leaf_indices_and_measure_numbers(component):
     r'''Call only when updating offsets.
     No separate state flags exist for leaf indices or measure numbers.
     '''
     from abjad.tools import contexttools
     from abjad.tools import iterationtools
     parentage = component._get_parentage()
     score_root = parentage.root
     if isinstance(score_root, contexttools.Context):
         contexts = iterationtools.iterate_contexts_in_expr(score_root)
         for context in contexts:
             for leaf_index, leaf in enumerate(
                 iterationtools.iterate_leaves_in_expr(context)):
                 leaf._leaf_index = leaf_index
             for measure_index, measure in enumerate(
                 iterationtools.iterate_measures_in_expr(context)):
                 measure_number = measure_index + 1
                 measure._measure_number = measure_number
     else:
         for leaf_index, leaf in enumerate(
             iterationtools.iterate_leaves_in_expr(score_root)):
             leaf._leaf_index = leaf_index
         for measure_index, measure in enumerate(
             iterationtools.iterate_measures_in_expr(score_root)):
             measure_number = measure_index + 1
             measure._measure_number = measure_number
def label_leaves_in_expr_with_tuplet_depth(expr, markup_direction=Down):
    r'''Label leaves in `expr` with tuplet depth:

    ::

        >>> staff = Staff("c'8 d'8 e'8 f'8 g'8")
        >>> tuplettools.FixedDurationTuplet(Duration(2, 8), staff[-3:])
        FixedDurationTuplet(1/4, [e'8, f'8, g'8])
        >>> labeltools.label_leaves_in_expr_with_tuplet_depth(staff)
        >>> f(staff)
        \new Staff {
            c'8 _ \markup { \small 0 }
            d'8 _ \markup { \small 0 }
            \times 2/3 {
                e'8 _ \markup { \small 1 }
                f'8 _ \markup { \small 1 }
                g'8 _ \markup { \small 1 }
            }
        }

    ::

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

    Returns none.
    '''

    for leaf in iterationtools.iterate_leaves_in_expr(expr):
        label = markuptools.MarkupCommand(
            'small', str(leaf._get_parentage().tuplet_depth))
        markup = markuptools.Markup(label, markup_direction)
        attach(markup, leaf)
def label_leaves_in_expr_with_leaf_indices(expr, markup_direction=Down):
    r'''Label leaves in `expr` with leaf indices:

    ::

        >>> staff = Staff("c'8 d'8 e'8 f'8")
        >>> labeltools.label_leaves_in_expr_with_leaf_indices(staff)
        >>> f(staff)
        \new Staff {
            c'8 _ \markup { \small 0 }
            d'8 _ \markup { \small 1 }
            e'8 _ \markup { \small 2 }
            f'8 _ \markup { \small 3 }
        }

    ::

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

    Returns none.
    '''

    for i, leaf in enumerate(iterationtools.iterate_leaves_in_expr(expr)):
        label = markuptools.MarkupCommand('small', str(i))
        markup = markuptools.Markup(label, markup_direction)
        attach(markup, leaf)
def label_leaves_in_expr_with_leaf_numbers(expr, markup_direction=Down):
    r'''Label leaves in `expr` with leaf numbers:

    ::

        >>> staff = Staff("c'8 d'8 e'8 f'8")
        >>> labeltools.label_leaves_in_expr_with_leaf_numbers(staff)
        >>> f(staff)
        \new Staff {
            c'8 _ \markup { \small 1 }
            d'8 _ \markup { \small 2 }
            e'8 _ \markup { \small 3 }
            f'8 _ \markup { \small 4 }
        }

    ::

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

    Number leaves starting from ``1``.

    Returns none.
    '''

    for i, leaf in enumerate(iterationtools.iterate_leaves_in_expr(expr)):
        leaf_number = i + 1
        label = markuptools.MarkupCommand('small', str(leaf_number))
        markup = markuptools.Markup(label, markup_direction)
        attach(markup, leaf)
 def __call__(self, expr, offset=0):
     leaves = list(iterationtools.iterate_leaves_in_expr(expr))
     groups = list(iterationtools.iterate_runs_in_expr(
         leaves, (notetools.Note, scoretools.Chord)))
     hairpin_tokens = datastructuretools.CyclicList(self.hairpin_tokens)
     for i, group in enumerate(groups):
         if not isinstance(group, selectiontools.SliceSelection):
             group = selectiontools.SliceSelection(group)
         is_short_group = False
         hairpin_token = hairpin_tokens[offset+i]
         if len(group) == 1:
             is_short_group = True
         elif self.minimum_duration is not None:
             if group.get_duration() < self.minimum_duration:
                 is_short_group = True
         if is_short_group:
             start_dynamic = hairpin_token[0]
             #contexttools.DynamicMark(start_dynamic)(group[0])
             command = marktools.LilyPondCommandMark(start_dynamic, 'right')
             attach(command, group[0])
         else:
             descriptor = ' '.join([x for x in hairpin_token if x])
             hairpin = spannertools.HairpinSpanner(
                 descriptor=descriptor, 
                 include_rests=False,
                 )
             attach(hairpin, group)
     return expr
def label_leaves_in_expr_with_pitch_numbers(expr, markup_direction=Down):
    r'''Label leaves in `expr` with pitch numbers:

    ::

        >>> staff = Staff(leaftools.make_leaves([None, 12, [13, 14, 15], None], [(1, 4)]))
        >>> labeltools.label_leaves_in_expr_with_pitch_numbers(staff)
        >>> f(staff)
        \new Staff {
            r4
            c''4 _ \markup { \small 12 }
            <cs'' d'' ef''>4 _ \markup { \column { \small 15 \small 14 \small 13 } }
            r4
        }

    ::

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

    Returns none.
    '''

    for leaf in iterationtools.iterate_leaves_in_expr(expr):
        for pitch in reversed(pitchtools.PitchSegment.from_selection(leaf)):
            if pitch is not None:
                label = markuptools.MarkupCommand('small', str(pitch.pitch_number))
                markup = markuptools.Markup(label, markup_direction)
                attach(markup, leaf)
def color_leaves_in_expr(expr, color):
    r"""Color leaves in `expr`:

    ::

        >>> staff = Staff("cs'8. [ r8. s8. <c' cs' a'>8. ]")

    ..  doctest::

        >>> f(staff)
        \new Staff {
            cs'8. [
            r8.
            s8.
            <c' cs' a'>8. ]
        }

    ::

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

    ::

        >>> labeltools.color_leaves_in_expr(staff, 'red')

    ..  doctest::

        >>> f(staff)
        \new Staff {
            \once \override Accidental #'color = #red
            \once \override Beam #'color = #red
            \once \override Dots #'color = #red
            \once \override NoteHead #'color = #red
            \once \override Stem #'color = #red
            cs'8. [
            \once \override Dots #'color = #red
            \once \override Rest #'color = #red
            r8.
            s8.
            \once \override Accidental #'color = #red
            \once \override Beam #'color = #red
            \once \override Dots #'color = #red
            \once \override NoteHead #'color = #red
            \once \override Stem #'color = #red
            <c' cs' a'>8. ]
        }

    ::

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

    Returns none.
    """
    from abjad.tools import labeltools

    for leaf in iterationtools.iterate_leaves_in_expr(expr):
        labeltools.color_leaf(leaf, color)
Example #8
0
 def _duration_in_seconds(self):
     from abjad.tools import iterationtools
     if self.is_simultaneous:
         return max([durationtools.Duration(0)] + 
             [x._get_duration(in_seconds=True) for x in self])
     else:
         duration = durationtools.Duration(0)
         for leaf in iterationtools.iterate_leaves_in_expr(self):
             duration += leaf._get_duration(in_seconds=True)
         return duration
 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
 def _run(self, expr):
     violators = []
     spanner_classes = (spannertools.OctavationSpanner, )
     for leaf in iterationtools.iterate_leaves_in_expr(expr):
         spanners = leaf._get_descendants()._get_spanners(spanner_classes)
         if 1 < len(spanners):
             for spanner in spanners:
                 if spanner not in violators:
                     violators.append(spanner)
     total = expr._get_descendants()._get_spanners(spanner_classes)
     return violators, len(total)
 def _run(self, expr):
     violators = []
     total = 0
     for leaf in iterationtools.iterate_leaves_in_expr(expr):
         total += 1
         if leaf._has_spanner(spannertools.BeamSpanner):
             beam = leaf._get_spanner(spannertools.BeamSpanner)
             if not isinstance(beam, spannertools.DuratedComplexBeamSpanner):
                 flag_count = leaf.written_duration.flag_count
                 if flag_count < 1:
                     violators.append(leaf)
     return violators, total
Example #12
0
 def _get_composite_offset_difference_series_from_leaves_in_expr(expr):
     from abjad.tools import iterationtools
     offsets = []
     for leaf in iterationtools.iterate_leaves_in_expr(expr):
         start_offset = leaf._get_timespan().start_offset
         if start_offset not in offsets:
             offsets.append(start_offset)
         stop_offset = leaf._get_timespan().stop_offset
         if stop_offset not in offsets:
             offsets.append(stop_offset)
     offsets.sort()
     return list(mathtools.difference_series(offsets))
 def _run(self, expr):
     violators = []
     spanner_classes = (spannertools.BeamSpanner,)
     all_beams = set()
     for leaf in iterationtools.iterate_leaves_in_expr(expr):
         beams  = leaf._get_spanners(spanner_classes)
         all_beams.update(beams)
         if 1 < len(beams):
             for beam in beams:
                 if beam not in violators:
                     violators.append(beam)
     total = len(all_beams)
     return violators, total
Example #14
0
    def respell_with_sharps(self):
        r'''Respell named pitches in mutation client with sharps:

        ::

            >>> staff = Staff("c'8 cs'8 d'8 ef'8 e'8 f'8")
            >>> show(staff) # doctest: +SKIP

        ..  doctest::

            >>> f(staff)
            \new Staff {
                c'8
                cs'8
                d'8
                ef'8
                e'8
                f'8
            }

        ::

            >>> mutate(staff).respell_with_sharps()
            >>> show(staff) # doctest: +SKIP

        ..  doctest::

            >>> f(staff)
            \new Staff {
                c'8
                cs'8
                d'8
                ds'8
                e'8
                f'8
            }

        Returns none.
        '''
        from abjad.tools import scoretools
        from abjad.tools import iterationtools
        for leaf in iterationtools.iterate_leaves_in_expr(self._client):
            if isinstance(leaf, scoretools.Chord):
                for note_head in leaf.note_heads:
                    note_head.written_pitch = \
                        note_head.written_pitch.respell_with_sharps()
            elif hasattr(leaf, 'written_pitch'):
                leaf.written_pitch = leaf.written_pitch.respell_with_sharps()
Example #15
0
 def _initialize_components(self, components):
     if components:
         raise Exception('deprecated')
     from abjad.tools import contexttools
     from abjad.tools import iterationtools
     if isinstance(components, scoretools.Component):
         components = [components]
     elif not components:
         components = []
     assert not any(
         isinstance(x, contexttools.Context) 
         for x in components), repr(components)
     if self._contiguity_constraint == 'logical voice':
         leaves = list(iterationtools.iterate_leaves_in_expr(components))
         assert Selection._all_are_contiguous_components_in_same_logical_voice(leaves)
     self.extend(components)
Example #16
0
    def select_leaves(
        self,
        start=0,
        stop=None,
        leaf_classes=None,
        recurse=True,
        allow_discontiguous_leaves=False,
        ):
        r'''Selects leaves in container.

        ..  container:: example

            ::

                >>> container = Container("c'8 d'8 r8 e'8")

            ::

                >>> container.select_leaves()
                ContiguousSelection(Note("c'8"), Note("d'8"), Rest('r8'), Note("e'8"))

        Returns contiguous leaf selection or free leaf selection.
        '''
        from abjad.tools import scoretools
        from abjad.tools import iterationtools
        from abjad.tools import leaftools
        from abjad.tools import selectiontools
        Selection = selectiontools.Selection
        leaf_classes = leaf_classes or (leaftools.Leaf,)
        expr = self
        if recurse:
            expr = iterationtools.iterate_leaves_in_expr(expr)
        music = [
                component for component in expr
                if isinstance(component, leaf_classes)
                ]
        music = music[start:stop]
        if allow_discontiguous_leaves:
            selection = selectiontools.Selection(music=music)
        else:
            assert Selection._all_are_contiguous_components_in_same_logical_voice(
                music)
            selection = selectiontools.ContiguousSelection(music=music)
        return selection
 def _run(self, expr):
     violators = []
     total = 0
     for leaf in iterationtools.iterate_leaves_in_expr(expr):
         total += 1
         flags = leaf.written_duration.flag_count
         left = getattr(leaf.set, 'stem_left_beam_count', None)
         right = getattr(leaf.set, 'stem_right_beam_count', None)
         if left is not None:
             if flags < left or \
                 (left < flags and right not in (flags, None)):
                 if leaf not in violators:
                     violators.append(leaf)
         if right is not None:
             if flags < right or \
                 (right < flags and left not in (flags, None)):
                 if leaf not in violators:
                     violators.append(leaf)
     return violators, total
 def _add_ties(self, result):
     from abjad.tools import selectiontools
     leaves = list(iterationtools.iterate_leaves_in_expr(result))
     written_durations = [leaf.written_duration for leaf in leaves]
     weights = [durationtools.Duration(numerator, self.talea_denominator) 
         for numerator in self.talea]
     parts = sequencetools.partition_sequence_by_weights_exactly(
         written_durations, weights=weights, cyclic=True, overhang=True)
     counts = [len(part) for part in parts]
     parts = sequencetools.partition_sequence_by_counts(leaves, counts)
     spanner_classes = (spannertools.TieSpanner,)
     for part in parts:
         part = selectiontools.SliceSelection(part)
         tie_spanner = spannertools.TieSpanner()
         # this is voodoo to temporarily neuter the contiguity constraint
         tie_spanner._contiguity_constraint = None
         for component in part:
             for spanner in component._get_spanners(
                 spanner_classes=spanner_classes):
                 spanner.detach()
         tie_spanner.extend(part)
def remove_markup_from_leaves_in_expr(expr):
    r'''Remove markup from leaves in `expr`:

    ::

        >>> staff = Staff("c'8 d'8 e'8 f'8")
        >>> labeltools.label_leaves_in_expr_with_pitch_class_numbers(staff)
        >>> f(staff)
        \new Staff {
            c'8 _ \markup { \small 0 }
            d'8 _ \markup { \small 2 }
            e'8 _ \markup { \small 4 }
            f'8 _ \markup { \small 5 }
        }

    ::

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

    ::

        >>> labeltools.remove_markup_from_leaves_in_expr(staff)
        >>> f(staff)
        \new Staff {
            c'8
            d'8
            e'8
            f'8
        }

    ::

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

    Returns none.
    '''

    for leaf in iterationtools.iterate_leaves_in_expr(expr):
        for markup in leaf._get_markup():
            markup.detach()
    def _run(self, expr):
        violators = []
        spanner_classes = (spannertools.GlissandoSpanner,)
        for leaf in iterationtools.iterate_leaves_in_expr(expr):
            glissandi = leaf._get_spanners(spanner_classes)
            if 1 < len(glissandi):
                if len(glissandi) == 2:
                    common_leaves = set(glissandi[0].leaves) & \
                        set(glissandi[1].leaves)
                    if len(common_leaves) == 1:
                        x = list(common_leaves)[0]
                        if (glissandi[0]._is_my_first_leaf(x) and
                            glissandi[1]._is_my_last_leaf(x)) or \
                            (glissandi[1]._is_my_first_leaf(x) and
                            glissandi[0]._is_my_last_leaf(x)):
                            break

                for glissando in glissandi:
                    if glissando not in violators:
                        violators.append(glissando)
        total = expr._get_descendants()._get_spanners(spanner_classes)
        return violators, len(total)
 def __call__(self, expr, offset=0):
     leaves = list(iterationtools.iterate_leaves_in_expr(expr))
     leaves = self._remove_outer_rests_from_sequence(leaves)
     #group = leaves
     group = selectiontools.SliceSelection(leaves)
     is_short_group = False
     if len(group) == 1:
         is_short_group = True
     elif self.minimum_duration is not None:
         if group.duration < self.minimum_duration:
             is_short_group = True
     if is_short_group:
         start_dynamic = self.hairpin_token[0]
         #contexttools.DynamicMark(start_dynamic)(group[0])
         command = marktools.LilyPondCommandMark(start_dynamic, 'right')
         attach(command, group[0])
     else:
         descriptor = ' '.join([x for x in self.hairpin_token if x])
         hairpin = spannertools.HairpinSpanner(
             descriptor=descriptor, 
             include_rests=False,
             )
         attach(hairpin, group)
     return expr
def list_named_pitches_in_expr(expr):
    '''List named pitches in `expr`:

    ::

        >>> staff = Staff("c'4 d'4 e'4 f'4")
        >>> beam = spannertools.BeamSpanner()
        >>> attach(beam, staff[:])

    ::

        >>> for x in pitchtools.list_named_pitches_in_expr(beam):
        ...     x
        ...
        NamedPitch("c'")
        NamedPitch("d'")
        NamedPitch("e'")
        NamedPitch("f'")

    Returns tuple.
    '''
    from abjad.tools import spannertools
    from abjad.tools import iterationtools
    from abjad.tools import leaftools
    from abjad.tools import pitchtools
    from abjad.tools import resttools

    # TODO: remove try-except
    try:
        result = pitchtools.get_named_pitch_from_pitch_carrier(expr)
        return pitchtools.PitchSegment(
            tokens=(result,),
            item_class=pitchtools.NamedPitch,
            )
    except (TypeError, MissingPitchError, ExtraPitchError):
        result = []
        if hasattr(expr, 'written_pitches'):
            result.extend(expr.written_pitches)
        # for pitch arrays
        elif hasattr(expr, 'pitches'):
            result.extend(expr.pitches)
        elif isinstance(expr, spannertools.Spanner):
            for leaf in expr.leaves:
                if hasattr(leaf, 'written_pitch') and not isinstance(leaf, resttools.Rest):
                    result.append(leaf.written_pitch)
                elif hasattr(leaf, 'written_pitches'):
                    result.extend(leaf.written_pitches)
        elif isinstance(expr, pitchtools.PitchSet):
            result.extend(sorted(list(expr)))
        elif isinstance(expr, (list, tuple, set)):
            for x in expr:
                result.extend(list_named_pitches_in_expr(x))
        else:
            for leaf in iterationtools.iterate_leaves_in_expr(expr):
                if hasattr(leaf, 'written_pitch') and not isinstance(leaf, resttools.Rest):
                    result.append(leaf.written_pitch)
                elif hasattr(leaf, 'written_pitches'):
                    result.extend(leaf.written_pitches)
        return pitchtools.PitchSegment(
            tokens=result,
            item_class=pitchtools.NamedPitch,
            )
def iterate_nontrivial_tie_chains_in_expr(expr, reverse=False):
    r'''Iterate nontrivial tie chains forward in `expr`:

    ::

        >>> staff = Staff(r"c'4 ~ \times 2/3 { c'16 d'8 } e'8 f'4 ~ f'16")

    ..  doctest::

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

    ::

        >>> for x in \
        ...     iterationtools.iterate_nontrivial_tie_chains_in_expr(staff):
        ...     x
        ...
        TieChain(Note("c'4"), Note("c'16"))
        TieChain(Note("f'4"), Note("f'16"))

    Iterate nontrivial tie chains backward in `expr`:

    ::

        >>> for x in \
        ...     iterationtools.iterate_nontrivial_tie_chains_in_expr(
        ...     staff, reverse=True):
        ...     x
        ...
        TieChain(Note("f'4"), Note("f'16"))
        TieChain(Note("c'4"), Note("c'16"))

    Returns generator.
    '''
    from abjad.tools import iterationtools
    from abjad.tools import spannertools

    spanner_classes = (spannertools.TieSpanner, )
    if not reverse:
        for leaf in iterationtools.iterate_leaves_in_expr(expr):
            tie_spanners = leaf._get_spanners(spanner_classes)
            if not tie_spanners or \
                tuple(tie_spanners)[0]._is_my_last_leaf(leaf):
                tie_chain = leaf._get_tie_chain()
                if not tie_chain.is_trivial:
                    yield tie_chain
    else:
        for leaf in iterationtools.iterate_leaves_in_expr(expr, reverse=True):
            tie_spanners = leaf._get_spanners(spanner_classes)
            if not(tie_spanners) or \
                tuple(tie_spanners)[0]._is_my_first_leaf(leaf):
                tie_chain = leaf._get_tie_chain()
                if not tie_chain.is_trivial:
                    yield tie_chain
Example #24
0
 def _split_by_duration(
     self,
     duration,
     fracture_spanners=False,
     tie_split_notes=True,
     ):
     from abjad.tools import scoretools
     from abjad.tools import containertools
     from abjad.tools import iterationtools
     from abjad.tools import leaftools
     from abjad.tools import measuretools
     from abjad.tools import notetools
     from abjad.tools import resttools
     from abjad.tools import selectiontools
     from abjad.tools import spannertools
     # check input
     duration = durationtools.Duration(duration)
     assert 0 <= duration, repr(duration)
     # if zero duration then return empty list and self
     if duration == 0:
         return [], self
     # get split point score offset
     global_split_point = self._get_timespan().start_offset + duration
     # get any duration-crossing descendents
     cross_offset = self._get_timespan().start_offset + duration
     duration_crossing_descendants = []
     for descendant in self._get_descendants():
         start_offset = descendant._get_timespan().start_offset
         stop_offset = descendant._get_timespan().stop_offset
         if start_offset < cross_offset < stop_offset:
             duration_crossing_descendants.append(descendant)
     # get any duration-crossing measure descendents
     measures = [
         x for x in duration_crossing_descendants 
         if isinstance(x, measuretools.Measure)
         ]
     # if we must split a power-of-two measure at non-power-of-two 
     # split point then go ahead and transform the power-of-two measure 
     # to non-power-of-two equivalent now; 
     # code that crawls and splits later on will be happier
     if len(measures) == 1:
         measure = measures[0]
         split_point_in_measure = \
             global_split_point - measure._get_timespan().start_offset
         if measure.has_non_power_of_two_denominator:
             if not measure.implied_prolation ==\
                 split_point_in_measure.implied_prolation:
                 raise NotImplementedError
         elif not mathtools.is_nonnegative_integer_power_of_two(
             split_point_in_measure.denominator):
             non_power_of_two_factors = mathtools.remove_powers_of_two(
                 split_point_in_measure.denominator)
             non_power_of_two_factors = mathtools.factors(
                 non_power_of_two_factors)
             non_power_of_two_product = 1
             for non_power_of_two_factor in non_power_of_two_factors:
                 non_power_of_two_product *= non_power_of_two_factor
             measuretools.scale_measure_denominator_and_adjust_measure_contents(
                 measure, non_power_of_two_product)
             # rederive duration crosses with possibly new measure contents
             cross_offset = self._get_timespan().start_offset + duration
             duration_crossing_descendants = []
             for descendant in self._get_descendants():
                 start_offset = descendant._get_timespan().start_offset
                 stop_offset = descendant._get_timespan().stop_offset
                 if start_offset < cross_offset < stop_offset:
                     duration_crossing_descendants.append(descendant)
     elif 1 < len(measures):
         raise Exception('measures can not nest.')
     # any duration-crossing leaf will be at end of list
     bottom = duration_crossing_descendants[-1]
     did_split_leaf = False
     # if split point necessitates leaf split
     if isinstance(bottom, leaftools.Leaf):
         assert isinstance(bottom, leaftools.Leaf)
         did_split_leaf = True
         split_point_in_bottom = \
             global_split_point - bottom._get_timespan().start_offset
         left_list, right_list = bottom._split_by_duration(
             split_point_in_bottom,
             fracture_spanners=fracture_spanners,
             tie_split_notes=tie_split_notes,
             )
         right = right_list[0]
         leaf_right_of_split = right
         leaf_left_of_split = left_list[-1]
         duration_crossing_containers = duration_crossing_descendants[:-1]
         if not len(duration_crossing_containers):
             return left_list, right_list
     # if split point falls between leaves
     # then find leaf to immediate right of split point
     # in order to start upward crawl through duration-crossing containers
     else:
         duration_crossing_containers = duration_crossing_descendants[:]
         for leaf in iterationtools.iterate_leaves_in_expr(bottom):
             if leaf._get_timespan().start_offset == global_split_point:
                 leaf_right_of_split = leaf
                 leaf_left_of_split = leaf_right_of_split._get_leaf(-1)
                 break
         else:
             message = 'can not split empty container {!r}.'
             message = message.format(bottom)
             raise Exception(message)
     # find component to right of split that is also immediate child of 
     # last duration-crossing container
     for component in \
         leaf_right_of_split._get_parentage(include_self=True):
         if component._parent is duration_crossing_containers[-1]:
             highest_level_component_right_of_split = component
             break
     else:
         message = 'should we be able to get here?'
         raise ValueError(message)
     # crawl back up through duration-crossing containers and 
     # fracture spanners if requested
     if fracture_spanners:
         start_offset = leaf_right_of_split._get_timespan().start_offset
         for parent in leaf_right_of_split._get_parentage():
             if parent._get_timespan().start_offset == start_offset:
                 for spanner in parent._get_spanners():
                     index = spanner.index(parent)
                     spanner.fracture(index, direction=Left)
             if parent is component:
                 break
     # crawl back up through duration-crossing containers and split each
     previous = highest_level_component_right_of_split
     for duration_crossing_container in \
         reversed(duration_crossing_containers):
         assert isinstance(
             duration_crossing_container, containertools.Container)
         i = duration_crossing_container.index(previous)
         left, right = duration_crossing_container._split_at_index(
             i,
             fracture_spanners=fracture_spanners,
             )
         previous = right
     # NOTE: If tie chain here is convenience, then fusing is good.
     #       If tie chain here is user-given, then fusing is less good.
     #       Maybe later model difference between user tie chains and not.
     left_tie_chain = leaf_left_of_split._get_tie_chain()
     right_tie_chain = leaf_right_of_split._get_tie_chain()
     left_tie_chain._fuse_leaves_by_immediate_parent()
     right_tie_chain._fuse_leaves_by_immediate_parent()
     # reapply tie here if crawl above killed tie applied to leaves
     if did_split_leaf:
         if tie_split_notes and \
             isinstance(leaf_left_of_split, notetools.Note):
             if leaf_left_of_split._get_parentage().root is \
                 leaf_right_of_split._get_parentage().root:
                 leaves_around_split = \
                     (leaf_left_of_split, leaf_right_of_split)
                 selection = selectiontools.ContiguousSelection(
                     leaves_around_split)
                 selection._attach_tie_spanner_to_leaf_pair()
     # return pair of left and right list-wrapped halves of container
     return ([left], [right])
Example #25
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
Example #26
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
def label_leaves_in_expr_with_leaf_durations(
    expr,
    label_durations=True,
    label_written_durations=True,
    markup_direction=Down,
    ):
    r'''Label leaves in expression with leaf durations.
    
    ..  container:: example

        **Example 1.** Label leaves with written durations:

        ::

            >>> tuplet = Tuplet((2, 3), "c'8 d'8 e'8")
            >>> staff = stafftools.RhythmicStaff([tuplet])
            >>> staff.override.text_script.staff_padding = 2.5
            >>> staff.override.time_signature.stencil = False
            >>> labeltools.label_leaves_in_expr_with_leaf_durations(
            ...     tuplet, 
            ...     label_durations=False,
            ...     label_written_durations=True)

        ::

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

        ..  doctest::

            >>> f(staff)
            \new RhythmicStaff \with {
                \override TextScript #'staff-padding = #2.5
                \override TimeSignature #'stencil = ##f
            } {
                \times 2/3 {
                    c'8 _ \markup { \small 1/8 }
                    d'8 _ \markup { \small 1/8 }
                    e'8 _ \markup { \small 1/8 }
                }
            }

    ..  container:: example
    
        **Example 2.** Label leaves with actual durations:

        ::

            >>> tuplet = Tuplet((2, 3), "c'8 d'8 e'8")
            >>> staff = stafftools.RhythmicStaff([tuplet])
            >>> staff.override.text_script.staff_padding = 2.5
            >>> staff.override.time_signature.stencil = False
            >>> labeltools.label_leaves_in_expr_with_leaf_durations(
            ...     tuplet, 
            ...     label_durations=True,
            ...     label_written_durations=False)

        ::

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

        ..  doctest::

            >>> f(staff)
            \new RhythmicStaff \with {
                \override TextScript #'staff-padding = #2.5
                \override TimeSignature #'stencil = ##f
            } {
                \times 2/3 {
                    c'8 _ \markup { \small 1/12 }
                    d'8 _ \markup { \small 1/12 }
                    e'8 _ \markup { \small 1/12 }
                }
            }

    ..  container:: example

        **Example 3.** Label leaves in tuplet with both written and actual
        durations:

        ::

            >>> tuplet = Tuplet((2, 3), "c'8 d'8 e'8")
            >>> staff = stafftools.RhythmicStaff([tuplet])
            >>> staff.override.text_script.staff_padding = 2.5
            >>> staff.override.time_signature.stencil = False
            >>> labeltools.label_leaves_in_expr_with_leaf_durations(
            ...     tuplet, 
            ...     label_durations=True,
            ...     label_written_durations=True)

        ::

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

        ..  doctest::

            >>> f(staff)
            \new RhythmicStaff \with {
                \override TextScript #'staff-padding = #2.5
                \override TimeSignature #'stencil = ##f
            } {
                \times 2/3 {
                    c'8 _ \markup { \column { \small 1/8 \small 1/12 } }
                    d'8 _ \markup { \column { \small 1/8 \small 1/12 } }
                    e'8 _ \markup { \column { \small 1/8 \small 1/12 } }
                }
            }

    Returns none.
    '''

    spanner_classes = (spannertools.TieSpanner,)
    for leaf in iterationtools.iterate_leaves_in_expr(expr):
        tie_spanners = leaf._get_spanners(spanner_classes)
        if not tie_spanners:
            if leaf.lilypond_duration_multiplier is not None:
                multiplier = '* %s' % str(leaf.lilypond_duration_multiplier)
            else:
                multiplier = ''
            if label_written_durations:
                label = markuptools.MarkupCommand(
                    'small', '{}{}'.format(
                        str(leaf.written_duration), multiplier))
                markup = markuptools.Markup(label, markup_direction)
                attach(markup, leaf)
            if label_durations:
                label = markuptools.MarkupCommand(
                    'small', str(leaf._get_duration()))
                markup = markuptools.Markup(label, markup_direction)
                attach(markup, leaf)
        elif tuple(tie_spanners)[0]._is_my_first_leaf(leaf):
            tie = tie_spanners.pop()
            if label_written_durations:
                written = sum([x.written_duration for x in tie])
                label = markuptools.MarkupCommand('small', str(written))
                markup = markuptools.Markup(label, markup_direction)
                attach(markup, leaf)
            if label_durations:
                prolated = sum([x._get_duration() for x in tie])
                label = markuptools.MarkupCommand('small', str(prolated))
                markup = markuptools.Markup(label, markup_direction)
                attach(markup, leaf)