Ejemplo n.º 1
0
 def _get_logical_tie(self):
     from abjad.tools import selectiontools
     from abjad.tools import spannertools
     prototype = (spannertools.Tie, )
     for component in self._get_parentage():
         tie_spanners = component._get_spanners(prototype)
         if len(tie_spanners) == 1:
             tie_spanner = tie_spanners.pop()
             return selectiontools.LogicalTie(music=tie_spanner._leaves)
         elif 1 < len(tie_spanners):
             message = 'multiple tie spanners found.'
             raise ExtraSpannerError(message)
     else:
         return selectiontools.LogicalTie(music=self)
Ejemplo n.º 2
0
 def _get_logical_tie(self):
     from abjad.tools import selectiontools
     from abjad.tools import spannertools
     prototype = (spannertools.Tie, )
     for component in self._get_parentage():
         tie_spanners = component._get_spanners(prototype)
         if len(tie_spanners) == 1:
             tie_spanner = tie_spanners.pop()
             return selectiontools.LogicalTie(
                 music=tie_spanner._get_leaves())
         elif 1 < len(tie_spanners):
             message = 'parentage of {!r} contains {} tie spanners.'
             message = message.format(self, len(tie_spanners))
             raise Exception(message)
     else:
         return selectiontools.LogicalTie(music=self)
Ejemplo n.º 3
0
    def __call__(self, argument):
        r'''Calls naive attack-point optimizer.

        Returns none.
        '''
        for logical_tie in iterate(argument).by_logical_tie(reverse=True):
            sub_logical_ties = []
            current_sub_logical_tie = []
            for leaf in logical_tie:
                tempos = leaf._get_indicators(indicatortools.MetronomeMark)
                if tempos:
                    if current_sub_logical_tie:
                        current_sub_logical_tie = \
                            selectiontools.LogicalTie(current_sub_logical_tie)
                        sub_logical_ties.append(current_sub_logical_tie)
                    current_sub_logical_tie = []
                current_sub_logical_tie.append(leaf)
            if current_sub_logical_tie:
                current_sub_logical_tie = selectiontools.LogicalTie(current_sub_logical_tie)
                sub_logical_ties.append(current_sub_logical_tie)
            for sub_logical_tie in sub_logical_ties:
                sub_logical_tie._fuse_leaves_by_immediate_parent()
Ejemplo n.º 4
0
    def __call__(self, logical_ties):
        r'''Calls hairpin handler on `logical_ties`.

        Passes silently when `logical_ties` is empty.

        Returns none.
        '''
        if not logical_ties:
            return
        if not isinstance(logical_ties[0], selectiontools.LogicalTie):
            assert isinstance(logical_ties[0], scoretools.Leaf)
            logical_ties = [selectiontools.LogicalTie(_) for _ in logical_ties]
        if (self.span == 'contiguous notes and chords'
            or isinstance(self.span, (tuple, list))):
            groups = self._group_contiguous_logical_ties(logical_ties)
        elif self.span == 'nontrivial ties':
            groups = [[_] for _ in logical_ties]
        else:
            raise ValueError(self.span)
        if isinstance(self.span, (tuple, list)):
            if not self.enchain_hairpins:
                groups = self._partition_groups(groups)
            else:
                groups = self._partition_enchained_groups(groups)
        hairpin_tokens = self.hairpin_tokens
        for group_index, group in enumerate(groups):
            notes = []
            for logical_tie in group:
                for note in logical_tie:
                    notes.append(note)
            if len(notes) == 0:
                continue
            total_notes = len(notes)
            notes_to_span = []
            for note_index, note in enumerate(notes):
                if self._index_matches_patterns(note_index, total_notes):
                    notes_to_span.append(note)
            if not notes_to_span:
                continue
            if self.include_following_rests:
                last_note = notes_to_span[-1]
                next_leaf = inspect_(last_note).get_leaf(1)
                prototype = (scoretools.Rest, scoretools.MultimeasureRest)
                if isinstance(next_leaf, prototype):
                    notes_to_span.append(next_leaf)
            if len(notes_to_span) == 1 and self.omit_lone_note_dynamic:
                continue
            if len(notes_to_span) == 1 and not self.omit_lone_note_dynamic:
                hairpin_token = hairpin_tokens[group_index]
                start_dynamic = hairpin_token[0]
                if start_dynamic == 'niente':
                    message = 'can not attach niente dynamics to components.'
                    raise Exception(message)
                dynamic = indicatortools.Dynamic(start_dynamic)
                attach(dynamic, notes[0])
                continue
            hairpin_token = hairpin_tokens[group_index]
            if hairpin_token is None:
                continue
            if isinstance(hairpin_token, tuple):
                descriptor = ' '.join([_ for _ in hairpin_token if _])
                include_rests = bool(self.include_following_rests)
                hairpin = spannertools.Hairpin(
                    descriptor=descriptor,
                    include_rests=include_rests,
                    )
                attach(hairpin, notes_to_span)
            # hook to allow callable custom classes like SwellSpecifier
            else:
                hairpin_token(notes_to_span)
            if self.flare:
                first_note = notes_to_span[0]
                prototype = scoretools.Note
                assert isinstance(first_note, prototype), repr(first_note)
                stencil = schemetools.Scheme('flared-hairpin')
                override(first_note).hairpin.stencil = stencil
