Ejemplo n.º 1
0
 def _split_simultaneous_by_duration(
     self,
     duration,
     tie_split_notes=True,
     repeat_ties=False,
     ):
     assert self.is_simultaneous
     left_components, right_components = [], []
     for component in self[:]:
         halves = component._split_by_duration(
             duration=duration,
             tie_split_notes=tie_split_notes,
             repeat_ties=repeat_ties,
             )
         left_components_, right_components_ = halves
         left_components.extend(left_components_)
         right_components.extend(right_components_)
     left_components = select(left_components)
     right_components = select(right_components)
     left_container = self.__copy__()
     right_container = self.__copy__()
     left_container.extend(left_components)
     right_container.extend(right_components)
     if inspect(self).parentage().parent is not None:
         containers = select([left_container, right_container])
         mutate(self).replace(containers)
     # return list-wrapped halves of container
     return [left_container], [right_container]
Ejemplo n.º 2
0
 def _split_simultaneous_by_duration(
     self, duration, tie_split_notes=True, repeat_ties=False
 ):
     assert self.is_simultaneous
     left_components, right_components = [], []
     for component in self[:]:
         halves = component._split_by_duration(
             duration=duration,
             tie_split_notes=tie_split_notes,
             repeat_ties=repeat_ties,
         )
         left_components_, right_components_ = halves
         left_components.extend(left_components_)
         right_components.extend(right_components_)
     left_components = select(left_components)
     right_components = select(right_components)
     left_container = self.__copy__()
     right_container = self.__copy__()
     left_container.extend(left_components)
     right_container.extend(right_components)
     if inspect(self).parentage().parent is not None:
         containers = select([left_container, right_container])
         mutate(self).replace(containers)
     # return list-wrapped halves of container
     return [left_container], [right_container]
Ejemplo n.º 3
0
    def _set_duration(self, new_duration):
        from .Chord import Chord
        from .Note import Note
        from .NoteMaker import NoteMaker
        from .Tuplet import Tuplet
        from abjad.spanners import tie as abjad_tie

        new_duration = Duration(new_duration)
        if self.multiplier is not None:
            multiplier = new_duration.__div__(self.written_duration)
            self.multiplier = multiplier
            return select(self)
        try:
            self.written_duration = new_duration
            return select(self)
        except exceptions.AssignabilityError:
            pass
        maker = NoteMaker()
        components = maker(0, new_duration)
        new_leaves = select(components).leaves()
        following_leaf_count = len(new_leaves) - 1
        following_leaves = following_leaf_count * self
        all_leaves = [self] + following_leaves
        for leaf, new_leaf in zip(all_leaves, new_leaves):
            leaf.written_duration = new_leaf.written_duration
        logical_tie = self._get_logical_tie()
        logical_tie_leaves = list(logical_tie.leaves)
        for leaf in logical_tie:
            detach(Tie, leaf)
            detach(RepeatTie, leaf)
        if self._parent is not None:
            index = self._parent.index(self)
            next_ = index + 1
            self._parent[next_:next_] = following_leaves
        index = logical_tie_leaves.index(self)
        next_ = index + 1
        logical_tie_leaves[next_:next_] = following_leaves
        if 1 < len(logical_tie_leaves) and isinstance(self, (Note, Chord)):
            abjad_tie(logical_tie_leaves)
        if isinstance(components[0], Leaf):
            return select(all_leaves)
        else:
            assert isinstance(components[0], Tuplet)
            assert len(components) == 1
            tuplet = components[0]
            multiplier = tuplet.multiplier
            tuplet = Tuplet(multiplier, [])
            mutate(all_leaves).wrap(tuplet)
            return select(tuplet)
Ejemplo n.º 4
0
Archivo: Leaf.py Proyecto: Abjad/abjad
    def _set_duration(self, new_duration, repeat_ties=False):
        from .Chord import Chord
        from .Note import Note
        from .NoteMaker import NoteMaker
        from .Tuplet import Tuplet
        from abjad.spanners import tie as abjad_tie

        new_duration = Duration(new_duration)
        if self.multiplier is not None:
            multiplier = new_duration.__div__(self.written_duration)
            self.multiplier = multiplier
            return select(self)
        try:
            self.written_duration = new_duration
            return select(self)
        except exceptions.AssignabilityError:
            pass
        maker = NoteMaker(repeat_ties=repeat_ties)
        components = maker(0, new_duration)
        new_leaves = select(components).leaves()
        following_leaf_count = len(new_leaves) - 1
        following_leaves = following_leaf_count * self
        all_leaves = [self] + following_leaves
        for leaf, new_leaf in zip(all_leaves, new_leaves):
            leaf.written_duration = new_leaf.written_duration
        logical_tie = self._get_logical_tie()
        logical_tie_leaves = list(logical_tie.leaves)
        for leaf in logical_tie:
            detach(TieIndicator, leaf)
            detach(RepeatTie, leaf)
        if self._parent is not None:
            index = self._parent.index(self)
            next_ = index + 1
            self._parent[next_:next_] = following_leaves
        index = logical_tie_leaves.index(self)
        next_ = index + 1
        logical_tie_leaves[next_:next_] = following_leaves
        if 1 < len(logical_tie_leaves) and isinstance(self, (Note, Chord)):
            abjad_tie(logical_tie_leaves)
        if isinstance(components[0], Leaf):
            return select(all_leaves)
        else:
            assert isinstance(components[0], Tuplet)
            assert len(components) == 1
            tuplet = components[0]
            multiplier = tuplet.multiplier
            tuplet = Tuplet(multiplier, [])
            mutate(all_leaves).wrap(tuplet)
            return select(tuplet)
Ejemplo n.º 5
0
    def __mul__(self, n):
        """
        Copies component `n` times and detaches spanners.

        Returns list of new components.
        """
        components = []
        for i in range(n):
            component = mutate(self).copy()
            components.append(component)
        result = select(components)
        return result
Ejemplo n.º 6
0
    def __mul__(self, n):
        """
        Copies component `n` times and detaches spanners.

        Returns list of new components.
        """
        components = []
        for i in range(n):
            component = mutate(self).copy()
            components.append(component)
        result = select(components)
        return result
