abjad.bind
|
Annotates |
|
Attaches |
|
Detaches indicators equals to |
- abjad.bind.annotate(component: Component, key: str, value: object) None[source]
Annotates
componentwithkeyequal tovalue.Annotations do not affect LilyPond output.
>>> staff = abjad.Staff("c'4 d' e' f'") >>> abjad.annotate(staff[0], "motive_number", 6) >>> abjad.show(staff)
>>> abjad.get.annotation(staff[0], "motive_number") 6
- abjad.bind.attach(indicator: Any, component: Component, *, check_duplicate_indicator: bool = False, context: str | None = None, deactivate: bool = False, direction: Vertical | None = None, do_not_test: bool = False, hide: bool = False, synthetic_offset: Offset | None = None, tag: Tag | None = None) None[source]
Attaches
indicatortocomponent.The class of
componentis almost always a leaf. (A small number of indicators can attach to both leaves and containers.) Acceptable types ofindicator:* indicator * abjad.Wrapper * abjad.BeforeGraceContainer (DEPRECATED) * abjad.AfterGraceContainer (DEPRECATED)
Attaches articulation to last note in staff:
>>> staff = abjad.Staff("c'4 d' e' f'") >>> articulation = abjad.Articulation(">") >>> abjad.attach(articulation, staff[-1]) >>> abjad.show(staff)
The
check_duplicate_indicator=Falsekeyword. Consider the case of a score with two staves. In the usual case, it is necessary to attach a metronome mark to the first note of only one of the two staves:>>> staff_1 = abjad.Staff("c''4 d''4 e''4 f''4") >>> staff_2 = abjad.Staff("c'4 d'4 e'4 f'4") >>> score = abjad.Score([staff_1, staff_2]) >>> metronome_mark = abjad.MetronomeMark(abjad.Duration(1, 4), 52) >>> abjad.attach(metronome_mark, staff_1[0]) >>> abjad.show(score)
But what should happen when a conflicting metronome mark is attached at the same moment in a different context? Abjad allows this behavior, but it is not clear what it should mean to have two metronome marks in effect at the same time. Set
check_duplicate_indicators=Trueto raise an exception instead.The
context=Nonekeyword. Indicators that affect many notes, rests or chords in a row define the context at which they take effect. Clefs effect all notes on a staff, for example, which is why attaching a clef to the first note in a staff effects all the others:>>> clef = abjad.Clef("alto") >>> clef.context 'Staff'
>>> staff = abjad.Staff("c'4 d' e' f'") >>> abjad.attach(clef, staff[0]) >>> abjad.show(staff)
>>> for leaf in abjad.select.leaves(staff): ... leaf, abjad.get.effective_indicator(leaf, abjad.Clef) ... (Note("c'4"), Clef(name='alto')) (Note("d'4"), Clef(name='alto')) (Note("e'4"), Clef(name='alto')) (Note("f'4"), Clef(name='alto'))
This example sets
context="MusicStaff"to show that the alto clef governs all notes in a custom staff context (rather than the default staff context):>>> voice = abjad.Voice("c'4 d' e' f'", name="MusicVoice") >>> staff = abjad.Staff([voice], name="MusicStaff") >>> clef = abjad.Clef("alto") >>> abjad.attach(clef, voice[0], context="MusicStaff") >>> abjad.show(staff)
>>> for leaf in abjad.select.leaves(staff): ... leaf, abjad.get.effective_indicator(leaf, abjad.Clef) ... (Note("c'4"), Clef(name='alto')) (Note("d'4"), Clef(name='alto')) (Note("e'4"), Clef(name='alto')) (Note("f'4"), Clef(name='alto'))
If multiple contexted indicators are attached at the same offset then
abjad.attach()raisesabjad.PersistentIndicatorErrorif all indicators are active. But simultaneous contexted indicators are allowed if only one is active (and all others are inactive):>>> staff = abjad.Staff("c'4 d' e' f'") >>> abjad.attach(abjad.Clef("treble"), staff[0]) >>> abjad.attach( ... abjad.Clef("alto"), ... staff[0], ... deactivate=True, ... tag=abjad.Tag("+PARTS"), ... ) >>> abjad.attach( ... abjad.Clef("tenor"), ... staff[0], ... deactivate=True, ... tag=abjad.Tag("+PARTS"), ... ) >>> abjad.show(staff)
Active indicator is always effective when competing inactive indicators are present:
>>> for note in staff: ... clef = abjad.get.effective_indicator(staff[0], abjad.Clef) ... note, clef ... (Note("c'4"), Clef(name='treble')) (Note("d'4"), Clef(name='treble')) (Note("e'4"), Clef(name='treble')) (Note("f'4"), Clef(name='treble'))
But a lone inactivate indicator is effective when no active indicator is present. Note that
tagmust be anabjad.Tagwhendeactivate=True:>>> staff = abjad.Staff("c'4 d' e' f'") >>> abjad.attach( ... abjad.Clef("alto"), ... staff[0], ... deactivate=True, ... tag=abjad.Tag("+PARTS"), ... ) >>> abjad.show(staff)
>>> for note in staff: ... clef = abjad.get.effective_indicator(staff[0], abjad.Clef) ... note, clef ... (Note("c'4"), Clef(name='alto')) (Note("d'4"), Clef(name='alto')) (Note("e'4"), Clef(name='alto')) (Note("f'4"), Clef(name='alto'))
- abjad.bind.detach(indicator, component: Component, *, by_id: bool = False) tuple[source]
Detaches indicators equals to
indicatorfromcomponent. Returns tuple of zero or more detached items.Detaches articulations from first note in staff:
>>> staff = abjad.Staff("c'4 d' e' f'") >>> abjad.attach(abjad.Articulation(">"), staff[0]) >>> abjad.show(staff)
>>> abjad.detach(abjad.Articulation, staff[0]) (Articulation(name='>'),)
>>> abjad.show(staff)
Set
by_idto true to detach exactindicatorfromcomponent(rather than detaching all indicatorslequal toindicator). The use ofby_idis motivated by the following.Consider the three document-specifier markups below:
>>> markup_1 = abjad.Markup(r"\markup tutti") >>> markup_2 = abjad.Markup(r"\markup { with the others }") >>> markup_3 = abjad.Markup(r"\markup { with the others }")
Markups two and three compare equal:
>>> markup_2 == markup_3 True
But document-tagging like this makes sense for score and two diferent parts:
>>> staff = abjad.Staff("c'4 d' e' f'") >>> tag = abjad.Tag(string="+SCORE") >>> abjad.attach(markup_1, staff[0], direction=abjad.UP, tag=tag) >>> abjad.attach( ... markup_2, ... staff[0], ... deactivate=True, ... direction=abjad.UP, ... tag=abjad.Tag("+PARTS_VIOLIN_1"), ... ) >>> abjad.attach( ... markup_3, ... staff[0], ... deactivate=True, ... direction=abjad.UP, ... tag=abjad.Tag("+PARTS_VIOLIN_2"), ... ) >>> abjad.show(staff)
>>> string = abjad.lilypond(staff, tags=True) >>> print(string) \new Staff { c'4 %! +SCORE ^ \markup tutti %! +PARTS_VIOLIN_1 %@% ^ \markup { with the others } %! +PARTS_VIOLIN_2 %@% ^ \markup { with the others } d'4 e'4 f'4 }
The question is then how to detach just one of the two markups that compare equal to each other?
Passing in one of the markup objects directory doesn’t work. This is because detach tests for equality to input argument:
>>> markups = abjad.detach(markup_2, staff[0]) >>> for markup in markups: ... markup ... Markup(string='\\markup { with the others }') Markup(string='\\markup { with the others }')
>>> abjad.show(staff)
>>> string = abjad.lilypond(staff, tags=True) >>> print(string) \new Staff { c'4 %! +SCORE ^ \markup tutti d'4 e'4 f'4 }
We start again:
>>> staff = abjad.Staff("c'4 d' e' f'") >>> tag = abjad.Tag(string="+SCORE") >>> abjad.attach(markup_1, staff[0], direction=abjad.UP, tag=tag) >>> abjad.attach( ... markup_2, ... staff[0], ... deactivate=True, ... direction=abjad.UP, ... tag=abjad.Tag("+PARTS_VIOLIN_1"), ... ) >>> abjad.attach( ... markup_3, ... staff[0], ... deactivate=True, ... direction=abjad.UP, ... tag=abjad.Tag("+PARTS_VIOLIN_2"), ... ) >>> abjad.show(staff)
>>> string = abjad.lilypond(staff, tags=True) >>> print(string) \new Staff { c'4 %! +SCORE ^ \markup tutti %! +PARTS_VIOLIN_1 %@% ^ \markup { with the others } %! +PARTS_VIOLIN_2 %@% ^ \markup { with the others } d'4 e'4 f'4 }
This time we set
by_idto true. Now detach checks the exact id of its input argument (rather than just testing for equality). This gives us what we want:>>> markups = abjad.detach(markup_2, staff[0], by_id=True) >>> for markup in markups: ... markup ... Markup(string='\\markup { with the others }')
>>> abjad.show(staff)
>>> string = abjad.lilypond(staff, tags=True) >>> print(string) \new Staff { c'4 %! +SCORE ^ \markup tutti %! +PARTS_VIOLIN_2 %@% ^ \markup { with the others } d'4 e'4 f'4 }
REGRESSION. Attach-detach-attach pattern works correctly when detaching wrappers:
>>> staff = abjad.Staff("c'4 d' e' f'") >>> abjad.attach(abjad.Clef("alto"), staff[0]) >>> abjad.show(staff)
>>> wrapper = abjad.get.wrappers(staff[0])[0] >>> wrappers = abjad.detach(wrapper, wrapper.component()) >>> abjad.show(staff)
>>> abjad.attach(abjad.Clef("tenor"), staff[0]) >>> abjad.show(staff)