Dear friends,

Abjad 3.1 is now available:

Docs: https://abjad.github.io/
GitHub: https://github.com/abjad/abjad
PyPI: https://pypi.org/project/Abjad/

Please note that the old www.projectabjad.org URL has been retired in favor
of GitHub doc hosting, as shown above.

There are hundreds of new features in this release; highlights follow below.

Here's to happy composing and to time with friends and family over the
holiday season.

We hope you enjoy,

Trevor Bača
* mail: [email protected]
* home: http://www.trevorbaca.com/

Josiah Wolf Oberholtzer
* mail: [email protected]
* home: http://josiahwolfoberholtzer.com

ABJAD 3.1 RELEASE NOTES

Abjad 3.1 includes a large number of new features and three important
changes.

Changes:

   - Respelled abjad.Container.is_simultaneous as
   abjad.Container.simultaneous
   - Removed abjad.Measure
   - Replaced old spanner classes with new factory functions

Select new features:

   - Annotated iteration
   - Attribute testing
   - Literal markup
   - Selector concatenation
   - Selector inclusion / exclusion
   - Tagged component, indicator, tweak output
   - Timespan expressions

Details appear below.
CHANGES1. RESPELLED ABJAD.CONTAINER.IS_SIMULTANEOUS AS
ABJAD.CONTAINER.SIMULTANEOUS

OLD: Container.is_simultaneous
NEW: Container.simultaneous

Example:

>>> voice_1 = abjad.Voice(r"a''4 \flageolet ( df'''16 )")
>>> literal = abjad.LilyPondLiteral(r"\voiceOne", "opening")
>>> abjad.attach(literal, voice_1[0])
>>> voice_2 = abjad.Voice(r"<a' a''>4 \flageolet ( <bf' f''>16 )")
>>> literal = abjad.LilyPondLiteral(r"\voiceTwo", "opening")
>>> abjad.attach(literal, voice_2[0])
>>> container = abjad.Container([voice_1, voice_2], simultaneous=True)
>>> staff = abjad.Staff("r2 r8.")
>>> staff.insert(1, container)
>>> markup = abjad.Markup("div. in 3", direction=abjad.Up)
>>> abjad.attach(markup, staff[0])
>>> abjad.override(staff[0]).text_script.self_alignment_X = -0.25
>>> abjad.override(staff[0]).text_script.staff_padding = 2
>>> abjad.show(staff)

[image: container-simultaneous]

Users should change is_simultaneous to simultaneous everywhere in existing
scores. Closes #1103.
2. REMOVED ABJAD.MEASURE

LilyPond does not model measures explicitly. This is now true in Abjad 3.1,
too. Attach abjad.TimeSignature indicators wherever you would call the
LilyPond \time command.

Recall that in Abjad you can iterate notes, rests and chords grouped
together by the measure that contains them:

>>> time_signature = abjad.TimeSignature((9, 8))
>>> staff = abjad.Staff("f''4. gf'' f'' gf'' f'' c''' c''' a'' fs''")
>>> first_leaf = staff[0]
>>> abjad.attach(time_signature, first_leaf)
>>> abjad.show(staff)

[image: staff]

>>> for group in groups:
...     print(group)
Selection([Note("f''4."), Note("gf''4."), Note("f''4.")])
Selection([Note("gf''4."), Note("f''4."), Note("c'''4.")])
Selection([Note("c'''4."), Note("a''4."), Note("fs''4.")])

>>> last_group = groups[-1]
>>> for note in last_group:
...     abjad.attach(abjad.Marcato(), note)
...
>>> abjad.show(staff)

[image: last-measure-articulations]

Also:

   - Removed abjad.Measure
   - Removed abjad.MeasureMaker
   - Removed abjad.Mutation.replace_measure_contents()

3. REPLACED SPANNERS WITH FACTORY FUNCTIONS