Ejemplo n.º 7
0
    def _add_or_remove_notes_to_achieve_written_duration(
            self, new_written_duration):
        from abjad.spanners import tie as abjad_tie
        from .NoteMaker import NoteMaker
        from .Tuplet import Tuplet

        new_written_duration = Duration(new_written_duration)
        maker = NoteMaker()
        if new_written_duration.is_assignable:
            self[0].written_duration = new_written_duration
            for leaf in self[1:]:
                mutate(leaf).extract()
            detach(Tie, self[0])
            detach(RepeatTie, self[0])
        elif new_written_duration.has_power_of_two_denominator:
            durations = maker(0, [new_written_duration])
            for leaf, token in zip(self, durations):
                leaf.written_duration = token.written_duration
            if len(self) == len(durations):
                pass
            elif len(durations) < len(self):
                for leaf in self[len(durations):]:
                    mutate(leaf).extract()
            elif len(self) < len(durations):
                # detach(Tie, self[0])
                detach(Tie, self[0])
                detach(RepeatTie, self[0])
                difference = len(durations) - len(self)
                extra_leaves = self[0] * difference
                for extra_leaf in extra_leaves:
                    # detach(Tie, extra_leaf)
                    detach(Tie, extra_leaf)
                    detach(RepeatTie, extra_leaf)
                extra_tokens = durations[len(self):]
                for leaf, token in zip(extra_leaves, extra_tokens):
                    leaf.written_duration = token.written_duration
                parent = inspect(self[-1]).parentage().parent
                index = parent.index(self[-1])
                next_ = index + 1
                parent[next_:next_] = extra_leaves
                leaves = self.leaves + extra_leaves
                # attach(Tie(), leaves)
                abjad_tie(leaves)
        else:
            components = maker(0, new_written_duration)
            assert isinstance(components[0], Tuplet)
            tuplet = components[0]
            logical_tie = tuplet[0]._get_logical_tie()
            duration = logical_tie._get_preprolated_duration()
            leaves_ = self._add_or_remove_notes_to_achieve_written_duration(
                duration)
            multiplier = tuplet.multiplier
            tuplet = Tuplet(multiplier, [])
            # mutate(self.leaves).wrap(tuplet)
            mutate(leaves_).wrap(tuplet)

        return self[0]._get_logical_tie()
Ejemplo n.º 8
0
    def _split_at_index(self, i):
        """
        Splits container to the left of index ``i``.

        Preserves tuplet multiplier when container is a tuplet.

        Preserves time signature denominator when container is a measure.

        Resizes resizable containers.

        Returns split parts.
        """
        from .Tuplet import Tuplet

        # partition my components
        left_components = self[:i]
        right_components = self[i:]
        # instantiate new left and right containers
        if isinstance(self, Tuplet):
            multiplier = self.multiplier
            left = type(self)(multiplier, [])
            mutate(left_components).wrap(left)
            right = type(self)(multiplier, [])
            mutate(right_components).wrap(right)
        else:
            left = self.__copy__()
            mutate(left_components).wrap(left)
            right = self.__copy__()
            mutate(right_components).wrap(right)
        # save left and right containers together for iteration
        halves = (left, right)
        nonempty_halves = [half for half in halves if len(half)]
        # incorporate left and right parents in score if possible
        selection = select(self)
        parent, start, stop = selection._get_parent_and_start_stop_indices()
        if parent is not None:
            parent._components.__setitem__(
                slice(start, stop + 1), nonempty_halves
            )
            for part in nonempty_halves:
                part._set_parent(parent)
        else:
            left._set_parent(None)
            right._set_parent(None)
        # return new left and right containers
        return halves
Ejemplo n.º 9
0
    def _match_anchor_leaf(self):
        from .Chord import Chord
        from .Note import Note

        first_grace = abjad_inspect(self).leaf(0)
        if not isinstance(first_grace, (Note, Chord)):
            message = f"must start with note or chord:\n"
            message += f"    {repr(self)}"
            raise Exception(message)
        anchor_leaf = self._get_on_beat_anchor_leaf()
        if isinstance(anchor_leaf,
                      (Note, Chord)) and isinstance(first_grace,
                                                    (Note, Chord)):
            if isinstance(first_grace, Note):
                chord = Chord(first_grace)
                mutate(first_grace).replace(chord)
                first_grace = chord
            anchor_pitches = abjad_inspect(anchor_leaf).pitches()
            highest_pitch = list(sorted(anchor_pitches))[-1]
            if highest_pitch not in first_grace.note_heads:
                first_grace.note_heads.append(highest_pitch)
            grace_mate_head = first_grace.note_heads.get(highest_pitch)
            tweak(grace_mate_head).font_size = 0
            tweak(grace_mate_head).transparent = True
Ejemplo n.º 10
0
    def _split_at_index(self, i):
        """
        Splits container to the left of index ``i``.

        Preserves tuplet multiplier when container is a tuplet.

        Preserves time signature denominator when container is a measure.

        Resizes resizable containers.

        Returns split parts.
        """
        from .Tuplet import Tuplet

        # partition my components
        left_components = self[:i]
        right_components = self[i:]
        # instantiate new left and right containers
        if isinstance(self, Tuplet):
            multiplier = self.multiplier
            left = type(self)(multiplier, [])
            mutate(left_components).wrap(left)
            right = type(self)(multiplier, [])
            mutate(right_components).wrap(right)
        else:
            left = self.__copy__()
            mutate(left_components).wrap(left)
            right = self.__copy__()
            mutate(right_components).wrap(right)
        # save left and right containers together for iteration
        halves = (left, right)
        nonempty_halves = [half for half in halves if len(half)]
        # incorporate left and right parents in score if possible
        selection = select(self)
        parent, start, stop = selection._get_parent_and_start_stop_indices()
        if parent is not None:
            parent._components.__setitem__(slice(start, stop + 1),
                                           nonempty_halves)
            for part in nonempty_halves:
                part._set_parent(parent)
        else:
            left._set_parent(None)
            right._set_parent(None)
        # return new left and right containers
        return halves
Ejemplo n.º 11
0
    def to_tuplet(self, proportions):
        r"""
        Changes logical tie to tuplet.

        ..  container:: example

            >>> staff = abjad.Staff(r"df'8 c'8 ~ c'16 cqs''4")
            >>> abjad.attach(abjad.Dynamic('p'), staff[0])
            >>> abjad.attach(abjad.HairpinIndicator('<'), staff[0])
            >>> abjad.attach(abjad.Dynamic('f'), staff[-1])
            >>> abjad.override(staff).dynamic_line_spanner.staff_padding = 3
            >>> time_signature = abjad.TimeSignature((9, 16))
            >>> abjad.attach(time_signature, staff[0])
            >>> abjad.show(staff) # doctest: +SKIP

            ..  docs::

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

            >>> logical_tie = abjad.inspect(staff[1]).logical_tie()
            >>> logical_tie.to_tuplet([2, 1, 1, 1])
            Tuplet(Multiplier(3, 5), "c'8 c'16 c'16 c'16")

            ..  docs::

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

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

        ..  container:: example

            >>> staff = abjad.Staff(r"c'8 ~ c'16 cqs''4")
            >>> abjad.hairpin('p < f', staff[:])
            >>> abjad.override(staff).dynamic_line_spanner.staff_padding = 3
            >>> time_signature = abjad.TimeSignature((7, 16))
            >>> abjad.attach(time_signature, staff[0])
            >>> abjad.show(staff) # doctest: +SKIP

            ..  docs::

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

        Returns tuplet.
        """
        from .Note import Note
        from .Note import Note
        from .NoteMaker import NoteMaker
        from .Tuplet import Tuplet
        proportions = Ratio(proportions)
        target_duration = self._get_preprolated_duration()
        prolated_duration = target_duration / sum(proportions.numbers)
        basic_written_duration = \
            prolated_duration.equal_or_greater_power_of_two
        written_durations = [
            _ * basic_written_duration for _ in proportions.numbers
            ]
        maker = NoteMaker()
        try:
            notes = [Note(0, _) for _ in written_durations]
        except exceptions.AssignabilityError:
            denominator = target_duration._denominator
            note_durations = [
                Duration(_, denominator)
                for _ in proportions.numbers
                ]
            notes = maker(0, note_durations)
        tuplet = Tuplet.from_duration(target_duration, notes)
        for leaf in self:
            detach(TieIndicator, leaf)
            detach(RepeatTie, leaf)
        mutate(self).replace(tuplet)
        return tuplet
