spanners

Classes and functions for modeling spanners: beams, hairpins, slurs, etc.


Functions

beam

Attaches beam indicators.

glissando

Attaches glissando indicators.

hairpin

Attaches hairpin indicators.

horizontal_bracket

Attaches group indicators.

ottava

Attaches ottava indicators.

phrasing_slur

Attaches phrasing slur indicators.

piano_pedal

Attaches piano pedal indicators.

slur

Attaches slur indicators.

text_spanner

Attaches text span indicators.

tie

Attaches tie indicators.

trill_spanner

Attaches trill spanner indicators.

abjad.spanners.beam(argument, *, beam_lone_notes=False, beam_rests=True, direction=None, durations=None, selector=<function <lambda>>, span_beam_count=None, start_beam=None, stemlet_length=None, stop_beam=None, tag=None)[source]

Attaches beam indicators.

>>> voice = abjad.Voice("c'8 d' e' f'")
>>> abjad.beam(voice[:], direction=abjad.UP)
>>> abjad.show(voice)  
Return type:

None

abjad.spanners.glissando(argument, *tweaks, allow_repeats=False, allow_ties=False, hide_middle_note_heads=False, hide_middle_stems=False, hide_stem_selector=None, left_broken=False, parenthesize_repeats=False, right_broken=False, right_broken_show_next=False, style=None, tag=None, zero_padding=False)[source]

Attaches glissando indicators.

>>> voice = abjad.Voice("c'8 d'8 e'8 f'8", name="Voice")
>>> staff = abjad.Staff([voice], name="Staff")
>>> abjad.glissando(voice[:])
>>> abjad.show(staff)  

Glissando avoids bend-after indicators:

>>> voice = abjad.Voice("c'8 d'8 e'8 f'8", name="Voice")
>>> staff = abjad.Staff([voice], name="Staff")
>>> bend_after = abjad.BendAfter()
>>> abjad.attach(bend_after, voice[1])
>>> abjad.glissando(voice[:])
>>> abjad.show(staff)  

Does not allow repeated pitches:

>>> voice = abjad.Voice("a8 a8 b8 ~ b8 c'8 c'8 d'8 ~ d'8", name="Voice")
>>> staff = abjad.Staff([voice], name="Staff")
>>> abjad.glissando(voice[:], allow_repeats=True)
>>> abjad.show(staff)  

Allows repeated pitches (but not ties):

>>> voice = abjad.Voice("a8 a8 b8 ~ b8 c'8 c'8 d'8 ~ d'8", name="Voice")
>>> staff = abjad.Staff([voice], name="Staff")
>>> abjad.glissando(voice[:], allow_repeats=True)
>>> abjad.show(staff)  

Allows both repeated pitches and ties:

>>> voice = abjad.Voice("a8 a8 b8 ~ b8 c'8 c'8 d'8 ~ d'8", name="Voice")
>>> staff = abjad.Staff([voice], name="Staff")
>>> abjad.glissando(
...     voice[:],
...     allow_repeats=True,
...     allow_ties=True,
... )
>>> abjad.show(staff)  

Ties are excluded when repeated pitches are not allowed because all ties comprise repeated pitches.

Spans and parenthesizes repeated pitches:

>>> voice = abjad.Voice("a8 a8 b8 ~ b8 c'8 c'8 d'8 ~ d'8", name="Voice")
>>> staff = abjad.Staff([voice], name="Staff")
>>> abjad.glissando(
...     voice[:],
...     allow_repeats=True,
...     parenthesize_repeats=True,
... )
>>> abjad.show(staff)  

Parenthesizes (but does not span) repeated pitches:

>>> voice = abjad.Voice("a8 a8 b8 ~ b8 c'8 c'8 d'8 ~ d'8", name="Voice")
>>> staff = abjad.Staff([voice], name="Staff")
>>> abjad.glissando(
...     voice[:],
...     parenthesize_repeats=True,
... )
>>> abjad.show(staff)  

With hide_middle_note_heads=True:

>>> voice = abjad.Voice("c'8 d'8 e'8 f'8", name="Voice")
>>> staff = abjad.Staff([voice], name="Staff")
>>> abjad.glissando(voice[:], hide_middle_note_heads=True)
>>> abjad.show(staff)  

With hide_middle_note_heads=True and hide_middle_stems=True:

>>> voice = abjad.Voice("c'8 d'8 e'8 f'8", name="Voice")
>>> abjad.glissando(
...     voice[:],
...     hide_middle_note_heads=True,
...     hide_middle_stems=True,
... )
>>> abjad.show(voice)  