LilyPond models beams, hairpins, slurs and other spanners with matching
start- and stop-commands. This is now true in Abjad 3.1, too. The
spanners.py module implements 12 factory functions to help you work with
spanners. These new factory functions are implemented in terms of matching
pairs of start and stop indicators: abjad.text_spanner() works by attaching
instances of the new abjad.StartTextSpan and abjad.StopTextSpan indicators
(which format as LilyPond \startTextSpan and \stopTextSpan). Closes #1033:

   - abjad.beam()
   - abjad.bow_contact_spanner()
   - abjad.glissando()
   - abjad.hairpin()
   - abjad.horizontal_bracket()
   - abjad.ottava()
   - abjad.phrasing_slur()
   - abjad.piano_pedal()
   - abjad.slur()
   - abjad.text_spanner()
   - abjad.tie()
   - abjad.trill_spanner()

CHANGED:

OLD: abjad.BowContactSpanner
NEW: abjad.bow_contact_spanner()

OLD: abjad.Glissando
NEW: abjad.glissando()

OLD: abjad.HorizontalBracket
NEW: abjad.horizontal_bracket()

OLD: abjad.OctavationSpanner
NEW: abjad.ottava()

OLD: abjad.PianoPedalSpanner
NEW: abjad.piano_pedal()

OLD: abjad.TrillSpanner
NEW: abjad.trill_spanner()

OLD: abjad.HairpinIndicator
NEW: abjad.StartHairpin

Also:

   - Added abjad.glissando(..., hide_stem_selector=None) keyword
   - Added abjad.glissando(..., left_broken=None) keyword
   - Added abjad.glissando(..., right_broken_show_next=None) keyword
   - Added abjad.glissando(..., hide_middle_stems=None) keyword
   - Removed abjad.mutate().splice()
   - Removed fracture_spanners=None keyword in all functions

NEW FUNCTIONALITY1. ANNOTATED ITERATION

Abjad 3.1 allows you to exclude annotated leaves from iteration.

Excludes leaves with "RED" or "BLUE" annotations:

>>> staff = abjad.Staff()
>>> 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.annotate(staff[0], "RED", True)
>>> abjad.annotate(staff[1], "BLUE", True)
>>> abjad.annotate(staff[2], "GREEN", True)
>>> abjad.annotate(staff[3], "RED", True)
>>> abjad.annotate(staff[4], "BLUE", True)
>>> abjad.annotate(staff[5], "GREEN", True)
>>> abjad.show(staff)

[image: annotated-exclusions]

>>> for leaf in abjad.iterate(staff).leaves(
...     exclude=["RED", "BLUE"],
...     ):
...     leaf
...
Note("af'8")
Note("gf'8")

2. ARTICULATIONS

Abjad 3.1 cleans up the direction-handling of four indicators. Closes #1064:

   - abjad.Dynamic.direction
   - abjad.Staccato.direction
   - abjad.RepeatTie.direction
   - abjad.Staccatissimo.direction

Without direction:

>>> staff = abjad.Staff("g' a' b' c''")
>>> for note in staff:
...     staccato = abjad.Staccato()
...     abjad.attach(staccato, note)
...
>>> abjad.show(staff)

[image: staccato-without-direction]

Forced up:

>>> staff = abjad.Staff("g' a' b' c''")
>>> for note in staff:
...     staccato = abjad.Staccato(direction=abjad.Up)
...     abjad.attach(staccato, note)
...
>>> abjad.show(staff)

[image: staccato-forced-up]

Forced down:

>>> staff = abjad.Staff("g' a' b' c''")
>>> for note in staff:
...     staccato = abjad.Staccato(direction=abjad.Down)
...     abjad.attach(staccato, note)
...
>>> abjad.show(staff)

[image: staccato-forced-down]

Abjad 3.1 adds support for the LilyPond halfopen and snappizzicato articulation
types.

Abjad 3.1 cleans up woodwind diagrams. Closes #1061
3. ATTRIBUTE TESTING

Abjad 3.1 adds support for attribute testing with the new attributes=None
 keyword:

   - abjad.inspect().effective(..., attributes=None)
   - abjad.inspect().effective_wrapper(..., attributes=None)
   - abjad.inspect().has_effective_indicator(..., attributes=None)
   - abjad.inspect().has_indicator(..., attributes=None)
   - abjad.inspect().indicator(..., attributes=None)
   - abjad.inspect().indicators(..., attributes=None)
   - abjad.inspect().wrapper(..., attributes=None)
   - abjad.inspect().wrappers(..., attributes=None)