Ejemplo n.º 5
0
    def iterate_rewrite_inputs(expr):
        r'''Iterates topmost masked logical ties, rest groups and containers
        in `expr`, masked by `expr`.

        ::

            >>> from abjad.tools import metertools
            >>> from abjad.tools import scoretools

        ::

            >>> string = "abj: ! 2/4 c'4 d'4 ~ !"
            >>> string += "! 4/4 d'8. r16 r8. e'16 ~ "
            >>> string += "2/3 { e'8 ~ e'8 f'8 ~ } f'4 ~ !"
            >>> string += "! 4/4 f'8 g'8 ~ g'4 a'4 ~ a'8 b'8 ~ !"
            >>> string += "! 2/4 b'4 c''4 !"
            >>> string = string.replace('!', '|')
            >>> staff = scoretools.Staff(string)

        ..  doctest::

            >>> print(format(staff))
            \new Staff {
                {
                    \time 2/4
                    c'4
                    d'4 ~
                }
                {
                    \time 4/4
                    d'8.
                    r16
                    r8.
                    e'16 ~
                    \times 2/3 {
                        e'8 ~
                        e'8
                        f'8 ~
                    }
                    f'4 ~
                }
                {
                    f'8
                    g'8 ~
                    g'4
                    a'4 ~
                    a'8
                    b'8 ~
                }
                {
                    \time 2/4
                    b'4
                    c''4
                }
            }

        ::

            >>> for x in metertools.MeterManager.iterate_rewrite_inputs(
            ...     staff[0]): x
            ...
            LogicalTie(Note("c'4"),)
            LogicalTie(Note("d'4"),)

        ::

            >>> for x in metertools.MeterManager.iterate_rewrite_inputs(
            ...     staff[1]): x
            ...
            LogicalTie(Note("d'8."),)
            LogicalTie(Rest('r16'), Rest('r8.'))
            LogicalTie(Note("e'16"),)
            Tuplet(Multiplier(2, 3), "e'8 ~ e'8 f'8 ~")
            LogicalTie(Note("f'4"),)

        ::

            >>> for x in metertools.MeterManager.iterate_rewrite_inputs(
            ...     staff[2]): x
            ...
            LogicalTie(Note("f'8"),)
            LogicalTie(Note("g'8"), Note("g'4"))
            LogicalTie(Note("a'4"), Note("a'8"))
            LogicalTie(Note("b'8"),)

        ::

            >>> for x in metertools.MeterManager.iterate_rewrite_inputs(
            ...     staff[3]): x
            ...
            LogicalTie(Note("b'4"),)
            LogicalTie(Note("c''4"),)

        Returns generator.
        '''
        from abjad.tools import scoretools
        from abjad.tools import selectiontools
        from abjad.tools import spannertools

        last_tie_spanner = None
        current_leaf_group = None
        current_leaf_group_is_silent = False

        for x in expr:
            if isinstance(x, (scoretools.Note, scoretools.Chord)):
                this_tie_spanner = x._get_spanners(spannertools.Tie) or None
                if current_leaf_group is None:
                    current_leaf_group = []
                elif current_leaf_group_is_silent or \
                    this_tie_spanner is None or \
                    last_tie_spanner != this_tie_spanner:
                    yield selectiontools.LogicalTie(current_leaf_group)
                    current_leaf_group = []
                current_leaf_group_is_silent = False
                current_leaf_group.append(x)
                last_tie_spanner = this_tie_spanner
            elif isinstance(x, (scoretools.Rest, scoretools.Skip)):
                if current_leaf_group is None:
                    current_leaf_group = []
                elif not current_leaf_group_is_silent:
                    yield selectiontools.LogicalTie(current_leaf_group)
                    current_leaf_group = []
                current_leaf_group_is_silent = True
                current_leaf_group.append(x)
                last_tie_spanner = None
            elif isinstance(x, scoretools.Container):
                if current_leaf_group is not None:
                    yield selectiontools.LogicalTie(current_leaf_group)
                    current_leaf_group = None
                    last_tie_spanner = None
                yield x

            else:
                message = 'unhandled component: {!r}.'
                message = message.format(x)
                raise Exception(message)
        if current_leaf_group is not None:
            yield selectiontools.LogicalTie(current_leaf_group)
