Source code for auxjad.mutate.respell_augmented_unisons

import abjad


[docs]def respell_augmented_unisons(selection: abjad.Selection, *, include_multiples: bool = False, respell_by_pitch_class: bool = False, ) -> None: r"""Mutates an input |abjad.Selection| in place and has no return value; this function changes the accidentals of individual pitches of all chords in a container in order to avoid augmented unisons. Basic usage: To use this function, apply it to a selection that contains chords that have augmented unisons. >>> container = abjad.Container(r"c'4 r4 <ef' e'>4 g'4 <c' cs'>4 r2.") >>> abjad.show(container) .. docs:: { c'4 r4 <ef' e'>4 g'4 <c' cs'>4 r2. } .. figure:: ../_images/respell_augmented_unisons-OXnGvQzGT2.png >>> auxjad.mutate.respell_augmented_unisons(container[:]) >>> abjad.show(container) .. docs:: { c'4 r4 <ds' e'>4 g'4 <c' df'>4 r2. } .. figure:: ../_images/respell_augmented_unisons-x33afbbamt.png This can be useful when using tuples of integers to create chords that contain minor seconds: >>> pitches = [(0, 1), (8, 9, 12), (0, 4, 5, 6), (-1, 5, 6)] >>> durations = [(1, 8), (3, 8), (7, 16), (1, 16)] >>> maker = abjad.LeafMaker() >>> chords = maker(pitches, durations) >>> staff = abjad.Staff(chords) >>> literal = abjad.LilyPondLiteral(r'\accidentalStyle dodecaphonic') >>> abjad.attach(literal, staff) >>> abjad.show(staff) .. docs:: \new Staff { \accidentalStyle dodecaphonic <c' cs'>8 <af' a' c''>4. <c' e' f' fs'>4.. <b f' fs'>16 } .. figure:: ../_images/respell_augmented_unisons-mWVWwV9uBx.png >>> auxjad.mutate.respell_augmented_unisons(staff[:]) >>> abjad.show(staff) .. docs:: \new Staff { \accidentalStyle dodecaphonic <c' df'>8 <gs' a' c''>4. <c' e' f' gf'>4.. <b f' gf'>16 } .. figure:: ../_images/respell_augmented_unisons-IfzaseW4oS.png .. note:: Auxjad automatically adds this function as an extension function to |abjad.mutate|. It can thus be used from either |auxjad.mutate|_ or |abjad.mutate| namespaces. Therefore, the two lines below are equivalent: >>> auxjad.mutate.respell_augmented_unisons(staff[:]) >>> abjad.mutate.respell_augmented_unisons(staff[:]) 2-note chords: The example below shows first the default spelling of 2-note chords in Abjad followed by the respelt 2-note chords. >>> staff = abjad.Staff() >>> for pitch in range(12): ... staff.append(abjad.Chord([pitch, pitch + 1], (1, 16))) >>> literal = abjad.LilyPondLiteral(r'\accidentalStyle dodecaphonic') >>> abjad.attach(literal, staff) >>> abjad.show(staff) .. docs:: \new Staff { \accidentalStyle dodecaphonic <c' cs'>16 <cs' d'>16 <d' ef'>16 <ef' e'>16 <e' f'>16 <f' fs'>16 <fs' g'>16 <g' af'>16 <af' a'>16 <a' bf'>16 <bf' b'>16 <b' c''>16 } .. figure:: ../_images/respell_augmented_unisons-qQduIqCRpz.png >>> auxjad.mutate.respell_augmented_unisons(staff[:]) >>> abjad.show(staff) .. docs:: \new Staff { \accidentalStyle dodecaphonic <c' df'>16 <cs' d'>16 <d' ef'>16 <ds' e'>16 <e' f'>16 <f' gf'>16 <fs' g'>16 <g' af'>16 <gs' a'>16 <a' bf'>16 <as' b'>16 <b' c''>16 } .. figure:: ../_images/respell_augmented_unisons-jvg032q24il.png augmented unissons in chords with 3 or more pitches: The function looks for all augmented unissons in chords of 3 or more pitches: >>> staff = abjad.Staff(r"<a c' cs' f'>1") >>> abjad.show(staff) .. docs:: \new Staff { <a c' cs' f'>1 } .. figure:: ../_images/respell_augmented_unisons-IklJO81q1E.png >>> auxjad.mutate.respell_augmented_unisons(staff[:]) >>> abjad.show(staff) .. docs:: \new Staff { <a c' df' f'>1 } .. figure:: ../_images/respell_augmented_unisons-gyficck05p.png ``include_multiples``: By default, this function only changes spelling for pitches that are 1 semitone apart. >>> staff = abjad.Staff(r"<c' cs''>1") >>> abjad.show(staff) .. docs:: \new Staff { <c' cs''>1 } .. figure:: ../_images/respell_augmented_unisons-HPqFrADjeh.png >>> auxjad.mutate.respell_augmented_unisons(staff[:]) >>> abjad.show(staff) .. docs:: \new Staff { <c' cs''>1 } .. figure:: ../_images/respell_augmented_unisons-uszf11qb72d.png To consider pitches in different octaves (thus including augmented unisons, augmented octaves, augmented fifteenths, etc.), call this function with the keyword argument ``include_multiples`` set to ``True``. >>> staff = abjad.Staff(r"<c' cs''>1") >>> auxjad.mutate.respell_augmented_unisons( ... staff[:], ... include_multiples=True, ... ) .. docs:: \new Staff { <c' df''>1 } .. figure:: ../_images/respell_augmented_unisons-8am8cu2rmgi.png ``respell_by_pitch_class``: By default, when this function changes the spelling of a pitch, it does not change the spelling of all other pitches with the same pitch-class. >>> staff = abjad.Staff(r"<c' cs' cs''>1") >>> abjad.show(staff) .. docs:: \new Staff { <c' cs' cs''>1 } .. figure:: ../_images/respell_augmented_unisons-eWixL7iCEq.png >>> auxjad.mutate.respell_augmented_unisons(staff[:]) >>> abjad.show(staff) .. docs:: \new Staff { <c' df' cs''>1 } .. figure:: ../_images/respell_augmented_unisons-47d16xk6gvs.png To alter all pitch-classes, call this function with the keyword argument ``respell_by_pitch_class`` set to ``True``. >>> staff = abjad.Staff(r"<c' cs' cs''>1") >>> auxjad.mutate.respell_augmented_unisons( ... staff[:], ... respell_by_pitch_class=True, ... ) >>> abjad.show(staff) .. docs:: \new Staff { <c' df' df''>1 } .. figure:: ../_images/respell_augmented_unisons-kobft0oq9sl.png """ if not isinstance(selection, abjad.Selection): raise TypeError("argument must be 'abjad.Selection'") if not isinstance(respell_by_pitch_class, bool): raise TypeError("'respell_by_pitch_class' must be 'bool'") if not isinstance(include_multiples, bool): raise TypeError("'include_multiples' must be 'bool'") for leaf in selection.leaves(): if isinstance(leaf, abjad.Chord): accidentals = [pitch.accidental for pitch in leaf.written_pitches] original_accidentals = accidentals[:] if not include_multiples: # dealing only with intervals of size equal to 1 semitone for i in range(len(leaf.written_pitches) - 1): p1 = leaf.written_pitches[i] p2 = leaf.written_pitches[i + 1] interval12 = p1 - p2 try: p3 = leaf.written_pitches[i + 2] interval23 = p2 - p3 except IndexError: p3 = None interval23 = None if (interval12 == abjad.NamedInterval('+A1') and interval23 != abjad.NamedInterval('+A1') and interval23 != abjad.NamedInterval('+m2')): if not respell_by_pitch_class: # respelling only one single note if p1.accidental == abjad.Accidental('f'): accidentals[i] = abjad.Accidental('s') elif p1.accidental == abjad.Accidental(''): accidentals[i + 1] = abjad.Accidental('f') else: # respelling all matching pitch-classes if p1.accidental == abjad.Accidental('f'): for j, p in enumerate(leaf.written_pitches): if p.pitch_class == p1.pitch_class: accidentals[j] = abjad.Accidental('s') elif p1.accidental == abjad.Accidental(''): for j, p in enumerate(leaf.written_pitches): if p.pitch_class == p2.pitch_class: accidentals[j] = abjad.Accidental('f') else: # dealing with augmented unisons as well as augmented 8as, # 15ths, etc. for i in range(len(leaf.written_pitches) - 1): for j in range(i + 1, len(leaf.written_pitches)): # no p3 this time since p1 and p2 are not necessary # consecutive pitches in the chord p1 = leaf.written_pitches[i] p2 = leaf.written_pitches[j] interval = abjad.NamedIntervalClass(p1 - p2) if (interval in (abjad.NamedIntervalClass('+A1'), abjad.NamedIntervalClass('-d1'), )): # no need for respell_by_pitch_class since this # will go through all notes in the chord anyway if p1.accidental == abjad.Accidental('f'): accidentals[i] = abjad.Accidental('s') if p1.accidental == abjad.Accidental('s'): accidentals[i] = abjad.Accidental('f') elif p1.accidental == abjad.Accidental(''): if p2.accidental == abjad.Accidental('s'): accidentals[j] = abjad.Accidental('f') elif p2.accidental == abjad.Accidental('f'): accidentals[j] = abjad.Accidental('s') # rewritting chord with new spelling respelt_pitches = [] for pitch, accidental, original_accidental in zip( leaf.written_pitches, accidentals, original_accidentals, ): if (accidental != original_accidental and accidental == abjad.Accidental('f')): respelt_pitches.append(pitch._respell(accidental='flats')) elif (accidental != original_accidental and accidental == abjad.Accidental('s')): respelt_pitches.append(pitch._respell(accidental='sharps')) else: respelt_pitches.append(pitch) leaf.written_pitches = respelt_pitches