Example:

>>> voice = abjad.Voice("c'4 d' e' f'")
>>> start_text_span = abjad.StartTextSpan()
>>> abjad.attach(start_text_span, voice[0])
>>> stop_text_span = abjad.StopTextSpan()
>>> abjad.attach(stop_text_span, voice[2])
>>> abjad.f(voice)
\new Voice
{
    c'4
    \startTextSpan
    d'4
    e'4
    \stopTextSpan
    f'4
}

>>> for note in voice:
...     note, abjad.inspect(note).effective(abjad.StartTextSpan)
...
(Note("c'4"), StartTextSpan(command='\\startTextSpan', concat_hspace_left=0.5))
(Note("d'4"), StartTextSpan(command='\\startTextSpan', concat_hspace_left=0.5))
(Note("e'4"), StartTextSpan(command='\\startTextSpan', concat_hspace_left=0.5))
(Note("f'4"), StartTextSpan(command='\\startTextSpan', concat_hspace_left=0.5))

>>> for note in voice:
...     note, abjad.inspect(note).effective(abjad.StopTextSpan)
...
(Note("c'4"), None)
(Note("d'4"), None)
(Note("e'4"), StopTextSpan(command='\\stopTextSpan'))
(Note("f'4"), StopTextSpan(command='\\stopTextSpan'))

>>> attributes = {'parameter': 'TEXT_SPANNER'}
>>> for note in voice:
...     indicator = abjad.inspect(note).effective(
...         object,
...         attributes=attributes,
...         )
...     note, indicator
...
(Note("c'4"), StartTextSpan(command='\\startTextSpan', concat_hspace_left=0.5))
(Note("d'4"), StartTextSpan(command='\\startTextSpan', concat_hspace_left=0.5))
(Note("e'4"), StopTextSpan(command='\\stopTextSpan'))
(Note("f'4"), StopTextSpan(command='\\stopTextSpan'))

4. CLEFS

Abjad 3.1 adds support for LilyPond varC and tenorvarC clef types.
5. DOCS

   - Cleaned up Ligeti example. Closes #896
   - Corrected assignability docs. Closes #897
   - Cleaned up Bartók example. Closes #1059
   - Added support for cropped PNGs. Closes #1066

6. DURATIONS

Duration multipliers are now implemented as an explicit property on notes,
rests and chords in Abjad 3.1. Closes #902:

OLD: abjad.attach(abjad.Multiplier((1, 2)), note)
NEW: note.multiplier = (1, 2)

Forbidden duration spelling has changed like this:

OLD: abjad.LeafMaker.forbidden_duration
NEW: abjad.LeafMaker.forbidden_note_duration
NEW: abjad.LeafMaker.forbidden_rest_duration

Monotonicity spelling has changed like this:

OLD: abjad.LeafMaker.decrease_monotonic=True
OLD: abjad.Meter.decrease_monotonic=True
OLD: abjad.NoteMaker.decrease_monotonic=True
OLD: abajd.Tuplet.from_duration_and_ratio(..., decrease_monotonic=True)

NEW: abjad.LeafMaker.increase_monotonic=None
NEW: abjad.Meter.increase_monotonic=None
NEW: abjad.NoteMaker.increase_monotonic=None
NEW: abajd.Tuplet.from_duration_and_ratio(..., increase_monotonic=None)

A new abjad.Duration.from_clock_string() constructor is available:

>>> abjad.Duration.from_clock_string("1'59''")
Duration(119, 1)

Durations may now be labeled in seconds:

>>> abjad.label().with_durations(..., in_seconds=None)

The interpreter representation of abjad.Offset has been changed to display
grace offsets.
7. GRACE MUSIC

