bind¶
Functions
Annotates |
|
Attaches |
|
Detaches indicators-equal-to- |
- abjad.bind.annotate(component, annotation, indicator)[source]¶
Annotates
component
withindicator
.Annotates first note in staff:
>>> staff = abjad.Staff("c'4 d' e' f'") >>> abjad.annotate(staff[0], "bow_direction", abjad.DOWN) >>> abjad.show(staff)
>>> abjad.get.annotation(staff[0], "bow_direction") <Vertical.DOWN: -1>
>>> abjad.get.annotation(staff[0], "bow_fraction") is None True
>>> abjad.get.annotation(staff[0], "bow_fraction", 99) 99
- Return type:
- abjad.bind.attach(attachable, target, *, check_duplicate_indicator=False, context=None, deactivate=False, direction=None, do_not_test=False, synthetic_offset=None, tag=None, wrapper=False)[source]¶
Attaches
attachable
to (leaf or container)target
.Acceptable types of
attachable
:* indicator * abjad.Wrapper * abjad.BeforeGraceContainer * abjad.AfterGraceContainer
The class of
target
is almost alwaysabjad.Leaf
. A small number of indicators (likeabjad.LilyPondLiteral
) can attach to bothabjad.Leaf
andabjad.Container
objects.Attaches clef to first note in staff:
>>> staff = abjad.Staff("c'4 d' e' f'") >>> abjad.attach(abjad.Clef("alto"), staff[0]) >>> abjad.show(staff)
Attaches accent to last note in staff:
>>> staff = abjad.Staff("c'4 d' e' f'") >>> abjad.attach(abjad.Articulation(">"), staff[-1]) >>> abjad.show(staff)
Works with context names:
>>> voice = abjad.Voice("c'4 d' e' f'", name="MusicVoice") >>> staff = abjad.Staff([voice], name="MusicStaff") >>> abjad.attach(abjad.Clef("alto"), voice[0], context="MusicStaff") >>> abjad.show(staff)
>>> for leaf in abjad.select.leaves(staff): ... leaf, abjad.get.effective(leaf, abjad.Clef) ... (Note("c'4"), Clef(name='alto', hide=False)) (Note("d'4"), Clef(name='alto', hide=False)) (Note("e'4"), Clef(name='alto', hide=False)) (Note("f'4"), Clef(name='alto', hide=False))
Derives context from
attachable.context
context whencontext=None
.If multiple contexted indicators are attached at the same offset then
abjad.attach()
raisesabjad.PersistentIndicatorError
if 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(staff[0], abjad.Clef) ... note, clef ... (Note("c'4"), Clef(name='treble', hide=False)) (Note("d'4"), Clef(name='treble', hide=False)) (Note("e'4"), Clef(name='treble', hide=False)) (Note("f'4"), Clef(name='treble', hide=False))
But a lone inactivate indicator is effective when no active indicator is present:
>>> 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(staff[0], abjad.Clef) ... note, clef ... (Note("c'4"), Clef(name='alto', hide=False)) (Note("d'4"), Clef(name='alto', hide=False)) (Note("e'4"), Clef(name='alto', hide=False)) (Note("f'4"), Clef(name='alto', hide=False))
Note that
tag
must be anabjad.Tag
whendeactivate=True
.Return type depends on value of
wrapper
:returns
abjad.Wrapper
whenwrapper
is truereturns none when
wrapper
is not true
- abjad.bind.detach(argument, target=None, by_id=False)[source]¶
Detaches indicators-equal-to-
argument
fromtarget
.Set
by_id
to true to detach exactargument
fromtarget
(rather than detaching all indicators-equal-to-argument
).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)
The use of
by_id
is 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'") >>> abjad.attach( ... markup_1, staff[0], direction=abjad.UP, tag=abjad.Tag(string="+SCORE") ... ) >>> 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'") >>> abjad.attach( ... markup_1, staff[0], direction=abjad.UP, tag=abjad.Tag(string="+SCORE") ... ) >>> 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_id
to 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] >>> abjad.detach(wrapper, wrapper.component) (Wrapper(annotation=None, context='Staff', deactivate=False, direction=None, indicator=Clef(name='alto', hide=False), synthetic_offset=None, tag=Tag(string='')),)
>>> abjad.show(staff)
>>> abjad.attach(abjad.Clef("tenor"), staff[0]) >>> abjad.show(staff)
Returns tuple of zero or more detached items.
Internals
Wrapper. |
- class abjad.bind.Wrapper(annotation=None, check_duplicate_indicator=False, component=None, context=None, deactivate=False, direction=None, indicator=None, synthetic_offset=None, tag=Tag(string=''))[source]¶
Wrapper.
>>> component = abjad.Note("c'4") >>> articulation = abjad.Articulation("accent") >>> abjad.attach(articulation, component, direction=abjad.UP) >>> abjad.get.wrapper(component) Wrapper(annotation=None, context=None, deactivate=False, direction=<Vertical.UP: 1>, indicator=Articulation(name='accent'), synthetic_offset=None, tag=Tag(string=''))
Duplicate indicator warnings take two forms.
>>> voice_1 = abjad.Voice("c''4 d'' e'' f''", name="VoiceI") >>> voice_2 = abjad.Voice("c'4 d' e' f'", name="VoiceII") >>> staff = abjad.Staff([voice_1, voice_2], simultaneous=True) >>> abjad.attach(abjad.Clef("alto"), voice_2[0]) >>> abjad.show(staff)
First form when attempting to attach a contexted indicator to a leaf that already carries a contexted indicator of the same type:
>>> # abjad.attach(abjad.Clef("treble"), voice_2[0])
Second form when attempting to attach a contexted indicator to a leaf governed by some other component carrying a contexted indicator of the same type.
>>> # abjad.attach(abjad.Clef("treble"), voice_1[0])
Attributes Summary
Copies wrapper.
Is true when self equals
argument
.Hashes wrapper.
Gets repr.
Gets wrapper annotation.
Is true when indicator is bundled.
Gets start component.
Gets context (name).
Is true when wrapper deactivates tag.
Gets direction of indicator.
Gets indicator or bundled indicator.
Gets indicator.
Gets start offset and checks to see whether indicator leaks to the right.
Gets site-adjusted start offset.
Gets start offset.
Gets synthetic offset.
Gets and sets tag.
Gets unbundled indicator.
Special methods
- __copy__(*arguments)[source]¶
Copies wrapper.
Preserves annotation flag:
>>> old_staff = abjad.Staff("c'4 d'4 e'4 f'4") >>> abjad.annotate(old_staff[0], "bow_direction", abjad.DOWN) >>> string = abjad.lilypond(old_staff) >>> print(string) \new Staff { c'4 d'4 e'4 f'4 }
>>> leaf = old_staff[0] >>> abjad.get.annotation(leaf, "bow_direction") <Vertical.DOWN: -1>
>>> new_staff = abjad.mutate.copy(old_staff) >>> string = abjad.lilypond(new_staff) >>> print(string) \new Staff { c'4 d'4 e'4 f'4 }
>>> leaf = new_staff[0] >>> abjad.get.annotation(leaf, "bow_direction") <Vertical.DOWN: -1>
Preserves tag:
>>> old_staff = abjad.Staff("c'4 d'4 e'4 f'4") >>> clef = abjad.Clef("alto") >>> abjad.attach(clef, old_staff[0], tag=abjad.Tag("RED:M1")) >>> string = abjad.lilypond(old_staff, tags=True) >>> print(string) \new Staff { %! M1 %! RED \clef "alto" c'4 d'4 e'4 f'4 }
>>> leaf = old_staff[0] >>> abjad.get.wrapper(leaf) Wrapper(annotation=None, context='Staff', deactivate=False, direction=None, indicator=Clef(name='alto', hide=False), synthetic_offset=None, tag=Tag(string='RED:M1'))
>>> new_staff = abjad.mutate.copy(old_staff) >>> string = abjad.lilypond(new_staff, tags=True) >>> print(string) \new Staff { %! M1 %! RED \clef "alto" c'4 d'4 e'4 f'4 }
>>> leaf = new_staff[0] >>> abjad.get.wrapper(leaf) Wrapper(annotation=None, context='Staff', deactivate=False, direction=None, indicator=Clef(name='alto', hide=False), synthetic_offset=None, tag=Tag(string='RED:M1'))
Preserves deactivate flag:
>>> old_staff = abjad.Staff("c'4 d'4 e'4 f'4") >>> abjad.attach( ... abjad.Clef("alto"), ... old_staff[0], ... deactivate=True, ... tag=abjad.Tag("RED:M1"), ... ) >>> string = abjad.lilypond(old_staff, tags=True) >>> print(string) \new Staff { %! M1 %! RED %@% \clef "alto" c'4 d'4 e'4 f'4 }
>>> leaf = old_staff[0] >>> abjad.get.wrapper(leaf) Wrapper(annotation=None, context='Staff', deactivate=True, direction=None, indicator=Clef(name='alto', hide=False), synthetic_offset=None, tag=Tag(string='RED:M1'))
>>> new_staff = abjad.mutate.copy(old_staff) >>> string = abjad.lilypond(new_staff, tags=True) >>> print(string) \new Staff { %! M1 %! RED %@% \clef "alto" c'4 d'4 e'4 f'4 }
>>> leaf = new_staff[0] >>> abjad.get.wrapper(leaf) Wrapper(annotation=None, context='Staff', deactivate=True, direction=None, indicator=Clef(name='alto', hide=False), synthetic_offset=None, tag=Tag(string='RED:M1'))
Copies all properties except component.
Copy operations must supply component after wrapper copy.
- Return type:
Methods
Read/write properties
- deactivate¶
Is true when wrapper deactivates tag.
- tag¶
Gets and sets tag.
Read-only properties
- annotation¶
Gets wrapper annotation.
>>> note = abjad.Note("c'4") >>> articulation = abjad.Articulation("accent") >>> abjad.attach(articulation, note, direction=abjad.UP) >>> wrapper = abjad.get.wrapper(note) >>> wrapper.annotation is None True
>>> note = abjad.Note("c'4") >>> articulation = abjad.Articulation("accent") >>> abjad.annotate(note, "foo", articulation) >>> abjad.get.annotation(note, "foo") Articulation(name='accent')
- component¶
Gets start component.
Returns component or none.
- context¶
Gets context (name).
- direction¶
Gets direction of indicator.
- indicator¶
Gets indicator.
- leaked_start_offset¶
Gets start offset and checks to see whether indicator leaks to the right.
This is either the wrapper’s synthetic offset (if set); or the START offset of the wrapper’s component (if indicator DOES NOT leak); or else the STOP offset of the wrapper’s component (if indicator DOES leak).
Start- and stop-text-spans attach to the same leaf. But stop-text-span leaks to the right:
>>> voice = abjad.Voice("c'2 d'2") >>> start_text_span = abjad.StartTextSpan() >>> abjad.attach(start_text_span, voice[0]) >>> stop_text_span = abjad.StopTextSpan(leak=True) >>> abjad.attach(stop_text_span, voice[0]) >>> abjad.show(voice)
>>> string = abjad.lilypond(voice) >>> print(string) \new Voice { c'2 \startTextSpan <> \stopTextSpan d'2 }
Start offset and leaked start offset are the same for start-text-span:
>>> wrapper = abjad.get.wrapper(voice[0], abjad.StartTextSpan) >>> wrapper.start_offset, wrapper.leaked_start_offset (Offset((0, 1)), Offset((0, 1)))
Start offset and leaked start offset differ for stop-text-span:
>>> wrapper = abjad.get.wrapper(voice[0], abjad.StopTextSpan) >>> wrapper.start_offset, wrapper.leaked_start_offset (Offset((0, 1)), Offset((1, 2)))
- site_adjusted_start_offset¶
Gets site-adjusted start offset.
>>> staff = abjad.Staff("c'4") >>> abjad.attach(abjad.Ottava(-1, site="before"), staff[0]) >>> abjad.attach(abjad.Ottava(0, site="after"), staff[0]) >>> for wrapper in abjad.get.wrappers(staff[0], abjad.Ottava): ... wrapper.indicator, wrapper.site_adjusted_start_offset ... (Ottava(n=-1, site='before'), Offset((0, 1))) (Ottava(n=0, site='after'), Offset((1, 4)))
Indicators with site equal to
absolute_after
,after
orclosing
give a site-adjusted start offset equal to the stop offset of the wrapper’s component.Indicators with any other site give a site-adjusted start offset equal to the start offset of the wrapper’s component. This is the usual case, and means that site-adjusted start offset equals vanilla start offset.
But if
synthetic_offset
is set thensynthetic_offset
is returned directly without examining the format site at all.
- start_offset¶
Gets start offset.
This is either the wrapper’s synthetic offset or the start offset of the wrapper’s component.
- synthetic_offset¶
Gets synthetic offset.