Note

Respects hide_middle_stems only when hide_middle_note_heads=True.

With right_broken=True:

>>> voice = abjad.Voice("c'8 d'8 e'8 f'8", name="Voice")
>>> abjad.glissando(voice[:], right_broken=True)
>>> abjad.show(voice)  

LilyPond output looks like this:

>>> string = abjad.lilypond(voice, tags=True)
>>> print(string)
\context Voice = "Voice"
{
    c'8
      %! abjad.glissando(7)
    \glissando
    d'8
      %! abjad.glissando(7)
    \glissando
    e'8
      %! abjad.glissando(7)
    \glissando
    f'8
      %! SHOW_TO_JOIN_BROKEN_SPANNERS
      %! abjad.glissando(7)
    %@% \glissando
}

With right_broken=True and hide_middle_note_heads=True:

>>> voice = abjad.Voice("c'8 d'8 e'8 f'8", name="Voice")
>>> abjad.glissando(
...     voice[:],
...     right_broken=True,
...     hide_middle_note_heads=True,
... )
>>> abjad.show(voice)  

LilyPond output looks like this:

>>> string = abjad.lilypond(voice, tags=True)
>>> print(string)
\context Voice = "Voice"
{
    c'8
      %! abjad.glissando(7)
    \glissando
      %! RIGHT_BROKEN
      %! SHOW_TO_JOIN_BROKEN_SPANNERS
      %! abjad.glissando(0)
    \hide NoteHead
      %! RIGHT_BROKEN
      %! SHOW_TO_JOIN_BROKEN_SPANNERS
      %! abjad.glissando(0)
    \override Accidental.stencil = ##f
      %! RIGHT_BROKEN
      %! SHOW_TO_JOIN_BROKEN_SPANNERS
      %! abjad.glissando(0)
    \override NoteColumn.glissando-skip = ##t
      %! RIGHT_BROKEN
      %! SHOW_TO_JOIN_BROKEN_SPANNERS
      %! abjad.glissando(0)
    \override NoteHead.no-ledgers = ##t
    d'8
    e'8
      %! HIDE_TO_JOIN_BROKEN_SPANNERS
      %! RIGHT_BROKEN
      %! abjad.glissando(4)
    \revert Accidental.stencil
      %! HIDE_TO_JOIN_BROKEN_SPANNERS
      %! RIGHT_BROKEN
      %! abjad.glissando(4)
    \revert NoteColumn.glissando-skip
      %! HIDE_TO_JOIN_BROKEN_SPANNERS
      %! RIGHT_BROKEN
      %! abjad.glissando(4)
    \revert NoteHead.no-ledgers
      %! HIDE_TO_JOIN_BROKEN_SPANNERS
      %! RIGHT_BROKEN
      %! abjad.glissando(4)
    \undo \hide NoteHead
    f'8
}

With right_broken=True, hide_middle_note_heads=True and right_broken_show_next=True:

>>> voice = abjad.Voice("c'8 d'8 e'8 f'8", name="Voice")
>>> abjad.glissando(
...     voice[:],
...     hide_middle_note_heads=True,
...     right_broken=True,
...     right_broken_show_next=True,
... )
>>> abjad.show(voice)  

LilyPond output looks like this:

>>> string = abjad.lilypond(voice, tags=True)
>>> print(string)
\context Voice = "Voice"
{
    c'8
      %! abjad.glissando(7)
    \glissando
      %! RIGHT_BROKEN
      %! SHOW_TO_JOIN_BROKEN_SPANNERS
      %! abjad.glissando(0)
    \hide NoteHead
      %! RIGHT_BROKEN
      %! SHOW_TO_JOIN_BROKEN_SPANNERS
      %! abjad.glissando(0)
    \override Accidental.stencil = ##f
      %! RIGHT_BROKEN
      %! SHOW_TO_JOIN_BROKEN_SPANNERS
      %! abjad.glissando(0)
    \override NoteColumn.glissando-skip = ##t
      %! RIGHT_BROKEN
      %! SHOW_TO_JOIN_BROKEN_SPANNERS
      %! abjad.glissando(0)
    \override NoteHead.no-ledgers = ##t
    d'8
    e'8
      %! HIDE_TO_JOIN_BROKEN_SPANNERS
      %! RIGHT_BROKEN
      %! abjad.glissando(4)
    \revert Accidental.stencil
      %! HIDE_TO_JOIN_BROKEN_SPANNERS
      %! RIGHT_BROKEN
      %! abjad.glissando(4)
    \revert NoteColumn.glissando-skip
      %! HIDE_TO_JOIN_BROKEN_SPANNERS
      %! RIGHT_BROKEN
      %! abjad.glissando(4)
    \revert NoteHead.no-ledgers
      %! HIDE_TO_JOIN_BROKEN_SPANNERS
      %! RIGHT_BROKEN
      %! abjad.glissando(4)
    \undo \hide NoteHead
    f'8
      %! RIGHT_BROKEN_SHOW_NEXT
      %! SHOW_TO_JOIN_BROKEN_SPANNERS
      %! abjad.glissando(5)
    %@% \revert Accidental.stencil
      %! RIGHT_BROKEN_SHOW_NEXT
      %! SHOW_TO_JOIN_BROKEN_SPANNERS
      %! abjad.glissando(5)
    %@% \revert NoteColumn.glissando-skip
      %! RIGHT_BROKEN_SHOW_NEXT
      %! SHOW_TO_JOIN_BROKEN_SPANNERS
      %! abjad.glissando(5)
    %@% \revert NoteHead.no-ledgers
      %! RIGHT_BROKEN_SHOW_NEXT
      %! SHOW_TO_JOIN_BROKEN_SPANNERS
      %! abjad.glissando(5)
    %@% \undo \hide NoteHead
}

With left_broken=True (and hide_middle_note_heads=True):

>>> voice = abjad.Voice("c'8 d'8 e'8 f'8", name="Voice")
>>> abjad.glissando(
...     voice[:],
...     left_broken=True,
...     hide_middle_note_heads=True,
... )
>>> abjad.show(voice)  

LilyPond output looks like this:

>>> string = abjad.lilypond(voice, tags=True)
>>> print(string)
\context Voice = "Voice"
{
      %! HIDE_TO_JOIN_BROKEN_SPANNERS
      %! LEFT_BROKEN
      %! abjad.glissando(2)
    \hide NoteHead
      %! HIDE_TO_JOIN_BROKEN_SPANNERS
      %! LEFT_BROKEN
      %! abjad.glissando(2)
    \override Accidental.stencil = ##f
      %! HIDE_TO_JOIN_BROKEN_SPANNERS
      %! LEFT_BROKEN
      %! abjad.glissando(2)
    \override NoteHead.no-ledgers = ##t
    c'8
      %! abjad.glissando(7)
    \glissando
      %! HIDE_TO_JOIN_BROKEN_SPANNERS
      %! LEFT_BROKEN
      %! abjad.glissando(3)
    \override NoteColumn.glissando-skip = ##t
    d'8
    e'8
      %! abjad.glissando(6)
    \revert Accidental.stencil
      %! abjad.glissando(6)
    \revert NoteColumn.glissando-skip
      %! abjad.glissando(6)
    \revert NoteHead.no-ledgers
      %! abjad.glissando(6)
    \undo \hide NoteHead
    f'8
}

Note

Respects left-broken only with hide_middle_note_heads=True.

Tweaks apply to every glissando:

>>> voice = abjad.Voice("c'8 d'8 e'8 f'8", name="Voice")
>>> abjad.glissando(
...     voice[:],
...     abjad.Tweak(r"- \tweak style #'trill"),
... )
>>> abjad.show(voice)  

With zero_padding=True on fixed pitch:

>>> voice = abjad.Voice("d'8 d'4. d'4. d'8", name="Voice")
>>> abjad.glissando(
...     voice[:],
...     allow_repeats=True,
...     zero_padding=True,
... )
>>> for note in voice[1:]:
...     abjad.override(note).NoteHead.transparent = True
...     abjad.override(note).NoteHead.X_extent = "#'(0 . 0)"
... 
>>> lilypond_file = abjad.LilyPondFile([r'\include "abjad.ily"', voice])
>>> abjad.show(lilypond_file)  

With zero_padding=True on changing pitches:

>>> voice = abjad.Voice("c'8. d'8. e'8. f'8.", name="Voice")
>>> abjad.glissando(voice[:], zero_padding=True)
>>> for note in voice[1:-1]:
...     abjad.override(note).NoteHead.transparent = True
...     abjad.override(note).NoteHead.X_extent = "#'(0 . 0)"
... 
>>> lilypond_file = abjad.LilyPondFile([r'\include "abjad.ily"', voice])
>>> abjad.show(lilypond_file)  

