Releases: Abjad/abjad
v3.9
Abjad 3.9 works with Python 3.10 and LilyPond 2.23.6 (and later).
#1453: Changed abjad/_stylesheets to abjad/scm
Users will need to update the way LilyPond is invoked:
OLD: lilypond --include=~/abjad/_stylesheets
NEW: lilypond --include=~/abjad/scm
#1452: Alphabetized all format contributions by format site.
The lexical order of commands in LilyPond output no longer depends on the (dynamic) order in which indicators are attached to leaves.
Alphabetized tags, and offset tags two spaces to the right in LilyPond output.
Added abjad.lilypond(..., site_comments=False)
keyword. Set to true to debug the names and contents of every format site.
Diffs of existing scores ported to Abjad 3.9 will likely appear to have changed a lot from Abjad 3.8. But note that no functionality has changed: all that has changed is the order of LilyPond commands in the LilyPond output Abjad creates.
#1447: Cleaned up typings.py.
Removed typing classes from global namespace.
REMOVED:
abjad.typings.DurationSequenceTyping
abjad.typings.IntegerSequence
abjad.typings.Number
abjad.typings.NumberPair
abjad.typings.OffsetSequenceTyping
abjad.typings.RatioSequenceTyping
RENAMED:
OLD: abjad.DurationTyping
NEW: abjad.typings.Duration
OLD: abjad.OffsetTyping
NEW: abjad.typings.Offset
OLD: abjad.PatternTyping
NEW: abjad.typings.Pattern
OLD: abjad.RatioTyping
NEW: abjad.typings.Ratio
v3.8
Abjad 3.8 works with LilyPond 2.23.6, and later.
The functionality of Abjad 3.7 and 3.8 otherwise remains the same.
#1444: Bumped LilyPond to 2.23.6.
LilyPond 2.23 introduces a few breaking changes.
One shows up in stylesheets:
OLD: \on-the-fly #print-page-number-check-first
NEW: \if \should-print-page-number
Another shows up in color quoting:
OLD:
abjad-color-music = #(
define-music-function (parser location color music) (symbol? ly:music?)
#{
\once \override Accidental.color = #(x11-color #'color)
...
$music #})
NEW:
abjad-color-music = #(
define-music-function (parser location color music) (symbol? ly:music?)
#{
\once \override Accidental.color = #(x11-color color)
...
$music #})
Run LilyPond's convert-ly
script on your scores and stylesheets to locate these changes.
#1442: Added py.typed marker.
Abjad includes inline typehints that can be read by typecheckers like mypy. Users of Abjad 3.7 have to tell mypy where Abjad is installed by setting the MYPYPATH
environment variable. But this is silly because mypy already knows the location installed packages, including Abjad. Including an (empty) py.typed
file in Abjad's source directory fixes this. Users of Abjad 3.8 no longer need to set MYPYPATH
to use mypy with Abjad.
v3.7
Changed in Abjad 3.7
Changes to Abjad 3.7 (2020-04-06) since Abjad 3.6 (2020-03-01).
BREAKING CHANGE (#1440). Cleaned up tweaks.
Removed tweaks
from all indicators. Use the new abjad.bundle()
function to create indicators "bundled" with tweaks. Then attach the resulting abjad.Bundle
to a note, rest or chord:
OLD: arpeggio = abjad.Arpeggio()
abjad.tweak(arpeggio).color = "#red"
abjad.attach(arpeggio, ...)
NEW: arpeggio = abjad.Arpeggio()
bundle = abjad.bundle(arpeggio, r"- \tweak color #red")
abjad.attach(bundle, ...)
OLD: articulation = abjad.Articulation(".")
abjad.tweak(articulation).color = "#red"
abjad.attach(articulation, ...)
NEW: articulation = abjad.Articulation(".")
bundle = abjad.bundle(articulation, r"- \tweak color #red")
abjad.attach(bundle, ...)
OLD: bend_after = abjad.BendAfter()
abjad.tweak(bend_after).color = "#red"
abjad.attach(bend_after, ...)
NEW: bend_after = abjad.BendAfter()
bundle = abjad.bundle(bend_after, r"- \tweak color #red")
abjad.attach(bundle, ...)
etc.
Two new frozen dataclasses are included in this commit. These are abjad.Bundle
and abjad.Tweak
:
>>> articulation = abjad.Articulation(".")
>>> bundle = abjad.bundle(
articulation,
r"- \tweak color #red",
r"- \tweak padding 1.25",
)
>>> bundle.indicator
Articulation(name='.')
>>> for _ in bundle.tweaks: _
...
Tweak(string='- \\tweak color #red', tag=None)
Tweak(string='- \\tweak padding 1.25', tag=None)
Inspect tweak properties like this:
>>> tweak = bundle.tweaks[0]
>>> tweak
Tweak(string='- \\tweak color #red', tag=None)
>>> tweak.string
'- \\tweak color #red'
>>> tweak.attribute()
'color'
>>> tweak.post_event()
True
>>> tweak.value()
'#red'
abjad.get.indicator()
knows about bundled indicators:
>>> note = abjad.Note("c'4")
>>> abjad.attach(bundle, note)
>>> abjad.get.indicator(note, abjad.Articulation)
Articulation(name='.')
Use wrapper properties to work with the bundle itself:
>>> wrapper = abjad.get.wrapper(note, abjad.Articulation)
>>> bundle = wrapper.indicator
>>> bundle.indicator
Articulation(name='.')
>>> for _ in bundle.tweaks: _
...
Tweak(string='- \\tweak color #red', tag=None)
Tweak(string='- \\tweak padding 1.25', tag=None)
Continue to use the old abjad.tweak()
function to tweak note-heads and tuplets. But note that you must now pass a tweak object to the function:
>>> note = abjad.Note("c'4")
>>> tweak = abjad.Tweak(r"\tweak color #red")
>>> abjad.tweak(note.note_head, tweak)
>>> for _ in note.note_head.tweaks: _
...
Tweak(string='\\tweak color #red', tag=None)
Additionally, removing the (mutable) tweaks
means that almost all Abjad indicators are now dataclasses decorated with frozen=True
:
abjad.Arpeggio
abjad.Articulation
abjad.BarLine
abjad.BeamCount
abjad.BendAfter
abjad.BreathMark
abjad.Clef
abjad.ColorFingering
abjad.Fermata
abjad.Glissando
abjad.KeyCluster
abjad.LilyPondLiteral
abjad.Mode
abjad.KeySignature
abjad.LaissezVibrer
abjad.MarginMarkup
abjad.Markup
abjad.Ottava
abjad.RehearsalMark
abjad.Repeat
abjad.RepeatTie
abjad.StaffChange
abjad.StartBeam
abjad.StartGroup
abjad.StartHairpin
abjad.StartMarkup
abjad.StartPhrasingSlur
abjad.StartPianoPedal
abjad.StartSlur
abjad.StartTextSpan
abjad.StartTrillSpan
abjad.StemTremolo
abjad.StopBeam
abjad.StopGroup
abjad.StopHairpin
abjad.StopPhrasingSlur
abjad.StopPianoPedal
abjad.StopSlur
abjad.StopTextSpan
abjad.StopTrillSpan
abjad.Tie
Objects created from these classes can not be changed after you create them, but otherwise behave the same as before. Note, however, that abjad.KeySignature
objects must now be initialized with explicit pitch-class and mode objects:
OLD: abjad.KeySignature("e", "major")
NEW: abjad.KeySignature(abjad.NamedPitchClass("e"), abjad.Mode("major"))
The abjad.Dynamic
, abjad.MetricModulation
, abjad.MetronomeMark
, abjad.TimeSignature
and instrument classes will be frozen in Abjad 3.8 but remain mutable in Abjad 3.7.
This commit also changes the order that articulations, spanners and other items appear in the LilyPond output that Abjad produces. Previous versions of Abjad relied in part on the (dynamic) order in which users attached such objects to score components. Abjad 3.7 sorts these elements by class name to better standardize the (lexical) order of such commands in LilyPond output.
BREAKING CHANGE (#1429). Moved direction from indicators to attach.
The 10 indicators that previously implemented a direction
attribute no longer implement that attribute. Use the new abjad.attach(..., direction=None)
keyword instead:
OLD: articulation = abjad.Articulation(".", direction=abjad.Up)
abjad.attach(articulation, note)
NEW: articulation = abjad.Articulation(".")
abjad.attach(articulation, note, direction=abjad.UP)
OLD: dynamic = abjad.Dynamic("f", direction=abjad.Up)
abjad.attach(dynamic, note)
NEW: dynamic = abjad.Dynamic("f")
abjad.attach(dynamic, note, direction=abjad.UP)
OLD: markup = abjad.Markup(r"\markup Allegro", direction=abjad.Up)
abjad.attach(markup, note)
NEW: markup = abjad.Markup(r"\markup Allegro")
abjad.attach(dynamic, markup, direction=abjad.UP)
OLD: repeat_tie = abjad.RepeatTie(direction=abjad.Up)
abjad.attach(repeat_tie, note)
NEW: repeat_tie = abjad.RepeatTie()
abjad.attach(repeat_tie, note, direction=abjad.UP)
OLD: start_beam = abjad.StartBeam(direction=abjad.Up)
abjad.attach(start_beam, note)
NEW: articulation = abjad.Articulation(".")
abjad.attach(articulation, note, direction=abjad.UP)
OLD: start_hairpin = abjad.StartHairpin(direction=abjad.Up)
abjad.attach(start_hairpin, note)
NEW: start_hairpin = abjad.StartHairping()
abjad.attach(start_hairpin, note, direction=abjad.UP)
OLD: start_phrasing_slur = abjad.StartPhrasingSlur(direction=abjad.Up)
abjad.attach(start_phrasing_slur, note)
NEW: start_phrasing_slur = abjad.StartPhrasingSlur()
abjad.attach(start_phrasing_slur, note, direction=abjad.UP)
OLD: start_slur = abjad.StartSlur(direction=abjad.Up)
abjad.attach(start_slur, note)
NEW: start_slur = abjad.StartSlur()
abjad.attach(start_slur, note, direction=abjad.UP)
OLD: start_text_span = abjad.StartTextSpan(direction=abjad.Up)
abjad.attach(start_text_span, note)
NEW: start_text_span = abjad.StartTextSpan()
abjad.attach(start_text_span, note, direction=abjad.UP)
OLD: tie = abjad.Tie(direction=abjad.Up)
abjad.attach(tie, note)
NEW: tie = abjad.Tie()
abjad.attach(tie, note, direction=abjad.UP)
Additionally, abjad.ColorFingering
and abjad.KeyCluster
should now also be directed with the abjad.attach(..., direction=None)
keyword:
OLD: fingering = abjad.ColorFingering(1)
abjad.attach(fingering, note)
NEW: fingering = abjad.ColorFingering(1)
abjad.attach(fingering, note, direction=abjad.UP)
OLD: cluster = abjad.KeyCluster()
abjad.attach(cluster, note)
NEW: cluster = abjad.KeyCluster()
abjad.attach(cluster, note, direction=abjad.UP)
Closes #748, from August 2016, Abjad's oldest open issue.
BREAKING CHANGE (#1428, #1409). Removed abjad.Selection
.
Abjad 3.6 (2020-03-01) deprecated the abjad.Selection
class. Abjad 3.7 now removes abjad.Selection
from the system. The old abjad.select()
factory function has been replaced by the vanilla functions housed in select.py
:
OLD:
abjad.select(...).chord(n)
abjad.select(...).chords()
abjad.select(...).components()
abjad.select(...).exclude([0], 2)
abjad.select(...).filter(lambda _: len(_) == 2)
abjad.select(...).get([0], 2)
abjad.select(...).group_by(lambda _: getattr(_, "foo"))
abjad.select(...).group_by_contiguity()
abjad.select(...).group_by_duration()
abjad.select(...).group_by_length()
abjad.select(...).group_by_measure()
abjad.select(...).group_by_pitch()
abjad.select(...).leaf(n)
abjad.select(...).leaves()
abjad.select(...).logical_tie(n)
abjad.select(...).logical_ties()
abjad.select(...).nontrivial()
abjad.select(...).note(n)
abjad.select(...).notes()
abjad.select(...).partition_by_counts([4, 4, 2], cyclic=True)
abjad.select(...).partition_by_ratio((2, 1))
abjad.select(...).rest(n)
abjad.select(...).rests()
abjad.select(...).run(n)
abjad.select(...).runs()
abjad.select(...).top()
abjad.select(...).tuplet(n)
abjad.select(...).tuplets()
abjad.select(...).with_next_leaf()
abjad.select(...).with_previous_leaf()
NEW:
abjad.select.chord(..., n)
abjad.select.chords(..., )
abjad.select.components(..., )
abjad.select.exclude(..., [0], 2)
abjad.select.filter(..., lambda _: len(_) == 2)
abjad.select.get(..., [0], 2)
abjad.select.group_by(..., lambda _: getattr(_, "foo"))
abjad.select.group_by_contiguity(..., )
abjad.select.group_by_duration(..., )
abjad.select.group_by_length(..., )
abjad.select.group_by_measure(..., )
abjad.select.group_by_pitch(..., )
abjad.select.leaf(..., n)
abj...
v3.6
Changed in Abjad 3.6
Changes to Abjad 3.6 (2022-03-01) since Abjad 3.5 (2022-02-01).
PERFORMANCE INCREASES. Abjad 3.6 runs significantly faster than previous versions of the system: user code rendering two or more pages of music runs 200% to 800% faster than before. Performance increases came from removing inspect-heavy functions, and from optimizing score updates. Total performance increase depends on the number of context indicators (like clefs and time signatures) used, and on the amount of looping used to find indicators in a score.
BREAKING CHANGE (#1407): The abjad.Selection
class is deprecated will be completely removed in Abjad 3.7.
CHANGED. In general, remove all `isinstance(..., abjad.Selection)` from your code:
Abjad 3.6 now passes built-in lists of components instead of custom selection
objects. Container slices now return a list:
OLD:
staff = abjad.Staff("c'4 d' e' f'")[:]
abjad.Selection(items=[Note("c'4"), Note("d'4"), Note("e'4"), Note("f'4")])
NEW:
staff = abjad.Staff("c'4 d' e' f'")[:]
[Note("c'4"), Note("d'4"), Note("e'4"), Note("f'4")]
CHANGED. `abjad.select.foo(...)` and `abjad.iterate.foo(...)` now match.
Selecting components means calling functions; class creation is no longer required:
OLD:
abjad.select(...).chord(n)
abjad.select(...).chords()
abjad.select(...).components()
abjad.select(...).exclude([0], 2)
abjad.select(...).filter(lambda _: len(_) == 2)
abjad.select(...).get([0], 2)
abjad.select(...).group_by(lambda _: getattr(_, "foo"))
abjad.select(...).group_by_contiguity()
abjad.select(...).group_by_duration()
abjad.select(...).group_by_length()
abjad.select(...).group_by_measure()
abjad.select(...).group_by_pitch()
abjad.select(...).leaf(n)
abjad.select(...).leaves()
abjad.select(...).logical_tie(n)
abjad.select(...).logical_ties()
abjad.select(...).nontrivial()
abjad.select(...).note(n)
abjad.select(...).notes()
abjad.select(...).partition_by_counts([4, 4, 2], cyclic=True)
abjad.select(...).partition_by_ratio((2, 1))
abjad.select(...).rest(n)
abjad.select(...).rests()
abjad.select(...).run(n)
abjad.select(...).runs()
abjad.select(...).top()
abjad.select(...).tuplet(n)
abjad.select(...).tuplets()
abjad.select(...).with_next_leaf()
abjad.select(...).with_previous_leaf()
NEW:
abjad.select.chord(..., n)
abjad.select.chords(..., )
abjad.select.components(..., )
abjad.select.exclude(..., [0], 2)
abjad.select.filter(..., lambda _: len(_) == 2)
abjad.select.get(..., [0], 2)
abjad.select.group_by(..., lambda _: getattr(_, "foo"))
abjad.select.group_by_contiguity(..., )
abjad.select.group_by_duration(..., )
abjad.select.group_by_length(..., )
abjad.select.group_by_measure(..., )
abjad.select.group_by_pitch(..., )
abjad.select.leaf(..., n)
abjad.select.leaves(..., )
abjad.select.logical_tie(..., n)
abjad.select.logical_ties(..., )
abjad.select.nontrivial(..., )
abjad.select.note(..., n)
abjad.select.notes(..., )
abjad.select.partition_by_counts(..., [4, 4, 2], cyclic=True)
abjad.select.partition_by_ratio(..., (2, 1))
abjad.select.rest(..., n)
abjad.select.rests(..., )
abjad.select.run(..., n)
abjad.select.runs(..., )
abjad.select.top(..., )
abjad.select.tuplet(..., n)
abjad.select.tuplets(..., )
abjad.select.with_next_leaf(..., )
abjad.select.with_previous_leaf(..., )
Dot-chained syntax continues to be allowed in Abjad 3.6 but will be removed in Abjad
3.7. Rewrite dot-chained method calls like this:
Example 1:
OLD:
result = abjad.select(...).tuplets()[:4].leaves()
NEW:
result = abjad.select.tuplets(...)[:4]
result = abjad.select.leaves(result)
Example 2:
OLD:
result = abjad.select(...).leaves().group_by_measure().get([0], 2)
NEW:
result = abjad.select.leaves(...)
result = abjad.select.group_by_measure(result)
result = abjad.select.get(result, [0], 2)
BREAKING CHANGE (#1415): Replaced abjad.Sequence
with sequence.py
module:
OLD:
abjad.Sequence(...).filter()
abjad.Sequence(...).flatten()
abjad.Sequence(...).group_by()
abjad.Sequence(...).is_decreasing()
abjad.Sequence(...).is_increasing()
abjad.Sequence(...).is_permutation()
abjad.Sequence(...).is_repetition_free()
abjad.Sequence(...).join()
abjad.Sequence(...).map()
abjad.Sequence(...).nwise()
abjad.Sequence(...).partition_by_counts()
abjad.Sequence(...).partition_by_ratio_of_lengths()
abjad.Sequence(...).partition_by_ratio_of_weights()
abjad.Sequence(...).partition_by_weights()
abjad.Sequence(...).permute()
abjad.Sequence(...).remove()
abjad.Sequence(...).remove_repeats()
abjad.Sequence(...).repeat()
abjad.Sequence(...).repeat_to_length()
abjad.Sequence(...).repeat_to_weight()
abjad.Sequence(...).replace()
abjad.Sequence(...).replace_at()
abjad.Sequence(...).retain()
abjad.Sequence(...).retain_pattern()
abjad.Sequence(...).reverse()
abjad.Sequence(...).rotate()
abjad.Sequence(...).sort()
abjad.Sequence(...).split()
abjad.Sequence(...).sum()
abjad.Sequence(...).sum_by_sign()
abjad.Sequence(...).truncate()
abjad.Sequence(...).weight()
abjad.Sequence(...).zip()
NEW:
abjad.sequence.filter(...)
abjad.sequence.flatten(...)
abjad.sequence.group_by(...)
abjad.sequence.is_decreasing(...)
abjad.sequence.is_increasing(...)
abjad.sequence.is_permutation(...)
abjad.sequence.is_repetition_free(...)
abjad.sequence.join(...)
abjad.sequence.map(...)
abjad.sequence.nwise(...)
abjad.sequence.partition_by_counts(...)
abjad.sequence.partition_by_ratio_of_lengths(...)
abjad.sequence.partition_by_ratio_of_weights(...)
abjad.sequence.partition_by_weights(...)
abjad.sequence.permute(...)
abjad.sequence.remove(...)
abjad.sequence.remove_repeats(...)
abjad.sequence.repeat(...)
abjad.sequence.repeat_to_length(...)
abjad.sequence.repeat_to_weight(...)
abjad.sequence.replace(...)
abjad.sequence.replace_at(...)
abjad.sequence.retain(...)
abjad.sequence.retain_pattern(...)
abjad.sequence.reverse(...)
abjad.sequence.rotate(...)
abjad.sequence.sort(...)
abjad.sequence.split(...)
abjad.sequence.sum(...)
abjad.sequence.sum_by_sign(...)
abjad.sequence.truncate(...)
abjad.sequence.weight(...)
abjad.sequence.zip(...)
BREAKING CHANGE (#1394): Replaced abjad.String
with string.py
module:
OLD:
abjad.String("text").capitalize_start()
abjad.String("text").delimit_words()
abjad.String("text").from_roman()
abjad.String("text").is_lilypond_identifier()
abjad.String("text").is_roman()
abjad.String("text").is_shout_case()
abjad.String("text").pluralize()
abjad.String("text").strip_roman()
abjad.String("text").to_shout_case()
abjad.String("text").to_upper_camel_case()
abjad.String.normalize("text")
abjad.String.sort_roman(["PartI", "PartII", "PartIII"])
abjad.String.to_tridirectional_lilypond_symbol("text")
abjad.String.to_tridirectional_ordinal_constant("text")
NEW:
abjad.string.capitalize_start("text")
abjad.string.delimit_words("text")
abjad.string.from_roman("text")
abjad.string.is_lilypond_identifier("text")
abjad.string.is_roman("text")
abjad.string.is_shout_case("text")
abjad.string.pluralize("text")
abjad.string.strip_roman("text")
abjad.string.to_shout_case("text")
abjad.string.to_upper_camel_case("text")
abjad.string.normalize("text")
abjad.string.sort_roman(["PartI", "PartII", "PartIII"])
abjad.string.to_tridirectional_lilypond_symbol("text")
abjad.string.to_tridirectional_ordinal_constant("text")
REMOVED:
abjad.String("text").base_26()
abjad.String("text").is_build_directory_name()
abjad.String("text").is_classfile_name()
abjad.String("text").is_dash_case()
abjad.String("text").is_lower_camel_case()
abjad.String("text").is_lowercase_file_name()
abjad.String("text").is_module_file_name()
abjad.String("text").is_package_name()
abjad.String("text").is_public_python_file_name()
abjad.String("text").is_rehearsal_mark()
abjad.String("text").is_snake_case()
abjad.String("text").is_snake_case_file_name()
abjad.String("text").is_snake_case_file_name_with_extension()
abjad.String("text").is_snake_case_package_name()
abjad.String("text").is_space_delimited_lowercase()
abjad.String("text").is_string()
abjad.String("text").is_stylesheet_name()
abjad.String("text").is_tools_file_name()
abjad.String("text").is_upper_camel_case()
abjad.String("text").match_strings()
abjad.String("text").m...
v3.5
Changed in Abjad 3.5
Changes to Abjad 3.5 (2022-02-01) since Abjad 3.4 (2021-05-01).
Abjad 3.5 requires Python 3.10.
#1384 <https://github.com/Abjad/abjad/issues/1384>
_. Moved abjad.ily
from
abjad/docs/_stylesheets
to abjad/abjad/_stylesheets
.
#1372 <https://github.com/Abjad/abjad/issues/1372>
_. Refactored all indicators as
dataclasses. Added new indicators.py
module.
#1370 <https://github.com/Abjad/abjad/issues/1370>
_. Fixed definition of Forte SC 4-25.
#1368 <https://github.com/Abjad/abjad/issues/1368>
_. Gutted abjad.Markup
. Markup is
no longer parsed:
OLD::
abjad.Markup('\italic "Allegro moderato"', literal=True)
NEW::
abjad.Markup(r'\markup \italic "Allegro moderator"')
REMOVED::
* abjad.Postscript; use strings instead
* abjad.PostscriptOperator; use strings instead
* abjad.Markup.__add__(), __radd__()
* abjad.Markup.postscript()
* abjad.markups.abjad_metronome_mark()
#1366 <https://github.com/Abjad/abjad/issues/1366>
_. Removed abjad.OrderedDict
. Use
dict()
instead.
#1360 <https://github.com/Abjad/abjad/issues/1360>
_. Replaced
abjad.StorageFormatManager
with format.py
module.
#1359 <https://github.com/Abjad/abjad/issues/1359>
_. Changed abjad.iterate()
to
iterate.py
module:
OLD::
abjad.iterate(argument).components()
abjad.iterate(argument).leaves()
abjad.iterate(argument).logical_ties()
abjad.iterate(argument).pitches()
NEW::
abjad.iterate.components(argument)
abjad.iterate.leaves(argument)
abjad.iterate.logical_ties(argument)
abjad.iterate.pitches(argument)
#1357 <https://github.com/Abjad/abjad/issues/1357>
_. Changed abjad.Label
to
label.py
module:
OLD::
abjad.Label(argument).by_selector()
abjad.Label(argument).color_container()
abjad.Label(argument).color_leaves()
abjad.Label(argument).color_note_heads()
abjad.Label(argument).remove_markup()
abjad.Label(argument).vertical_moments()
abjad.Label(argument).with_durations()
abjad.Label(argument).with_indices()
abjad.Label(argument).with_intervals()
abjad.Label(argument).with_pitches()
abjad.Label(argument).with_set_classes()
abjad.Label(argument).with_start_offsets()
NEW::
abjad.label.by_selector(argument)
abjad.label.color_container(argument)
abjad.label.color_leaves(argument)
abjad.label.color_note_heads(argument)
abjad.label.remove_markup(argument)
abjad.label.vertical_moments(argument)
abjad.label.with_durations(argument)
abjad.label.with_indices(argument)
abjad.label.with_intervals(argument)
abjad.label.with_pitches(argument)
abjad.label.with_set_classes(argument)
abjad.label.with_start_offsets(argument)
#1303 <https://github.com/Abjad/abjad/issues/1303>
_. Removed default.ily stylesheet.
#1293 <https://github.com/Abjad/abjad/issues/1293>
_. Gutted abjad.LilyPondFile
:
Removed abjad.ContextBlock; use abjad.Block instead::
>>> string = r"""\Staff
... \name FluteStaff
... \type Engraver_group
... \alias Staff
... \remove Forbid_line_break_engraver
... \consists Horizontal_bracket_engraver
... \accepts FluteUpperVoice
... \accepts FluteLowerVoice
... \override Beam.positions = #'(-4 . -4)
... \override Stem.stem-end-position = -6
... autoBeaming = ##f
... tupletFullLength = ##t
... \accidentalStyle dodecaphonic"""
>>> block = abjad.Block(name="context")
>>> block.items.append(string)
>>> string = abjad.lilypond(block)
>>> print(string)
\context
{
\Staff
\name FluteStaff
\type Engraver_group
\alias Staff
\remove Forbid_line_break_engraver
\consists Horizontal_bracket_engraver
\accepts FluteUpperVoice
\accepts FluteLowerVoice
\override Beam.positions = #'(-4 . -4)
\override Stem.stem-end-position = -6
autoBeaming = ##f
tupletFullLength = ##t
\accidentalStyle dodecaphonic
}
Removed ``abjad.Block.__setattr__()``. Use ``abjad.Block.items`` instead.
REMOVED::
* abjad.DateTimeToken
* abjad.LilyPondDimension
* abjad.LilyPondLanguageToken
* abjad.LilyPondVersionToken
* abjad.PackageGitCommitToken
* abjad.LilyPondFile.comments
* abjad.LilyPondFile.includes
* abjad.LilyPondFile.use_relative_includes
* Removed courtesy blank lines from abjad.LilyPondFile output
* abjad.LilyPondFile.default_paper_size
* abjad.LilyPondFile.global_staff_size:
OLD::
* abjad.LilyPondFile.default_paper_size = ("a4", "letter")
* abjad.LilyPondFile.global_staff_size = 16
NEW::
preamble = r"""
#(set-default-paper-size "a4" 'letter)
#(set-global-staff-size 16)"""
* abjad.LilyPondFile(items=[preamble, ...])
OLD::
* abjad.LilyPondFile.header_block
* abjad.LilyPondFile.layout_block
* abjad.LilyPondFile.paper_block
NEW::
* abjad.LilyPondFile["header"]
* abjad.LilyPondFile["layout"]
* abjad.LilyPondFile["paper"]
Limited ``abjad.LilyPondFile.__getitem__()`` to strings:
OLD::
* lilypond_file["My_Staff"]
* lilypond_file[abjad.Staff]
NEW::
* lilypond_file["My_Staff"]
#1136 <https://github.com/Abjad/abjad/issues/1136>
_. Collapsed
abjad.AnnotatedTimespan
into abjad.Timespan
.
CONFIGURATION::
* Removed abjad.AbjadConfiguration.composer_email
* Removed abjad.AbjadConfiguration.composer_full_name
* Removed abjad.AbjadConfiguration.composer_github_username
* Removed abjad.AbjadConfiguration.composer_last_name
* Removed abjad.AbjadConfiguration.composer_scores_directory
* Removed abjad.AbjadConfiguration.composer_uppercase_name
* Removed abjad.AbjadConfiguration.composer_website
* Added abjad.AbjadConfiguration.sphinx_stylesheets_directory colon-delimited paths
ENUMERATION: `abjad.enumerate.yield_outer_product()previously returned a generator of
abjad.Sequence`` objects. The function now returns a list of list.
I/O::
* Taught abjad.persist.as_ly() to write file-terminal newline.
* Cleaned up abjad.persist.as_midi().
* Cleaned up abjad.run_lilypond():
OLD: abjad.run_lilypond() returned true or false.
NEW: abjad.run_lilypond() returns integer exit code.
* Cleaned up abjad.io.profile():
* removed print_to_terminal=True keyword
* function now always returns a string
LABEL: Taught abjad.Label.color_note_heads()
to color accidentals.
SELECTION: Changed abjad.select()
to a true synonym for abjad.Selection()
.
Deprecated abjad.SegmentMaker
. Define scores as a linear sequence of function calls
instead.
Deprecated all score templates. Define make_empty_score()
function instead.
v3.4
Changed in Abjad 3.4
Changes to Abjad 3.4 (2021-05-01) since Abjad 3.3 (2021-03-01).
Removed support for IPython.
#1338 Cleaned up tuplet formatting and block formatting. Opening brace now appears on its own line in LilyPond output:
OLD:
>>> tuplet = abjad.Tuplet("3:2", "c'4 d' e'")
>>> string = abjad.lilypond(tuplet)
>>> print(string)
\times 2/3 {
c'4
d'4
e'4
}
>>> staff = abjad.Staff("c'4 d' e' f'")
>>> block = abjad.Block(name="score")
>>> block.items.append(staff)
>>> string = abjad.lilypond(block)
>>> print(string)
\score {
\new Staff
{
c'4
d'4
e'4
f'4
}
}
NEW:
>>> tuplet = abjad.Tuplet("3:2", "c'4 d' e'")
>>> string = abjad.lilypond(tuplet)
>>> print(string)
\times 2/3
{
c'4
d'4
e'4
}
>>> staff = abjad.Staff("c'4 d' e' f'")
>>> block = abjad.Block(name="score")
>>> block.items.append(staff)
>>> string = abjad.lilypond(block)
>>> print(string)
\score
{
\new Staff
{
c'4
d'4
e'4
f'4
}
}
#1299. Removed deprecated stravinsky
keyword from pitch classes. The function of the keyword was to transpose sets and segments such that the first element was set equal to 0 (after operations like inversion or rotation). Transpose sets and segments separately (after inversion or rotation) when required instead.
v3.3
Changed in Abjad 3.3
Changes to Abjad 3.3 (2021-03-01) since Abjad 3.2 (2021-01-19).
#1328. Removed abjad.WoodwindFingering
. Use LilyPond \woodwind-fingering
instead.
#1323. Removed abjad.f()
. Use abjad.lilypond()
instead:
OLD:
>>> abjad.f(score)
NEW:
>>> string = abjad.lilypond(score)
>>> print(string)
#1293. Removed abjad.LilyPondFile.new()
constructor. Use abjad.LilyPondFile
initializer instead:
OLD:
>>> abjad.LilyPondFile.new(score)
NEW:
>>> block = abjad.Block(name="score")
>>> block.items.append(score)
>>> abjad.LilyPondFile(items=[block])
#1086. Gutted markup interface. Externalize markup in a LilyPond stylesheet and set literal=True
instead:
REMOVED:
abjad.Markup.bold()
abjad.Markup.center_column()
abjad.Markup.hcenter_in()
abjad.Markup.italic()
abjad.Markup.with_dimensions()
...
OLD:
>>> markup = abjad.Markup("Allegro assai")
>>> markup = markup.bold()
NEW:
Create a markup library in an external LilyPond file;
assign each new piece of markup to a LilyPond variable:
allegro-assai = \markup \bold { Allegro assai }
Then initialize in Abjad like this:
>>> abjad.Markup(r"\allegro-assai", literal=True)
Markup can still be initialized locally in Abjad;
type markup exactly as in LilyPond:
>>> string = r"\markup \bold { Allegro assai }"
>>> abjad.Markup(string, literal=True)
(The literal=True
keyword will be removed in a future release of Abjad. All markup will then initialize as though literal=True
.)
#1086. Removed Scheme proxy classes. Type Scheme settings as literal LilyPond code instead:
REMOVED:
abjad.SchemeMoment
abjad.SchemeAssociativeList
abjad.SchemeColor
abjad.SchemePair
abjad.SpacingVector
abjad.SchemeSymbol
abjad.SchemeVector
abjad.SchemeVectorConstant
CHANGED:
>>> scheme_moment = abjad.SchemeMoment((1, 24))
>>> abjad.override(score).proportional_notation_duration = scheme_moment
>>> abjad.override(score).proportionalNotationDuration = "#(ly:make-moment 1 24)"
CHANGED:
>>> abjad.override(voice).note_head.color = abjad.SchemeColor("red")
>>> abjad.override(voice).NoteHead.color = "#red"
CHANGED:
>>> abjad.override(voice).note_head.style = abjad.SchemeSymbol("harmonic")
>>> abjad.override(voice).NoteHead.style = "#'harmonic"
CHANGED:
>>> spacing_vector = abjad.SpacingVector(0, 10, 10, 0)
>>> abjad.override(score).staff_grouper.staff_staff_spacing = spacing_vector
>>> string = "#'((basic-distance . 10) (minimum-distance . 10))
>>> abjad.override(score).StaffGrouper.staff_staff_spacing = string
CHANGED:
>>> string = "tuplet-number::calc-denominator-text"
>>> abjad.override(score).tuplet_number.text = string
>>> string = "#tuplet-number::calc-denominator-text"
>>> abjad.override(score).TupletNumber.text = string
Fixed in Abjad 3.3
#1319. Taught the auxilliary note in pitched trills to transpose (Tsz Kiu Pang).
#1309. Taught abjad.Meter.rewrite_meter()
more about handling grace notes (Tsz Kiu Pang).
#1129. Taught tweaked note heads to copy correctly (Tsz Kiu Pang).
#1174. Taught abjad.Selection.group_by_measure()
to respect pick-measures created at the beginning
of a score with abjad.TimeSignature.partial
(Tsz Kiu Pang).
v3.2
Abjad 3.2
Changes to Abjad 3.2 (2021-01-19) since Abjad 3.1 (2019-12-19).
#1244. Taught tuplets to preserve input ratios without reducing terms of fraction:
NEW. Taught abjad.Tuplet to preserve tuplet ratio without reducing:
>>> tuplet = abjad.Tuplet("6:4", "c'4 d' e'")
>>> abjad.f(tuplet)
\times 4/6 {
c'4
d'4
e'4
}
>>> tuplet = abjad.Tuplet((4, 6), "c'4 d' e'")
>>> abjad.f(tuplet)
\times 4/6 {
c'4
d'4
e'4
}
NEW. Taught Abjad about LilyPond \tuplet command:
>>> voice = abjad.Voice(r"\tuplet 6/4 { c'4 d' e' }")
>>> string = abjad.lilypond(voice)
>>> print(string)
\new Voice
{
\times 4/6 {
c'4
d'4
e'4
}
}
Tuplet multiplier now returns a nonreduced fraction:
OLD: abjad.Tuplet.multiplier returns abjad.Multiplier
NEW: abjad.Tuplet.multiplier returns abjad.NonreducedFraction
Tuplet interpreter representation now shows colon string:
OLD:
>>> abjad.Tuplet("6:4", "c'4 d' e'")
Tuplet(Multiplier(4, 6), "c'4 d'4 e'4")
NEW:
>>> abjad.Tuplet("6:4", "c'4 d' e'")
Tuplet('6:4', "c'4 d'4 e'4")
#1231. Changed abjad.mathtools
to abjad.math
:
OLD:
abjad.mathtools.all_are_equal()
abjad.mathtools.all_are_integer_equivalent()
abjad.mathtools.all_are_integer_equivalent_numbers()
abjad.mathtools.all_are_nonnegative_integer_equivalent_numbers()
abjad.mathtools.all_are_nonnegative_integer_powers_of_two()
abjad.mathtools.all_are_nonnegative_integers()
abjad.mathtools.all_are_pairs_of_types()
abjad.mathtools.all_are_positive_integers()
abjad.mathtools.are_relatively_prime()
abjad.mathtools.arithmetic_mean()
abjad.mathtools.binomial_coefficient()
abjad.mathtools.cumulative_products()
abjad.mathtools.cumulative_sums()
abjad.mathtools.difference_series()
abjad.mathtools.divisors()
abjad.mathtools.factors()
abjad.mathtools.fraction_to_proper_fraction()
abjad.mathtools.greatest_common_divisor()
abjad.mathtools.greatest_power_of_two_less_equal()
abjad.mathtools.integer_equivalent_number_to_integer()
abjad.mathtools.integer_to_base_k_tuple()
abjad.mathtools.integer_to_binary_string()
abjad.mathtools.is_assignable_integer()
abjad.mathtools.is_integer_equivalent()
abjad.mathtools.is_integer_equivalent_n_tuple()
abjad.mathtools.is_integer_equivalent_number()
abjad.mathtools.is_nonnegative_integer()
abjad.mathtools.is_nonnegative_integer_equivalent_number()
abjad.mathtools.is_nonnegative_integer_power_of_two()
abjad.mathtools.is_positive_integer()
abjad.mathtools.is_positive_integer_equivalent_number()
abjad.mathtools.is_positive_integer_power_of_two()
abjad.mathtools.least_common_multiple()
abjad.mathtools._least_common_multiple_helper()
abjad.mathtools.partition_integer_into_canonic_parts()
abjad.mathtools.sign()
abjad.mathtools.weight()
abjad.mathtools.yield_all_compositions_of_integer()
NEW:
abjad.math.all_are_equal()
abjad.math.all_are_integer_equivalent()
abjad.math.all_are_integer_equivalent_numbers()
abjad.math.all_are_nonnegative_integer_equivalent_numbers()
abjad.math.all_are_nonnegative_integer_powers_of_two()
abjad.math.all_are_nonnegative_integers()
abjad.math.all_are_pairs_of_types()
abjad.math.all_are_positive_integers()
abjad.math.are_relatively_prime()
abjad.math.arithmetic_mean()
abjad.math.binomial_coefficient()
abjad.math.cumulative_products()
abjad.math.cumulative_sums()
abjad.math.difference_series()
abjad.math.divisors()
abjad.math.factors()
abjad.math.fraction_to_proper_fraction()
abjad.math.greatest_common_divisor()
abjad.math.greatest_power_of_two_less_equal()
abjad.math.integer_equivalent_number_to_integer()
abjad.math.integer_to_base_k_tuple()
abjad.math.integer_to_binary_string()
abjad.math.is_assignable_integer()
abjad.math.is_integer_equivalent()
abjad.math.is_integer_equivalent_n_tuple()
abjad.math.is_integer_equivalent_number()
abjad.math.is_nonnegative_integer()
abjad.math.is_nonnegative_integer_equivalent_number()
abjad.math.is_nonnegative_integer_power_of_two()
abjad.math.is_positive_integer()
abjad.math.is_positive_integer_equivalent_number()
abjad.math.is_positive_integer_power_of_two()
abjad.math.least_common_multiple()
abjad.math._least_common_multiple_helper()
abjad.math.partition_integer_into_canonic_parts()
abjad.math.sign()
abjad.math.weight()
abjad.math.yield_all_compositions_of_integer()
#1214. Changed abjad.mutate()
constructor to abjad.mutate
module:
OLD:
abjad.mutate(argument).copy()
abjad.mutate(argument).eject_contents()
abjad.mutate(argument).extract()
abjad.mutate(argument).fuse()
abjad.mutate(argument).logical_tie_to_tuplet()
abjad.mutate(argument).replace()
abjad.mutate(argument).scale()
abjad.mutate(argument).swap()
abjad.mutate(argument).transpose()
abjad.mutate(argument).wrap()
NEW:
abjad.mutate.copy(argument)
abjad.mutate.eject_contents(argument)
abjad.mutate.extract(argument)
abjad.mutate.fuse(argument)
abjad.mutate.logical_tie_to_tuplet(argument)
abjad.mutate.replace(argument)
abjad.mutate.scale(argument)
abjad.mutate.swap(argument)
abjad.mutate.transpose(argument)
abjad.mutate.wrap(argument)
#1213. Changed abjad.IOManager
class to abjad.io
module:
OLD:
abjad.IOManager.compare_files()
abjad.IOManager.execute_file()
abjad.IOManager.execute_string()
abjad.IOManager.find_executable()
abjad.IOManager.make_subprocess()
abjad.IOManager.open_file()
abjad.IOManager.open_last_log()
abjad.IOManager.profile()
abjad.IOManager.run_command()
abjad.IOManager.run_lilypond()
abjad.IOManager.spawn_subprocess()
NEW:
abjad.io.compare_files()
abjad.io.execute_file()
abjad.io.execute_string()
abjad.io.find_executable()
abjad.io.make_subprocess()
abjad.io.open_file()
abjad.io.open_last_log()
abjad.io.profile()
abjad.io.run_command()
abjad.io.run_lilypond()
abjad.io.spawn_subprocess()
#1212. Changed abjad.persist()
constructor to abjad.persist
module:
OLD:
abjad.persist(argument).as_ly()
abjad.persist(argument).as_midi()
abjad.persist(argument).as_pdf()
abjad.persist(argument).as_png()
NEW:
abjad.persist.as_ly(argument)
abjad.persist.as_midi(argument)
abjad.persist.as_pdf(argument)
abjad.persist.as_png(argument)
You must now pass an explicit path to the following:
abjad.persist.as_ly(argument)
abjad.persist.as_midi(argument)
abjad.persist.as_pdf(argument)
abjad.persist.as_png(argument)
#1196. Changed abjad.inspect()
constructor to abjad.get
module:
OLD:
abjad.inspect(argument)after_grace_container()
abjad.inspect(argument)annotation()
abjad.inspect(argument)annotation_wrappers()
abjad.inspect(argument)bar_line_crossing()
abjad.inspect(argument)before_grace_container()
abjad.inspect(argument)contents()
abjad.inspect(argument)descendants()
abjad.inspect(argument)duration()
abjad.inspect(argument)effective()
abjad.inspect(argument)effective_staff()
abjad.inspect(argument)effective_wrapper()
abjad.inspect(argument)grace()
abjad.inspect(argument)has_effective_indicator()
abjad.inspect(argument)has_indicator()
abjad.inspect(argument)indicator()
abjad.inspect(argument)indicators()
abjad.inspect(argument)leaf()
abjad.inspect(argument)lineage()
abjad.inspect(argument)logical_tie()
abjad.inspect(argument)markup()
abjad.inspect(argument)measure_number()
abjad.inspect(argument)parentage()
abjad.inspect(argument)pitches()
abjad.inspect(argument)report_modifications()
abjad.inspect(argument)sounding_pitch()
abjad.inspect(argument)sounding_pitches()
abjad.inspect(argument)sustained()
abjad.inspect(argument)timespan()
NEW:
abjad.get.after_grace_container(argument)
abjad.get.annotation(argument)
abjad.get.annotation_wrappers(argument)
abjad.get.bar_line_crossing(argument)
abjad.get.before_grace_container(argument)
abjad.get.contents(argument)
abjad.get.descendants(argument)
abjad.get.duration(argument)
abjad.get.effective(argument)
abjad.get.effective_staff(argument)
abjad.get.effective_wrapper(argument)
abjad.get.grace(argument)
abjad.get.has_effective_indicator(argument)
abjad.get.has_indicator(argument)
abjad.get.indicator(argument)
abjad.get.indicators(argument)
abjad.get.leaf(argument)
abjad.get.lineage(argument)
abjad.get.logical_tie(argument)
abjad.get.markup(argument)
abjad.get.measure_number(argument)
abjad.get.parentage(argument)
abjad.get.pitches(argument)
abjad.get.report_modifications(argument)
abjad.get.sounding_pitch(argument)
abjad.get.sounding_pitches(argument)
abjad.get.sustained(argument)
abjad.get.timespan(argument)
#1191. Removed abjad.Infinity
, abjad.NegativeInfinity
"singletons." Previously abjad.Infinity
was an instance of the abjad.mathtools.Infinity
class. This was confusing. Because abjad.Infinity
looked like a class but wasn't:
OLD:
foo is abjad.Infinity
foo is not abjad.Infinity
NEW:
foo == abjad.Infinity()
foo != abjad.Infinity()
Moved four fancy iteration functions to t...
Abjad 3.1
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
asabjad.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.
CHANGES
1. 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)
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)
>>> 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)
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 FUNCTIONALITY
1. 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)
>>> 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)
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)
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)
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.forbidde...
Abjad 3.0.0
NEW CONFIGURATION FUNCTIONALITY:
* Added AbjadConfiguration.composer_scores_directory
* Added composer template data to AbjadConfiguration
* Integrated pathlib into abjad.Configuration
The four main abjad.Configuration properties now return path objects
instead of strings:
* abjad.Configuration.configuration_directory
* abjad.Configuration.configuration_file_path
* abjad.Configuration.home_directory
* abjad.Configuration.temp_directory
* Changed 'directory_path' to just 'directory' in abjad.Configuration
OLD: Configuration.configuration_file_name
NEW: Configuration.file_path
OLD: Configuration.configuration_directory_name
NEW: Configuration.configuration_directory
NEW CONTAINER FUNCTIONALITY:
* Added bracket comments to measure-open, measure-close.
OLD:
>>> measure = abjad.Measure((3, 4), "c'4 d' e'")
>>> abjad.f(measure)
{
\time 3/4
c'4
d'4
e'4
}
NEW:
>>> measure = abjad.Measure((3, 4), "c'4 d' e'")
>>> abjad.f(measure)
{ % measure
\time 3/4
c'4
d'4
e'4
} % measure
* Removed Container.reverse(); no longer supported
* Removed Component.name; preserved Container.name
* Taught containers to initialize from collections of strings:
staff = abjad.Staff([
r"\times 9/10 { r8 c'16 c'16 bf'4 ~ bf'16 r16 }",
r"\times 9/10 { bf'16 e''16 e''4 ~ e''16 r16 fs''16 af''16 }",
r"\times 4/5 { a'16 r4 }",
])
abjad.f(staff)
\new Staff {
{
\tweak text #tuplet-number::calc-fraction-text
\times 9/10 {
r8
c'16
c'16
bf'4 ~
bf'16
r16
}
}
{
\tweak text #tuplet-number::calc-fraction-text
\times 9/10 {
bf'16
e''16
e''4 ~
e''16
r16
fs''16
af''16
}
}
{
\times 4/5 {
a'16
r4
}
}
}
* Taught simultaneous containers to accept vanilla containers
(in addition to contexts)
OLD: abjad.Container.music
NEW: abjad.Container.components
NEW CONTEXT FUNCTIONALITY:
OLD: abjad.Context.context_name
NEW: abjad.Context.lilypond_type
* Closes #895
NEW DATA STRUCTURE FUNCTIONALITY:
* Removed abjad.ClefList; use list instead
* Removed abjad.PerformerList; use list instead
* Removed abjad.PitchRangeList; use list instead
* Removed abjad.InstrumentDictionary; use abjad.OrderedDict instead
* Removed abjad.MetronomeMarkDictionary; use abjad.OrderedDict instead
OLD: abjad.TypedOrderedDict
NEW: abjad.OrderedDict
* Closes #909
NEW FORMAT FUNCTIONALITY:
* Added abjad.Container.identifier property. Use to set parse handles on any
Abjad container:
>>> container = abjad.Container("c'4 d' e' f'")
>>> container.identifier = '%*% AB'
>>> abjad.f(container)
{ %*% AB
c'4
d'4
e'4
f'4
} %*% AB
* Changed context open-statement formatting to strictly one-per-line:
OLD:
\new Score \with {
\override BarLine.stencil = ##f
\override BarNumber.transparent = ##t
\override SpanBar.stencil = ##f
\override TimeSignature.stencil = ##f
} <<
\new PianoStaff <<
\context Staff = "Treble Staff" {
\clef "treble"
r16
r16
r16
r16
r16
c'16
d'16
e'16
f'16
g'16
}
\context Staff = "Bass Staff" {
\clef "bass"
c16
d16
e16
f16
g16
r16
r16
r16
r16
r16
}
>>
>>
NEW:
\new Score
\with
{
\override BarLine.stencil = ##f
\override BarNumber.transparent = ##t
\override SpanBar.stencil = ##f
\override TimeSignature.stencil = ##f
}
<<
\new PianoStaff
<<
\context Staff = "Treble Staff"
{
\clef "treble"
r16
r16
r16
r16
r16
c'16
d'16
e'16
f'16
g'16
}
\context Staff = "Bass Staff"
{
\clef "bass"
c16
d16
e16
f16
g16
r16
r16
r16
r16
r16
}
>>
>>
MODEL. Note that this makes lexical postprocessing incredibly easy. Any chunk
of anything can be parsed out of Abjad's LilyPond output as a sequence of
consecutive lines. Target application might be anything from assignment to
variables (for externalization in complex scores) or tagging parts of LilyPond
files on and off.
* Removed 'right' format slot
NEW INDICATOR FUNCTIONALITY:
* Added abjad.hairpin() factory function:
With three-part string descriptor:
>>> staff = abjad.Staff("c'4 d' e' f'")
>>> abjad.hairpin('p < f', staff[:])
>>> abjad.override(staff[0]).dynamic_line_spanner.staff_padding = 4
>>> abjad.f(staff)
\new Staff
{
\once \override DynamicLineSpanner.staff-padding = #4
c'4
\p
\<
d'4
e'4
f'4
\f
}
With dynamic objects:
>>> staff = abjad.Staff("c'4 d' e' f'")
>>> start = abjad.Dynamic('niente', command=r'\!')
>>> trend = abjad.DynamicTrend('o<')
>>> abjad.tweak(trend).color = 'blue'
>>> stop = abjad.Dynamic('"f"')
>>> abjad.hairpin([start, trend, stop], staff[:])
>>> abjad.override(staff[0]).dynamic_line_spanner.staff_padding = 4
>>> abjad.f(staff)
\new Staff
{
\once \override DynamicLineSpanner.staff-padding = #4
c'4
\!
- \tweak color #blue
- \tweak circled-tip ##t
- \tweak stencil #abjad-flared-hairpin
\<
d'4
e'4
f'4
_ #(make-dynamic-script
(markup
#:whiteout
#:line (
#:general-align Y -2 #:normal-text #:larger "“"
#:hspace -0.4
#:dynamic "f"
#:hspace -0.2
#:general-align Y -2 #:normal-text #:larger "”"
)
)
)
}
* Closes #991
* Added abjad.HairpinStart:
>>> staff = abjad.Staff("c'4 d' e' f' c' d' e' r4")
>>> abjad.attach(abjad.Dynamic('p'), staff[0])
>>> abjad.attach(abjad.HairpinStart('<|'), staff[0])
>>> abjad.attach(abjad.Dynamic('f'), staff[3])
>>> abjad.attach(abjad.Dynamic('f'), staff[4])
>>> abjad.attach(abjad.HairpinStart('|>o'), staff[4])
>>> abjad.attach(abjad.Dynamic('niente', command=r'\!'), staff[-1])
>>> abjad.override(staff).dynamic_line_spanner.staff_padding = 4.5
>>> abjad.f(staff)
\new Staff
\with
{
\override DynamicLineSpanner.staff-padding = #4.5
}
{
c'4
\p
- \tweak stencil #abjad-flared-hairpin
\<
d'4
e'4
f'4
\f
c'4
\f
- \tweak circled-tip ##t
- \tweak stencil #abjad-flared-hairpin
\>
d'4
e'4
r4
\!
}
* Added abjad-flared-hairpin to docs/source/_stylesheets/default.ily
* Added abjad.text_spanner...