Ejemplo n.º 12
0
    def rhythm(
        class_,
        selections,
        divisions=None,
        attach_lilypond_voice_commands=None,
        implicit_scaling=None,
        pitched_staff=None,
        simultaneous_selections=None,
        time_signatures=None,
        ):
        r"""
        Makes rhythm-styled LilyPond file.

        ..  container:: example

            Makes rhythmic staff:

            >>> divisions = [(3, 4), (4, 8), (1, 4)]
            >>> maker = abjad.NoteMaker()
            >>> selections = [
            ...     maker(6 * [0], [(1, 8)]),
            ...     maker(8 * [0], [(1, 16)]),
            ...     maker(2 * [0], [(1, 8)]),
            ...     ]
            >>> for selection in selections:
            ...     abjad.attach(abjad.Beam(), selection[:])
            ...
            >>> lilypond_file = abjad.LilyPondFile.rhythm(
            ...     selections,
            ...     divisions,
            ...     )
            >>> abjad.show(lilypond_file) # doctest: +SKIP

            ..  docs::

                >>> score = lilypond_file[abjad.Score]
                >>> abjad.f(score)
                \new Score
                <<
                    \new GlobalContext
                    {
                        {   % measure
                            \time 3/4
                            s1 * 3/4
                        }   % measure
                        {   % measure
                            \time 4/8
                            s1 * 1/2
                        }   % measure
                        {   % measure
                            \time 1/4
                            s1 * 1/4
                        }   % measure
                    }
                    \new RhythmicStaff
                    {
                        {   % measure
                            \time 3/4
                            c'8
                            [
                            c'8
                            c'8
                            c'8
                            c'8
                            c'8
                            ]
                        }   % measure
                        {   % measure
                            \time 4/8
                            c'16
                            [
                            c'16
                            c'16
                            c'16
                            c'16
                            c'16
                            c'16
                            c'16
                            ]
                        }   % measure
                        {   % measure
                            \time 1/4
                            c'8
                            [
                            c'8
                            ]
                        }   % measure
                    }
                >>

        ..  container:: example

            Set time signatures explicitly:

            >>> divisions = [(3, 4), (4, 8), (1, 4)]
            >>> maker = abjad.NoteMaker()
            >>> selections = [
            ...     maker(6 * [0], [(1, 8)]),
            ...     maker(8 * [0], [(1, 16)]),
            ...     maker(2 * [0], [(1, 8)]),
            ...     ]
            >>> for selection in selections:
            ...     abjad.attach(abjad.Beam(), selection[:])
            ...
            >>> lilypond_file = abjad.LilyPondFile.rhythm(
            ...     selections,
            ...     [(6, 8), (4, 8), (2, 8)],
            ...     )
            >>> abjad.show(lilypond_file) # doctest: +SKIP

            ..  docs::

                >>> score = lilypond_file[abjad.Score]
                >>> abjad.f(score)
                \new Score
                <<
                    \new GlobalContext
                    {
                        {   % measure
                            \time 6/8
                            s1 * 3/4
                        }   % measure
                        {   % measure
                            \time 4/8
                            s1 * 1/2
                        }   % measure
                        {   % measure
                            \time 2/8
                            s1 * 1/4
                        }   % measure
                    }
                    \new RhythmicStaff
                    {
                        {   % measure
                            \time 6/8
                            c'8
                            [
                            c'8
                            c'8
                            c'8
                            c'8
                            c'8
                            ]
                        }   % measure
                        {   % measure
                            \time 4/8
                            c'16
                            [
                            c'16
                            c'16
                            c'16
                            c'16
                            c'16
                            c'16
                            c'16
                            ]
                        }   % measure
                        {   % measure
                            \time 2/8
                            c'8
                            [
                            c'8
                            ]
                        }   % measure
                    }
                >>

        ..  container:: example

            Makes pitched staff:

            >>> divisions = [(3, 4), (4, 8), (1, 4)]
            >>> maker = abjad.NoteMaker()
            >>> selections = [
            ...     maker(6 * [0], [(1, 8)]),
            ...     maker(8 * [0], [(1, 16)]),
            ...     maker(2 * [0], [(1, 8)]),
            ...     ]
            >>> for selection in selections:
            ...     abjad.attach(abjad.Beam(), selection[:])
            ...
            >>> lilypond_file = abjad.LilyPondFile.rhythm(
            ...     selections,
            ...     divisions,
            ...     pitched_staff=True,
            ...     )
            >>> abjad.show(lilypond_file) # doctest: +SKIP

            ..  docs::

                >>> abjad.f(lilypond_file[abjad.Score])
                \new Score
                <<
                    \new GlobalContext
                    {
                        {   % measure
                            \time 3/4
                            s1 * 3/4
                        }   % measure
                        {   % measure
                            \time 4/8
                            s1 * 1/2
                        }   % measure
                        {   % measure
                            \time 1/4
                            s1 * 1/4
                        }   % measure
                    }
                    \new Staff
                    {
                        {   % measure
                            \time 3/4
                            c'8
                            [
                            c'8
                            c'8
                            c'8
                            c'8
                            c'8
                            ]
                        }   % measure
                        {   % measure
                            \time 4/8
                            c'16
                            [
                            c'16
                            c'16
                            c'16
                            c'16
                            c'16
                            c'16
                            c'16
                            ]
                        }   % measure
                        {   % measure
                            \time 1/4
                            c'8
                            [
                            c'8
                            ]
                        }   % measure
                    }
                >>

        ..  container:: example

            Makes simultaneous voices:

            >>> divisions = [(3, 4), (4, 8), (1, 4)]
            >>> maker = abjad.NoteMaker()
            >>> selections = [
            ...     maker(6 * [0], [(1, 8)]),
            ...     maker(8 * [0], [(1, 16)]),
            ...     maker(2 * [0], [(1, 8)]),
            ...     ]
            >>> for selection in selections:
            ...     abjad.attach(abjad.Beam(), selection[:])
            ...
            >>> for note in abjad.iterate(selections).components(abjad.Note):
            ...     note.written_pitch = abjad.NamedPitch("e'")
            ...
            >>> selection_1 = selections[0] + selections[1] + selections[2]
            >>> selections = [
            ...     maker(12 * [0], [(1, 16)]),
            ...     maker(16 * [0], [(1, 32)]),
            ...     maker(4 * [0], [(1, 16)]),
            ...     ]
            >>> for selection in selections:
            ...     abjad.attach(abjad.Beam(), selection[:])
            ...
            >>> selection_2 = selections[0] + selections[1] + selections[2]
            >>> selections = {
            ...     'Voice 1': selection_1,
            ...     'Voice 2': selection_2,
            ... }
            >>> lilypond_file = abjad.LilyPondFile.rhythm(
            ...     selections,
            ...     divisions,
            ...     )
            >>> voice_1 = lilypond_file['Voice 1']
            >>> abjad.attach(abjad.LilyPondLiteral(r'\voiceOne'), voice_1)
            >>> voice_2 = lilypond_file['Voice 2']
            >>> abjad.attach(abjad.LilyPondLiteral(r'\voiceTwo'), voice_2)
            >>> abjad.show(lilypond_file) # doctest: +SKIP

            ..  docs::

                >>> abjad.f(lilypond_file[abjad.Score])
                \new Score
                <<
                    \new GlobalContext
                    {
                        {   % measure
                            \time 3/4
                            s1 * 3/4
                        }   % measure
                        {   % measure
                            \time 4/8
                            s1 * 1/2
                        }   % measure
                        {   % measure
                            \time 1/4
                            s1 * 1/4
                        }   % measure
                    }
                    \new Staff
                    <<
                        \context Voice = "Voice 1"
                        {
                            \voiceOne
                            e'8
                            [
                            e'8
                            e'8
                            e'8
                            e'8
                            e'8
                            ]
                            e'16
                            [
                            e'16
                            e'16
                            e'16
                            e'16
                            e'16
                            e'16
                            e'16
                            ]
                            e'8
                            [
                            e'8
                            ]
                        }
                        \context Voice = "Voice 2"
                        {
                            \voiceTwo
                            c'16
                            [
                            c'16
                            c'16
                            c'16
                            c'16
                            c'16
                            c'16
                            c'16
                            c'16
                            c'16
                            c'16
                            c'16
                            ]
                            c'32
                            [
                            c'32
                            c'32
                            c'32
                            c'32
                            c'32
                            c'32
                            c'32
                            c'32
                            c'32
                            c'32
                            c'32
                            c'32
                            c'32
                            c'32
                            c'32
                            ]
                            c'16
                            [
                            c'16
                            c'16
                            c'16
                            ]
                        }
                    >>
                >>

        Returns LilyPond file.
        """
        if isinstance(selections, list):
            for selection in selections:
                if not isinstance(selection, Selection):
                    message = f'must be selection: {selection!r}.'
                    raise TypeError(message)
        elif isinstance(selections, dict):
            for selection in selections.values():
                if not isinstance(selection, Selection):
                    message = f'must be selection: {selection!r}.'
                    raise TypeError(message)
        else:
            message = f'must be list or dictionary: {selections!r}.'
            raise TypeError(message)
        score = Score()
        lilypond_file = LilyPondFile.new(
            score,
            includes=['default.ily', 'rhythm-maker-docs.ily'],
            )
        if pitched_staff is None:
            if isinstance(selections, list):
                selections_ = selections
            elif isinstance(selections, dict):
                selections_ = selections.values()
            else:
                raise TypeError(selections)
            for note in iterate(selections_).leaves(Note):
                if note.written_pitch != NamedPitch("c'"):
                    pitched_staff = True
                    break
        if isinstance(selections, list):
            if divisions is None:
                duration = abjad_inspect(selections).duration()
                divisions = [duration]
            time_signatures = time_signatures or divisions
            maker = MeasureMaker(implicit_scaling=implicit_scaling)
            measures = maker(time_signatures)
            if pitched_staff:
                staff = Staff(measures)
            else:
                staff = Staff(measures, lilypond_type='RhythmicStaff')
            selections = sequence(selections).flatten(depth=-1)
            selections_ = copy.deepcopy(selections)
            try:
                agent = mutate(staff)
                measures = agent.replace_measure_contents(selections)
            except StopIteration:
                if pitched_staff:
                    staff = Staff(selections_)
                else:
                    staff = Staff(
                        selections_,
                        lilypond_type='RhythmicStaff',
                        )
        elif isinstance(selections, dict):
            voices = []
            for voice_name in sorted(selections):
                selections_ = selections[voice_name]
                selections_ = sequence(selections_).flatten(depth=-1)
                selections_ = copy.deepcopy(selections_)
                voice = Voice(selections_, name=voice_name)
                if attach_lilypond_voice_commands:
                    voice_name_to_command_string = {
                        'Voice 1': 'voiceOne',
                        'Voice 2': 'voiceTwo',
                        'Voice 3': 'voiceThree',
                        'Voice 4': 'voiceFour',
                        }
                    command_string = voice_name_to_command_string.get(
                        voice_name,
                        )
                    if command_string:
                        command = LilyPondLiteral('\\' + command_string)
                        attach(command, voice)
                voices.append(voice)
            staff = Staff(voices, is_simultaneous=True)
            if divisions is None:
                duration = abjad_inspect(staff).duration()
                divisions = [duration]
        else:
            message = 'must be list or dictionary of selections:'
            message += f' {selections!r}.'
            raise TypeError(message)
        score.append(staff)
        assert isinstance(divisions, collections.Sequence), repr(divisions)
        time_signatures = time_signatures or divisions
        context = Context(lilypond_type='GlobalContext')
        maker = MeasureMaker(implicit_scaling=implicit_scaling)
        measures = maker(time_signatures)
        context.extend(measures)
        score.insert(0, context)
        return lilypond_file