With indexed tweaks:

>>> voice = abjad.Voice("d'4 d' d' d'", name="Voice")
>>> abjad.glissando(
...     voice[:],
...     (abjad.Tweak(r"- \tweak color #red"), 0),
...     (abjad.Tweak(r"- \tweak color #red"), -1),
...     allow_repeats=True,
...     zero_padding=True,
... )
>>> for note in voice[1:-1]:
...     abjad.override(note).NoteHead.transparent = True
...     abjad.override(note).NoteHead.X_extent = "#'(0 . 0)"
... 
>>> lilypond_file = abjad.LilyPondFile([r'\include "abjad.ily"', voice])
>>> abjad.show(lilypond_file)  
abjad.spanners.hairpin(descriptor, argument, *, direction=None, selector=<function <lambda>>, tag=None)[source]

Attaches hairpin indicators.

With three-part string descriptor:

>>> voice = abjad.Voice("c'4 d' e' f'")
>>> abjad.hairpin("p < f", voice[:], direction=abjad.UP)
>>> abjad.override(voice[0]).DynamicLineSpanner.staff_padding = 4
>>> abjad.show(voice)  

With two-part string descriptor:

>>> voice = abjad.Voice("c'4 d' e' f'")
>>> abjad.hairpin("< !", voice[:])
>>> abjad.override(voice[0]).DynamicLineSpanner.staff_padding = 4
>>> abjad.show(voice)  

With dynamic objects:

>>> voice = abjad.Voice("c'4 d' e' f'")
>>> start_dynamic = abjad.Dynamic("niente", command=r"\!")
>>> start_hairpin = abjad.StartHairpin("o<|")
>>> bundle = abjad.bundle(start_hairpin, r"- \tweak color #blue")
>>> stop_dynamic = abjad.Dynamic('"f"')
>>> abjad.hairpin([start_dynamic, bundle, stop_dynamic], voice[:])
>>> abjad.override(voice[0]).DynamicLineSpanner.staff_padding = 4
>>> lilypond_file = abjad.LilyPondFile([r'\include "abjad.ily"', voice])
>>> abjad.show(lilypond_file)  
Return type:

None

abjad.spanners.horizontal_bracket(argument, *, selector=<function <lambda>>, start_group=None, stop_group=None, tag=None)[source]

Attaches group indicators.

>>> voice = abjad.Voice("c'4 d' e' f'")
>>> abjad.horizontal_bracket(voice[:])
>>> abjad.show(voice)  
Return type:

None

abjad.spanners.ottava(argument, *, selector=<function <lambda>>, start_ottava=Ottava(n=1, site='before'), stop_ottava=Ottava(n=0, site='after'), tag=None)[source]

Attaches ottava indicators.

>>> staff = abjad.Staff("c'4 d' e' f'")
>>> abjad.ottava(staff[:])
>>> abjad.show(staff)  
Return type:

None

abjad.spanners.phrasing_slur(argument, *, direction=None, selector=<function <lambda>>, start_phrasing_slur=None, stop_phrasing_slur=None, tag=None)[source]

Attaches phrasing slur indicators.

>>> voice = abjad.Voice("c'4 d' e' f'")
>>> abjad.phrasing_slur(voice[:], direction=abjad.UP)
>>> abjad.show(voice)  
Return type:

None

abjad.spanners.piano_pedal(argument, *, context=None, selector=<function <lambda>>, start_piano_pedal=None, stop_piano_pedal=None, tag=None)[source]

Attaches piano pedal indicators.

>>> staff = abjad.Staff("c'4 d' e' f'")
>>> abjad.piano_pedal(staff[:], context="Staff")
>>> abjad.setting(staff).pedalSustainStyle = "#'mixed"
>>> abjad.override(staff).SustainPedalLineSpanner.staff_padding = 5
>>> abjad.show(staff)  
Return type:

None

abjad.spanners.slur(argument, *, direction=None, selector=<function <lambda>>, start_slur=None, stop_slur=None, tag=None)[source]

Attaches slur indicators.

>>> voice = abjad.Voice("c'4 d' e' f'")
>>> abjad.slur(voice[:], direction=abjad.UP)
>>> abjad.show(voice)  
Return type:

None

abjad.spanners.text_spanner(argument, *, direction=None, selector=<function <lambda>>, start_text_span=None, stop_text_span=None, tag=None)[source]

Attaches text span indicators.

Single spanner:

>>> voice = abjad.Voice("c'4 d' e' f'")
>>> start_text_span = abjad.StartTextSpan(
...     left_text=abjad.Markup(r"\upright pont."),
...     right_text=abjad.Markup(r"\markup \upright tasto"),
...     style=r"\abjad-solid-line-with-arrow",
... )
>>> abjad.text_spanner(
...     voice[:], direction=abjad.UP, start_text_span=start_text_span
... )
>>> abjad.override(voice[0]).TextSpanner.staff_padding = 4
>>> lilypond_file = abjad.LilyPondFile([r'\include "abjad.ily"', voice])
>>> abjad.show(lilypond_file)  

Enchained spanners:

>>> voice = abjad.Voice("c'4 d' e' f' r")
>>> start_text_span = abjad.StartTextSpan(
...     left_text=abjad.Markup(r"\upright pont."),
...     style=r"\abjad-dashed-line-with-arrow",
... )
>>> abjad.text_spanner(voice[:3], start_text_span=start_text_span)
>>> start_text_span = abjad.StartTextSpan(
...     left_text=abjad.Markup(r"\upright tasto"),
...     right_text=abjad.Markup(r"\markup \upright pont."),
...     style=r"\abjad-dashed-line-with-arrow",
... )
>>> abjad.text_spanner(voice[-3:], start_text_span=start_text_span)
>>> abjad.override(voice).TextSpanner.staff_padding = 4
>>> lilypond_file = abjad.LilyPondFile([r'\include "abjad.ily"', voice])
>>> abjad.show(lilypond_file)  
>>> voice = abjad.Voice("c'4 d' e' f' r")
>>> start_text_span = abjad.StartTextSpan(
...     left_text=abjad.Markup(r"\upright pont."),
...     style=r"\abjad-dashed-line-with-arrow",
... )
>>> abjad.text_spanner(voice[:3], start_text_span=start_text_span)
>>> start_text_span = abjad.StartTextSpan(
...     left_text=abjad.Markup(r"\upright tasto"),
...     style=r"\abjad-solid-line-with-hook",
... )
>>> abjad.text_spanner(voice[-3:], start_text_span=start_text_span)
>>> abjad.override(voice).TextSpanner.staff_padding = 4
>>> lilypond_file = abjad.LilyPondFile([r'\include "abjad.ily"', voice])
>>> abjad.show(lilypond_file)  
Return type:

None

abjad.spanners.tie(argument, *, direction=None, repeat=False, selector=<function <lambda>>, tag=None)[source]

Attaches tie indicators.

>>> staff = abjad.Staff("c'4 c' c' c'")
>>> abjad.tie(staff[:], direction=abjad.UP)
>>> abjad.show(staff)  

With repeat ties:

>>> voice = abjad.Voice("c'4 c' c' c'", name="Voice")
>>> abjad.tie(voice[:], repeat=True)
>>> abjad.show(voice)  

Removes any existing ties before attaching new tie:

>>> voice = abjad.Voice("c'4 ~ c' ~ c' ~ c'", name="Voice")
>>> abjad.tie(voice[:])
>>> abjad.show(voice)  

Ties consecutive chords if all adjacent pairs have at least one pitch in common:

>>> voice = abjad.Voice("<c'>4 <c' d'>4 <d'>4", name="Voice")
>>> abjad.tie(voice[:])
>>> abjad.show(voice)  

Enharmonics are allowed:

>>> voice = abjad.Voice("c'4 bs c' dff'", name="Voice")
>>> abjad.tie(voice[:])
>>> abjad.show(voice)  

Repeat tie threshold works like this:

>>> voice = abjad.Voice("d'4. d'2 d'4. d'2", name="Voice")
>>> abjad.tie(voice[:], repeat=(4, 8))
>>> abjad.show(voice)  

Detaches ties before attach:

>>> voice = abjad.Voice("d'2 ~ d'8 ~ d'8 ~ d'8 ~ d'8", name="Voice")
>>> abjad.show(voice)  
>>> abjad.tie(voice[:], repeat=(4, 8))
>>> abjad.show(voice)  
Return type:

None

abjad.spanners.trill_spanner(argument, *, selector=<function <lambda>>, start_trill_span=None, stop_trill_span=None, tag=None)[source]

Attaches trill spanner indicators.

>>> voice = abjad.Voice("c'4 d' e' f'")
>>> abjad.trill_spanner(voice[:])
>>> abjad.show(voice)  
Return type:

None