import collections
import fractions
from . import math as _math
from . import score as _score
[docs]class Parentage(collections.abc.Sequence):
r'''
Parentage of a component.
.. container:: example
>>> score = abjad.Score()
>>> string = r"""\new Voice = "Treble_Voice" { e'4 }"""
>>> treble_staff = abjad.Staff(string, name="Treble_Staff")
>>> score.append(treble_staff)
>>> string = r"""\new Voice = "Bass_Voice" { c4 }"""
>>> bass_staff = abjad.Staff(string, name="Bass_Staff")
>>> clef = abjad.Clef('bass')
>>> abjad.attach(clef, bass_staff[0][0])
>>> score.append(bass_staff)
>>> abjad.show(score) # doctest: +SKIP
.. docs::
>>> string = abjad.lilypond(score)
>>> print(string)
\new Score
<<
\context Staff = "Treble_Staff"
{
\context Voice = "Treble_Voice"
{
e'4
}
}
\context Staff = "Bass_Staff"
{
\context Voice = "Bass_Voice"
{
\clef "bass"
c4
}
}
>>
>>> bass_voice = score["Bass_Voice"]
>>> note = bass_voice[0]
>>> for component in abjad.get.parentage(note):
... component
...
Note('c4')
Voice('c4', name='Bass_Voice')
Staff('{ c4 }', name='Bass_Staff')
Score("{ { e'4 } } { { c4 } }", simultaneous=True)
'''
### CLASS VARIABLES ###
__slots__ = ("_component", "_components")
### INITIALIZER ###
def __init__(self, component=None):
components = []
if component is not None:
assert isinstance(component, _score.Component), repr(component)
components.extend(component._get_parentage())
self._component = component
self._components = tuple(components)
### SPECIAL METHODS ###
[docs] def __eq__(self, argument):
"""
Is true when ``argument`` is a parent with the same components as this parentage.
"""
if isinstance(argument, type(self)):
if len(self) == len(argument):
for c, d in zip(self, argument):
if c is not d:
return False
else:
return True
return False
[docs] def __getitem__(self, argument):
"""
Gets ``argument``.
Returns component or tuple of components.
"""
return self.components.__getitem__(argument)
[docs] def __len__(self) -> int:
"""
Gets number of components in parentage.
"""
return len(self.components)
[docs] def __repr__(self):
"""
Gets repr.
"""
return f"{type(self).__name__}(component={self.component!r})"
### PRIVATE METHODS ###
@staticmethod
def _id_string(component):
lhs = component.__class__.__name__
rhs = getattr(component, "name", None) or id(component)
return f"{lhs}-{rhs!r}"
def _prolations(self):
prolations = []
default = fractions.Fraction(1)
for parent in self:
prolation = getattr(parent, "implied_prolation", default)
prolations.append(prolation)
return prolations
### PUBLIC PROPERTIES ###
@property
def component(self) -> _score.Component:
r"""
Gets component.
.. container:: example
REGRESSION. Works with grace notes (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 component in abjad.select.components(staff):
... parentage = abjad.get.parentage(component)
... print(f"{repr(component):30} {repr(parentage.component)}")
Staff("{ c'4 d'4 { { <e' g'>16 gs'16 a'16 as'16 } { e'4 } } f'4 }") 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') Voice("c'4 d'4 { { <e' g'>16 gs'16 a'16 as'16 } { e'4 } } f'4", name='MusicVoice')
Note("c'4") Note("c'4")
BeforeGraceContainer("cs'16") BeforeGraceContainer("cs'16")
Note("cs'16") Note("cs'16")
Note("d'4") Note("d'4")
Container("{ <e' g'>16 gs'16 a'16 as'16 } { e'4 }") Container("{ <e' g'>16 gs'16 a'16 as'16 } { e'4 }")
OnBeatGraceContainer("<e' g'>16 gs'16 a'16 as'16") OnBeatGraceContainer("<e' g'>16 gs'16 a'16 as'16")
Chord("<e' g'>16") Chord("<e' g'>16")
Note("gs'16") Note("gs'16")
Note("a'16") Note("a'16")
Note("as'16") Note("as'16")
Voice("e'4", name='MusicVoice') Voice("e'4", name='MusicVoice')
Note("e'4") Note("e'4")
Note("f'4") Note("f'4")
AfterGraceContainer("fs'16") AfterGraceContainer("fs'16")
Note("fs'16") Note("fs'16")
"""
return self._component
@property
def components(self) -> tuple[_score.Component]:
r"""
Gets components.
.. container:: example
REGRESSION. Works with grace notes (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 component in abjad.select.components(staff):
... parentage = abjad.get.parentage(component)
... components = parentage.components
... print(f"{repr(component)}:")
... for component_ in components:
... print(f" {repr(component_)}")
Staff("{ c'4 d'4 { { <e' g'>16 gs'16 a'16 as'16 } { e'4 } } f'4 }"):
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'):
Voice("c'4 d'4 { { <e' g'>16 gs'16 a'16 as'16 } { e'4 } } f'4", name='MusicVoice')
Staff("{ c'4 d'4 { { <e' g'>16 gs'16 a'16 as'16 } { e'4 } } f'4 }")
Note("c'4"):
Note("c'4")
Voice("c'4 d'4 { { <e' g'>16 gs'16 a'16 as'16 } { e'4 } } f'4", name='MusicVoice')
Staff("{ c'4 d'4 { { <e' g'>16 gs'16 a'16 as'16 } { e'4 } } f'4 }")
BeforeGraceContainer("cs'16"):
BeforeGraceContainer("cs'16")
Voice("c'4 d'4 { { <e' g'>16 gs'16 a'16 as'16 } { e'4 } } f'4", name='MusicVoice')
Staff("{ c'4 d'4 { { <e' g'>16 gs'16 a'16 as'16 } { e'4 } } f'4 }")
Note("cs'16"):
Note("cs'16")
BeforeGraceContainer("cs'16")
Voice("c'4 d'4 { { <e' g'>16 gs'16 a'16 as'16 } { e'4 } } f'4", name='MusicVoice')
Staff("{ c'4 d'4 { { <e' g'>16 gs'16 a'16 as'16 } { e'4 } } f'4 }")
Note("d'4"):
Note("d'4")
Voice("c'4 d'4 { { <e' g'>16 gs'16 a'16 as'16 } { e'4 } } f'4", name='MusicVoice')
Staff("{ c'4 d'4 { { <e' g'>16 gs'16 a'16 as'16 } { e'4 } } f'4 }")
Container("{ <e' g'>16 gs'16 a'16 as'16 } { e'4 }"):
Container("{ <e' g'>16 gs'16 a'16 as'16 } { e'4 }")
Voice("c'4 d'4 { { <e' g'>16 gs'16 a'16 as'16 } { e'4 } } f'4", name='MusicVoice')
Staff("{ c'4 d'4 { { <e' g'>16 gs'16 a'16 as'16 } { e'4 } } f'4 }")
OnBeatGraceContainer("<e' g'>16 gs'16 a'16 as'16"):
OnBeatGraceContainer("<e' g'>16 gs'16 a'16 as'16")
Container("{ <e' g'>16 gs'16 a'16 as'16 } { e'4 }")
Voice("c'4 d'4 { { <e' g'>16 gs'16 a'16 as'16 } { e'4 } } f'4", name='MusicVoice')
Staff("{ c'4 d'4 { { <e' g'>16 gs'16 a'16 as'16 } { e'4 } } f'4 }")
Chord("<e' g'>16"):
Chord("<e' g'>16")
OnBeatGraceContainer("<e' g'>16 gs'16 a'16 as'16")
Container("{ <e' g'>16 gs'16 a'16 as'16 } { e'4 }")
Voice("c'4 d'4 { { <e' g'>16 gs'16 a'16 as'16 } { e'4 } } f'4", name='MusicVoice')
Staff("{ c'4 d'4 { { <e' g'>16 gs'16 a'16 as'16 } { e'4 } } f'4 }")
Note("gs'16"):
Note("gs'16")
OnBeatGraceContainer("<e' g'>16 gs'16 a'16 as'16")
Container("{ <e' g'>16 gs'16 a'16 as'16 } { e'4 }")
Voice("c'4 d'4 { { <e' g'>16 gs'16 a'16 as'16 } { e'4 } } f'4", name='MusicVoice')
Staff("{ c'4 d'4 { { <e' g'>16 gs'16 a'16 as'16 } { e'4 } } f'4 }")
Note("a'16"):
Note("a'16")
OnBeatGraceContainer("<e' g'>16 gs'16 a'16 as'16")
Container("{ <e' g'>16 gs'16 a'16 as'16 } { e'4 }")
Voice("c'4 d'4 { { <e' g'>16 gs'16 a'16 as'16 } { e'4 } } f'4", name='MusicVoice')
Staff("{ c'4 d'4 { { <e' g'>16 gs'16 a'16 as'16 } { e'4 } } f'4 }")
Note("as'16"):
Note("as'16")
OnBeatGraceContainer("<e' g'>16 gs'16 a'16 as'16")
Container("{ <e' g'>16 gs'16 a'16 as'16 } { e'4 }")
Voice("c'4 d'4 { { <e' g'>16 gs'16 a'16 as'16 } { e'4 } } f'4", name='MusicVoice')
Staff("{ c'4 d'4 { { <e' g'>16 gs'16 a'16 as'16 } { e'4 } } f'4 }")
Voice("e'4", name='MusicVoice'):
Voice("e'4", name='MusicVoice')
Container("{ <e' g'>16 gs'16 a'16 as'16 } { e'4 }")
Voice("c'4 d'4 { { <e' g'>16 gs'16 a'16 as'16 } { e'4 } } f'4", name='MusicVoice')
Staff("{ c'4 d'4 { { <e' g'>16 gs'16 a'16 as'16 } { e'4 } } f'4 }")
Note("e'4"):
Note("e'4")
Voice("e'4", name='MusicVoice')
Container("{ <e' g'>16 gs'16 a'16 as'16 } { e'4 }")
Voice("c'4 d'4 { { <e' g'>16 gs'16 a'16 as'16 } { e'4 } } f'4", name='MusicVoice')
Staff("{ c'4 d'4 { { <e' g'>16 gs'16 a'16 as'16 } { e'4 } } f'4 }")
Note("f'4"):
Note("f'4")
Voice("c'4 d'4 { { <e' g'>16 gs'16 a'16 as'16 } { e'4 } } f'4", name='MusicVoice')
Staff("{ c'4 d'4 { { <e' g'>16 gs'16 a'16 as'16 } { e'4 } } f'4 }")
AfterGraceContainer("fs'16"):
AfterGraceContainer("fs'16")
Voice("c'4 d'4 { { <e' g'>16 gs'16 a'16 as'16 } { e'4 } } f'4", name='MusicVoice')
Staff("{ c'4 d'4 { { <e' g'>16 gs'16 a'16 as'16 } { e'4 } } f'4 }")
Note("fs'16"):
Note("fs'16")
AfterGraceContainer("fs'16")
Voice("c'4 d'4 { { <e' g'>16 gs'16 a'16 as'16 } { e'4 } } f'4", name='MusicVoice')
Staff("{ c'4 d'4 { { <e' g'>16 gs'16 a'16 as'16 } { e'4 } } f'4 }")
"""
return self._components
@property
def orphan(self) -> bool:
r"""
Is true when component has no parent.
.. container:: example
REGRESSION. Works with grace notes (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 component in abjad.select.components(staff):
... parentage = abjad.get.parentage(component)
... print(f"{repr(component):30} {repr(parentage.orphan)}")
Staff("{ c'4 d'4 { { <e' g'>16 gs'16 a'16 as'16 } { e'4 } } f'4 }") True
Voice("c'4 d'4 { { <e' g'>16 gs'16 a'16 as'16 } { e'4 } } f'4", name='MusicVoice') False
Note("c'4") False
BeforeGraceContainer("cs'16") False
Note("cs'16") False
Note("d'4") False
Container("{ <e' g'>16 gs'16 a'16 as'16 } { e'4 }") False
OnBeatGraceContainer("<e' g'>16 gs'16 a'16 as'16") False
Chord("<e' g'>16") False
Note("gs'16") False
Note("a'16") False
Note("as'16") False
Voice("e'4", name='MusicVoice') False
Note("e'4") False
Note("f'4") False
AfterGraceContainer("fs'16") False
Note("fs'16") False
"""
return self.parent is None
@property
def parent(self) -> _score.Component | None:
r"""
Gets parent.
.. container:: example
REGRESSION. Works with grace notes (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 component in abjad.select.components(staff):
... parentage = abjad.get.parentage(component)
... print(f"{repr(component):30} {repr(parentage.parent)}")
Staff("{ c'4 d'4 { { <e' g'>16 gs'16 a'16 as'16 } { e'4 } } f'4 }") None
Voice("c'4 d'4 { { <e' g'>16 gs'16 a'16 as'16 } { e'4 } } f'4", name='MusicVoice') Staff("{ c'4 d'4 { { <e' g'>16 gs'16 a'16 as'16 } { e'4 } } f'4 }")
Note("c'4") Voice("c'4 d'4 { { <e' g'>16 gs'16 a'16 as'16 } { e'4 } } f'4", name='MusicVoice')
BeforeGraceContainer("cs'16") Voice("c'4 d'4 { { <e' g'>16 gs'16 a'16 as'16 } { e'4 } } f'4", name='MusicVoice')
Note("cs'16") BeforeGraceContainer("cs'16")
Note("d'4") Voice("c'4 d'4 { { <e' g'>16 gs'16 a'16 as'16 } { e'4 } } f'4", name='MusicVoice')
Container("{ <e' g'>16 gs'16 a'16 as'16 } { e'4 }") Voice("c'4 d'4 { { <e' g'>16 gs'16 a'16 as'16 } { e'4 } } f'4", name='MusicVoice')
OnBeatGraceContainer("<e' g'>16 gs'16 a'16 as'16") Container("{ <e' g'>16 gs'16 a'16 as'16 } { e'4 }")
Chord("<e' g'>16") OnBeatGraceContainer("<e' g'>16 gs'16 a'16 as'16")
Note("gs'16") OnBeatGraceContainer("<e' g'>16 gs'16 a'16 as'16")
Note("a'16") OnBeatGraceContainer("<e' g'>16 gs'16 a'16 as'16")
Note("as'16") OnBeatGraceContainer("<e' g'>16 gs'16 a'16 as'16")
Voice("e'4", name='MusicVoice') Container("{ <e' g'>16 gs'16 a'16 as'16 } { e'4 }")
Note("e'4") Voice("e'4", name='MusicVoice')
Note("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") Voice("c'4 d'4 { { <e' g'>16 gs'16 a'16 as'16 } { e'4 } } f'4", name='MusicVoice')
Note("fs'16") AfterGraceContainer("fs'16")
"""
return self.get(n=1)
@property
def prolation(self) -> fractions.Fraction:
r"""
Gets prolation.
.. container:: example
REGRESSION. Works with grace notes (and containers):
>>> music_voice = abjad.Voice(
... r"\times 2/3 { c'4 d' e' } \times 2/3 { f' g' a' }",
... name="MusicVoice"
... )
>>> container = abjad.BeforeGraceContainer("cs'16")
>>> abjad.attach(container, music_voice[0][1])
>>> container = abjad.on_beat_grace_container(
... "a'8 b'", music_voice[1][:1]
... )
>>> container = abjad.AfterGraceContainer("fs'16")
>>> abjad.attach(container, music_voice[1][2])
>>> 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"
{
\times 2/3 {
c'4
\grace {
cs'16
}
d'4
e'4
}
\times 2/3 {
<<
\context Voice = "On_Beat_Grace_Container"
{
\set fontSize = #-3
\slash
\voiceOne
<
\tweak font-size 0
\tweak transparent ##t
f'
a'
>8
[
(
b'8
)
]
}
\context Voice = "MusicVoice"
{
\voiceTwo
f'4
}
>>
\oneVoice
g'4
\afterGrace
a'4
{
fs'16
}
}
}
}
>>> for component in abjad.select.components(staff):
... parentage = abjad.get.parentage(component)
... print(f"{repr(component):30} {repr(parentage.prolation)}")
Staff("{ { 2/3 c'4 d'4 e'4 } { 2/3 { { <f' a'>8 b'8 } { f'4 } } g'4 a'4 } }") Fraction(1, 1)
Voice("{ 2/3 c'4 d'4 e'4 } { 2/3 { { <f' a'>8 b'8 } { f'4 } } g'4 a'4 }", name='MusicVoice') Fraction(1, 1)
Tuplet('3:2', "c'4 d'4 e'4") Fraction(2, 3)
Note("c'4") Fraction(2, 3)
BeforeGraceContainer("cs'16") Fraction(2, 3)
Note("cs'16") Fraction(2, 3)
Note("d'4") Fraction(2, 3)
Note("e'4") Fraction(2, 3)
Tuplet('3:2', "{ { <f' a'>8 b'8 } { f'4 } } g'4 a'4") Fraction(2, 3)
Container("{ <f' a'>8 b'8 } { f'4 }") Fraction(2, 3)
OnBeatGraceContainer("<f' a'>8 b'8") Fraction(2, 3)
Chord("<f' a'>8") Fraction(2, 3)
Note("b'8") Fraction(2, 3)
Voice("f'4", name='MusicVoice') Fraction(2, 3)
Note("f'4") Fraction(2, 3)
Note("g'4") Fraction(2, 3)
Note("a'4") Fraction(2, 3)
AfterGraceContainer("fs'16") Fraction(2, 3)
Note("fs'16") Fraction(2, 3)
"""
prolations = [fractions.Fraction(1)] + self._prolations()
products = _math.cumulative_products(prolations)
return products[-1]
@property
def root(self) -> _score.Component:
r"""
Gets root.
.. container:: example
REGRESSION. Works with grace notes (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 component in abjad.select.components(staff):
... parentage = abjad.get.parentage(component)
... print(f"{repr(component):30} {repr(parentage.root)}")
Staff("{ c'4 d'4 { { <e' g'>16 gs'16 a'16 as'16 } { e'4 } } f'4 }") 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') Staff("{ c'4 d'4 { { <e' g'>16 gs'16 a'16 as'16 } { e'4 } } f'4 }")
Note("c'4") Staff("{ c'4 d'4 { { <e' g'>16 gs'16 a'16 as'16 } { e'4 } } f'4 }")
BeforeGraceContainer("cs'16") Staff("{ c'4 d'4 { { <e' g'>16 gs'16 a'16 as'16 } { e'4 } } f'4 }")
Note("cs'16") Staff("{ c'4 d'4 { { <e' g'>16 gs'16 a'16 as'16 } { e'4 } } f'4 }")
Note("d'4") Staff("{ c'4 d'4 { { <e' g'>16 gs'16 a'16 as'16 } { e'4 } } f'4 }")
Container("{ <e' g'>16 gs'16 a'16 as'16 } { e'4 }") Staff("{ c'4 d'4 { { <e' g'>16 gs'16 a'16 as'16 } { e'4 } } f'4 }")
OnBeatGraceContainer("<e' g'>16 gs'16 a'16 as'16") Staff("{ c'4 d'4 { { <e' g'>16 gs'16 a'16 as'16 } { e'4 } } f'4 }")
Chord("<e' g'>16") Staff("{ c'4 d'4 { { <e' g'>16 gs'16 a'16 as'16 } { e'4 } } f'4 }")
Note("gs'16") Staff("{ c'4 d'4 { { <e' g'>16 gs'16 a'16 as'16 } { e'4 } } f'4 }")
Note("a'16") Staff("{ c'4 d'4 { { <e' g'>16 gs'16 a'16 as'16 } { e'4 } } f'4 }")
Note("as'16") Staff("{ c'4 d'4 { { <e' g'>16 gs'16 a'16 as'16 } { e'4 } } f'4 }")
Voice("e'4", name='MusicVoice') Staff("{ c'4 d'4 { { <e' g'>16 gs'16 a'16 as'16 } { e'4 } } f'4 }")
Note("e'4") Staff("{ c'4 d'4 { { <e' g'>16 gs'16 a'16 as'16 } { e'4 } } f'4 }")
Note("f'4") Staff("{ c'4 d'4 { { <e' g'>16 gs'16 a'16 as'16 } { e'4 } } f'4 }")
AfterGraceContainer("fs'16") Staff("{ c'4 d'4 { { <e' g'>16 gs'16 a'16 as'16 } { e'4 } } f'4 }")
Note("fs'16") Staff("{ c'4 d'4 { { <e' g'>16 gs'16 a'16 as'16 } { e'4 } } f'4 }")
"""
root = self.get(n=-1)
assert isinstance(root, _score.Component), repr(root)
return root
### PUBLIC METHODS ###
[docs] def count(self, prototype=None) -> int:
r"""
Gets number of ``prototype`` in parentage.
Gets tuplet count:
.. container:: example
>>> staff = abjad.Staff(
... r"\times 2/3 { c'2 \times 2/3 { d'8 e' f' } } \times 2/3 { c'4 d' e' }"
... )
>>> abjad.show(staff) # doctest: +SKIP
.. docs::
>>> string = abjad.lilypond(staff)
>>> print(string)
\new Staff
{
\times 2/3 {
c'2
\times 2/3 {
d'8
e'8
f'8
}
}
\times 2/3 {
c'4
d'4
e'4
}
}
>>> for component in abjad.select.components(staff):
... parentage = abjad.get.parentage(component)
... count = parentage.count(abjad.Tuplet)
... print(f"{repr(component):55} {repr(count)}")
Staff("{ 2/3 c'2 { 2/3 d'8 e'8 f'8 } } { 2/3 c'4 d'4 e'4 }") 0
Tuplet('3:2', "c'2 { 2/3 d'8 e'8 f'8 }") 1
Note("c'2") 1
Tuplet('3:2', "d'8 e'8 f'8") 2
Note("d'8") 2
Note("e'8") 2
Note("f'8") 2
Tuplet('3:2', "c'4 d'4 e'4") 1
Note("c'4") 1
Note("d'4") 1
Note("e'4") 1
.. container:: example
Gets voice count:
>>> outer_red_voice = abjad.Voice("e''8 d''", name="Red_Voice")
>>> inner_red_voice = abjad.Voice("c''4 b' c''8", name="Red_Voice")
>>> inner_blue_voice = abjad.Voice("e'4 f' e'8", name="Blue_Voice")
>>> container = abjad.Container(
... [inner_red_voice, inner_blue_voice],
... simultaneous=True,
... )
>>> outer_red_voice.append(container)
>>> outer_red_voice.extend("d''8")
>>> abjad.override(outer_red_voice).NoteHead.color = "#red"
>>> command = abjad.VoiceNumber(1)
>>> abjad.attach(command, outer_red_voice[0])
>>> abjad.override(inner_blue_voice).NoteHead.color = "#blue"
>>> command = abjad.VoiceNumber(2)
>>> abjad.attach(command, inner_blue_voice[0])
>>> dynamic = abjad.Dynamic("f")
>>> abjad.attach(dynamic, outer_red_voice[0])
>>> abjad.show(outer_red_voice) # doctest: +SKIP
.. docs::
>>> string = abjad.lilypond(outer_red_voice)
>>> print(string)
\context Voice = "Red_Voice"
\with
{
\override NoteHead.color = #red
}
{
\voiceOne
e''8
\f
d''8
<<
\context Voice = "Red_Voice"
{
c''4
b'4
c''8
}
\context Voice = "Blue_Voice"
\with
{
\override NoteHead.color = #blue
}
{
\voiceTwo
e'4
f'4
e'8
}
>>
d''8
}
>>> for leaf in abjad.iterate.leaves(outer_red_voice):
... depth = abjad.get.parentage(leaf).count(abjad.Voice)
... print(leaf, depth)
...
Note("e''8") 1
Note("d''8") 1
Note("c''4") 2
Note("b'4") 2
Note("c''8") 2
Note("e'4") 2
Note("f'4") 2
Note("e'8") 2
Note("d''8") 1
.. container:: example
REGRESSION. Works with grace notes (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 component in abjad.select.components(staff):
... parentage = abjad.get.parentage(component)
... count = parentage.count(abjad.Staff)
... print(f"{repr(component):30} {repr(count)}")
Staff("{ c'4 d'4 { { <e' g'>16 gs'16 a'16 as'16 } { e'4 } } f'4 }") 1
Voice("c'4 d'4 { { <e' g'>16 gs'16 a'16 as'16 } { e'4 } } f'4", name='MusicVoice') 1
Note("c'4") 1
BeforeGraceContainer("cs'16") 1
Note("cs'16") 1
Note("d'4") 1
Container("{ <e' g'>16 gs'16 a'16 as'16 } { e'4 }") 1
OnBeatGraceContainer("<e' g'>16 gs'16 a'16 as'16") 1
Chord("<e' g'>16") 1
Note("gs'16") 1
Note("a'16") 1
Note("as'16") 1
Voice("e'4", name='MusicVoice') 1
Note("e'4") 1
Note("f'4") 1
AfterGraceContainer("fs'16") 1
Note("fs'16") 1
"""
n = 0
if prototype is None:
prototype = _score.Component
for component in self:
if isinstance(component, prototype):
n += 1
return n
[docs] def get(self, prototype=None, n=0) -> _score.Component | None:
r"""
Gets instance ``n`` of ``prototype`` in parentage.
.. container:: example
>>> outer_red_voice = abjad.Voice("e''8 d''", name="Red_Voice")
>>> inner_red_voice = abjad.Voice("c''4 b' c''8", name="Red_Voice")
>>> inner_blue_voice = abjad.Voice("e'4 f' e'8", name="Blue_Voice")
>>> container = abjad.Container(
... [inner_red_voice, inner_blue_voice],
... simultaneous=True,
... )
>>> outer_red_voice.append(container)
>>> outer_red_voice.extend("d''8")
>>> abjad.override(outer_red_voice).NoteHead.color = "#red"
>>> command = abjad.VoiceNumber(1)
>>> abjad.attach(command, outer_red_voice[0])
>>> abjad.override(inner_blue_voice).NoteHead.color = "#blue"
>>> command = abjad.VoiceNumber(2)
>>> abjad.attach(command, inner_blue_voice[0])
>>> dynamic = abjad.Dynamic("f")
>>> abjad.attach(dynamic, outer_red_voice[0])
>>> abjad.show(outer_red_voice) # doctest: +SKIP
.. docs::
>>> string = abjad.lilypond(outer_red_voice)
>>> print(string)
\context Voice = "Red_Voice"
\with
{
\override NoteHead.color = #red
}
{
\voiceOne
e''8
\f
d''8
<<
\context Voice = "Red_Voice"
{
c''4
b'4
c''8
}
\context Voice = "Blue_Voice"
\with
{
\override NoteHead.color = #blue
}
{
\voiceTwo
e'4
f'4
e'8
}
>>
d''8
}
.. container:: example
>>> leaf = abjad.get.leaf(inner_red_voice, 0)
>>> leaf
Note("c''4")
>>> parentage = abjad.get.parentage(leaf)
Returns self when ``n=0``:
>>> parentage.get(abjad.Component, 0)
Note("c''4")
Returns parents with positive ``n``:
>>> parentage.get(abjad.Component, 1)
Voice("c''4 b'4 c''8", name='Red_Voice')
>>> parentage.get(abjad.Component, 2)
Container("{ c''4 b'4 c''8 } { e'4 f'4 e'8 }")
>>> parentage.get(abjad.Component, 3)
Voice("e''8 d''8 { { c''4 b'4 c''8 } { e'4 f'4 e'8 } } d''8", name='Red_Voice')
Returns none with ``n`` greater than score depth:
>>> parentage.get(abjad.Component, 4) is None
True
>>> parentage.get(abjad.Component, 5) is None
True
>>> parentage.get(abjad.Component, 99) is None
True
Returns score root with ``n=-1``:
>>> parentage.get(abjad.Component, -1)
Voice("e''8 d''8 { { c''4 b'4 c''8 } { e'4 f'4 e'8 } } d''8", name='Red_Voice')
With other negative ``n``:
>>> parentage.get(abjad.Component, -2)
Container("{ c''4 b'4 c''8 } { e'4 f'4 e'8 }")
>>> parentage.get(abjad.Component, -3)
Voice("c''4 b'4 c''8", name='Red_Voice')
>>> parentage.get(abjad.Component, -4)
Note("c''4")
Returns none for sufficiently negative ``n``:
>>> parentage.get(abjad.Component, -5) is None
True
>>> parentage.get(abjad.Component, -7) is None
True
>>> parentage.get(abjad.Component, -99) is None
True
.. container:: example
Works with nested voices and tuplets:
>>> leaf = abjad.get.leaf(inner_red_voice, 0)
>>> parentage = abjad.get.parentage(leaf)
>>> leaf
Note("c''4")
Nonnegative ``n``:
>>> parentage.get(abjad.Voice, 0)
Voice("c''4 b'4 c''8", name='Red_Voice')
>>> parentage.get(abjad.Voice, 1)
Voice("e''8 d''8 { { c''4 b'4 c''8 } { e'4 f'4 e'8 } } d''8", name='Red_Voice')
>>> parentage.get(abjad.Voice, 2) is None
True
>>> parentage.get(abjad.Voice, 9) is None
True
Negative ``n``:
>>> parentage.get(abjad.Voice, -1)
Voice("e''8 d''8 { { c''4 b'4 c''8 } { e'4 f'4 e'8 } } d''8", name='Red_Voice')
>>> parentage.get(abjad.Voice, -2)
Voice("c''4 b'4 c''8", name='Red_Voice')
>>> parentage.get(abjad.Voice, -3) is None
True
>>> parentage.get(abjad.Voice, -99) is None
True
.. container:: example
REGRESSION. Works with grace notes (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 component in abjad.select.components(staff):
... parentage = abjad.get.parentage(component)
... result = parentage.get(abjad.Staff)
... print(f"{repr(component):30} {repr(result)}")
Staff("{ c'4 d'4 { { <e' g'>16 gs'16 a'16 as'16 } { e'4 } } f'4 }") 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') Staff("{ c'4 d'4 { { <e' g'>16 gs'16 a'16 as'16 } { e'4 } } f'4 }")
Note("c'4") Staff("{ c'4 d'4 { { <e' g'>16 gs'16 a'16 as'16 } { e'4 } } f'4 }")
BeforeGraceContainer("cs'16") Staff("{ c'4 d'4 { { <e' g'>16 gs'16 a'16 as'16 } { e'4 } } f'4 }")
Note("cs'16") Staff("{ c'4 d'4 { { <e' g'>16 gs'16 a'16 as'16 } { e'4 } } f'4 }")
Note("d'4") Staff("{ c'4 d'4 { { <e' g'>16 gs'16 a'16 as'16 } { e'4 } } f'4 }")
Container("{ <e' g'>16 gs'16 a'16 as'16 } { e'4 }") Staff("{ c'4 d'4 { { <e' g'>16 gs'16 a'16 as'16 } { e'4 } } f'4 }")
OnBeatGraceContainer("<e' g'>16 gs'16 a'16 as'16") Staff("{ c'4 d'4 { { <e' g'>16 gs'16 a'16 as'16 } { e'4 } } f'4 }")
Chord("<e' g'>16") Staff("{ c'4 d'4 { { <e' g'>16 gs'16 a'16 as'16 } { e'4 } } f'4 }")
Note("gs'16") Staff("{ c'4 d'4 { { <e' g'>16 gs'16 a'16 as'16 } { e'4 } } f'4 }")
Note("a'16") Staff("{ c'4 d'4 { { <e' g'>16 gs'16 a'16 as'16 } { e'4 } } f'4 }")
Note("as'16") Staff("{ c'4 d'4 { { <e' g'>16 gs'16 a'16 as'16 } { e'4 } } f'4 }")
Voice("e'4", name='MusicVoice') Staff("{ c'4 d'4 { { <e' g'>16 gs'16 a'16 as'16 } { e'4 } } f'4 }")
Note("e'4") Staff("{ c'4 d'4 { { <e' g'>16 gs'16 a'16 as'16 } { e'4 } } f'4 }")
Note("f'4") Staff("{ c'4 d'4 { { <e' g'>16 gs'16 a'16 as'16 } { e'4 } } f'4 }")
AfterGraceContainer("fs'16") Staff("{ c'4 d'4 { { <e' g'>16 gs'16 a'16 as'16 } { e'4 } } f'4 }")
Note("fs'16") Staff("{ c'4 d'4 { { <e' g'>16 gs'16 a'16 as'16 } { e'4 } } f'4 }")
"""
if prototype is None:
prototype = (_score.Component,)
if not isinstance(prototype, tuple):
prototype = (prototype,)
if 0 <= n:
i = 0
for component in self:
if isinstance(component, prototype):
if i == n:
return component
i += 1
else:
i = -1
for component in reversed(self):
if isinstance(component, prototype):
if i == n:
return component
i -= 1
return None
[docs] def logical_voice(self) -> dict:
r"""
Gets logical voice.
Gets logical voice of note:
.. container:: example
>>> voice = abjad.Voice("c'4 d'4 e'4 f'4", name="MusicVoice")
>>> staff = abjad.Staff([voice], name="Music_Staff")
>>> score = abjad.Score([staff], name="Score")
>>> abjad.show(score) # doctest: +SKIP
.. docs::
>>> string = abjad.lilypond(score)
>>> print(string)
\context Score = "Score"
<<
\context Staff = "Music_Staff"
{
\context Voice = "MusicVoice"
{
c'4
d'4
e'4
f'4
}
}
>>
>>> note = voice[0]
>>> parentage = abjad.get.parentage(note)
>>> parentage.logical_voice()
{'score': "Score-'Score'", 'staff group': '', 'staff': "Staff-'Music_Staff'", 'voice': "Voice-'MusicVoice'"}
.. container:: example
REGRESSION. Works with grace notes (and containers):
>>> voice = abjad.Voice("c'4 d' e' f'", name="MusicVoice")
>>> container_1 = abjad.BeforeGraceContainer("cs'16")
>>> abjad.attach(container_1, voice[1])
>>> container_2 = abjad.AfterGraceContainer("fs'16")
>>> abjad.attach(container_2, voice[3])
>>> abjad.show(voice) # doctest: +SKIP
.. docs::
>>> string = abjad.lilypond(voice)
>>> print(string)
\context Voice = "MusicVoice"
{
c'4
\grace {
cs'16
}
d'4
e'4
\afterGrace
f'4
{
fs'16
}
}
>>> abjad.get.parentage(voice).logical_voice()
{'score': '', 'staff group': '', 'staff': '', 'voice': "Voice-'MusicVoice'"}
>>> abjad.get.parentage(container_1).logical_voice()
{'score': '', 'staff group': '', 'staff': '', 'voice': "Voice-'MusicVoice'"}
>>> abjad.get.parentage(container_1[0]).logical_voice()
{'score': '', 'staff group': '', 'staff': '', 'voice': "Voice-'MusicVoice'"}
>>> abjad.get.parentage(container_2).logical_voice()
{'score': '', 'staff group': '', 'staff': '', 'voice': "Voice-'MusicVoice'"}
>>> abjad.get.parentage(container_2[0]).logical_voice()
{'score': '', 'staff group': '', 'staff': '', 'voice': "Voice-'MusicVoice'"}
"""
keys = ("score", "staff group", "staff", "voice")
logical_voice = dict.fromkeys(keys, "")
for component in self:
if isinstance(component, _score.Voice):
if not logical_voice["voice"]:
logical_voice["voice"] = self._id_string(component)
elif isinstance(component, _score.Staff):
if not logical_voice["staff"]:
logical_voice["staff"] = self._id_string(component)
# explicit staff demands a nested voice:
# if no explicit voice has been found,
# create implicit voice here with random integer
if not logical_voice["voice"]:
logical_voice["voice"] = str(id(component))
elif isinstance(component, _score.StaffGroup):
if not logical_voice["staff group"]:
logical_voice["staff group"] = self._id_string(component)
elif isinstance(component, _score.Score):
if not logical_voice["score"]:
logical_voice["score"] = self._id_string(component)
logical_voice_ = dict(logical_voice)
return logical_voice_
[docs] def score_index(self) -> tuple[int | str, ...]:
r"""
Gets score index.
.. container:: example
>>> staff_1 = abjad.Staff(r"\times 2/3 { c''2 b'2 a'2 }")
>>> staff_2 = abjad.Staff("c'2 d'2")
>>> score = abjad.Score([staff_1, staff_2])
>>> abjad.show(score) # doctest: +SKIP
.. docs::
>>> string = abjad.lilypond(score)
>>> print(string)
\new Score
<<
\new Staff
{
\times 2/3 {
c''2
b'2
a'2
}
}
\new Staff
{
c'2
d'2
}
>>
>>> for component in abjad.select.components(score):
... parentage = abjad.get.parentage(component)
... component, parentage.score_index()
...
(Score("{ { 2/3 c''2 b'2 a'2 } } { c'2 d'2 }", simultaneous=True), ())
(Staff("{ 2/3 c''2 b'2 a'2 }"), (0,))
(Tuplet('3:2', "c''2 b'2 a'2"), (0, 0))
(Note("c''2"), (0, 0, 0))
(Note("b'2"), (0, 0, 1))
(Note("a'2"), (0, 0, 2))
(Staff("c'2 d'2"), (1,))
(Note("c'2"), (1, 0))
(Note("d'2"), (1, 1))
Score root sets score index to ``()``.
.. container:: example
REGRESSION. Works with grace notes (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 component in abjad.select.components(staff):
... parentage = abjad.get.parentage(component)
... score_index = parentage.score_index()
... print(f"{repr(component):30} {repr(score_index)}")
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') (0,)
Note("c'4") (0, 0)
BeforeGraceContainer("cs'16") (0, 0, 1, '-G')
Note("cs'16") (0, 0, 1, '-G', 0)
Note("d'4") (0, 1)
Container("{ <e' g'>16 gs'16 a'16 as'16 } { e'4 }") (0, 2)
OnBeatGraceContainer("<e' g'>16 gs'16 a'16 as'16") (0, 2, 0)
Chord("<e' g'>16") (0, 2, 0, 0)
Note("gs'16") (0, 2, 0, 1)
Note("a'16") (0, 2, 0, 2)
Note("as'16") (0, 2, 0, 3)
Voice("e'4", name='MusicVoice') (0, 2, 1)
Note("e'4") (0, 2, 1, 0)
Note("f'4") (0, 3)
AfterGraceContainer("fs'16") (0, 0, 3, '+G')
Note("fs'16") (0, 0, 3, '+G', 0)
"""
result: list[int | str] = []
current = self[0]
for parent in self[1:]:
if isinstance(current, _score.BeforeGraceContainer):
tuple_ = type(self)(current._main_leaf).score_index()
list_ = list(tuple_) + ["-G"]
result[0:0] = list_
elif isinstance(current, _score.AfterGraceContainer):
tuple_ = type(self)(current._main_leaf).score_index()
list_ = list(tuple_) + ["+G"]
result[0:0] = list_
else:
index = parent.index(current)
result.insert(0, index)
current = parent
return tuple(result)