Ejemplo n.º 13
0
    def _split_by_durations(
        self,
        durations,
        cyclic=False,
        tie_split_notes=True,
        repeat_ties=False,
        ):
        from .AfterGraceContainer import AfterGraceContainer
        from .Chord import Chord
        from .GraceContainer import GraceContainer
        from .Note import Note
        from .Selection import Selection
        from .Tuplet import Tuplet
        durations = [Duration(_) for _ in durations]
        durations = Sequence(durations)
        leaf_duration = inspect(self).duration()
        if cyclic:
            durations = durations.repeat_to_weight(leaf_duration)
        if sum(durations) < leaf_duration:
            last_duration = leaf_duration - sum(durations)
            durations = list(durations)
            durations.append(last_duration)
            durations = Sequence(durations)
        durations = durations.truncate(weight=leaf_duration)
        originally_tied = inspect(self).has_indicator(TieIndicator)
        originally_repeat_tied = inspect(self).has_indicator(RepeatTie)
        result_selections = []
        grace_container = self._detach_grace_container()
        after_grace_container = self._detach_after_grace_container()
        leaf_prolation = inspect(self).parentage().prolation
        for duration in durations:
            new_leaf = copy.copy(self)
            preprolated_duration = duration / leaf_prolation
            selection = new_leaf._set_duration(
                preprolated_duration,
                repeat_ties=repeat_ties,
                )
            result_selections.append(selection)
        result_components = Sequence(result_selections).flatten(depth=-1)
        result_components = select(result_components)
        result_leaves = select(result_components).leaves(grace_notes=False)
        assert all(isinstance(_, Selection) for _ in result_selections)
        assert all(isinstance(_, Component) for _ in result_components)
        assert result_leaves.are_leaves()
