"""
Package for Just Intonation.
"""
import math
import abjad
import quicktions
[docs]class JIVector:
"""
JI vector.
>>> from abjadext import microtones
.. container:: example
>>> vector = microtones.JIVector(syntonic_commas_down=2)
>>> vector.syntonic_commas_down
2
>>> vector = microtones.JIVector(syntonic_commas_down=2)
>>> vector.syntonic_commas_up
0
"""
def __init__(
self,
diatonic_accidental="natural",
syntonic_commas_down=0,
syntonic_commas_up=0,
septimal_commas_down=0,
septimal_commas_up=0,
undecimal_quarter_tones_down=0,
undecimal_quarter_tones_up=0,
tridecimal_third_tones_down=0,
tridecimal_third_tones_up=0,
seventeen_limit_schismas_down=0,
seventeen_limit_schismas_up=0,
nineteen_limit_schismas_down=0,
nineteen_limit_schismas_up=0,
twenty_three_limit_commas_down=0,
twenty_three_limit_commas_up=0,
):
self.diatonic_accidental = diatonic_accidental
self.syntonic_commas_down = syntonic_commas_down
self.syntonic_commas_up = syntonic_commas_up
self.septimal_commas_down = septimal_commas_down
self.septimal_commas_up = septimal_commas_up
self.undecimal_quarter_tones_down = undecimal_quarter_tones_down
self.undecimal_quarter_tones_up = undecimal_quarter_tones_up
self.tridecimal_third_tones_down = tridecimal_third_tones_down
self.tridecimal_third_tones_up = tridecimal_third_tones_up
self.seventeen_limit_schismas_down = seventeen_limit_schismas_down
self.seventeen_limit_schismas_up = seventeen_limit_schismas_up
self.nineteen_limit_schismas_down = nineteen_limit_schismas_down
self.nineteen_limit_schismas_up = nineteen_limit_schismas_up
self.twenty_three_limit_commas_down = twenty_three_limit_commas_down
self.twenty_three_limit_commas_up = twenty_three_limit_commas_up
[docs] def __repr__(self):
"""
Gets interpreter representation.
.. container:: example
>>> microtones.JIVector()
JIVector(diatonic_accidental='natural', syntonic_commas_down=0, syntonic_commas_up=0, septimal_commas_down=0, septimal_commas_up=0, undecimal_quarter_tones_down=0, undecimal_quarter_tones_up=0, tridecimal_third_tones_down=0, tridecimal_third_tones_up=0, seventeen_limit_schismas_down=0, seventeen_limit_schismas_up=0, nineteen_limit_schismas_down=0, nineteen_limit_schismas_up=0, twenty_three_limit_commas_down=0, twenty_three_limit_commas_up=0)
"""
return abjad.StorageFormatManager(self).get_repr_format()
[docs] def has_just_accidentals(self):
"""
Is true when vector has just accidentals.
.. container:: example
>>> vector = microtones.JIVector()
>>> vector.has_just_accidentals()
False
>>> vector = microtones.JIVector(syntonic_commas_down=1)
>>> vector.has_just_accidentals()
True
"""
return any(
[
self.syntonic_commas_down,
self.syntonic_commas_up,
self.septimal_commas_down,
self.septimal_commas_up,
self.undecimal_quarter_tones_down,
self.undecimal_quarter_tones_up,
self.tridecimal_third_tones_down,
self.tridecimal_third_tones_up,
self.seventeen_limit_schismas_down,
self.seventeen_limit_schismas_up,
self.nineteen_limit_schismas_down,
self.nineteen_limit_schismas_up,
self.twenty_three_limit_commas_down,
self.twenty_three_limit_commas_up,
]
)
[docs] def calculate_ji_markup(self):
r"""
Calculates JI markup.
.. container:: example
>>> vector = microtones.JIVector(syntonic_commas_down=1)
>>> print(abjad.lilypond(vector.calculate_ji_markup()))
\markup { \natural-one-syntonic-comma-down }
"""
int_to_word = {"1": "one", "2": "two", "3": "three"}
accumulated_accidentals = []
if self.diatonic_accidental == "double sharp":
self.diatonic_accidental = "double-sharp"
if self.diatonic_accidental == "double flat":
self.diatonic_accidental = "double-flat"
if self.syntonic_commas_down == self.syntonic_commas_up:
self.syntonic_commas_down = 0
self.syntonic_commas_up = 0
string = fr"\{self.diatonic_accidental}"
accumulated_accidentals.append(string)
elif self.syntonic_commas_down > self.syntonic_commas_up:
self.syntonic_commas_down -= self.syntonic_commas_up
self.syntonic_commas_up = 0
string = fr"\{self.diatonic_accidental}"
string += f"-{int_to_word[str(self.syntonic_commas_down)]}"
string += "-syntonic-comma-down"
accumulated_accidentals.append(string)
else:
self.syntonic_commas_up -= self.syntonic_commas_down
self.syntonic_commas_down = 0
string = fr"\{self.diatonic_accidental}"
string += f"-{int_to_word[str(self.syntonic_commas_up)]}"
string += "-syntonic-comma-up"
accumulated_accidentals.append(string)
if self.septimal_commas_down == self.septimal_commas_up:
self.septimal_commas_down = 0
self.septimal_commas_up = 0
elif self.septimal_commas_down > self.septimal_commas_up:
self.septimal_commas_down -= self.septimal_commas_up
self.septimal_commas_up = 0
string = fr"\{int_to_word[str(self.septimal_commas_down)]}"
string += "-septimal-comma-down"
accumulated_accidentals.append(string)
else:
self.septimal_commas_up -= self.septimal_commas_down
self.septimal_commas_down = 0
string = fr"\{int_to_word[str(self.septimal_commas_up)]}"
string += "-septimal-comma-up"
accumulated_accidentals.append(string)
if self.undecimal_quarter_tones_down == self.undecimal_quarter_tones_up:
self.undecimal_quarter_tones_down = 0
self.undecimal_quarter_tones_up = 0
elif self.undecimal_quarter_tones_down > self.undecimal_quarter_tones_up:
self.undecimal_quarter_tones_down -= self.undecimal_quarter_tones_up
self.undecimal_quarter_tones_up = 0
string = fr"\{int_to_word[str(self.undecimal_quarter_tones_down)]}"
string += "-undecimal-quarter-tone-down"
accumulated_accidentals.append(string)
else:
self.undecimal_quarter_tones_up -= self.undecimal_quarter_tones_down
self.undecimal_quarter_tones_down = 0
string = fr"\{int_to_word[str(self.undecimal_quarter_tones_up)]}"
string += "-undecimal-quarter-tone-up"
accumulated_accidentals.append(string)
if self.tridecimal_third_tones_down == self.tridecimal_third_tones_up:
self.tridecimal_third_tones_down = 0
self.tridecimal_third_tones_up = 0
elif self.tridecimal_third_tones_down > self.tridecimal_third_tones_up:
self.tridecimal_third_tones_down -= self.tridecimal_third_tones_up
self.tridecimal_third_tones_up = 0
string = fr"\{int_to_word[str(self.tridecimal_third_tones_down)]}"
string += "-tridecimal-third-tone-down"
accumulated_accidentals.append(string)
else:
self.tridecimal_third_tones_up -= self.tridecimal_third_tones_down
self.tridecimal_third_tones_down = 0
string = fr"\{int_to_word[str(self.tridecimal_third_tones_up)]}"
string += "-tridecimal-third-tone-up"
accumulated_accidentals.append(string)
if self.seventeen_limit_schismas_down == self.seventeen_limit_schismas_up:
self.seventeen_limit_schismas_down = 0
self.seventeen_limit_schismas_up = 0
elif self.seventeen_limit_schismas_down > self.seventeen_limit_schismas_up:
self.seventeen_limit_schismas_down -= self.seventeen_limit_schismas_up
self.seventeen_limit_schismas_up = 0
string = fr"\{int_to_word[str(self.seventeen_limit_schismas_down)]}"
string += "-seventeen-limit-schisma-down"
accumulated_accidentals.append(string)
else:
self.seventeen_limit_schismas_up -= self.seventeen_limit_schismas_down
self.seventeen_limit_schismas_down = 0
string = fr"\{int_to_word[str(self.seventeen_limit_schismas_up)]}"
string += "-seventeen-limit-schisma-up"
accumulated_accidentals.append(string)
if self.nineteen_limit_schismas_down == self.nineteen_limit_schismas_up:
self.nineteen_limit_schismas_down = 0
self.nineteen_limit_schismas_up = 0
elif self.nineteen_limit_schismas_down > self.nineteen_limit_schismas_up:
self.nineteen_limit_schismas_down -= self.nineteen_limit_schismas_up
self.nineteen_limit_schismas_up = 0
string = fr"\{int_to_word[str(self.nineteen_limit_schismas_down)]}"
string += "-nineteen-limit-schisma-down"
accumulated_accidentals.append(string)
else:
self.nineteen_limit_schismas_up -= self.nineteen_limit_schismas_down
self.nineteen_limit_schismas_down = 0
string = fr"\{int_to_word[str(self.nineteen_limit_schismas_up)]}"
string += "-nineteen-limit-schisma-up"
accumulated_accidentals.append(string)
if self.twenty_three_limit_commas_down == self.twenty_three_limit_commas_up:
self.twenty_three_limit_commas_down = 0
self.twenty_three_limit_commas_up = 0
elif self.twenty_three_limit_commas_down > self.twenty_three_limit_commas_up:
self.twenty_three_limit_commas_down -= self.twenty_three_limit_commas_up
self.twenty_three_limit_commas_up = 0
string = fr"\{int_to_word[str(self.twenty_three_limit_commas_down)]}"
string += "-twenty-three-limit-comma-down"
accumulated_accidentals.append(string)
else:
self.twenty_three_limit_commas_up -= self.twenty_three_limit_commas_down
self.twenty_three_limit_commas_down = 0
string = fr"\{int_to_word[str(self.twenty_three_limit_commas_up)]}"
string += "-twenty-three-limit-comma-up"
accumulated_accidentals.append(string)
if len(accumulated_accidentals):
accumulated_accidentals.reverse()
if accumulated_accidentals[-1] == r"\natural":
if self.has_just_accidentals():
accumulated_accidentals = [_ for _ in accumulated_accidentals[:-1]]
for i, s in enumerate(accumulated_accidentals):
if s == r"\natural":
accumulated_accidentals[i] = r"\abjad-natural"
if s == r"\sharp":
accumulated_accidentals[i] = r"\abjad-sharp"
if s == r"\flat":
accumulated_accidentals[i] = r"\abjad-flat"
literal_components = []
for accidental_string in accumulated_accidentals:
accidental_string = accidental_string + " "
literal_components.append(accidental_string)
if len(literal_components) == 1:
literal = abjad.Markup(
fr"\markup {{ {literal_components[0]} }}", literal=True
)
else:
kerned_components = []
for i, item in enumerate(literal_components):
kerned_components.append(item)
if i != len(literal_components) - 1:
kerned_components.append(r"\hspace #0.125 ")
kerned_components_string = ""
for kerned_component in kerned_components:
kerned_components_string += kerned_component
literal = abjad.Markup(
fr"\markup \concat {{ {kerned_components_string} }}", literal=True
)
else:
literal = abjad.Markup(
fr" \markup {{ \abjad-{self.diatonic_accidental} }}", literal=True
)
self.accidental_literal = literal
return literal
[docs]class JIBundle:
"""
JI bundle.
.. container:: example
>>> bundle = microtones.JIBundle()
>>> bundle.pitch
"c'"
>>> print(abjad.storage(bundle.vector))
microtones.JIVector(
diatonic_accidental='natural',
syntonic_commas_down=0,
syntonic_commas_up=0,
septimal_commas_down=0,
septimal_commas_up=0,
undecimal_quarter_tones_down=0,
undecimal_quarter_tones_up=0,
tridecimal_third_tones_down=0,
tridecimal_third_tones_up=0,
seventeen_limit_schismas_down=0,
seventeen_limit_schismas_up=0,
nineteen_limit_schismas_down=0,
nineteen_limit_schismas_up=0,
twenty_three_limit_commas_down=0,
twenty_three_limit_commas_up=0,
)
"""
def __init__(self, pitch="c'", vector=JIVector()):
self.pitch = pitch
self.vector = vector
[docs] def __repr__(self):
"""
Gets interpreter representation.
.. container:: example
>>> microtones.JIBundle()
JIBundle(pitch="c'", vector=JIVector(diatonic_accidental='natural', syntonic_commas_down=0, syntonic_commas_up=0, septimal_commas_down=0, septimal_commas_up=0, undecimal_quarter_tones_down=0, undecimal_quarter_tones_up=0, tridecimal_third_tones_down=0, tridecimal_third_tones_up=0, seventeen_limit_schismas_down=0, seventeen_limit_schismas_up=0, nineteen_limit_schismas_down=0, nineteen_limit_schismas_up=0, twenty_three_limit_commas_down=0, twenty_three_limit_commas_up=0))
"""
return abjad.StorageFormatManager(self).get_repr_format()
def _is_prime(n):
if n == 1:
return False
if n % 2 == 0:
return False
i = 3
while i * i <= n:
if n % i == 0:
return False
i += 2
return True
def _prime_factors(n):
prime_factor_list = []
while not n % 2:
prime_factor_list.append(2)
n //= 2
while not n % 3:
prime_factor_list.append(3)
n //= 3
i = 5
while n != 1:
if _is_prime(i):
while not n % i:
prime_factor_list.append(i)
n //= i
i += 2
return prime_factor_list
_numerator_factor_to_intervals = {
2: ("+P8",),
3: ("+P8", "+P5"),
5: ("+P8", "+P8", "+M3"),
7: ("+P8", "+P8", "+m7"),
11: ("+P8", "+P8", "+P8", "+P4"),
13: ("+P8", "+P8", "+P8", "+M6"),
17: ("+P8", "+P8", "+P8", "+P8", "+A1"),
19: ("+P8", "+P8", "+P8", "+P8", "+m3"),
23: ("+P8", "+P8", "+P8", "+P8", "+A4"),
}
_numerator_factor_to_nudge = {
5: "syntonic_commas_down",
7: "septimal_commas_down",
11: "undecimal_quarter_tones_up",
13: "tridecimal_third_tones_down",
17: "seventeen_limit_schismas_down",
19: "nineteen_limit_schismas_up",
23: "twenty_three_limit_commas_up",
}
[docs]def make_ji_bundle(pitch, ratio):
r"""
Makes JI bundle.
.. container:: example
>>> bundle = microtones.make_ji_bundle(abjad.NamedPitch("c'"), "3/2")
>>> bundle.pitch
NamedPitch("g'")
>>> print(abjad.storage(bundle.vector))
microtones.JIVector(
diatonic_accidental='natural',
syntonic_commas_down=0,
syntonic_commas_up=0,
septimal_commas_down=0,
septimal_commas_up=0,
undecimal_quarter_tones_down=0,
undecimal_quarter_tones_up=0,
tridecimal_third_tones_down=0,
tridecimal_third_tones_up=0,
seventeen_limit_schismas_down=0,
seventeen_limit_schismas_up=0,
nineteen_limit_schismas_down=0,
nineteen_limit_schismas_up=0,
twenty_three_limit_commas_down=0,
twenty_three_limit_commas_up=0,
)
"""
if isinstance(pitch, str):
pitch = abjad.NamedPitch(pitch)
elif isinstance(pitch, int):
pitch = abjad.NumberedPitch(pitch)
ratio = quicktions.Fraction(ratio)
numerator_factors = _prime_factors(ratio.numerator)
denominator_factors = _prime_factors(ratio.denominator)
accidental_vector = JIVector(diatonic_accidental=pitch.accidental.name)
for prime in numerator_factors:
assert prime <= 23
for string in _numerator_factor_to_intervals[prime]:
pitch = abjad.NamedInterval(string).transpose(pitch)
if prime in _numerator_factor_to_nudge:
string = _numerator_factor_to_nudge[prime]
value = getattr(accidental_vector, string)
setattr(accidental_vector, string, value + 1)
for prime in denominator_factors:
assert prime <= 23
for string in _numerator_factor_to_intervals[prime]:
string = string.replace("+", "-")
pitch = abjad.NamedInterval(string).transpose(pitch)
if prime in _numerator_factor_to_nudge:
string = _numerator_factor_to_nudge[prime]
if string.endswith("_up"):
string = string.replace("_up", "_down")
else:
string = string.replace("_down", "_up")
value = getattr(accidental_vector, string)
setattr(accidental_vector, string, value + 1)
accidental_vector.diatonic_accidental = pitch.accidental.name
return JIBundle(pitch, accidental_vector)
[docs]def return_cent_deviation_markup(
ratio=1, fundamental="a'", chris=False
): # chris values are temp.
pitch = None
ratio = quicktions.Fraction(ratio)
tonic_cent_difference = abjad.NamedPitch(fundamental).number * 100
log_ratio = quicktions.Fraction(math.log10(ratio))
log_2 = quicktions.Fraction(1200 / math.log10(2))
ji_cents = quicktions.Fraction(log_ratio * log_2)
et_cents = (
make_ji_bundle(fundamental, ratio).pitch.number * 100
) - tonic_cent_difference
cent_difference = ji_cents - et_cents
final_cents = round(float(cent_difference))
if chris is True:
final_cents = round(float(cent_difference), 2)
if chris is True:
p_string = f"{fundamental}4"
demo_note = abjad.Note(p_string)
demo_head = demo_note.note_head
tune_to_ratio(demo_head, quicktions.Fraction(ratio) * quicktions.Fraction(9, 8))
pitch = abjad.NumberedPitch(demo_head.written_pitch)
if 50 < abs(final_cents):
if chris is False:
p_string = f"{fundamental}4"
demo_note = abjad.Note(p_string)
demo_head = demo_note.note_head
tune_to_ratio(demo_head, ratio)
pitch = abjad.NumberedPitch(demo_head.written_pitch)
semitones = final_cents / 100
parts = math.modf(semitones)
pitch += parts[1]
remainder = round(parts[0] * 100)
if 50 < abs(remainder):
if 0 < remainder:
pitch += 1
remainder = -100 + remainder
else:
pitch -= 1
remainder = 100 + remainder
final_cents = remainder
if final_cents < 0:
cent_string = f"{final_cents}"
if chris is True:
if not cent_string[0].isalpha():
pitch_string = str(abjad.NamedPitchClass(pitch))
pos, acc = pitch_string[0], pitch_string[1:]
pos = pos.capitalize()
acc = acc.replace("s", "♯")
acc = acc.replace("f", "♭")
cent_string = pos + acc + cent_string
cent_string = cent_string.replace("A♭", "G♯")
if chris is False:
if pitch is not None:
pitch_string = str(abjad.NamedPitchClass(pitch))
pos, acc = pitch_string[0], pitch_string[1:]
pos = pos.capitalize()
acc = acc.replace("s", "♯")
acc = acc.replace("f", "♭")
cent_string = pos + acc + cent_string
else:
cent_string = f"+{final_cents}"
if chris is True:
if not cent_string[0].isalpha():
pitch_string = str(abjad.NamedPitchClass(pitch))
pos, acc = pitch_string[0], pitch_string[1:]
pos = pos.capitalize()
acc = acc.replace("s", "♯")
acc = acc.replace("f", "♭")
cent_string = pos + acc + cent_string
cent_string = cent_string.replace("A♭", "G♯")
if chris is False:
if pitch is not None:
pitch_string = str(abjad.NamedPitchClass(pitch))
pos, acc = pitch_string[0], pitch_string[1:]
pos = pos.capitalize()
acc = acc.replace("s", "♯")
acc = acc.replace("f", "♭")
cent_string = pos + acc + cent_string
mark = abjad.Markup(
fr"\markup \center-align {{ {cent_string} }}",
direction=abjad.Up,
literal=True,
)
return mark
[docs]def tune_to_ratio(
note_head,
ratio,
*,
omit_just_accidental=False,
tempered=False,
):
r"""
Transposes notehead in place and tweaks accidental stencil.
.. container:: example
All implemented accidentals are available for both stylesheets:
>>> note = abjad.Note("c'4")
>>> microtones.tune_to_ratio(note.note_head, "7/4")
>>> staff = abjad.Staff([note])
>>> score = abjad.Score([staff])
>>> moment = "#(ly:make-moment 1 25)"
>>> abjad.setting(score).proportional_notation_duration = moment
>>> lilypond_file = abjad.LilyPondFile(
... items=[score, abjad.Block(name="layout")],
... includes=["default.ily", "ekmelos-ji-accidental-markups.ily"],
... global_staff_size=16,
... )
>>> style = '"dodecaphonic"'
>>> lilypond_file.layout_block.items.append(fr"\accidentalStyle {style}" )
>>> abjad.show(lilypond_file) # doctest: +SKIP
>>> note = abjad.Note("c'4")
>>> microtones.tune_to_ratio(note.note_head, "7/4")
>>> staff = abjad.Staff([note])
>>> score = abjad.Score([staff])
>>> moment = "#(ly:make-moment 1 25)"
>>> abjad.setting(score).proportional_notation_duration = moment
>>> lilypond_file = abjad.LilyPondFile(
... items=[score, abjad.Block(name="layout")],
... includes=["default.ily", "heji2-ji-accidental-markups.ily"],
... global_staff_size=16,
... )
>>> style = '"dodecaphonic"'
>>> lilypond_file.layout_block.items.append(fr"\accidentalStyle {style}" )
>>> abjad.show(lilypond_file) # doctest: +SKIP
.. container:: example
Tweaks accidentals when ``omit_just_accidental=False``:
>>> note = abjad.Note("c'4")
>>> microtones.tune_to_ratio(note.note_head, "5/1", omit_just_accidental=False)
>>> print(abjad.lilypond(note)) # doctest: +SKIP
Does not tweak accidentals when ``omit_just_accidental=True``:
>>> note = abjad.Note("c'4")
>>> microtones.tune_to_ratio(note.note_head, "5/1", omit_just_accidental=True)
>>> print(abjad.lilypond(note)) # doctest: +SKIP
.. docs::
>>> print(abjad.lilypond(note))
e'''4
.. container:: example
A harmonic series with the ekmelos font.
>>> ratios = [f"{_ + 1}/1" for _ in range(23)]
>>> notes = [abjad.Note("a,,,8") for _ in ratios]
>>> for note, ratio in zip(notes, ratios):
... microtones.tune_to_ratio(note.note_head, ratio)
...
>>> staff = abjad.Staff()
>>> staff.extend(notes)
>>> abjad.attach(abjad.Clef("bass"), staff[0])
>>> abjad.attach(abjad.Clef("treble"), staff[6])
>>> score = abjad.Score([staff])
>>> moment = "#(ly:make-moment 1 25)"
>>> abjad.setting(score).proportional_notation_duration = moment
>>> lilypond_file = abjad.LilyPondFile(
... items=[score, abjad.Block(name="layout")],
... includes=[
... "default.ily",
... "harmonic-series-layout.ily",
... "ekmelos-ji-accidental-markups.ily"
... ],
... global_staff_size=16,
... )
>>> style = '"dodecaphonic"'
>>> lilypond_file.layout_block.items.append(fr"\accidentalStyle {style}" )
>>> abjad.show(lilypond_file) # doctest: +SKIP
.. docs::
>>> print(abjad.lilypond(staff))
\new Staff
{
\clef "bass"
\tweak Accidental.stencil #ly:text-interface::print
\tweak Accidental.text \markup { \abjad-natural }
a,,,8
\tweak Accidental.stencil #ly:text-interface::print
\tweak Accidental.text \markup { \abjad-natural }
a,,8
\tweak Accidental.stencil #ly:text-interface::print
\tweak Accidental.text \markup { \abjad-natural }
e,8
\tweak Accidental.stencil #ly:text-interface::print
\tweak Accidental.text \markup { \abjad-natural }
a,8
\tweak Accidental.stencil #ly:text-interface::print
\tweak Accidental.text \markup { \sharp-one-syntonic-comma-down }
cs8
\tweak Accidental.stencil #ly:text-interface::print
\tweak Accidental.text \markup { \abjad-natural }
e8
\clef "treble"
\tweak Accidental.stencil #ly:text-interface::print
\tweak Accidental.text \markup { \one-septimal-comma-down }
g8
\tweak Accidental.stencil #ly:text-interface::print
\tweak Accidental.text \markup { \abjad-natural }
a8
\tweak Accidental.stencil #ly:text-interface::print
\tweak Accidental.text \markup { \abjad-natural }
b8
\tweak Accidental.stencil #ly:text-interface::print
\tweak Accidental.text \markup { \sharp-one-syntonic-comma-down }
cs'8
\tweak Accidental.stencil #ly:text-interface::print
\tweak Accidental.text \markup { \one-undecimal-quarter-tone-up }
d'8
\tweak Accidental.stencil #ly:text-interface::print
\tweak Accidental.text \markup { \abjad-natural }
e'8
\tweak Accidental.stencil #ly:text-interface::print
\tweak Accidental.text \markup \concat { \one-tridecimal-third-tone-down \hspace #0.125 \abjad-sharp }
fs'8
\tweak Accidental.stencil #ly:text-interface::print
\tweak Accidental.text \markup { \one-septimal-comma-down }
g'8
\tweak Accidental.stencil #ly:text-interface::print
\tweak Accidental.text \markup { \sharp-one-syntonic-comma-down }
gs'8
\tweak Accidental.stencil #ly:text-interface::print
\tweak Accidental.text \markup { \abjad-natural }
a'8
\tweak Accidental.stencil #ly:text-interface::print
\tweak Accidental.text \markup \concat { \one-seventeen-limit-schisma-down \hspace #0.125 \abjad-sharp }
as'8
\tweak Accidental.stencil #ly:text-interface::print
\tweak Accidental.text \markup { \abjad-natural }
b'8
\tweak Accidental.stencil #ly:text-interface::print
\tweak Accidental.text \markup { \one-nineteen-limit-schisma-up }
c''8
\tweak Accidental.stencil #ly:text-interface::print
\tweak Accidental.text \markup { \sharp-one-syntonic-comma-down }
cs''8
\tweak Accidental.stencil #ly:text-interface::print
\tweak Accidental.text \markup { \one-septimal-comma-down }
d''8
\tweak Accidental.stencil #ly:text-interface::print
\tweak Accidental.text \markup { \one-undecimal-quarter-tone-up }
d''8
\tweak Accidental.stencil #ly:text-interface::print
\tweak Accidental.text \markup \concat { \one-twenty-three-limit-comma-up \hspace #0.125 \abjad-sharp }
ds''8
}
A harmonic series with the HEJI2 font.
>>> ratios = [f"{_ + 1}/1" for _ in range(23)]
>>> notes = [abjad.Note("a,,,8") for _ in ratios]
>>> for note, ratio in zip(notes, ratios):
... microtones.tune_to_ratio(note.note_head, ratio)
...
>>> staff = abjad.Staff()
>>> staff.extend(notes)
>>> abjad.attach(abjad.Clef("bass"), staff[0])
>>> abjad.attach(abjad.Clef("treble"), staff[6])
>>> abjad.attach(abjad.TimeSignature((24, 32)), staff[0])
>>> score = abjad.Score([staff])
>>> moment = "#(ly:make-moment 1 25)"
>>> abjad.setting(score).proportional_notation_duration = moment
>>> lilypond_file = abjad.LilyPondFile(
... items=[score, abjad.Block(name="layout")],
... includes=[
... "default.ily",
... "harmonic-series-layout.ily",
... "heji2-ji-accidental-markups.ily"
... ],
... global_staff_size=16,
... )
>>> style = '"dodecaphonic"'
>>> lilypond_file.layout_block.items.append(fr"\accidentalStyle {style}" )
>>> abjad.show(lilypond_file) # doctest: +SKIP
.. container:: example
Prints tempered accidentals when ``tempered=True``:
>>> note = abjad.Note("c'4")
>>> microtones.tune_to_ratio(note.note_head, "5/1", tempered=True)
>>> staff = abjad.Staff([note])
>>> score = abjad.Score([staff])
>>> moment = "#(ly:make-moment 1 25)"
>>> abjad.setting(score).proportional_notation_duration = moment
>>> lilypond_file = abjad.LilyPondFile(
... items=[score, abjad.Block(name="layout")],
... includes=["default.ily", "ekmelos-ji-accidental-markups.ily"],
... global_staff_size=16,
... )
>>> style = '"dodecaphonic"'
>>> lilypond_file.layout_block.items.append(fr"\accidentalStyle {style}" )
>>> abjad.show(lilypond_file) # doctest: +SKIP
.. docs::
>>> print(abjad.lilypond(note))
\tweak Accidental.stencil #ly:text-interface::print
\tweak Accidental.text \tempered-natural
e'''4
"""
bundle = make_ji_bundle(note_head.written_pitch, ratio)
note_head.written_pitch = bundle.pitch
if omit_just_accidental:
return
if tempered is True:
tempered_accidental = note_head.written_pitch.accidental.name
tempered_accidental = tempered_accidental.replace(" ", "-")
manager = abjad.tweak(note_head, literal=True)
manager.Accidental.stencil = r"#ly:text-interface::print"
manager.Accidental.text = fr"\tempered-{tempered_accidental}"
else:
markup = bundle.vector.calculate_ji_markup()
manager = abjad.tweak(note_head, literal=True)
manager.Accidental.stencil = r"#ly:text-interface::print"
alteration_literal = markup
manager.Accidental.text = alteration_literal