def test_LilyPondParser__spanners__Hairpin_03(): """ Dynamics can terminate hairpins. """ maker = abjad.NoteMaker() target = abjad.Staff(maker([0] * 3, [(1, 4)])) abjad.hairpin("<", target[0:2]) abjad.hairpin("p > f", target[1:]) assert format(target) == abjad.String.normalize( r""" \new Staff { c'4 \< c'4 \p \> c'4 \f } """ ) string = r"\new Staff \relative c' { c \< c \p \> c \f }" parser = abjad.parser.LilyPondParser() result = parser(string) assert format(target) == format(result) and target is not result
def test_LilyPondParser__spanners__Hairpin_01(): maker = abjad.NoteMaker() target = abjad.Staff(maker([0] * 5, [(1, 4)])) abjad.hairpin("< !", target[:3]) abjad.hairpin("> ppp", target[2:]) assert format(target) == abjad.String.normalize(r""" \new Staff { c'4 \< c'4 c'4 \! \> c'4 c'4 \ppp } """) parser = abjad.parser.LilyPondParser() result = parser(format(target)) assert format(target) == format(result) and target is not result
def test_LilyPondParser__spanners__Hairpin_01(): maker = abjad.NoteMaker() target = abjad.Staff(maker([0] * 5, [(1, 4)])) abjad.hairpin("< !", target[:3]) abjad.hairpin("> ppp", target[2:]) assert format(target) == abjad.String.normalize( r""" \new Staff { c'4 \< c'4 c'4 \! \> c'4 c'4 \ppp } """ ) parser = abjad.parser.LilyPondParser() result = parser(format(target)) assert format(target) == format(result) and target is not result
def test_LilyPondParser__spanners__Hairpin_02(): """ Dynamics can terminate hairpins. """ maker = abjad.NoteMaker() target = abjad.Staff(maker([0] * 3, [(1, 4)])) abjad.hairpin("<", target[0:2]) abjad.hairpin("p > f", target[1:]) assert format(target) == abjad.String.normalize(r""" \new Staff { c'4 \< c'4 \p \> c'4 \f } """) string = r"\new Staff \relative c' { c \< c \p \> c \f }" parser = abjad.parser.LilyPondParser() result = parser(string) assert format(target) == format(result) and target is not result
def test_mutate_replace_01(): """ Moves parentage from two old notes to five new notes. Equivalent to staff[1:3] = new_notes. """ staff = abjad.Staff("c'8 d'8 e'8 f'8") abjad.beam(staff[:2]) abjad.beam(staff[2:]) abjad.hairpin("< !", staff[:]) assert abjad.lilypond(staff) == abjad.String.normalize(r""" \new Staff { c'8 \< [ d'8 ] e'8 [ f'8 \! ] } """), print(abjad.lilypond(staff)) old_notes = staff[1:3] new_notes = abjad.Selection([ abjad.Note("c''16"), abjad.Note("c''16"), abjad.Note("c''16"), abjad.Note("c''16"), abjad.Note("c''16"), ]) abjad.mutate.replace(old_notes, new_notes) assert abjad.lilypond(staff) == abjad.String.normalize(r""" \new Staff { c'8 \< [ c''16 c''16 c''16 c''16 c''16 f'8 \! ] } """), print(abjad.lilypond(staff)) assert abjad.wf.wellformed(staff)
def test_Mutation_replace_01(): """ Moves parentage from two old notes to five new notes. Equivalent to staff[1:3] = new_notes. """ staff = abjad.Staff("c'8 d'8 e'8 f'8") abjad.beam(staff[:2]) abjad.beam(staff[2:]) abjad.hairpin("< !", staff[:]) assert format(staff) == abjad.String.normalize( r""" \new Staff { c'8 \< [ d'8 ] e'8 [ f'8 \! ] } """ ), print(format(staff)) old_notes = staff[1:3] new_notes = 5 * abjad.Note("c''16") abjad.mutate(old_notes).replace(new_notes) assert format(staff) == abjad.String.normalize( r""" \new Staff { c'8 \< [ c''16 c''16 c''16 c''16 c''16 f'8 \! ] } """ ), print(format(staff)) assert abjad.inspect(staff).wellformed()
def test_Mutation_replace_01(): """ Moves parentage from two old notes to five new notes. Equivalent to staff[1:3] = new_notes. """ staff = abjad.Staff("c'8 d'8 e'8 f'8") abjad.beam(staff[:2]) abjad.beam(staff[2:]) abjad.hairpin("< !", staff[:]) assert format(staff) == abjad.String.normalize( r""" \new Staff { c'8 \< [ d'8 ] e'8 [ f'8 \! ] } """ ), print(format(staff)) old_notes = staff[1:3] new_notes = 5 * abjad.Note("c''16") abjad.mutate(old_notes).replace(new_notes) assert format(staff) == abjad.String.normalize( r""" \new Staff { c'8 \< [ c''16 c''16 c''16 c''16 c''16 f'8 \! ] } """ ), print(format(staff)) assert abjad.inspect(staff).wellformed()
def test_mutate_copy_08(): """ Copies hairpin. """ staff = abjad.Staff("c'8 cs'8 d'8 ef'8 e'8 f'8 fs'8 g'8") abjad.hairpin("< !", staff[:4]) assert abjad.lilypond(staff) == abjad.String.normalize( r""" \new Staff { c'8 \< cs'8 d'8 ef'8 \! e'8 f'8 fs'8 g'8 } """ ) new_notes = abjad.mutate.copy(staff[:4]) staff.extend(new_notes) assert abjad.lilypond(staff) == abjad.String.normalize( r""" \new Staff { c'8 \< cs'8 d'8 ef'8 \! e'8 f'8 fs'8 g'8 c'8 \< cs'8 d'8 ef'8 \! } """ ) assert abjad.wf.wellformed(staff)
def test_Mutation_copy_08(): """ Copies hairpin. """ staff = abjad.Staff("c'8 cs'8 d'8 ef'8 e'8 f'8 fs'8 g'8") abjad.hairpin("< !", staff[:4]) assert format(staff) == abjad.String.normalize(r""" \new Staff { c'8 \< cs'8 d'8 ef'8 \! e'8 f'8 fs'8 g'8 } """) new_notes = abjad.mutate(staff[:4]).copy() staff.extend(new_notes) assert format(staff) == abjad.String.normalize(r""" \new Staff { c'8 \< cs'8 d'8 ef'8 \! e'8 f'8 fs'8 g'8 c'8 \< cs'8 d'8 ef'8 \! } """) assert abjad.inspect(staff).wellformed()
def dynamics(self, dynamics: dict, material_name=None): """ :param dynamics: dict (key: str, value: abjad.Selection) :param material_name: str """ if material_name is None: selectable = self.container else: selectable = self.select_material(self.container, material_name=material_name) for key, select in dynamics.items(): selection = select(selectable) if abjad.Dynamic.is_dynamic_name(key): if isinstance(selection, abjad.Leaf): abjad.attach(abjad.Dynamic(key), selection) else: for _ in selection: abjad.attach(abjad.Dynamic(key), _) elif isinstance(selection[0], abjad.Selection): for sel in selection: abjad.hairpin(key, sel) else: abjad.hairpin(key, selection)
import abjad class AnnotatedDuration(abjad.Duration): def __init__(self, annotation): self.annotation = annotation dur = AnnotatedDuration((3, 8)) dur.annotation = "note" print(dur.annotation) staff = abjad.Staff("c'1 d'1 c'1. d'1. c'1. d'1. ") abjad.hairpin("p < f", staff[:]) abjad.override(staff).dynamic_line_spanner.staff_padding = 3 durations = [(3, 4), (4, 4), (5, 4)] result = abjad.mutate.split( staff[:], durations, cyclic=True, ) abjad.f(result) meters = [abjad.Meter(_) for _ in durations] result2 = abjad.select(staff).leaves() result2 = result2.group_by # for measure, time_sig in zip(result2, meters): # print(measure)
def make_bartok_score(): """ make the Bartok example score. """ # make score skeleton score = abjad.Score() piano_staff = abjad.StaffGroup(lilypond_type='PianoStaff') upper_staff = abjad.Staff([]) lower_staff = abjad.Staff([]) piano_staff.append(upper_staff) piano_staff.append(lower_staff) score.append(piano_staff) # make upper measures upper_measures = [] upper_measures.append(abjad.Container()) upper_measures.append(abjad.Container()) upper_measures.append(abjad.Container()) upper_measures.append(abjad.Container()) upper_measures.append(abjad.Container()) lower_measures = copy.deepcopy(upper_measures) upper_staff.extend(upper_measures) lower_staff.extend(lower_measures) # add leaves to upper measures upper_measures[0].extend("a'8 g'8 f'8 e'8") abjad.attach(abjad.TimeSignature((2, 4)), upper_measures[0][0]) upper_measures[1].extend("d'4 g'8 f'8 e'8 d'8") abjad.attach(abjad.TimeSignature((3, 4)), upper_measures[1][0]) upper_measures[2].extend("c'8 d'16 e'16 f'8 e'8") abjad.attach(abjad.TimeSignature((2, 4)), upper_measures[2][0]) upper_measures[3].append("d'2") upper_measures[4].append("d'2") # add leaves to lower measures lower_measures[0].extend("b4 d'8 c'8") lower_measures[1].extend("b8 a8 af4 c'8 bf8") lower_measures[2].extend("a8 g8 fs8 g16 a16") # make parallel music for measure 4 upper_voice = abjad.Voice("b2", name='upper voice') command = abjad.LilyPondLiteral(r'\voiceOne') abjad.attach(command, upper_voice) lower_voice = abjad.Voice("b4 a4", name='lower voice') command = abjad.LilyPondLiteral(r'\voiceTwo') abjad.attach(command, lower_voice) lower_measures[3].extend([upper_voice, lower_voice]) lower_measures[3].is_simultaneous = True # make parallel music for measure 5 upper_voice = abjad.Voice("b2", name='upper voice') command = abjad.LilyPondLiteral(r'\voiceOne') abjad.attach(command, upper_voice) lower_voice = abjad.Voice("g2", name='lower voice') command = abjad.LilyPondLiteral(r'\voiceTwo') abjad.attach(command, lower_voice) lower_measures[4].extend([upper_voice, lower_voice]) lower_measures[4].is_simultaneous = True # add bass clef clef = abjad.Clef('bass') leaf = abjad.inspect(lower_staff).leaf(0) abjad.attach(clef, leaf) # add dynamics dynamic = abjad.Dynamic('pp') abjad.attach(dynamic, upper_measures[0][0]) dynamic = abjad.Dynamic('mp') abjad.attach(dynamic, upper_measures[1][1]) dynamic = abjad.Dynamic('pp') abjad.attach(dynamic, lower_measures[0][1]) dynamic = abjad.Dynamic('mp') abjad.attach(dynamic, lower_measures[1][3]) # add final bar line score.add_final_bar_line() # select leaves for attaching spanners to upper_leaves = abjad.select(upper_staff).leaves() lower_leaves = abjad.select(lower_staff).leaves() # attach beams abjad.beam(upper_leaves[:4]) abjad.beam(lower_leaves[1:5]) abjad.beam(lower_leaves[6:10]) # attach slurs abjad.slur(upper_leaves[:5]) abjad.slur(upper_leaves[5:]) abjad.slur(lower_leaves[1:6]) # attach hairpins abjad.hairpin('<', upper_leaves[-7:-2]) abjad.hairpin('>', upper_leaves[-2:]) # attach a ritardando with markup start_text_span = abjad.StartTextSpan(left_text=abjad.Markup('ritard.')) abjad.text_spanner(upper_leaves[-7:], start_text_span=start_text_span) # tie notes abjad.tie(upper_leaves[-2:]) # tie more notes note_1 = lower_staff[-2]['upper voice'][0] note_2 = lower_staff[-1]['upper voice'][0] notes = abjad.select([note_1, note_2]) abjad.tie(notes) # return the score return score
def attach_dynamics(reference_voice): leaves = abjad.select(reference_voice).leaves() leaf_count = len(leaves) underlying_dynamics = cary.make_underlying_dynamics() for i, dynamic in enumerate(underlying_dynamics): #print(f'underlying {i}: {dynamic}') pass dynamic_index_pairs = [] underlying_dynamic_index = 0 for dynamic_token in cary.dynamic_tokens: if dynamic_token[0] == 'specific underlying': assert len(dynamic_token) == 3, repr(dynamic_token) start_leaf, stop_leaf = dynamic_token[1] underlying_index = dynamic_token[2] for leaf_index in range(start_leaf, stop_leaf+1): underlying_dynamic = underlying_dynamics[underlying_index] if 641 <= leaf_index: leaf_index -= 2 pair = (leaf_index, underlying_dynamic) dynamic_index_pairs.append(pair) underlying_index += 1 else: start = dynamic_token[1] #stop = dynamic_token[-1] + 1 if dynamic_token[0] == 'underlying': stop = dynamic_token[-1] + 1 else: stop = start + 1 for leaf_index in range(start, stop): if 641 <= leaf_index: leaf_index -= 2 if dynamic_token[0] == 'underlying': pair = ( leaf_index, underlying_dynamics[underlying_dynamic_index], ) else: pair = (leaf_index, dynamic_token[0]) dynamic_index_pairs.append(pair) underlying_dynamic_index += 1 lone_dynamic_tokens = [] hairpin_tokens = [] hairpin_token = None for dynamic_index_pair in dynamic_index_pairs: index, string = dynamic_index_pair if string[-1] in ('<', '>'): start_dynamic, hairpin = string.split() hairpin_token = { 'hairpin': hairpin, 'start_dynamic': start_dynamic, 'start_index': index } elif hairpin_token is not None: hairpin_token['stop_dynamic'] = string hairpin_token['stop_index'] = index hairpin_tokens.append(hairpin_token) hairpin_token = None else: lone_dynamic_token = { 'dynamic': string, 'index': index, } lone_dynamic_tokens.append(lone_dynamic_token) for lone_dynamic_token in lone_dynamic_tokens: index = lone_dynamic_token['index'] leaf = leaves[index] dynamic = lone_dynamic_token['dynamic'] dynamic = abjad.Dynamic(dynamic) abjad.label(leaf).color_leaves('red') if isinstance(leaf, abjad.Note): abjad.attach(dynamic, leaf) abjad.override(leaf).dynamic_text.color = 'red' # TODO: redefine minimum hairpin duration after score audit #minimum_hairpin_duration = abjad.Duration(6, 128) for hairpin_token in hairpin_tokens: start_index = hairpin_token['start_index'] stop_index = hairpin_token['stop_index'] + 1 if not stop_index < leaf_count - 1: continue leaves_ = leaves[start_index:stop_index] #duration = abjad.inspect(leaves_).duration() #if duration < minimum_hairpin_duration: if False: dynamic = abjad.Dynamic(hairpin_token['start_dynamic']) abjad.attach(dynamic, leaves_[0]) dynamic = abjad.Dynamic(hairpin_token['stop_dynamic']) abjad.attach(dynamic, leaves_[-1]) abjad.label(leaves_[0]).color_leaves('blue') abjad.label(leaves_[-1]).color_leaves('blue') else: strings = [ hairpin_token['start_dynamic'], hairpin_token['hairpin'], hairpin_token['stop_dynamic'], ] descriptor = ' '.join(strings) abjad.hairpin(descriptor, leaves_) for leaf_ in leaves_: abjad.override(leaf_).dynamic_text.color = 'green' abjad.override(leaf_).hairpin.color = 'green'
def make_bartok_score(): """ Makes Bartók score. """ # makes empty score score = abjad.Score() piano_staff = abjad.StaffGroup(lilypond_type="PianoStaff") upper_staff = abjad.Staff(name="Upper_Staff") upper_staff_voice = abjad.Voice(name="Upper_Staff_Voice") upper_staff.append(upper_staff_voice) lower_staff = abjad.Staff(name="Lower_Staff") lower_staff_voice_2 = abjad.Voice(name="Lower_Staff_Voice_II") lower_staff.append(lower_staff_voice_2) piano_staff.append(upper_staff) piano_staff.append(lower_staff) score.append(piano_staff) # populates upper measures upper_staff_voice.append(r"{ \time 2/4 a'8 g'8 f'8 e'8 }") upper_staff_voice.append(r"{ \time 3/4 d'4 g'8 f'8 e'8 d'8 }") upper_staff_voice.append(r"{ \time 2/4 c'8 d'16 e'16 f'8 e'8 }") upper_staff_voice.append("{ d'2 }") upper_staff_voice.append("{ d'2 }") # populates lower measures lower_staff_voice_2.append("{ b4 d'8 c'8 }") lower_staff_voice_2.append("{ b8 a8 af4 c'8 bf8 }") lower_staff_voice_2.append("{ a8 g8 fs8 g16 a16 }") # makes simultaneous music for measure 4 container = abjad.Container( [ abjad.Voice(name="Lower_Staff_Voice_I"), abjad.Voice(name="Lower_Staff_Voice_II"), ], simultaneous=True, ) literal = abjad.LilyPondLiteral(r"\voiceOne") abjad.attach(literal, container["Lower_Staff_Voice_I"]) container["Lower_Staff_Voice_I"].append("b2") literal = abjad.LilyPondLiteral(r"\voiceTwo") abjad.attach(literal, container["Lower_Staff_Voice_II"]) container["Lower_Staff_Voice_II"].extend("b4 a4") lower_staff.append(container) # measure 5 container = abjad.Container( [ abjad.Voice(name="Lower_Staff_Voice_I"), abjad.Voice(name="Lower_Staff_Voice_II"), ], simultaneous=True, ) literal = abjad.LilyPondLiteral(r"\voiceOne") abjad.attach(literal, container["Lower_Staff_Voice_I"]) container["Lower_Staff_Voice_I"].append("b2") literal = abjad.LilyPondLiteral(r"\voiceTwo") abjad.attach(literal, container["Lower_Staff_Voice_II"]) container["Lower_Staff_Voice_II"].append("g2") lower_staff.append(container) # get leaves upper_staff_leaves = abjad.select(upper_staff).leaves() lower_staff_voice_1_leaves = [] for leaf in abjad.select(lower_staff).leaves(): voice = abjad.inspect(leaf).parentage().get(abjad.Voice) if voice.name == "Lower_Staff_Voice_I": lower_staff_voice_1_leaves.append(leaf) lower_staff_voice_2_leaves = [] for leaf in abjad.select(lower_staff).leaves(): voice = abjad.inspect(leaf).parentage().get(abjad.Voice) if voice.name == "Lower_Staff_Voice_II": lower_staff_voice_2_leaves.append(leaf) # adds bass clef and final bar line clef = abjad.Clef("bass") leaf = lower_staff_voice_2_leaves[0] abjad.attach(clef, leaf) score.add_final_bar_line() # adds dynamics abjad.attach(abjad.Dynamic("pp"), upper_staff_leaves[0]) abjad.attach(abjad.Dynamic("mp"), upper_staff_leaves[5]) abjad.attach(abjad.Dynamic("pp"), lower_staff_voice_2_leaves[1]) abjad.attach(abjad.Dynamic("mp"), lower_staff_voice_2_leaves[6]) abjad.override(upper_staff).dynamic_line_spanner.staff_padding = 2 abjad.override(lower_staff).dynamic_line_spanner.staff_padding = 3 # attaches beams abjad.beam(upper_staff_leaves[:4]) abjad.beam(lower_staff_voice_2_leaves[1:5]) abjad.beam(lower_staff_voice_2_leaves[6:10]) # attaches slurs abjad.slur(upper_staff_leaves[:5]) abjad.slur(upper_staff_leaves[5:]) abjad.slur(lower_staff_voice_2_leaves[1:6]) abjad.slur(lower_staff_voice_2_leaves[-10:]) leaf = lower_staff_voice_2_leaves[-10] abjad.override(leaf).slur.direction = abjad.Down # attaches hairpins abjad.hairpin("< !", upper_staff_leaves[-7:-2]) abjad.hairpin("> !", upper_staff_leaves[-2:]) leaf = upper_staff_leaves[-2] abjad.override(leaf).hairpin.to_barline = False # attaches text spanner with ritardando markup markup = abjad.Markup("ritard.") start_text_span = abjad.StartTextSpan(left_text=markup) abjad.text_spanner(upper_staff_leaves[-7:], start_text_span=start_text_span) abjad.override(upper_staff_leaves[-7]).text_spanner.staff_padding = 2 # ties notes abjad.tie(upper_staff_leaves[-2:]) abjad.tie(lower_staff_voice_1_leaves) # returns score return score
def make_bartok_score(): """ make the Bartok example score. """ # make score skeleton score = abjad.Score() piano_staff = abjad.StaffGroup(lilypond_type="PianoStaff") upper_staff = abjad.Staff([]) lower_staff = abjad.Staff([]) piano_staff.append(upper_staff) piano_staff.append(lower_staff) score.append(piano_staff) # make upper measures upper_measures = [] upper_measures.append(abjad.Container()) upper_measures.append(abjad.Container()) upper_measures.append(abjad.Container()) upper_measures.append(abjad.Container()) upper_measures.append(abjad.Container()) lower_measures = copy.deepcopy(upper_measures) upper_staff.extend(upper_measures) lower_staff.extend(lower_measures) # add leaves to upper measures upper_measures[0].extend("a'8 g'8 f'8 e'8") abjad.attach(abjad.TimeSignature((2, 4)), upper_measures[0][0]) upper_measures[1].extend("d'4 g'8 f'8 e'8 d'8") abjad.attach(abjad.TimeSignature((3, 4)), upper_measures[1][0]) upper_measures[2].extend("c'8 d'16 e'16 f'8 e'8") abjad.attach(abjad.TimeSignature((2, 4)), upper_measures[2][0]) upper_measures[3].append("d'2") upper_measures[4].append("d'2") # add leaves to lower measures lower_measures[0].extend("b4 d'8 c'8") lower_measures[1].extend("b8 a8 af4 c'8 bf8") lower_measures[2].extend("a8 g8 fs8 g16 a16") # make parallel music for measure 4 upper_voice = abjad.Voice("b2", name="upper voice") command = abjad.LilyPondLiteral(r"\voiceOne") abjad.attach(command, upper_voice) lower_voice = abjad.Voice("b4 a4", name="lower voice") command = abjad.LilyPondLiteral(r"\voiceTwo") abjad.attach(command, lower_voice) lower_measures[3].extend([upper_voice, lower_voice]) lower_measures[3].is_simultaneous = True # make parallel music for measure 5 upper_voice = abjad.Voice("b2", name="upper voice") command = abjad.LilyPondLiteral(r"\voiceOne") abjad.attach(command, upper_voice) lower_voice = abjad.Voice("g2", name="lower voice") command = abjad.LilyPondLiteral(r"\voiceTwo") abjad.attach(command, lower_voice) lower_measures[4].extend([upper_voice, lower_voice]) lower_measures[4].is_simultaneous = True # add bass clef clef = abjad.Clef("bass") leaf = abjad.inspect(lower_staff).leaf(0) abjad.attach(clef, leaf) # add dynamics dynamic = abjad.Dynamic("pp") abjad.attach(dynamic, upper_measures[0][0]) dynamic = abjad.Dynamic("mp") abjad.attach(dynamic, upper_measures[1][1]) dynamic = abjad.Dynamic("pp") abjad.attach(dynamic, lower_measures[0][1]) dynamic = abjad.Dynamic("mp") abjad.attach(dynamic, lower_measures[1][3]) # add final bar line score.add_final_bar_line() # select leaves for attaching spanners to upper_leaves = abjad.select(upper_staff).leaves() lower_leaves = abjad.select(lower_staff).leaves() # attach beams abjad.beam(upper_leaves[:4]) abjad.beam(lower_leaves[1:5]) abjad.beam(lower_leaves[6:10]) # attach slurs abjad.slur(upper_leaves[:5]) abjad.slur(upper_leaves[5:]) abjad.slur(lower_leaves[1:6]) # attach hairpins abjad.hairpin("<", upper_leaves[-7:-2]) abjad.hairpin(">", upper_leaves[-2:]) # attach a ritardando with markup start_text_span = abjad.StartTextSpan(left_text=abjad.Markup("ritard.")) abjad.text_spanner(upper_leaves[-7:], start_text_span=start_text_span) # tie notes abjad.tie(upper_leaves[-2:]) # tie more notes note_1 = lower_staff[-2]["upper voice"][0] note_2 = lower_staff[-1]["upper voice"][0] notes = abjad.select([note_1, note_2]) abjad.tie(notes) # return the score return score
def write_indicators( self, material_name=None, dynamics=None, articulations=None, slur_up=None, slur_down=None, change_staffs_names=None, pitched=True, ): """Write indicators to leaves.""" if material_name is not None: selection1 = abjad.Selection(self.container).components( abjad.Container) for container in selection1: if container.name is not None and ( (isinstance(material_name, list) or material_name in container.name)): selection2 = abjad.Selection(container).leaves( pitched=pitched) if dynamics: for key in dynamics: if dynamics[key] == "all": for i, leaf in enumerate(selection2[0::2]): a = i b = i + 1 abjad.hairpin(key, selection2[a:b]) else: for i in dynamics[key]: if isinstance(i, tuple): a, b = i b = b + 1 abjad.hairpin(key, selection2[a:b]) else: abjad.hairpin(key, selection2[i]) # attach slurs if slur_up: for n in slur_up: a, b = n b = b abjad.attach(abjad.StartSlur(), selection2[a]) abjad.attach(abjad.StopSlur(), selection2[b]) if slur_down: for n in slur_down: a, b = n abjad.attach(abjad.StartSlur(direction=abjad.Down), selection2[a]) abjad.attach(abjad.StopSlur(), selection2[b]) if articulations: for key in articulations: for i in articulations[key]: abjad.attach(abjad.Articulation(key), selection2[i]) else: selection = abjad.Selection(self.container).leaves(pitched=pitched) if dynamics: for key in dynamics: for i in dynamics[key]: if isinstance(i, tuple): a, b = i b = b + 1 abjad.hairpin(key, selection[a:b]) else: abjad.hairpin(key, selection[i]) # attach slurs if slur_up: for n in slur_up: a, b = n b = b abjad.attach(abjad.StartSlur(), selection[a]) abjad.attach(abjad.StopSlur(), selection[b]) if slur_down: for n in slur_down: a, b = n abjad.attach(abjad.StartSlur(direction=abjad.Down), selection[a]) abjad.attach(abjad.StopSlur(), selection[b]) if articulations: for key in articulations: for i in articulations[key]: abjad.attach(abjad.Articulation(key), selection[i])