#        for leaf in result_leaves:
#            detach(Tie, leaf)
        # strip result leaves of all indicators
        for leaf in result_leaves:
            detach(object, leaf)
        # replace leaf with flattened result
        if self._parent is not None:
            mutate(self).replace(result_components)
        # move indicators
        first_result_leaf = result_leaves[0]
        last_result_leaf = result_leaves[-1]
        for indicator in inspect(self).indicators():
            detach(indicator, self)
            direction = getattr(indicator, '_time_orientation', enums.Left)
            if direction is enums.Left:
                attach(indicator, first_result_leaf)
            elif direction == enums.Right:
                attach(indicator, last_result_leaf)
            else:
                raise ValueError(direction)
        # move grace containers
        if grace_container is not None:
            container = grace_container[0]
            assert isinstance(container, GraceContainer), repr(container)
            attach(container, first_result_leaf)
        if after_grace_container is not None:
            container = after_grace_container[0]
            prototype = AfterGraceContainer
            assert isinstance(container, prototype), repr(container)
            attach(container, last_result_leaf)
        if isinstance(result_components[0], Tuplet):
            mutate(result_components).fuse()
        # tie split notes
        if (tie_split_notes and
            isinstance(self, (Note, Chord)) and
            1 < len(result_leaves)):
            result_leaves._attach_tie_to_leaves(repeat_ties=repeat_ties)
        #assert not inspect(result_leaves[0]).has_indicator(RepeatTie)
        detach(RepeatTie, result_leaves[0])
        #assert not inspect(result_leaves[-1]).has_indicator(TieIndicator)
        detach(TieIndicator, result_leaves[-1])
        if originally_repeat_tied:
            tie = RepeatTie()
            attach(tie, result_leaves[0])
        if originally_tied:
            tie = TieIndicator()
            attach(tie, result_leaves[-1])
        assert isinstance(result_leaves, Selection)
        assert all(isinstance(_, Leaf) for _ in result_leaves)
        return result_leaves
