Source code for abjad.iterate

import typing

from . import _iterlib
from . import duration as _duration
from . import pcollections as _pcollections
from . import pitch as _pitch
from . import score as _score
from . import select as _select


@typing.overload
def components(
    argument,
    *,
    exclude=None,
    grace=None,
    reverse=None,
) -> typing.Iterator[_score.Component]:
    ...


@typing.overload
def components(
    argument,
    prototype: typing.Type[_score.Tuplet],
    *,
    exclude=None,
    grace=None,
    reverse=None,
) -> typing.Iterator[_score.Tuplet]:
    ...


@typing.overload
def components(
    argument,
    prototype: typing.Type[_score.Container],
    *,
    exclude=None,
    grace=None,
    reverse=None,
) -> typing.Iterator[_score.Container]:
    ...


@typing.overload
def components(
    argument,
    prototype: typing.Type[_score.Leaf],
    *,
    exclude=None,
    grace=None,
    reverse=None,
) -> typing.Iterator[_score.Leaf]:
    ...


[docs]def components( argument, prototype=None, *, exclude=None, grace=None, reverse=None, ): r""" Iterates components in ``argument``. .. container:: example Grace iteration is controlled by a ternary flag. >>> music_voice = abjad.Voice("c'4 d' e' f'", name="MusicVoice") >>> container = abjad.BeforeGraceContainer("cs'16") >>> abjad.attach(container, music_voice[1]) >>> container = abjad.on_beat_grace_container( ... "g'16 gs' a' as'", music_voice[2:3] ... ) >>> abjad.attach(abjad.Articulation(">"), container[0]) >>> container = abjad.AfterGraceContainer("fs'16") >>> abjad.attach(container, music_voice[3]) >>> staff = abjad.Staff([music_voice]) >>> lilypond_file = abjad.LilyPondFile([r'\include "abjad.ily"', staff]) >>> abjad.show(lilypond_file) # doctest: +SKIP .. docs:: >>> string = abjad.lilypond(staff) >>> print(string) \new Staff { \context Voice = "MusicVoice" { c'4 \grace { cs'16 } d'4 << \context Voice = "On_Beat_Grace_Container" { \set fontSize = #-3 \slash \voiceOne < \tweak font-size 0 \tweak transparent ##t e' g' >16 - \accent [ ( gs'16 a'16 as'16 ) ] } \context Voice = "MusicVoice" { \voiceTwo e'4 } >> \oneVoice \afterGrace f'4 { fs'16 } } } Leave ``grace`` unset to iterate grace and nongrace components together: >>> for component in abjad.iterate.components(staff): ... component Staff("{ c'4 d'4 { { <e' g'>16 gs'16 a'16 as'16 } { e'4 } } f'4 }") Voice("c'4 d'4 { { <e' g'>16 gs'16 a'16 as'16 } { e'4 } } f'4", name='MusicVoice') Note("c'4") BeforeGraceContainer("cs'16") Note("cs'16") Note("d'4") Container("{ <e' g'>16 gs'16 a'16 as'16 } { e'4 }") OnBeatGraceContainer("<e' g'>16 gs'16 a'16 as'16") Chord("<e' g'>16") Note("gs'16") Note("a'16") Note("as'16") Voice("e'4", name='MusicVoice') Note("e'4") Note("f'4") AfterGraceContainer("fs'16") Note("fs'16") >>> for component in abjad.iterate.components(staff, reverse=True): ... component Staff("{ c'4 d'4 { { <e' g'>16 gs'16 a'16 as'16 } { e'4 } } f'4 }") Voice("c'4 d'4 { { <e' g'>16 gs'16 a'16 as'16 } { e'4 } } f'4", name='MusicVoice') AfterGraceContainer("fs'16") Note("fs'16") Note("f'4") Container("{ <e' g'>16 gs'16 a'16 as'16 } { e'4 }") Voice("e'4", name='MusicVoice') Note("e'4") OnBeatGraceContainer("<e' g'>16 gs'16 a'16 as'16") Note("as'16") Note("a'16") Note("gs'16") Chord("<e' g'>16") Note("d'4") BeforeGraceContainer("cs'16") Note("cs'16") Note("c'4") Set ``grace=True`` to iterate only grace components: >>> for component in abjad.iterate.components(staff, grace=True): ... component BeforeGraceContainer("cs'16") Note("cs'16") OnBeatGraceContainer("<e' g'>16 gs'16 a'16 as'16") Chord("<e' g'>16") Note("gs'16") Note("a'16") Note("as'16") AfterGraceContainer("fs'16") Note("fs'16") >>> for component in abjad.iterate.components(staff, grace=True, reverse=True): ... component AfterGraceContainer("fs'16") Note("fs'16") OnBeatGraceContainer("<e' g'>16 gs'16 a'16 as'16") Note("as'16") Note("a'16") Note("gs'16") Chord("<e' g'>16") BeforeGraceContainer("cs'16") Note("cs'16") Set ``grace=False`` to iterate only nongrace components: >>> for component in abjad.iterate.components(staff, grace=False): ... component Staff("{ c'4 d'4 { { <e' g'>16 gs'16 a'16 as'16 } { e'4 } } f'4 }") Voice("c'4 d'4 { { <e' g'>16 gs'16 a'16 as'16 } { e'4 } } f'4", name='MusicVoice') Note("c'4") Note("d'4") Container("{ <e' g'>16 gs'16 a'16 as'16 } { e'4 }") Voice("e'4", name='MusicVoice') Note("e'4") Note("f'4") >>> for component in abjad.iterate.components(staff, grace=False, reverse=True): ... component Staff("{ c'4 d'4 { { <e' g'>16 gs'16 a'16 as'16 } { e'4 } } f'4 }") Voice("c'4 d'4 { { <e' g'>16 gs'16 a'16 as'16 } { e'4 } } f'4", name='MusicVoice') Note("f'4") Container("{ <e' g'>16 gs'16 a'16 as'16 } { e'4 }") Voice("e'4", name='MusicVoice') Note("e'4") Note("d'4") Note("c'4") """ return _iterlib._public_iterate_components( argument, prototype, exclude=exclude, grace=grace, reverse=reverse, )
[docs]def leaves( argument, prototype=None, *, exclude=None, grace=None, pitched=None, reverse=None, ) -> typing.Iterator: r""" Iterates leaves in ``argument``. Set ``exclude=<annotation>`` to exclude leaves with annotation: .. container:: example >>> staff = abjad.Staff() >>> score = abjad.Score([staff], name="Score") >>> staff.extend("<c' bf'>8 <g' a'>8") >>> staff.extend("af'8 r8") >>> staff.extend("r8 gf'8") >>> abjad.attach(abjad.TimeSignature((2, 8)), staff[0]) >>> abjad.attach("RED", staff[0]) >>> abjad.attach("BLUE", staff[1]) >>> abjad.attach("GREEN", staff[2]) >>> abjad.attach("RED", staff[3]) >>> abjad.attach("BLUE", staff[4]) >>> abjad.attach("GREEN", staff[5]) >>> abjad.show(staff) # doctest: +SKIP .. docs:: >>> string = abjad.lilypond(staff) >>> print(string) \new Staff { \time 2/8 <c' bf'>8 <g' a'>8 af'8 r8 r8 gf'8 } >>> for leaf in abjad.iterate.leaves(staff, exclude=['RED', 'BLUE']): ... leaf ... Note("af'8") Note("gf'8") Excludes leaves to which ``'RED'`` or ``'BLUE'`` attaches. .. container:: example Grace iteration is controlled by a ternary flag. >>> music_voice = abjad.Voice("c'4 d' e' f'", name="MusicVoice") >>> container = abjad.BeforeGraceContainer("cs'16") >>> abjad.attach(container, music_voice[1]) >>> container = abjad.on_beat_grace_container( ... "g'16 gs' a' as'", music_voice[2:3] ... ) >>> abjad.attach(abjad.Articulation(">"), container[0]) >>> container = abjad.AfterGraceContainer("fs'16") >>> abjad.attach(container, music_voice[3]) >>> staff = abjad.Staff([music_voice]) >>> lilypond_file = abjad.LilyPondFile([r'\include "abjad.ily"', staff]) >>> abjad.show(lilypond_file) # doctest: +SKIP .. docs:: >>> string = abjad.lilypond(staff) >>> print(string) \new Staff { \context Voice = "MusicVoice" { c'4 \grace { cs'16 } d'4 << \context Voice = "On_Beat_Grace_Container" { \set fontSize = #-3 \slash \voiceOne < \tweak font-size 0 \tweak transparent ##t e' g' >16 - \accent [ ( gs'16 a'16 as'16 ) ] } \context Voice = "MusicVoice" { \voiceTwo e'4 } >> \oneVoice \afterGrace f'4 { fs'16 } } } Leave ``grace`` unset to iterate grace and nongrace leaves together: >>> for leaf in abjad.iterate.leaves(staff): ... leaf Note("c'4") Note("cs'16") Note("d'4") Chord("<e' g'>16") Note("gs'16") Note("a'16") Note("as'16") Note("e'4") Note("f'4") Note("fs'16") Set ``grace=True`` to iterate only grace leaves: >>> for leaf in abjad.iterate.leaves(staff, grace=True): ... leaf Note("cs'16") Chord("<e' g'>16") Note("gs'16") Note("a'16") Note("as'16") Note("fs'16") Set ``grace=False`` to iterate only nongrace leaves: >>> for leaf in abjad.iterate.leaves(staff, grace=False): ... leaf Note("c'4") Note("d'4") Note("e'4") Note("f'4") .. container:: example Pitched iteration is controlled by a ternary flag. >>> staff = abjad.Staff() >>> score = abjad.Score([staff], name="Score") >>> staff.extend("<c' bf'>8 <g' a'>8") >>> staff.extend("af'8 r8") >>> staff.extend("r8 gf'8") >>> abjad.attach(abjad.TimeSignature((2, 8)), staff[0]) >>> abjad.show(staff) # doctest: +SKIP .. docs:: >>> string = abjad.lilypond(staff) >>> print(string) \new Staff { \time 2/8 <c' bf'>8 <g' a'>8 af'8 r8 r8 gf'8 } Leaves ``pitched`` unset to iterate pitched and unpitched leaves together: >>> for leaf in abjad.iterate.leaves(staff): ... leaf ... Chord("<c' bf'>8") Chord("<g' a'>8") Note("af'8") Rest('r8') Rest('r8') Note("gf'8") >>> for leaf in abjad.iterate.leaves(staff, reverse=True): ... leaf Note("gf'8") Rest('r8') Rest('r8') Note("af'8") Chord("<g' a'>8") Chord("<c' bf'>8") Set ``pitched=True`` to iterate pitched leaves only: >>> for leaf in abjad.iterate.leaves(staff, pitched=True): ... leaf ... Chord("<c' bf'>8") Chord("<g' a'>8") Note("af'8") Note("gf'8") >>> for leaf in abjad.iterate.leaves(staff, pitched=True, reverse=True): ... leaf Note("gf'8") Note("af'8") Chord("<g' a'>8") Chord("<c' bf'>8") Set ``pitched=False`` to iterate unpitched leaves only: >>> for leaf in abjad.iterate.leaves(staff, pitched=False): ... leaf ... Rest('r8') Rest('r8') >>> for leaf in abjad.iterate.leaves(staff, pitched=False): ... leaf ... Rest('r8') Rest('r8') """ return _iterlib._public_iterate_leaves( argument, prototype=prototype, exclude=exclude, grace=grace, pitched=pitched, reverse=reverse, )
[docs]def logical_ties( argument, *, exclude=None, grace=None, nontrivial=None, pitched=None, reverse=None, ) -> typing.Iterator[_select.LogicalTie]: r""" Iterates logical ties in ``argument``. Iterates logical ties: .. container:: example >>> string = r"c'4 ~ \times 2/3 { c'16 d'8 } e'8 f'4 ~ f'16" >>> staff = abjad.Staff(string) >>> abjad.show(staff) # doctest: +SKIP .. docs:: >>> string = abjad.lilypond(staff) >>> print(string) \new Staff { c'4 ~ \times 2/3 { c'16 d'8 } e'8 f'4 ~ f'16 } >>> for logical_tie in abjad.iterate.logical_ties(staff): ... logical_tie ... LogicalTie(items=[Note("c'4"), Note("c'16")]) LogicalTie(items=[Note("d'8")]) LogicalTie(items=[Note("e'8")]) LogicalTie(items=[Note("f'4"), Note("f'16")]) .. container:: example Grace iteration is controlled by a ternary flag. >>> music_voice = abjad.Voice("c'4 d' e' f'", name="MusicVoice") >>> container = abjad.BeforeGraceContainer("cs'16") >>> abjad.attach(container, music_voice[1]) >>> container = abjad.on_beat_grace_container( ... "g'16 gs' a' as'", music_voice[2:3] ... ) >>> abjad.attach(abjad.Articulation(">"), container[0]) >>> container = abjad.AfterGraceContainer("fs'16") >>> abjad.attach(container, music_voice[3]) >>> staff = abjad.Staff([music_voice]) >>> lilypond_file = abjad.LilyPondFile([r'\include "abjad.ily"', staff]) >>> abjad.show(lilypond_file) # doctest: +SKIP .. docs:: >>> string = abjad.lilypond(staff) >>> print(string) \new Staff { \context Voice = "MusicVoice" { c'4 \grace { cs'16 } d'4 << \context Voice = "On_Beat_Grace_Container" { \set fontSize = #-3 \slash \voiceOne < \tweak font-size 0 \tweak transparent ##t e' g' >16 - \accent [ ( gs'16 a'16 as'16 ) ] } \context Voice = "MusicVoice" { \voiceTwo e'4 } >> \oneVoice \afterGrace f'4 { fs'16 } } } Leave ``grace`` unset to iterate grace and nongrace logical ties together: >>> for lt in abjad.iterate.logical_ties(staff): ... lt LogicalTie(items=[Note("c'4")]) LogicalTie(items=[Note("cs'16")]) LogicalTie(items=[Note("d'4")]) LogicalTie(items=[Chord("<e' g'>16")]) LogicalTie(items=[Note("gs'16")]) LogicalTie(items=[Note("a'16")]) LogicalTie(items=[Note("as'16")]) LogicalTie(items=[Note("e'4")]) LogicalTie(items=[Note("f'4")]) LogicalTie(items=[Note("fs'16")]) >>> for lt in abjad.iterate.logical_ties(staff, reverse=True): ... lt LogicalTie(items=[Note("fs'16")]) LogicalTie(items=[Note("f'4")]) LogicalTie(items=[Note("e'4")]) LogicalTie(items=[Note("as'16")]) LogicalTie(items=[Note("a'16")]) LogicalTie(items=[Note("gs'16")]) LogicalTie(items=[Chord("<e' g'>16")]) LogicalTie(items=[Note("d'4")]) LogicalTie(items=[Note("cs'16")]) LogicalTie(items=[Note("c'4")]) Set ``grace=True`` to iterate grace logical ties only: >>> for lt in abjad.iterate.logical_ties(staff, grace=True): ... lt LogicalTie(items=[Note("cs'16")]) LogicalTie(items=[Chord("<e' g'>16")]) LogicalTie(items=[Note("gs'16")]) LogicalTie(items=[Note("a'16")]) LogicalTie(items=[Note("as'16")]) LogicalTie(items=[Note("fs'16")]) >>> for lt in abjad.iterate.logical_ties(staff, grace=True, reverse=True): ... lt LogicalTie(items=[Note("fs'16")]) LogicalTie(items=[Note("as'16")]) LogicalTie(items=[Note("a'16")]) LogicalTie(items=[Note("gs'16")]) LogicalTie(items=[Chord("<e' g'>16")]) LogicalTie(items=[Note("cs'16")]) Set ``grace=False`` to iterate nongrace logical ties only: >>> for lt in abjad.iterate.logical_ties(staff, grace=False): ... lt LogicalTie(items=[Note("c'4")]) LogicalTie(items=[Note("d'4")]) LogicalTie(items=[Note("e'4")]) LogicalTie(items=[Note("f'4")]) >>> for lt in abjad.iterate.logical_ties(staff, grace=False, reverse=True): ... lt LogicalTie(items=[Note("f'4")]) LogicalTie(items=[Note("e'4")]) LogicalTie(items=[Note("d'4")]) LogicalTie(items=[Note("c'4")]) .. container:: example Logical tie triviality is controlled by a ternary flag. >>> string = r"c'4 ~ \times 2/3 { c'8 d'4 }" >>> string += r" e'4 ~ \times 2/3 { e'8 f' }" >>> staff = abjad.Staff(string) >>> abjad.show(staff) # doctest: +SKIP .. docs:: >>> string = abjad.lilypond(staff) >>> print(string) \new Staff { c'4 ~ \times 2/3 { c'8 d'4 } e'4 ~ \tweak edge-height #'(0.7 . 0) \times 2/3 { e'8 f'8 } } Leave ``nontrivial`` unset to iterate trivial and nontrivial logical ties together: >>> for lt in abjad.iterate.logical_ties(staff): ... lt LogicalTie(items=[Note("c'4"), Note("c'8")]) LogicalTie(items=[Note("d'4")]) LogicalTie(items=[Note("e'4"), Note("e'8")]) LogicalTie(items=[Note("f'8")]) >>> for lt in abjad.iterate.logical_ties(staff, reverse=True): ... lt LogicalTie(items=[Note("f'8")]) LogicalTie(items=[Note("e'4"), Note("e'8")]) LogicalTie(items=[Note("d'4")]) LogicalTie(items=[Note("c'4"), Note("c'8")]) Set ``nontrivial=True`` to iterate nontrivial logical ties only: >>> for lt in abjad.iterate.logical_ties(staff, nontrivial=True): ... lt LogicalTie(items=[Note("c'4"), Note("c'8")]) LogicalTie(items=[Note("e'4"), Note("e'8")]) >>> for lt in abjad.iterate.logical_ties(staff, nontrivial=True, reverse=True): ... lt LogicalTie(items=[Note("e'4"), Note("e'8")]) LogicalTie(items=[Note("c'4"), Note("c'8")]) Set ``nontrivial=False`` to iterate trivial logical ties only: >>> for lt in abjad.iterate.logical_ties(staff, nontrivial=False): ... lt LogicalTie(items=[Note("d'4")]) LogicalTie(items=[Note("f'8")]) >>> for lt in abjad.iterate.logical_ties(staff, nontrivial=False, reverse=True): ... lt LogicalTie(items=[Note("f'8")]) LogicalTie(items=[Note("d'4")]) .. container:: example Logical tie pitchedness is controlled by a ternary flag. >>> string = r"c'4 ~ \times 2/3 { c'8 r4 }" >>> string += r"d'4 ~ \times 2/3 { d'8 r4 }" >>> staff = abjad.Staff(string) >>> abjad.show(staff) # doctest: +SKIP .. docs:: >>> string = abjad.lilypond(staff) >>> print(string) \new Staff { c'4 ~ \times 2/3 { c'8 r4 } d'4 ~ \times 2/3 { d'8 r4 } } Leave ``pitched`` unset to iterate pitched and unpitched logical ties together: >>> for lt in abjad.iterate.logical_ties(staff): ... lt LogicalTie(items=[Note("c'4"), Note("c'8")]) LogicalTie(items=[Rest('r4')]) LogicalTie(items=[Note("d'4"), Note("d'8")]) LogicalTie(items=[Rest('r4')]) >>> for lt in abjad.iterate.logical_ties(staff, reverse=True): ... lt LogicalTie(items=[Rest('r4')]) LogicalTie(items=[Note("d'4"), Note("d'8")]) LogicalTie(items=[Rest('r4')]) LogicalTie(items=[Note("c'4"), Note("c'8")]) Set ``pitched=True`` to iterate pitched logical ties only: >>> for lt in abjad.iterate.logical_ties(staff, pitched=True): ... lt LogicalTie(items=[Note("c'4"), Note("c'8")]) LogicalTie(items=[Note("d'4"), Note("d'8")]) >>> for lt in abjad.iterate.logical_ties(staff, pitched=True, reverse=True): ... lt LogicalTie(items=[Note("d'4"), Note("d'8")]) LogicalTie(items=[Note("c'4"), Note("c'8")]) Set ``pitched=False`` to iterate unpitched logical ties only: >>> for lt in abjad.iterate.logical_ties(staff, pitched=False): ... lt LogicalTie(items=[Rest('r4')]) LogicalTie(items=[Rest('r4')]) >>> for lt in abjad.iterate.logical_ties(staff, pitched=False, reverse=True): ... lt LogicalTie(items=[Rest('r4')]) LogicalTie(items=[Rest('r4')]) .. container:: example REGRESSION. Yields logical tie even when leaves are missing in input: >>> voice = abjad.Voice("c'8 [ ~ c' ~ c' d' ]") >>> abjad.show(voice) # doctest: +SKIP .. docs:: >>> string = abjad.lilypond(voice) >>> print(string) \new Voice { c'8 [ ~ c'8 ~ c'8 d'8 ] } >>> selection = voice[:2] >>> for logical_tie in abjad.iterate.logical_ties(selection): ... logical_tie ... LogicalTie(items=[Note("c'8"), Note("c'8"), Note("c'8")]) """ return _iterlib._iterate_logical_ties( argument, exclude=exclude, grace=grace, nontrivial=nontrivial, pitched=pitched, reverse=reverse, )
[docs]def pitches(argument) -> typing.Iterator[_pitch.NamedPitch]: r""" Iterates pitches in ``argument``. Iterates pitches in container: .. container:: example >>> staff = abjad.Staff("c'8 d'8 e'8 f'8") >>> abjad.show(staff) # doctest: +SKIP .. docs:: >>> string = abjad.lilypond(staff) >>> print(string) \new Staff { c'8 d'8 e'8 f'8 } >>> for pitch in abjad.iterate.pitches(staff): ... pitch ... NamedPitch("c'") NamedPitch("d'") NamedPitch("e'") NamedPitch("f'") .. container:: example Iterates pitches in pitch set: >>> pitch_set = abjad.PitchSet([0, 2, 4, 5]) >>> for pitch in abjad.iterate.pitches(pitch_set): ... pitch ... NumberedPitch(0) NumberedPitch(2) NumberedPitch(4) NumberedPitch(5) .. container:: example Iterates different types of object in tuple: >>> argument = ( ... abjad.NamedPitch("c'"), ... abjad.Note("d'4"), ... abjad.Chord("<e' fs' g>4"), ... ) >>> for pitch in abjad.iterate.pitches(argument): ... pitch ... NamedPitch("c'") NamedPitch("d'") NamedPitch('g') NamedPitch("e'") NamedPitch("fs'") """ if isinstance(argument, _pitch.Pitch): pitch = _pitch.NamedPitch(argument) yield pitch result = [] try: result.extend(argument.pitches) except AttributeError: pass if isinstance(argument, _score.Chord): result.extend(argument.written_pitches) elif isinstance(argument, _pcollections.PitchSet): result.extend(sorted(list(argument))) elif isinstance(argument, list | tuple | set): for item in argument: for pitch_ in pitches(item): result.append(pitch_) else: for leaf in leaves(argument): try: result.append(leaf.written_pitch) except AttributeError: pass try: result.extend(leaf.written_pitches) except AttributeError: pass for pitch in result: yield pitch
[docs]def timeline( argument, prototype=None, *, exclude=None, reverse=None ) -> tuple[_score.Component, ...]: r""" Iterates leaves in ``argument`` in timeline order. Timeline-iterates leaves: .. container:: example >>> score = abjad.Score() >>> score.append(abjad.Staff("c'4 d'4 e'4 f'4")) >>> score.append(abjad.Staff("g'8 a'8 b'8 c''8")) >>> abjad.show(score) # doctest: +SKIP .. docs:: >>> string = abjad.lilypond(score) >>> print(string) \new Score << \new Staff { c'4 d'4 e'4 f'4 } \new Staff { g'8 a'8 b'8 c''8 } >> >>> for leaf in abjad.iterate.timeline(score): ... leaf ... Note("c'4") Note("g'8") Note("a'8") Note("d'4") Note("b'8") Note("c''8") Note("e'4") Note("f'4") >>> for component in abjad.iterate.timeline(score, reverse=True): ... component ... Note("f'4") Note("e'4") Note("c''8") Note("b'8") Note("d'4") Note("a'8") Note("g'8") Note("c'4") .. container:: example REGRESSION. Works with grace note (and containers): >>> music_voice = abjad.Voice("c'4 d' e' f'", name="MusicVoice") >>> container = abjad.BeforeGraceContainer("cs'16") >>> abjad.attach(container, music_voice[1]) >>> container = abjad.on_beat_grace_container( ... "g'16 gs' a' as'", music_voice[2:3] ... ) >>> abjad.attach(abjad.Articulation(">"), container[0]) >>> container = abjad.AfterGraceContainer("fs'16") >>> abjad.attach(container, music_voice[3]) >>> staff = abjad.Staff([music_voice]) >>> lilypond_file = abjad.LilyPondFile([r'\include "abjad.ily"', staff]) >>> abjad.show(lilypond_file) # doctest: +SKIP .. docs:: >>> string = abjad.lilypond(staff) >>> print(string) \new Staff { \context Voice = "MusicVoice" { c'4 \grace { cs'16 } d'4 << \context Voice = "On_Beat_Grace_Container" { \set fontSize = #-3 \slash \voiceOne < \tweak font-size 0 \tweak transparent ##t e' g' >16 - \accent [ ( gs'16 a'16 as'16 ) ] } \context Voice = "MusicVoice" { \voiceTwo e'4 } >> \oneVoice \afterGrace f'4 { fs'16 } } } >>> for leaf in abjad.iterate.timeline(staff): ... leaf Note("c'4") Note("cs'16") Note("d'4") Chord("<e' g'>16") Note("gs'16") Note("a'16") Note("as'16") Note("e'4") Note("f'4") Note("fs'16") >>> for leaf in abjad.iterate.timeline(staff, reverse=True): ... leaf Note("fs'16") Note("f'4") Note("e'4") Note("as'16") Note("a'16") Note("gs'16") Chord("<e' g'>16") Note("d'4") Note("cs'16") Note("c'4") Iterates leaves when ``prototype`` is none. """ generator = leaves(argument, prototype=prototype, exclude=exclude) components = list(generator) components.sort(key=lambda _: _._get_timespan().start_offset) offset_to_components: dict[_duration.Offset, list[_score.Component]] = dict() for component in components: start_offset = component._get_timespan().start_offset if start_offset not in offset_to_components: offset_to_components[start_offset] = [] for component in components: start_offset = component._get_timespan().start_offset offset_to_components[start_offset].append(component) result: list[_score.Component] = [] for start_offset, list_ in offset_to_components.items(): result.extend(list_) if reverse: result.reverse() return tuple(result)