Ejemplo n.º 6
0
    def recurse(
        boundary_depth=None,
        boundary_offsets=None,
        depth=0,
        logical_tie=None,
    ):
        offsets = metertools.MeterManager.get_offsets_at_depth(
            depth,
            offset_inventory,
        )

        #print('DEPTH:', depth)

        logical_tie_duration = logical_tie._preprolated_duration
        logical_tie_timespan = logical_tie.get_timespan()
        logical_tie_start_offset = logical_tie_timespan.start_offset
        logical_tie_stop_offset = logical_tie_timespan.stop_offset
        logical_tie_starts_in_offsets = logical_tie_start_offset in offsets
        logical_tie_stops_in_offsets = logical_tie_stop_offset in offsets

        if not metertools.MeterManager.is_acceptable_logical_tie(
                logical_tie_duration=logical_tie_duration,
                logical_tie_starts_in_offsets=logical_tie_starts_in_offsets,
                logical_tie_stops_in_offsets=logical_tie_stops_in_offsets,
                maximum_dot_count=maximum_dot_count,
        ):

            #print('UNACCEPTABLE:', logical_tie, logical_tie_start_offset, logical_tie_stop_offset)
            #print('\t', ' '.join([str(x) for x in offsets]))
            split_offset = None
            offsets = metertools.MeterManager.get_offsets_at_depth(
                depth,
                offset_inventory,
            )

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

            for offset in offsets:
                if logical_tie_start_offset < offset < logical_tie_stop_offset:
                    split_offset = offset
                    break

            #print('\tABS:', split_offset)
            if split_offset is not None:
                split_offset -= logical_tie_start_offset
                #print('\tREL:', split_offset)
                #print()
                shards = mutate(logical_tie[:]).split(
                    [split_offset],
                    use_messiaen_style_ties=use_messiaen_style_ties,
                )
                logical_ties = \
                    [selectiontools.LogicalTie(shard) for shard in shards]
                for logical_tie in logical_ties:
                    recurse(
                        boundary_depth=boundary_depth,
                        boundary_offsets=boundary_offsets,
                        depth=depth,
                        logical_tie=logical_tie,
                    )
            else:
                #print()
                recurse(
                    boundary_depth=boundary_depth,
                    boundary_offsets=boundary_offsets,
                    depth=depth + 1,
                    logical_tie=logical_tie,
                )

        elif metertools.MeterManager.is_boundary_crossing_logical_tie(
                boundary_depth=boundary_depth,
                boundary_offsets=boundary_offsets,
                logical_tie_start_offset=logical_tie_start_offset,
                logical_tie_stop_offset=logical_tie_stop_offset,
        ):

            #print('BOUNDARY CROSSING', logical_tie, logical_tie_start_offset, logical_tie_stop_offset)
            offsets = boundary_offsets
            if logical_tie_start_offset in boundary_offsets:
                offsets = reversed(boundary_offsets)
            split_offset = None
            for offset in offsets:
                if logical_tie_start_offset < offset < logical_tie_stop_offset:
                    split_offset = offset
                    break
            assert split_offset is not None
            #print('\tABS:', split_offset)
            split_offset -= logical_tie_start_offset
            #print('\tREL:', split_offset)
            #print()
            shards = mutate(logical_tie[:]).split(
                [split_offset],
                use_messiaen_style_ties=use_messiaen_style_ties,
            )
            logical_ties = \
                [selectiontools.LogicalTie(shard) for shard in shards]
            for logical_tie in logical_ties:
                recurse(
                    boundary_depth=boundary_depth,
                    boundary_offsets=boundary_offsets,
                    depth=depth,
                    logical_tie=logical_tie,
                )

        else:
            #print('ACCEPTABLE:', logical_tie, logical_tie_start_offset, logical_tie_stop_offset)
            #print('\t', ' '.join([str(x) for x in offsets]))
            #print()
            logical_tie[:]._fuse()