Ejemplo n.º 14
0
def on_beat_grace_container(
    contents,
    anchor_voice_selection,
    *,
    anchor_voice_number=2,
    do_not_beam=None,
    do_not_slash=None,
    do_not_slur=None,
    do_not_stop_polyphony=None,
    font_size=-3,
    grace_voice_number=1,
    leaf_duration=None,
):
    r"""
    Makes on-beat grace container and wraps around ``selection``.

    ..  container:: example

        GRACE NOTES ABOVE.

        Note-to-note anchor:

        >>> music_voice = abjad.Voice("c'4 d' e' f'", name="Music_Voice")
        >>> string = "g'8 a' b' c'' d'' c'' b' a' b' c'' d''"
        >>> result = abjad.on_beat_grace_container(
        ...     string, music_voice[1:3], leaf_duration=(1, 30)
        ... )
        >>> staff = abjad.Staff([music_voice])
        >>> abjad.show(staff) # doctest: +SKIP

        ..  docs::

            >>> abjad.f(staff)
            \new Staff
            {
                \context Voice = "Music_Voice"
                {
                    c'4
                    <<
                        \context Voice = "On_Beat_Grace_Container"
                        {
                            \set fontSize = #-3 %! abjad.on_beat_grace_container(1)
                            \slash %! abjad.on_beat_grace_container(2)
                            \voiceOne %! abjad.on_beat_grace_container(3)
                            <
                                \tweak font-size #0
                                \tweak transparent ##t
                                d'
                                g'
                            >8 * 4/15
                            [
                            (
                            a'8 * 4/15
                            b'8 * 4/15
                            c''8 * 4/15
                            d''8 * 4/15
                            c''8 * 4/15
                            b'8 * 4/15
                            a'8 * 4/15
                            b'8 * 4/15
                            c''8 * 4/15
                            d''8 * 4/15
                            )
                            ]
                        }
                        \context Voice = "Music_Voice"
                        {
                            \voiceTwo %! abjad.on_beat_grace_container(4)
                            d'4
                            e'4
                        }
                    >>
                    \oneVoice %! abjad.on_beat_grace_container(5)
                    f'4
                }
            }

        Note-to-chord anchor:

        >>> music_voice = abjad.Voice(
        ...     "<a c'>4 <b d'> <c' e'> <d' f'>", name="Music_Voice"
        ... )
        >>> string = "g'8 a' b' c'' d'' c'' b' a' b' c'' d''"
        >>> result = abjad.on_beat_grace_container(
        ...     string, music_voice[1:3], leaf_duration=(1, 30)
        ... )
        >>> staff = abjad.Staff([music_voice])
        >>> abjad.show(staff) # doctest: +SKIP

        ..  docs::

            >>> abjad.f(staff)
            \new Staff
            {
                \context Voice = "Music_Voice"
                {
                    <a c'>4
                    <<
                        \context Voice = "On_Beat_Grace_Container"
                        {
                            \set fontSize = #-3 %! abjad.on_beat_grace_container(1)
                            \slash %! abjad.on_beat_grace_container(2)
                            \voiceOne %! abjad.on_beat_grace_container(3)
                            <
                                \tweak font-size #0
                                \tweak transparent ##t
                                d'
                                g'
                            >8 * 4/15
                            [
                            (
                            a'8 * 4/15
                            b'8 * 4/15
                            c''8 * 4/15
                            d''8 * 4/15
                            c''8 * 4/15
                            b'8 * 4/15
                            a'8 * 4/15
                            b'8 * 4/15
                            c''8 * 4/15
                            d''8 * 4/15
                            )
                            ]
                        }
                        \context Voice = "Music_Voice"
                        {
                            \voiceTwo %! abjad.on_beat_grace_container(4)
                            <b d'>4
                            <c' e'>4
                        }
                    >>
                    \oneVoice %! abjad.on_beat_grace_container(5)
                    <d' f'>4
                }
            }

        Chord-to-note anchor:

        >>> music_voice = abjad.Voice("c'4 d' e' f'", name="Music_Voice")
        >>> string = "<g' b'>8 a' b' c'' d'' c'' b' a' b' c'' d''"
        >>> result = abjad.on_beat_grace_container(
        ...     string, music_voice[1:3], leaf_duration=(1, 30)
        ... )
        >>> staff = abjad.Staff([music_voice])
        >>> abjad.show(staff) # doctest: +SKIP

        ..  docs::

            >>> abjad.f(staff)
            \new Staff
            {
                \context Voice = "Music_Voice"
                {
                    c'4
                    <<
                        \context Voice = "On_Beat_Grace_Container"
                        {
                            \set fontSize = #-3 %! abjad.on_beat_grace_container(1)
                            \slash %! abjad.on_beat_grace_container(2)
                            \voiceOne %! abjad.on_beat_grace_container(3)
                            <
                                \tweak font-size #0
                                \tweak transparent ##t
                                d'
                                g'
                                b'
                            >8 * 4/15
                            [
                            (
                            a'8 * 4/15
                            b'8 * 4/15
                            c''8 * 4/15
                            d''8 * 4/15
                            c''8 * 4/15
                            b'8 * 4/15
                            a'8 * 4/15
                            b'8 * 4/15
                            c''8 * 4/15
                            d''8 * 4/15
                            )
                            ]
                        }
                        \context Voice = "Music_Voice"
                        {
                            \voiceTwo %! abjad.on_beat_grace_container(4)
                            d'4
                            e'4
                        }
                    >>
                    \oneVoice %! abjad.on_beat_grace_container(5)
                    f'4
                }
            }

        Chord-to-chord anchor:

        >>> music_voice = abjad.Voice(
        ...     "<a c'>4 <b d'> <c' e'> <d' f'>", name="Music_Voice"
        ... )
        >>> string = "<g' b'>8 a' b' c'' d'' c'' b' a' b' c'' d''"
        >>> result = abjad.on_beat_grace_container(
        ...     string, music_voice[1:3], leaf_duration=(1, 30)
        ... )
        >>> staff = abjad.Staff([music_voice])
        >>> abjad.show(staff) # doctest: +SKIP

        ..  docs::

            >>> abjad.f(staff)
            \new Staff
            {
                \context Voice = "Music_Voice"
                {
                    <a c'>4
                    <<
                        \context Voice = "On_Beat_Grace_Container"
                        {
                            \set fontSize = #-3 %! abjad.on_beat_grace_container(1)
                            \slash %! abjad.on_beat_grace_container(2)
                            \voiceOne %! abjad.on_beat_grace_container(3)
                            <
                                \tweak font-size #0
                                \tweak transparent ##t
                                d'
                                g'
                                b'
                            >8 * 4/15
                            [
                            (
                            a'8 * 4/15
                            b'8 * 4/15
                            c''8 * 4/15
                            d''8 * 4/15
                            c''8 * 4/15
                            b'8 * 4/15
                            a'8 * 4/15
                            b'8 * 4/15
                            c''8 * 4/15
                            d''8 * 4/15
                            )
                            ]
                        }
                        \context Voice = "Music_Voice"
                        {
                            \voiceTwo %! abjad.on_beat_grace_container(4)
                            <b d'>4
                            <c' e'>4
                        }
                    >>
                    \oneVoice %! abjad.on_beat_grace_container(5)
                    <d' f'>4
                }
            }

    ..  container:: example

        GRACE NOTES BELOW.

        Note-to-note anchor:

        >>> music_voice = abjad.Voice("c'4 d' e' f'", name="Music_Voice")
        >>> string = "g8 a b c' d' c' b a b c' d'"
        >>> result = abjad.on_beat_grace_container(
        ...     string,
        ...     music_voice[1:3],
        ...     anchor_voice_number=1,
        ...     grace_voice_number=2,
        ...     leaf_duration=(1, 30),
        ... )
        >>> staff = abjad.Staff([music_voice])
        >>> abjad.show(staff) # doctest: +SKIP

        ..  docs::

            >>> abjad.f(staff)
            \new Staff
            {
                \context Voice = "Music_Voice"
                {
                    c'4
                    <<
                        \context Voice = "On_Beat_Grace_Container"
                        {
                            \set fontSize = #-3 %! abjad.on_beat_grace_container(1)
                            \slash %! abjad.on_beat_grace_container(2)
                            \voiceTwo %! abjad.on_beat_grace_container(3)
                            <
                                g
                                \tweak font-size #0
                                \tweak transparent ##t
                                d'
                            >8 * 4/15
                            [
                            (
                            a8 * 4/15
                            b8 * 4/15
                            c'8 * 4/15
                            d'8 * 4/15
                            c'8 * 4/15
                            b8 * 4/15
                            a8 * 4/15
                            b8 * 4/15
                            c'8 * 4/15
                            d'8 * 4/15
                            )
                            ]
                        }
                        \context Voice = "Music_Voice"
                        {
                            \voiceOne %! abjad.on_beat_grace_container(4)
                            d'4
                            e'4
                        }
                    >>
                    \oneVoice %! abjad.on_beat_grace_container(5)
                    f'4
                }
            }

        Note-to-chord anchor:

        >>> music_voice = abjad.Voice(
        ...     "<c' e'>4 <d' f'> <e' g'> <f' a'>", name="Music_Voice"
        ... )
        >>> string = "g8 a b c' d' c' b a b c' d'"
        >>> result = abjad.on_beat_grace_container(
        ...     string,
        ...     music_voice[1:3],
        ...     anchor_voice_number=1,
        ...     grace_voice_number=2,
        ...     leaf_duration=(1, 30),
        ... )
        >>> staff = abjad.Staff([music_voice])
        >>> abjad.show(staff) # doctest: +SKIP

        ..  docs::

            >>> abjad.f(staff)
            \new Staff
            {
                \context Voice = "Music_Voice"
                {
                    <c' e'>4
                    <<
                        \context Voice = "On_Beat_Grace_Container"
                        {
                            \set fontSize = #-3 %! abjad.on_beat_grace_container(1)
                            \slash %! abjad.on_beat_grace_container(2)
                            \voiceTwo %! abjad.on_beat_grace_container(3)
                            <
                                g
                                \tweak font-size #0
                                \tweak transparent ##t
                                f'
                            >8 * 4/15
                            [
                            (
                            a8 * 4/15
                            b8 * 4/15
                            c'8 * 4/15
                            d'8 * 4/15
                            c'8 * 4/15
                            b8 * 4/15
                            a8 * 4/15
                            b8 * 4/15
                            c'8 * 4/15
                            d'8 * 4/15
                            )
                            ]
                        }
                        \context Voice = "Music_Voice"
                        {
                            \voiceOne %! abjad.on_beat_grace_container(4)
                            <d' f'>4
                            <e' g'>4
                        }
                    >>
                    \oneVoice %! abjad.on_beat_grace_container(5)
                    <f' a'>4
                }
            }

        Chord-to-note anchor:

        >>> music_voice = abjad.Voice("c'4 d' e' f'", name="Music_Voice")
        >>> string = "<e g>8 a b c' d' c' b a b c' d'"
        >>> result = abjad.on_beat_grace_container(
        ...     string,
        ...     music_voice[1:3],
        ...     anchor_voice_number=1,
        ...     grace_voice_number=2,
        ...     leaf_duration=(1, 30),
        ... )
        >>> staff = abjad.Staff([music_voice])
        >>> abjad.show(staff) # doctest: +SKIP

        ..  docs::

            >>> abjad.f(staff)
            \new Staff
            {
                \context Voice = "Music_Voice"
                {
                    c'4
                    <<
                        \context Voice = "On_Beat_Grace_Container"
                        {
                            \set fontSize = #-3 %! abjad.on_beat_grace_container(1)
                            \slash %! abjad.on_beat_grace_container(2)
                            \voiceTwo %! abjad.on_beat_grace_container(3)
                            <
                                e
                                g
                                \tweak font-size #0
                                \tweak transparent ##t
                                d'
                            >8 * 4/15
                            [
                            (
                            a8 * 4/15
                            b8 * 4/15
                            c'8 * 4/15
                            d'8 * 4/15
                            c'8 * 4/15
                            b8 * 4/15
                            a8 * 4/15
                            b8 * 4/15
                            c'8 * 4/15
                            d'8 * 4/15
                            )
                            ]
                        }
                        \context Voice = "Music_Voice"
                        {
                            \voiceOne %! abjad.on_beat_grace_container(4)
                            d'4
                            e'4
                        }
                    >>
                    \oneVoice %! abjad.on_beat_grace_container(5)
                    f'4
                }
            }

        Chord-to-chord anchor:

        >>> music_voice = abjad.Voice(
        ...     "<c' e'>4 <d' f'> <e' g'> <f' a'>", name="Music_Voice"
        ... )
        >>> string = "<e g>8 a b c' d' c' b a b c' d'"
        >>> result = abjad.on_beat_grace_container(
        ...     string,
        ...     music_voice[1:3],
        ...     anchor_voice_number=1,
        ...     grace_voice_number=2,
        ...     leaf_duration=(1, 30),
        ... )
        >>> staff = abjad.Staff([music_voice])
        >>> abjad.show(staff) # doctest: +SKIP

        ..  docs::

            >>> abjad.f(staff)
            \new Staff
            {
                \context Voice = "Music_Voice"
                {
                    <c' e'>4
                    <<
                        \context Voice = "On_Beat_Grace_Container"
                        {
                            \set fontSize = #-3 %! abjad.on_beat_grace_container(1)
                            \slash %! abjad.on_beat_grace_container(2)
                            \voiceTwo %! abjad.on_beat_grace_container(3)
                            <
                                e
                                g
                                \tweak font-size #0
                                \tweak transparent ##t
                                f'
                            >8 * 4/15
                            [
                            (
                            a8 * 4/15
                            b8 * 4/15
                            c'8 * 4/15
                            d'8 * 4/15
                            c'8 * 4/15
                            b8 * 4/15
                            a8 * 4/15
                            b8 * 4/15
                            c'8 * 4/15
                            d'8 * 4/15
                            )
                            ]
                        }
                        \context Voice = "Music_Voice"
                        {
                            \voiceOne %! abjad.on_beat_grace_container(4)
                            <d' f'>4
                            <e' g'>4
                        }
                    >>
                    \oneVoice %! abjad.on_beat_grace_container(5)
                    <f' a'>4
                }
            }

    ..  container:: example

        Raises exception when duration of on-beat grace container exceeds
        duration of anchor container:

        >>> music_voice = abjad.Voice("c'4 d' e' f'", name="Music_Voice")
        >>> string = "g'8 a' b' c'' d'' c'' b' a' b' c'' d''"
        >>> result = abjad.on_beat_grace_container(
        ...     string, music_voice[1:2], leaf_duration=(1, 8)
        ... )
        Traceback (most recent call last):
            ...
        Exception: grace Duration(11, 8) exceeds anchor Duration(1, 4).

    """
    from .Container import Container
    from .Selection import Selection
    from .Voice import Voice
    from abjad.spanners import beam
    from abjad.spanners import slur

    def _site(n):
        return Tag(f"abjad.on_beat_grace_container({n})")

    assert isinstance(anchor_voice_selection, Selection)
    if not anchor_voice_selection.are_contiguous_same_parent(
            ignore_before_after_grace=True):
        message = "selection must be contiguous in same parent:\n"
        message += f"   {repr(anchor_voice_selection)}"
        raise Exception(message)
    on_beat_grace_container = OnBeatGraceContainer(contents,
                                                   leaf_duration=leaf_duration)
    if not isinstance(anchor_voice_selection, Selection):
        raise Exception(f"must be selection:\n {repr(anchor_voice_selection)}")
    anchor_leaf = abjad_inspect(anchor_voice_selection).leaf(0)
    anchor_voice = abjad_inspect(anchor_leaf).parentage().get(Voice)
    if anchor_voice.name is None:
        raise Exception(
            f"anchor voice must be named:\n   {repr(anchor_voice)}")
    anchor_voice_insert = Voice(name=anchor_voice.name)
    mutate(anchor_voice_selection).wrap(anchor_voice_insert)
    container = Container(simultaneous=True)
    mutate(anchor_voice_insert).wrap(container)
    container.insert(0, on_beat_grace_container)
    on_beat_grace_container._match_anchor_leaf()
    on_beat_grace_container._set_leaf_durations()
    insert_duration = abjad_inspect(anchor_voice_insert).duration()
    grace_container_duration = abjad_inspect(
        on_beat_grace_container).duration()
    if insert_duration < grace_container_duration:
        message = f"grace {repr(grace_container_duration)}"
        message += f" exceeds anchor {repr(insert_duration)}."
        raise Exception(message)
    if font_size is not None:
        string = rf"\set fontSize = #{font_size}"
        literal = LilyPondLiteral(string)
        attach(literal, on_beat_grace_container, tag=_site(1))
    if not do_not_beam:
        beam(on_beat_grace_container[:])
    if not do_not_slash:
        literal = LilyPondLiteral(r"\slash")
        attach(literal, on_beat_grace_container[0], tag=_site(2))
    if not do_not_slur:
        slur(on_beat_grace_container[:])
    voice_number_to_string = {
        1: r"\voiceOne",
        2: r"\voiceTwo",
        3: r"\voiceThree",
        4: r"\voiceFour",
    }
    first_grace = abjad_inspect(on_beat_grace_container).leaf(0)
    one_voice_literal = LilyPondLiteral(r"\oneVoice",
                                        format_slot="absolute_before")
    string = voice_number_to_string.get(grace_voice_number, None)
    if string is not None:
        literal
        detach(one_voice_literal, anchor_leaf)
        attach(LilyPondLiteral(string), first_grace, tag=_site(3))
    string = voice_number_to_string.get(anchor_voice_number, None)
    if string is not None:
        detach(one_voice_literal, anchor_leaf)
        attach(LilyPondLiteral(string), anchor_leaf, tag=_site(4))
    if not do_not_stop_polyphony:
        last_anchor_leaf = abjad_inspect(anchor_voice_selection).leaf(-1)
        next_leaf = abjad_inspect(last_anchor_leaf).leaf(1)
        if next_leaf is not None:
            literal = LilyPondLiteral(r"\oneVoice",
                                      format_slot="absolute_before")
            attach(literal, next_leaf, tag=_site(5))
    return on_beat_grace_container