Abjad 3.1 improves the ways grace notes are created, inspected and
iterated. The old abjad.GraceContainer class has been renamed
abjad.BeforeGraceContainer; the old abjad.AcciaccaturaContainer and
abjad.AppoggiaturaContainer classes have been removed; an entirely new
abjad.OnBeatGraceContainer class has been added to model Ferneyhough-style
on-beat runs of appoggiaturas.

The resulting collection of classes exhibits a 3-way symmetry:

   - abjad.BeforeGraceContainer
   - abjad.OnBeatGraceContainer
   - abjad.AfterGraceContainer

This series of commits closes #1032, #1076, #1104, #1105, #1107, #1120,
#1121.

The new on-beat grace container works like this:

>>> music_voice = abjad.Voice("c'4 d' e' f'", name="Music_Voice")
>>> string = "g'8 a' b' c'' d'' c'' b' a' b' c'' d''"
>>> result = abjad.on_beat_grace_container(
...     string, music_voice[1:3], leaf_duration=(1, 30), do_not_slash=True
... )
>>> staff = abjad.Staff([music_voice])
>>> abjad.show(staff)

[image: on-beat-grace-container]

All three grace containers work together like this:

>>> music_voice = abjad.Voice("c'4 d' e' f'", name="Music_Voice")
>>> 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], do_not_slash=True,
... )
>>> abjad.attach(abjad.Articulation(">"), container[0])
>>> container = abjad.AfterGraceContainer("fs'16")
>>> abjad.attach(container, music_voice[3])
>>> staff = abjad.Staff([music_voice])
>>> abjad.show(staff)

[image: grace-containers]

Refer to this figure for the examples below.

Grace iteration is now controlled by a ternary flag. Set grace=None to
iterate grace and nongrace components together:

>>> for component in abjad.iterate(staff).components():
...     component
Staff("c'4 d'4 e'4 f'4")
Note("c'4")
BeforeGraceContainer("cs'16")
Note("cs'16")
Note("d'4")
OnBeatGraceContainer("<g' \\tweak Accidental.stencil ##f e'>16 * 1
gs'16 * 1 a'16 * 1 as'16 * 1")
Note("<g' \\tweak Accidental.stencil ##f e'>16 * 1")
Note("gs'16 * 1")
Note("a'16 * 1")
Note("as'16 * 1")
Note("e'4")
Note("f'4")
AfterGraceContainer("fs'16")
Note("fs'16")

Set grace=True to iterate only grace components:

>>> for component in abjad.iterate(staff).components(grace=True):
...     component
BeforeGraceContainer("cs'16")
Note("cs'16")
OnBeatGraceContainer("<g' \\tweak Accidental.stencil ##f e'>16 * 1
gs'16 * 1 a'16 * 1 as'16 * 1")
Note("<g' \\tweak Accidental.stencil ##f e'>16 * 1")
Note("gs'16 * 1")
Note("a'16 * 1")
Note("as'16 * 1")
AfterGraceContainer("fs'16")
Note("fs'16")

Set grace=False to iterate only nongrace components:

>>> for component in abjad.iterate(staff).components(grace=False):
...     component
Staff("c'4 d'4 e'4 f'4")
Note("c'4")
Note("d'4")
Note("e'4")
Note("f'4")

Use abjad.inspect().leaf() to inspect grace notes immediately before or
after any note, rest or chord:

>>> for current_leaf in abjad.select(staff).leaves():
...     previous_leaf = abjad.inspect(current_leaf).leaf(-1)
...     next_leaf = abjad.inspect(current_leaf).leaf(1)
...     print(f"previous leaf: {repr(previous_leaf)}")
...     print(f"current leaf:  {repr(current_leaf)}")
...     print(f"next leaf:     {repr(next_leaf)}")
...     print("---")
previous leaf: None
current leaf:  Note("c'4")
next leaf:     Note("cs'16")
---
previous leaf: Note("c'4")
current leaf:  Note("cs'16")
next leaf:     Note("d'4")
---
previous leaf: Note("cs'16")
current leaf:  Note("d'4")
next leaf:     Chord("<e' g'>16")
---
previous leaf: Note("d'4")
current leaf:  Chord("<e' g'>16")
next leaf:     Note("gs'16")
---
previous leaf: Chord("<e' g'>16")
current leaf:  Note("gs'16")
next leaf:     Note("a'16")
---
previous leaf: Note("gs'16")
current leaf:  Note("a'16")
next leaf:     Note("as'16")
---
previous leaf: Note("a'16")
current leaf:  Note("as'16")
next leaf:     Note("e'4")
---
previous leaf: Note("as'16")
current leaf:  Note("e'4")
next leaf:     Note("f'4")
---
previous leaf: Note("e'4")
current leaf:  Note("f'4")
next leaf:     Note("fs'16")
---
previous leaf: Note("f'4")
current leaf:  Note("fs'16")
next leaf:     None
---

Grace note timespans work like this:

>>> for component in abjad.select(voice).components():
...     timespan = abjad.inspect(component).timespan()
...     print(f"{repr(component):30} {repr(timespan)}")
<Staff{1}>                     Timespan(Offset((0, 1)), Offset((1, 1)))
<Voice-"Music_Voice"{4}>       Timespan(Offset((0, 1)), Offset((1, 1)))
Note("c'4")                    Timespan(Offset((0, 1)), Offset((1, 4)))
BeforeGraceContainer("cs'16")  Timespan(Offset((1, 4),
displacement=Duration(-1, 16)), Offset((1, 4)))
Note("cs'16")                  Timespan(Offset((1, 4),
displacement=Duration(-1, 16)), Offset((1, 4)))
Note("d'4")                    Timespan(Offset((1, 4)), Offset((1, 2)))
<<<2>>>                        Timespan(Offset((1, 2)), Offset((3, 4)))
OnBeatGraceContainer("<e' g'>16 gs'16 a'16 as'16") Timespan(Offset((1,
2)), Offset((1, 2), displacement=Duration(1, 4)))
Chord("<e' g'>16")             Timespan(Offset((1, 2)), Offset((1, 2),
displacement=Duration(1, 16)))
Note("gs'16")                  Timespan(Offset((1, 2),
displacement=Duration(1, 16)), Offset((1, 2), displacement=Duration(1,
8)))
Note("a'16")                   Timespan(Offset((1, 2),
displacement=Duration(1, 8)), Offset((1, 2), displacement=Duration(3,
16)))
Note("as'16")                  Timespan(Offset((1, 2),
displacement=Duration(3, 16)), Offset((1, 2), displacement=Duration(1,
4)))
Voice("e'4", name='Music_Voice') Timespan(Offset((1, 2)), Offset((3, 4)))
Note("e'4")                    Timespan(Offset((1, 2),
displacement=Duration(1, 4)), Offset((3, 4)))
Note("f'4")                    Timespan(Offset((3, 4)), Offset((1, 1)))
AfterGraceContainer("fs'16")   Timespan(Offset((1, 1),
displacement=Duration(-1, 16)), Offset((1, 1)))
Note("fs'16")                  Timespan(Offset((1, 1),
displacement=Duration(-1, 16)), Offset((1, 1)))

Grace notes may now be slurred:

>>> voice = abjad.Voice("c'4 d'4 e'4 f'4")
>>> container = abjad.BeforeGraceContainer("cs'16")
>>> abjad.attach(container, voice[1])
>>> leaves = abjad.select(voice).leaves()
>>> abjad.slur(leaves[1:3])
>>> abjad.show(voice)

[image: grace-note-slur]

CHANGED:

OLD: abjad.GraceContainer
NEW: abjad.BeforeGraceContainer

OLD: abjad.inspect().grace_container()
NEW: abjad.inspect().before_grace_container()

OLD: abjad.select().components(grace_notes=True)
NEW: abjad.select().components(grace=True)

OLD: abjad.select().leaves(grace_notes=True)
NEW: abjad.select().leaves(grace=True)

OLD: abjad.inspect().grace_note()
NEW: abjad.inspect().grace()

Also:

   - Fixed abjad.AfterGraceContainer chords. Closes #1074
   - Fixed score-initial grace note measure numbers. Closes #1098
   - Removed do_not_iterate_grace_containers=None keyword
   - Removed abjad.inspect().parentage(grace=None) keyword

8. INSPECTION

   - Removed abjad.inspect().vertical_moment()
   - Removed abjad.inspect().vertical_moment_at()
   - Preserved abjad.iterate().vertical_moments()
   - Removed abjad.inspect().contents(..., include_self=True)
   - Removed abjad.inspect().descendants(..., include_self=True)
   - Removed abjad.inspect().parentage(..., include_self=True)
   - Restricted abjad.inspect().leaf(n) such that n in (-1, 0, 1)

9. IO

   - Added abjad.IOManager.run_lilypond(..., liypond_log_file_path=None)
    keyword
   - Added abjad.Path.remove_lilypond_warnings()
   - Cleaned up abjad.IOManager Unicode decode handling
   - Removed abjad.ImportManager
   - Set explicit encoding in abjad.IOManager.save_last_ly_as_pdf(). Closes
   #1090

10. LITERAL MARKUP

Abjad 3.1 adds support for literal markup. Markup with pound signs, double
quotes are now possible for the first time with the literal=True keyword.
Closes #397:

>>> markup = abjad.Markup(
... r'\markup \with-color #red { \note #"4" #1 }',
... direction=abjad.Up,
... literal=True,
... )
>>> note = abjad.Note("cs'4")
>>> abjad.attach(markup, note)
>>> abjad.show(note)

[image: literal-markup]

Fixed tweaked markup bug. Closes #806
11. MATHTOOLS

Abjad 3.1 mathtools functions are now housed in a consolidated
mathtools.py file.
Closes #1084.
12. MUTATION

   - Fixed now-power-of-two abjad.mutate().split() bug. Closes #1018
   - Removed abjad.mutate().split(..., tie_split_notes=True) keyword.
   Closes #1021, #1092

13. OBJECT TEMPLATING

Abajd 3.1 extends abjad.new() with support for variable-length *arguments.
Closes #1085.
14. PARENT INDEXING

Abjad 3.1 adds support for parent indexing with the new n=0 keyword
available in abjad.Parentage.get().

Get the first (innermost), second and last (outermost) voices in the
parentage of leaf like this:

>>> abjad.inspect(leaf).parentage().get(prototype=abjad.Voice, n=0)
>>> abjad.inspect(leaf).parentage().get(prototype=abjad.Voice, n=1)
>>> abjad.inspect(leaf).parentage().get(prototype=abjad.Voice, n=-1)

CHANGED:

OLD: abjad.inspect().is_wellformed()
NEW: abjad.inspect().wellformed()

OLD: abjad.parentage().logical_voice property
NEW: abjad.parentage().logical_voice() method

OLD: Parentage.score_index property
NEW: Parentage.score_index() method

OLD: Parentage.get_first()
NEW: Parentage.get(..., n=0)

OLD: abjad.Parentage.depth property
NEW: abjad.Parentage.count() method

OLD: abjad.Parentage.tuplet_depth property
NEW: abjad.Parentage.count(prototype=abjad.Tuplet) method

15. PARSER

   - Fixed parser multimeasure rest multipliers. Closes #1049
   - Fixed parser \breathe. Closes #1119

16. SELECTORS

Abjad 3.1 supports the patterned inclusion of components with the new
abjad.select().get() selector.

Gets every other note:

>>> staff = abjad.Staff("c'8 d' e' f' g' a' b' c''")
>>> for note in abjad.select(staff).notes().get([0], 2):
...     print(note)
c'8
e'8
g'8
b'8

Gets notes 2 and 5:

>>> staff = abjad.Staff("c'8 d' e' f' g' a' b' c''")
>>> for note in abjad.select(staff).notes().get([2, 5]):
...     print(note)
e'8
a'8

Abjad 3.1 supports the patterned exclusion of components with the new
abjad.select().exclude() selector.

Excludes every other note:

>>> staff = abjad.Staff("c'8 d' e' f' g' a' b' c''")
>>> for note in abjad.select(staff).notes().exclude([0], 2):
...     print(note)
d'8
f'8
a'8
c''8

Excludes notes 2 and 5:

>>> staff = abjad.Staff("c'8 d' e' f' g' a' b' c''")
>>> for note in abjad.select(staff).notes().exclude([2, 5]):
...     print(note)
d'8
f'8
a'8
c''8

Abjad 3.1 supports selector concatenation with __add__(). Closes #1029:

>>> staff = abjad.Staff("c'8 r8 d'8 e'8 r8 f'8 g'8 a'8")
>>> left = abjad.select().leaves()[:2]
>>> right = abjad.select().leaves()[-2:]
>>> selector = left + right
>>> selector(staff)
Selection([Note("c'8"), Rest('r8'), Note("g'8"), Note("a'8")])

Also:

   - Added abjad.select().logical_tie()
   - Added abjad.select().runs() grace note support
   - Added abjad.Selection.filter_by_duration(..., preprolated=None) keyword
   - Replaced abjad.inspect().tuplet() with abjad.select().tuplet()

17. SEQUENCE MANIPULATION

Abjad 3.1 adds a new abjad.Sequence.replace() method:

>>> sequence = abjad.sequence([0, 2, 3, 0, 2, 3, 0, 2, 3])
>>> sequence.replace(0, 1)
Sequence([1, 2, 3, 1, 2, 3, 1, 2, 3])

18. TAGS

Abjad 3.1 adds support for tags. Abjad tags are user-defined strings you
can add to the Abjad objects you create. Abjad tags appear as LilyPond
comments following the special two-character string %!. Use Abjad tags to
help debug complex LilyPond output. Set strict=None to an integer-valued
column number to align Abjad tags in LilyPond output.

Tag indicators like this:

>>> note = abjad.Note("c'4")
>>> tag = abjad.Tag("this is a tag")
>>> abjad.attach(abjad.Staccato(), note, tag=tag)
>>> abjad.f(note, strict=20)
c'4
\staccato           %! this is a tag

Tag notes like this:

>>> tag = abjad.Tag("NoteMaker")
>>> maker = abjad.NoteMaker(tag=tag)
>>> notes = maker([0], [(1, 16), (1, 8), (1, 8)])
>>> staff = abjad.Staff(notes)
>>> abjad.f(staff, strict=20)
\new Staff
{
    c'16        %! NoteMaker
    c'8         %! NoteMaker
    c'8         %! NoteMaker
}

Tag tuplets like this:

>>> tag = abjad.Tag("Tuplet")
>>> tuplet = abjad.Tuplet((2, 3), "c'4 d' e'", tag=tag)
>>> abjad.f(tuplet, strict=20)
\times 2/3 {        %! Tuplet
    c'4
    d'4
    e'4
}                   %! Tuplet

Tag contexts like this:

>>> tag = abjad.Tag("Voice")
>>> voice = abjad.Voice("c'4 d' e' f'", tag=tag)
>>> tag = abjad.Tag("Staff")
>>> staff = abjad.Staff([voice], tag=tag)
>>> tag = abjad.Tag("Score")
>>> score = abjad.Score([staff], tag=tag)
>>> abjad.f(score, strict=20)
\new Score          %! Score
<<                  %! Score
    \new Staff      %! Staff
    {               %! Staff
        \new Voice  %! Voice
        {           %! Voice
            c'4
            d'4
            e'4
            f'4
        }           %! Voice
    }               %! Staff
>>                  %! Score

Tag tweaks like this:

>>> staff = abjad.Staff("c'4 d' e' f'")
>>> markup = abjad.Markup("Allegro", direction=abjad.Up).italic()
>>> tag = abjad.tags.ONLY_PARTS
>>> abjad.tweak(markup, tag=tag).color = "red"
>>> abjad.attach(markup, staff[0])
>>> abjad.f(staff)
\new Staff
{
    c'4
    - \tweak color #red %! +PARTS
    ^ \markup {
        \italic
            Allegro
        }
    d'4
    e'4
    f'4
}

Also:

   - abjad.LeafMaker output may be tagged
   - abjad.NoteMaker output may be tagged
   - score templates may be tagged
   - rhythm-makers may be tagged

19. TIES

Abjad 3.1 replaces the old tie spanner with two new indicators and a
factory function. Closes #1033, #1097:

   - Added abjad.Tie
   - Added abjad.RepeatTie
   - Added abjad.tie()

Abjad 3.1 cleans up repeat-tie handling. Closes #1099:

   - Removed repeat_ties=None keyword from abjad.mutate().rewrite_meter()
   - Removed repeat_ties=None keyword from abjad.mutate().split()
   - Removed repeat_ties=None keyword from abjad.NoteMaker
   - Removed repeat_ties=None keyword from abjad.LeafMaker

20. TIME SIGNATURES

Abjad 3.1 suppresses LilyPond’s “strange time signature” warning for
non-power-of-two time signatures like 7/12.
21. TIMESPANS

Frozen timespan expressions are available in Abjad 3.1 with new
abjad.timespan() factory function. Empty arguments initialize an expression
that can be used as a timespan initializer:

>>> expression = abjad.timespan()
>>> expression(start_offset=0, stop_offset=(1, 4))
Timespan(start_offset=Offset(0, 1), stop_offset=Offset(1, 4))

Abjad 3.1 adds support for abjad.Timespan.__contains__():

>>> timespan = abjad.timespan(0, (1, 4))

>>> -1 in timespan
False

>>> 0 in timespan
True

>>> Offset(1, 8) in timespan
True

>>> Offset(1, 4) in timespan
True

>>> Offset(1, 2) in timespan
False

>>> abjad.timespan(0, (1, 4)) in timespan
True

>>> abjad.timespan((1, 16), (2, 16)) in timespan
True

>>> abjad.timespan(0, (1, 2)) in timespan
False

CHANGED:

OLD: abjad.timespan_2_delays_timespan_1()
NEW: abjad.timespan().delays_timespan()

OLD:

    abjad.timespans.OffsetTimespanTimeRelation
    abjad.timespans.offset_happens_after_timespan_starts()
    abjad.timespans.offset_happens_after_timespan_stops()
    abjad.timespans.offset_happens_before_timespan_starts()
    abjad.timespans.offset_happens_before_timespan_stops()
    abjad.timespans.offset_happens_during_timespan()
    abjad.timespans.offset_happens_when_timespan_starts()
    abjad.timespans.offset_happens_when_timespan_stops()

NEW:

    timespan.start_offset < offset
    timespan.stop_offset < offset
    offset < timespan.start_offset
    offset < timespan.stop_offset
    offset in timespan
    offset == timespan.start_offset
    offset == timespan.stop_offset

REMOVED. Removed timespantools functions. Use abjad.Timespan methods
instead.

timespan_2_contains_timespan_1_improperly()
timespan_2_curtails_timespan_1()
timespan_2_happens_during_timespan_1()
timespan_2_intersects_timespan_1()
timespan_2_is_congruent_to_timespan_1()
timespan_2_overlaps_all_of_timespan_1()
timespan_2_overlaps_only_start_of_timespan_1()
timespan_2_overlaps_only_stop_of_timespan_1()
timespan_2_overlaps_start_of_timespan_1()
timespan_2_overlaps_stop_of_timespan_1()
timespan_2_starts_after_timespan_1_starts()
timespan_2_starts_after_timespan_1_stops()
timespan_2_starts_before_timespan_1_starts()
timespan_2_starts_before_timespan_1_stops()
timespan_2_starts_during_timespan_1()
timespan_2_starts_when_timespan_1_starts()
timespan_2_starts_when_timespan_1_stops()
timespan_2_stops_after_timespan_1_starts()
timespan_2_stops_after_timespan_1_stops()
timespan_2_stops_before_timespan_1_starts()
timespan_2_stops_before_timespan_1_stops()
timespan_2_stops_during_timespan_1()
timespan_2_stops_when_timespan_1_starts()
timespan_2_stops_when_timespan_1_stops()
timespan_2_trisects_timespan_1()

Also:

   - Removed abjad.TimeRelation

Reply via email to