Ejemplo n.º 15
0
    def _split_by_durations(self, durations, cyclic=False):
        from .Chord import Chord
        from .Note import Note
        from .Selection import Selection
        from .Tuplet import Tuplet

        durations = [Duration(_) for _ in durations]
        durations = Sequence(durations)
        leaf_duration = inspect(self).duration()
        if cyclic:
            durations = durations.repeat_to_weight(leaf_duration)
        if sum(durations) < leaf_duration:
            last_duration = leaf_duration - sum(durations)
            durations = list(durations)
            durations.append(last_duration)
            durations = Sequence(durations)
        durations = durations.truncate(weight=leaf_duration)
        originally_tied = inspect(self).has_indicator(Tie)
        originally_repeat_tied = inspect(self).has_indicator(RepeatTie)
        result_selections = []
        # detach grace containers
        before_grace_container = self._before_grace_container
        if before_grace_container is not None:
            detach(before_grace_container, self)
        after_grace_container = self._after_grace_container
        if after_grace_container is not None:
            detach(after_grace_container, self)
        # do other things
        leaf_prolation = inspect(self).parentage().prolation
        for duration in durations:
            new_leaf = copy.copy(self)
            preprolated_duration = duration / leaf_prolation
            selection = new_leaf._set_duration(preprolated_duration)
            result_selections.append(selection)
        result_components = Sequence(result_selections).flatten(depth=-1)
        result_components = select(result_components)
        result_leaves = select(result_components).leaves(grace=False)
        assert all(isinstance(_, Selection) for _ in result_selections)
        assert all(isinstance(_, Component) for _ in result_components)
        assert result_leaves.are_leaves()
        # strip result leaves of all indicators
        for leaf in result_leaves:
            detach(object, leaf)
        # replace leaf with flattened result
        if inspect(self).parentage().parent is not None:
            mutate(self).replace(result_components)
        # move indicators
        first_result_leaf = result_leaves[0]
        last_result_leaf = result_leaves[-1]
        for indicator in inspect(self).indicators():
            detach(indicator, self)
            direction = getattr(indicator, "_time_orientation", enums.Left)
            if direction is enums.Left:
                attach(indicator, first_result_leaf)
            elif direction == enums.Right:
                attach(indicator, last_result_leaf)
            else:
                raise ValueError(direction)
        # reattach grace containers
        if before_grace_container is not None:
            attach(before_grace_container, first_result_leaf)
        if after_grace_container is not None:
            attach(after_grace_container, last_result_leaf)
        # fuse tuplets
        if isinstance(result_components[0], Tuplet):
            mutate(result_components).fuse()
        # tie split notes
        if isinstance(self, (Note, Chord)) and 1 < len(result_leaves):
            result_leaves._attach_tie_to_leaves()
        if originally_repeat_tied and not inspect(
                result_leaves[0]).has_indicator(RepeatTie):
            attach(RepeatTie(), result_leaves[0])
        if originally_tied and not inspect(
                result_leaves[-1]).has_indicator(Tie):
            attach(Tie(), result_leaves[-1])
        assert isinstance(result_leaves, Selection)
        assert all(isinstance(_, Leaf) for _ in result_leaves)
        return result_leaves
Ejemplo n.º 16
0
Archivo: Leaf.py Proyecto: Abjad/abjad
    def _split_by_durations(
        self, durations, cyclic=False, tie_split_notes=True, repeat_ties=False
    ):
        from .AfterGraceContainer import AfterGraceContainer
        from .Chord import Chord
        from .GraceContainer import GraceContainer
        from .Note import Note
        from .Selection import Selection
        from .Tuplet import Tuplet

        durations = [Duration(_) for _ in durations]
        durations = Sequence(durations)
        leaf_duration = inspect(self).duration()
        if cyclic:
            durations = durations.repeat_to_weight(leaf_duration)
        if sum(durations) < leaf_duration:
            last_duration = leaf_duration - sum(durations)
            durations = list(durations)
            durations.append(last_duration)
            durations = Sequence(durations)
        durations = durations.truncate(weight=leaf_duration)
        originally_tied = inspect(self).has_indicator(TieIndicator)
        originally_repeat_tied = inspect(self).has_indicator(RepeatTie)
        result_selections = []
        grace_container = self._detach_grace_container()
        after_grace_container = self._detach_after_grace_container()
        leaf_prolation = inspect(self).parentage().prolation
        for duration in durations:
            new_leaf = copy.copy(self)
            preprolated_duration = duration / leaf_prolation
            selection = new_leaf._set_duration(
                preprolated_duration, repeat_ties=repeat_ties
            )
            result_selections.append(selection)
        result_components = Sequence(result_selections).flatten(depth=-1)
        result_components = select(result_components)
        result_leaves = select(result_components).leaves(grace_notes=False)
        assert all(isinstance(_, Selection) for _ in result_selections)
        assert all(isinstance(_, Component) for _ in result_components)
        assert result_leaves.are_leaves()
        #        for leaf in result_leaves:
        #            detach(Tie, leaf)
        # strip result leaves of all indicators
        for leaf in result_leaves:
            detach(object, leaf)
        # replace leaf with flattened result
        if self._parent is not None:
            mutate(self).replace(result_components)
        # move indicators
        first_result_leaf = result_leaves[0]
        last_result_leaf = result_leaves[-1]
        for indicator in inspect(self).indicators():
            detach(indicator, self)
            direction = getattr(indicator, "_time_orientation", enums.Left)
            if direction is enums.Left:
                attach(indicator, first_result_leaf)
            elif direction == enums.Right:
                attach(indicator, last_result_leaf)
            else:
                raise ValueError(direction)
        # move grace containers
        if grace_container is not None:
            container = grace_container[0]
            assert isinstance(container, GraceContainer), repr(container)
            attach(container, first_result_leaf)
        if after_grace_container is not None:
            container = after_grace_container[0]
            prototype = AfterGraceContainer
            assert isinstance(container, prototype), repr(container)
            attach(container, last_result_leaf)
        if isinstance(result_components[0], Tuplet):
            mutate(result_components).fuse()
        # tie split notes
        if (
            tie_split_notes
            and isinstance(self, (Note, Chord))
            and 1 < len(result_leaves)
        ):
            result_leaves._attach_tie_to_leaves(repeat_ties=repeat_ties)
        # assert not inspect(result_leaves[0]).has_indicator(RepeatTie)
        detach(RepeatTie, result_leaves[0])
        # assert not inspect(result_leaves[-1]).has_indicator(TieIndicator)
        detach(TieIndicator, result_leaves[-1])
        if originally_repeat_tied:
            tie = RepeatTie()
            attach(tie, result_leaves[0])
        if originally_tied:
            tie = TieIndicator()
            attach(tie, result_leaves[-1])
        assert isinstance(result_leaves, Selection)
        assert all(isinstance(_, Leaf) for _ in result_leaves)
        return result_leaves