def _set_duration(self, new_duration, repeat_ties=False): import abjad new_duration = Duration(new_duration) # change LilyPond multiplier if leaf already has LilyPond multiplier if self._get_indicators(Multiplier): detach(Multiplier, self) multiplier = new_duration.__div__(self.written_duration) attach(multiplier, self) return select(self) # change written duration if new duration is assignable try: self.written_duration = new_duration return select(self) except exceptions.AssignabilityError: pass # make new notes or tuplets if new duration is nonassignable maker = abjad.NoteMaker(repeat_ties=repeat_ties, ) components = maker(0, new_duration) if isinstance(components[0], Leaf): tied_leaf_count = len(components) - 1 tied_leaves = tied_leaf_count * self all_leaves = [self] + tied_leaves for leaf, component in zip(all_leaves, components): leaf.written_duration = component.written_duration self._splice(tied_leaves, grow_spanners=True) if not inspect(self).has_spanner(abjad.Tie): tie = abjad.Tie() if tie._attachment_test(self): tie = abjad.Tie(repeat=repeat_ties) attach(tie, all_leaves) return select(all_leaves) else: assert isinstance(components[0], abjad.Tuplet) tuplet = components[0] components = tuplet[:] tied_leaf_count = len(components) - 1 tied_leaves = tied_leaf_count * self all_leaves = [self] + tied_leaves for leaf, component in zip(all_leaves, components): leaf.written_duration = component.written_duration self._splice(tied_leaves, grow_spanners=True) if not inspect(self).has_spanner(abjad.Tie): tie = abjad.Tie() if tie._attachment_test(self): tie = abjad.Tie(repeat=repeat_ties) attach(tie, all_leaves) multiplier = tuplet.multiplier tuplet = abjad.Tuplet(multiplier, []) abjad.mutate(all_leaves).wrap(tuplet) return select(tuplet)
def _set_duration(self, new_duration): from .Chord import Chord from .Note import Note from .NoteMaker import NoteMaker from .Tuplet import Tuplet from abjad.spanners import tie as abjad_tie new_duration = Duration(new_duration) if self.multiplier is not None: multiplier = new_duration.__div__(self.written_duration) self.multiplier = multiplier return select(self) try: self.written_duration = new_duration return select(self) except exceptions.AssignabilityError: pass maker = NoteMaker() components = maker(0, new_duration) new_leaves = select(components).leaves() following_leaf_count = len(new_leaves) - 1 following_leaves = following_leaf_count * self all_leaves = [self] + following_leaves for leaf, new_leaf in zip(all_leaves, new_leaves): leaf.written_duration = new_leaf.written_duration logical_tie = self._get_logical_tie() logical_tie_leaves = list(logical_tie.leaves) for leaf in logical_tie: detach(Tie, leaf) detach(RepeatTie, leaf) if self._parent is not None: index = self._parent.index(self) next_ = index + 1 self._parent[next_:next_] = following_leaves index = logical_tie_leaves.index(self) next_ = index + 1 logical_tie_leaves[next_:next_] = following_leaves if 1 < len(logical_tie_leaves) and isinstance(self, (Note, Chord)): abjad_tie(logical_tie_leaves) if isinstance(components[0], Leaf): return select(all_leaves) else: assert isinstance(components[0], Tuplet) assert len(components) == 1 tuplet = components[0] multiplier = tuplet.multiplier tuplet = Tuplet(multiplier, []) mutate(all_leaves).wrap(tuplet) return select(tuplet)
def _set_duration(self, new_duration, repeat_ties=False): from .Chord import Chord from .Note import Note from .NoteMaker import NoteMaker from .Tuplet import Tuplet from abjad.spanners import tie as abjad_tie new_duration = Duration(new_duration) if self.multiplier is not None: multiplier = new_duration.__div__(self.written_duration) self.multiplier = multiplier return select(self) try: self.written_duration = new_duration return select(self) except exceptions.AssignabilityError: pass maker = NoteMaker(repeat_ties=repeat_ties) components = maker(0, new_duration) new_leaves = select(components).leaves() following_leaf_count = len(new_leaves) - 1 following_leaves = following_leaf_count * self all_leaves = [self] + following_leaves for leaf, new_leaf in zip(all_leaves, new_leaves): leaf.written_duration = new_leaf.written_duration logical_tie = self._get_logical_tie() logical_tie_leaves = list(logical_tie.leaves) for leaf in logical_tie: detach(TieIndicator, leaf) detach(RepeatTie, leaf) if self._parent is not None: index = self._parent.index(self) next_ = index + 1 self._parent[next_:next_] = following_leaves index = logical_tie_leaves.index(self) next_ = index + 1 logical_tie_leaves[next_:next_] = following_leaves if 1 < len(logical_tie_leaves) and isinstance(self, (Note, Chord)): abjad_tie(logical_tie_leaves) if isinstance(components[0], Leaf): return select(all_leaves) else: assert isinstance(components[0], Tuplet) assert len(components) == 1 tuplet = components[0] multiplier = tuplet.multiplier tuplet = Tuplet(multiplier, []) mutate(all_leaves).wrap(tuplet) return select(tuplet)
def _split_by_durations( self, durations, cyclic=False, fracture_spanners=False, tie_split_notes=True, repeat_ties=False, ): import abjad durations = [Duration(_) for _ in durations] durations = sequence(durations) leaf_duration = inspect(self).duration() if cyclic: durations = durations.repeat_to_weight(leaf_duration) if sum(durations) < leaf_duration: last_duration = leaf_duration - sum(durations) durations = list(durations) durations.append(last_duration) durations = sequence(durations) durations = durations.truncate(weight=leaf_duration) result_selections = [] # detach grace containers grace_container = self._detach_grace_container() after_grace_container = self._detach_after_grace_container() leaf_prolation = inspect(self).parentage().prolation for duration in durations: new_leaf = copy.copy(self) preprolated_duration = duration / leaf_prolation selection = new_leaf._set_duration( preprolated_duration, repeat_ties=repeat_ties, ) result_selections.append(selection) result_components = sequence(result_selections).flatten(depth=-1) result_components = select(result_components) result_leaves = select(result_components).leaves() assert all(isinstance(_, abjad.Selection) for _ in result_selections) assert all(isinstance(_, Component) for _ in result_components) assert result_leaves.are_leaves() if inspect(self).has_spanner(abjad.Tie): for leaf in result_leaves: detach(abjad.Tie, leaf) # strip result leaves of indicators (other than multipliers) for leaf in result_leaves: multiplier = inspect(leaf).indicator(Multiplier) detach(object, leaf) if multiplier is not None: attach(multiplier, leaf) # replace leaf with flattened result selection = select(self) parent, start, stop = selection._get_parent_and_start_stop_indices() if parent: parent.__setitem__(slice(start, stop + 1), result_components) else: selection._give_dominant_spanners(result_components) selection._withdraw_from_crossing_spanners() # fracture spanners if fracture_spanners: first_selection = result_selections[0] for spanner in inspect(first_selection[-1]).spanners(): index = spanner._index(first_selection[-1]) spanner._fracture(index, direction=enums.Right) last_selection = result_selections[-1] for spanner in inspect(last_selection[0]).spanners(): index = spanner._index(last_selection[0]) spanner._fracture(index, direction=enums.Left) for middle_selection in result_selections[1:-1]: spanners = inspect(middle_selection[0]).spanners() for spanner in spanners: index = spanner._index(middle_selection[0]) spanner._fracture(index, direction=enums.Left) spanners = inspect(middle_selection[-1]).spanners() for spanner in spanners: index = spanner._index(middle_selection[-1]) spanner._fracture(index, direction=enums.Right) # move indicators first_result_leaf = result_leaves[0] last_result_leaf = result_leaves[-1] for indicator in inspect(self).indicators(): if isinstance(indicator, Multiplier): continue detach(indicator, self) direction = getattr(indicator, '_time_orientation', enums.Left) if direction is enums.Left: attach(indicator, first_result_leaf) elif direction == enums.Right: attach(indicator, last_result_leaf) else: raise ValueError(direction) # move grace containers if grace_container is not None: container = grace_container[0] assert isinstance(container, abjad.GraceContainer), repr(container) attach(container, first_result_leaf) if after_grace_container is not None: container = after_grace_container[0] prototype = abjad.AfterGraceContainer assert isinstance(container, prototype), repr(container) attach(container, last_result_leaf) if isinstance(result_components[0], abjad.Tuplet): abjad.mutate(result_components).fuse() # tie split notes if isinstance(self, (abjad.Note, abjad.Chord)) and tie_split_notes: result_leaves._attach_tie_to_leaves(repeat_ties=repeat_ties, ) assert isinstance(result_selections, list), repr(result_selections) assert all(isinstance(_, abjad.Selection) for _ in result_selections) return result_selections
def _detach_grace_container(self): if self._grace_container is not None: return detach(self._grace_container, self)
def _add_or_remove_notes_to_achieve_written_duration( self, new_written_duration): from abjad.spanners import tie as abjad_tie from .NoteMaker import NoteMaker from .Tuplet import Tuplet new_written_duration = Duration(new_written_duration) maker = NoteMaker() if new_written_duration.is_assignable: self[0].written_duration = new_written_duration for leaf in self[1:]: mutate(leaf).extract() detach(TieIndicator, self[0]) detach(RepeatTie, self[0]) elif new_written_duration.has_power_of_two_denominator: durations = maker(0, [new_written_duration]) for leaf, token in zip(self, durations): leaf.written_duration = token.written_duration if len(self) == len(durations): pass elif len(durations) < len(self): for leaf in self[len(durations):]: mutate(leaf).extract() elif len(self) < len(durations): #detach(Tie, self[0]) detach(TieIndicator, self[0]) detach(RepeatTie, self[0]) difference = len(durations) - len(self) extra_leaves = self[0] * difference for extra_leaf in extra_leaves: #detach(Tie, extra_leaf) detach(TieIndicator, extra_leaf) detach(RepeatTie, extra_leaf) extra_tokens = durations[len(self):] for leaf, token in zip(extra_leaves, extra_tokens): leaf.written_duration = token.written_duration parent = inspect(self[-1]).parentage().parent index = parent.index(self[-1]) next_ = index + 1 parent[next_:next_] = extra_leaves leaves = self.leaves + extra_leaves #attach(Tie(), leaves) abjad_tie(leaves) else: components = maker(0, new_written_duration) assert isinstance(components[0], Tuplet) tuplet = components[0] logical_tie = tuplet[0]._get_logical_tie() duration = logical_tie._get_preprolated_duration() leaves_ = self._add_or_remove_notes_to_achieve_written_duration( duration) multiplier = tuplet.multiplier tuplet = Tuplet(multiplier, []) #mutate(self.leaves).wrap(tuplet) mutate(leaves_).wrap(tuplet) return self[0]._get_logical_tie()
def to_tuplet(self, proportions): r""" Changes logical tie to tuplet. .. container:: example >>> staff = abjad.Staff(r"df'8 c'8 ~ c'16 cqs''4") >>> abjad.attach(abjad.Dynamic('p'), staff[0]) >>> abjad.attach(abjad.HairpinIndicator('<'), staff[0]) >>> abjad.attach(abjad.Dynamic('f'), staff[-1]) >>> abjad.override(staff).dynamic_line_spanner.staff_padding = 3 >>> time_signature = abjad.TimeSignature((9, 16)) >>> abjad.attach(time_signature, staff[0]) >>> abjad.show(staff) # doctest: +SKIP .. docs:: >>> abjad.f(staff) \new Staff \with { \override DynamicLineSpanner.staff-padding = #3 } { \time 9/16 df'8 \p \< c'8 ~ c'16 cqs''4 \f } >>> logical_tie = abjad.inspect(staff[1]).logical_tie() >>> logical_tie.to_tuplet([2, 1, 1, 1]) Tuplet(Multiplier(3, 5), "c'8 c'16 c'16 c'16") .. docs:: >>> abjad.f(staff) \new Staff \with { \override DynamicLineSpanner.staff-padding = #3 } { \time 9/16 df'8 \p \< \tweak text #tuplet-number::calc-fraction-text \times 3/5 { c'8 c'16 c'16 c'16 } cqs''4 \f } >>> abjad.show(staff) # doctest: +SKIP .. container:: example >>> staff = abjad.Staff(r"c'8 ~ c'16 cqs''4") >>> abjad.hairpin('p < f', staff[:]) >>> abjad.override(staff).dynamic_line_spanner.staff_padding = 3 >>> time_signature = abjad.TimeSignature((7, 16)) >>> abjad.attach(time_signature, staff[0]) >>> abjad.show(staff) # doctest: +SKIP .. docs:: >>> abjad.f(staff) \new Staff \with { \override DynamicLineSpanner.staff-padding = #3 } { \time 7/16 c'8 \p \< ~ c'16 cqs''4 \f } Returns tuplet. """ from .Note import Note from .Note import Note from .NoteMaker import NoteMaker from .Tuplet import Tuplet proportions = Ratio(proportions) target_duration = self._get_preprolated_duration() prolated_duration = target_duration / sum(proportions.numbers) basic_written_duration = \ prolated_duration.equal_or_greater_power_of_two written_durations = [ _ * basic_written_duration for _ in proportions.numbers ] maker = NoteMaker() try: notes = [Note(0, _) for _ in written_durations] except exceptions.AssignabilityError: denominator = target_duration._denominator note_durations = [ Duration(_, denominator) for _ in proportions.numbers ] notes = maker(0, note_durations) tuplet = Tuplet.from_duration(target_duration, notes) for leaf in self: detach(TieIndicator, leaf) detach(RepeatTie, leaf) mutate(self).replace(tuplet) return tuplet
def _split_by_durations( self, durations, cyclic=False, tie_split_notes=True, repeat_ties=False, ): from .AfterGraceContainer import AfterGraceContainer from .Chord import Chord from .GraceContainer import GraceContainer from .Note import Note from .Selection import Selection from .Tuplet import Tuplet durations = [Duration(_) for _ in durations] durations = Sequence(durations) leaf_duration = inspect(self).duration() if cyclic: durations = durations.repeat_to_weight(leaf_duration) if sum(durations) < leaf_duration: last_duration = leaf_duration - sum(durations) durations = list(durations) durations.append(last_duration) durations = Sequence(durations) durations = durations.truncate(weight=leaf_duration) originally_tied = inspect(self).has_indicator(TieIndicator) originally_repeat_tied = inspect(self).has_indicator(RepeatTie) result_selections = [] grace_container = self._detach_grace_container() after_grace_container = self._detach_after_grace_container() leaf_prolation = inspect(self).parentage().prolation for duration in durations: new_leaf = copy.copy(self) preprolated_duration = duration / leaf_prolation selection = new_leaf._set_duration( preprolated_duration, repeat_ties=repeat_ties, ) result_selections.append(selection) result_components = Sequence(result_selections).flatten(depth=-1) result_components = select(result_components) result_leaves = select(result_components).leaves(grace_notes=False) assert all(isinstance(_, Selection) for _ in result_selections) assert all(isinstance(_, Component) for _ in result_components) assert result_leaves.are_leaves() # for leaf in result_leaves: # detach(Tie, leaf) # strip result leaves of all indicators for leaf in result_leaves: detach(object, leaf) # replace leaf with flattened result if self._parent is not None: mutate(self).replace(result_components) # move indicators first_result_leaf = result_leaves[0] last_result_leaf = result_leaves[-1] for indicator in inspect(self).indicators(): detach(indicator, self) direction = getattr(indicator, '_time_orientation', enums.Left) if direction is enums.Left: attach(indicator, first_result_leaf) elif direction == enums.Right: attach(indicator, last_result_leaf) else: raise ValueError(direction) # move grace containers if grace_container is not None: container = grace_container[0] assert isinstance(container, GraceContainer), repr(container) attach(container, first_result_leaf) if after_grace_container is not None: container = after_grace_container[0] prototype = AfterGraceContainer assert isinstance(container, prototype), repr(container) attach(container, last_result_leaf) if isinstance(result_components[0], Tuplet): mutate(result_components).fuse() # tie split notes if (tie_split_notes and isinstance(self, (Note, Chord)) and 1 < len(result_leaves)): result_leaves._attach_tie_to_leaves(repeat_ties=repeat_ties) #assert not inspect(result_leaves[0]).has_indicator(RepeatTie) detach(RepeatTie, result_leaves[0]) #assert not inspect(result_leaves[-1]).has_indicator(TieIndicator) detach(TieIndicator, result_leaves[-1]) if originally_repeat_tied: tie = RepeatTie() attach(tie, result_leaves[0]) if originally_tied: tie = TieIndicator() attach(tie, result_leaves[-1]) assert isinstance(result_leaves, Selection) assert all(isinstance(_, Leaf) for _ in result_leaves) return result_leaves
def _move_indicators(self, recipient_component): for wrapper in inspect(self).wrappers(): detach(wrapper, self) attach(wrapper, recipient_component)
def on_beat_grace_container( contents, anchor_voice_selection, *, anchor_voice_number=2, do_not_beam=None, do_not_slash=None, do_not_slur=None, do_not_stop_polyphony=None, font_size=-3, grace_voice_number=1, leaf_duration=None, ): r""" Makes on-beat grace container and wraps around ``selection``. .. container:: example GRACE NOTES ABOVE. Note-to-note anchor: >>> music_voice = abjad.Voice("c'4 d' e' f'", name="Music_Voice") >>> string = "g'8 a' b' c'' d'' c'' b' a' b' c'' d''" >>> result = abjad.on_beat_grace_container( ... string, music_voice[1:3], leaf_duration=(1, 30) ... ) >>> staff = abjad.Staff([music_voice]) >>> abjad.show(staff) # doctest: +SKIP .. docs:: >>> abjad.f(staff) \new Staff { \context Voice = "Music_Voice" { c'4 << \context Voice = "On_Beat_Grace_Container" { \set fontSize = #-3 %! abjad.on_beat_grace_container(1) \slash %! abjad.on_beat_grace_container(2) \voiceOne %! abjad.on_beat_grace_container(3) < \tweak font-size #0 \tweak transparent ##t d' g' >8 * 4/15 [ ( a'8 * 4/15 b'8 * 4/15 c''8 * 4/15 d''8 * 4/15 c''8 * 4/15 b'8 * 4/15 a'8 * 4/15 b'8 * 4/15 c''8 * 4/15 d''8 * 4/15 ) ] } \context Voice = "Music_Voice" { \voiceTwo %! abjad.on_beat_grace_container(4) d'4 e'4 } >> \oneVoice %! abjad.on_beat_grace_container(5) f'4 } } Note-to-chord anchor: >>> music_voice = abjad.Voice( ... "<a c'>4 <b d'> <c' e'> <d' f'>", name="Music_Voice" ... ) >>> string = "g'8 a' b' c'' d'' c'' b' a' b' c'' d''" >>> result = abjad.on_beat_grace_container( ... string, music_voice[1:3], leaf_duration=(1, 30) ... ) >>> staff = abjad.Staff([music_voice]) >>> abjad.show(staff) # doctest: +SKIP .. docs:: >>> abjad.f(staff) \new Staff { \context Voice = "Music_Voice" { <a c'>4 << \context Voice = "On_Beat_Grace_Container" { \set fontSize = #-3 %! abjad.on_beat_grace_container(1) \slash %! abjad.on_beat_grace_container(2) \voiceOne %! abjad.on_beat_grace_container(3) < \tweak font-size #0 \tweak transparent ##t d' g' >8 * 4/15 [ ( a'8 * 4/15 b'8 * 4/15 c''8 * 4/15 d''8 * 4/15 c''8 * 4/15 b'8 * 4/15 a'8 * 4/15 b'8 * 4/15 c''8 * 4/15 d''8 * 4/15 ) ] } \context Voice = "Music_Voice" { \voiceTwo %! abjad.on_beat_grace_container(4) <b d'>4 <c' e'>4 } >> \oneVoice %! abjad.on_beat_grace_container(5) <d' f'>4 } } Chord-to-note anchor: >>> music_voice = abjad.Voice("c'4 d' e' f'", name="Music_Voice") >>> string = "<g' b'>8 a' b' c'' d'' c'' b' a' b' c'' d''" >>> result = abjad.on_beat_grace_container( ... string, music_voice[1:3], leaf_duration=(1, 30) ... ) >>> staff = abjad.Staff([music_voice]) >>> abjad.show(staff) # doctest: +SKIP .. docs:: >>> abjad.f(staff) \new Staff { \context Voice = "Music_Voice" { c'4 << \context Voice = "On_Beat_Grace_Container" { \set fontSize = #-3 %! abjad.on_beat_grace_container(1) \slash %! abjad.on_beat_grace_container(2) \voiceOne %! abjad.on_beat_grace_container(3) < \tweak font-size #0 \tweak transparent ##t d' g' b' >8 * 4/15 [ ( a'8 * 4/15 b'8 * 4/15 c''8 * 4/15 d''8 * 4/15 c''8 * 4/15 b'8 * 4/15 a'8 * 4/15 b'8 * 4/15 c''8 * 4/15 d''8 * 4/15 ) ] } \context Voice = "Music_Voice" { \voiceTwo %! abjad.on_beat_grace_container(4) d'4 e'4 } >> \oneVoice %! abjad.on_beat_grace_container(5) f'4 } } Chord-to-chord anchor: >>> music_voice = abjad.Voice( ... "<a c'>4 <b d'> <c' e'> <d' f'>", name="Music_Voice" ... ) >>> string = "<g' b'>8 a' b' c'' d'' c'' b' a' b' c'' d''" >>> result = abjad.on_beat_grace_container( ... string, music_voice[1:3], leaf_duration=(1, 30) ... ) >>> staff = abjad.Staff([music_voice]) >>> abjad.show(staff) # doctest: +SKIP .. docs:: >>> abjad.f(staff) \new Staff { \context Voice = "Music_Voice" { <a c'>4 << \context Voice = "On_Beat_Grace_Container" { \set fontSize = #-3 %! abjad.on_beat_grace_container(1) \slash %! abjad.on_beat_grace_container(2) \voiceOne %! abjad.on_beat_grace_container(3) < \tweak font-size #0 \tweak transparent ##t d' g' b' >8 * 4/15 [ ( a'8 * 4/15 b'8 * 4/15 c''8 * 4/15 d''8 * 4/15 c''8 * 4/15 b'8 * 4/15 a'8 * 4/15 b'8 * 4/15 c''8 * 4/15 d''8 * 4/15 ) ] } \context Voice = "Music_Voice" { \voiceTwo %! abjad.on_beat_grace_container(4) <b d'>4 <c' e'>4 } >> \oneVoice %! abjad.on_beat_grace_container(5) <d' f'>4 } } .. container:: example GRACE NOTES BELOW. Note-to-note anchor: >>> music_voice = abjad.Voice("c'4 d' e' f'", name="Music_Voice") >>> string = "g8 a b c' d' c' b a b c' d'" >>> result = abjad.on_beat_grace_container( ... string, ... music_voice[1:3], ... anchor_voice_number=1, ... grace_voice_number=2, ... leaf_duration=(1, 30), ... ) >>> staff = abjad.Staff([music_voice]) >>> abjad.show(staff) # doctest: +SKIP .. docs:: >>> abjad.f(staff) \new Staff { \context Voice = "Music_Voice" { c'4 << \context Voice = "On_Beat_Grace_Container" { \set fontSize = #-3 %! abjad.on_beat_grace_container(1) \slash %! abjad.on_beat_grace_container(2) \voiceTwo %! abjad.on_beat_grace_container(3) < g \tweak font-size #0 \tweak transparent ##t d' >8 * 4/15 [ ( a8 * 4/15 b8 * 4/15 c'8 * 4/15 d'8 * 4/15 c'8 * 4/15 b8 * 4/15 a8 * 4/15 b8 * 4/15 c'8 * 4/15 d'8 * 4/15 ) ] } \context Voice = "Music_Voice" { \voiceOne %! abjad.on_beat_grace_container(4) d'4 e'4 } >> \oneVoice %! abjad.on_beat_grace_container(5) f'4 } } Note-to-chord anchor: >>> music_voice = abjad.Voice( ... "<c' e'>4 <d' f'> <e' g'> <f' a'>", name="Music_Voice" ... ) >>> string = "g8 a b c' d' c' b a b c' d'" >>> result = abjad.on_beat_grace_container( ... string, ... music_voice[1:3], ... anchor_voice_number=1, ... grace_voice_number=2, ... leaf_duration=(1, 30), ... ) >>> staff = abjad.Staff([music_voice]) >>> abjad.show(staff) # doctest: +SKIP .. docs:: >>> abjad.f(staff) \new Staff { \context Voice = "Music_Voice" { <c' e'>4 << \context Voice = "On_Beat_Grace_Container" { \set fontSize = #-3 %! abjad.on_beat_grace_container(1) \slash %! abjad.on_beat_grace_container(2) \voiceTwo %! abjad.on_beat_grace_container(3) < g \tweak font-size #0 \tweak transparent ##t f' >8 * 4/15 [ ( a8 * 4/15 b8 * 4/15 c'8 * 4/15 d'8 * 4/15 c'8 * 4/15 b8 * 4/15 a8 * 4/15 b8 * 4/15 c'8 * 4/15 d'8 * 4/15 ) ] } \context Voice = "Music_Voice" { \voiceOne %! abjad.on_beat_grace_container(4) <d' f'>4 <e' g'>4 } >> \oneVoice %! abjad.on_beat_grace_container(5) <f' a'>4 } } Chord-to-note anchor: >>> music_voice = abjad.Voice("c'4 d' e' f'", name="Music_Voice") >>> string = "<e g>8 a b c' d' c' b a b c' d'" >>> result = abjad.on_beat_grace_container( ... string, ... music_voice[1:3], ... anchor_voice_number=1, ... grace_voice_number=2, ... leaf_duration=(1, 30), ... ) >>> staff = abjad.Staff([music_voice]) >>> abjad.show(staff) # doctest: +SKIP .. docs:: >>> abjad.f(staff) \new Staff { \context Voice = "Music_Voice" { c'4 << \context Voice = "On_Beat_Grace_Container" { \set fontSize = #-3 %! abjad.on_beat_grace_container(1) \slash %! abjad.on_beat_grace_container(2) \voiceTwo %! abjad.on_beat_grace_container(3) < e g \tweak font-size #0 \tweak transparent ##t d' >8 * 4/15 [ ( a8 * 4/15 b8 * 4/15 c'8 * 4/15 d'8 * 4/15 c'8 * 4/15 b8 * 4/15 a8 * 4/15 b8 * 4/15 c'8 * 4/15 d'8 * 4/15 ) ] } \context Voice = "Music_Voice" { \voiceOne %! abjad.on_beat_grace_container(4) d'4 e'4 } >> \oneVoice %! abjad.on_beat_grace_container(5) f'4 } } Chord-to-chord anchor: >>> music_voice = abjad.Voice( ... "<c' e'>4 <d' f'> <e' g'> <f' a'>", name="Music_Voice" ... ) >>> string = "<e g>8 a b c' d' c' b a b c' d'" >>> result = abjad.on_beat_grace_container( ... string, ... music_voice[1:3], ... anchor_voice_number=1, ... grace_voice_number=2, ... leaf_duration=(1, 30), ... ) >>> staff = abjad.Staff([music_voice]) >>> abjad.show(staff) # doctest: +SKIP .. docs:: >>> abjad.f(staff) \new Staff { \context Voice = "Music_Voice" { <c' e'>4 << \context Voice = "On_Beat_Grace_Container" { \set fontSize = #-3 %! abjad.on_beat_grace_container(1) \slash %! abjad.on_beat_grace_container(2) \voiceTwo %! abjad.on_beat_grace_container(3) < e g \tweak font-size #0 \tweak transparent ##t f' >8 * 4/15 [ ( a8 * 4/15 b8 * 4/15 c'8 * 4/15 d'8 * 4/15 c'8 * 4/15 b8 * 4/15 a8 * 4/15 b8 * 4/15 c'8 * 4/15 d'8 * 4/15 ) ] } \context Voice = "Music_Voice" { \voiceOne %! abjad.on_beat_grace_container(4) <d' f'>4 <e' g'>4 } >> \oneVoice %! abjad.on_beat_grace_container(5) <f' a'>4 } } .. container:: example Raises exception when duration of on-beat grace container exceeds duration of anchor container: >>> music_voice = abjad.Voice("c'4 d' e' f'", name="Music_Voice") >>> string = "g'8 a' b' c'' d'' c'' b' a' b' c'' d''" >>> result = abjad.on_beat_grace_container( ... string, music_voice[1:2], leaf_duration=(1, 8) ... ) Traceback (most recent call last): ... Exception: grace Duration(11, 8) exceeds anchor Duration(1, 4). """ from .Container import Container from .Selection import Selection from .Voice import Voice from abjad.spanners import beam from abjad.spanners import slur def _site(n): return Tag(f"abjad.on_beat_grace_container({n})") assert isinstance(anchor_voice_selection, Selection) if not anchor_voice_selection.are_contiguous_same_parent( ignore_before_after_grace=True): message = "selection must be contiguous in same parent:\n" message += f" {repr(anchor_voice_selection)}" raise Exception(message) on_beat_grace_container = OnBeatGraceContainer(contents, leaf_duration=leaf_duration) if not isinstance(anchor_voice_selection, Selection): raise Exception(f"must be selection:\n {repr(anchor_voice_selection)}") anchor_leaf = abjad_inspect(anchor_voice_selection).leaf(0) anchor_voice = abjad_inspect(anchor_leaf).parentage().get(Voice) if anchor_voice.name is None: raise Exception( f"anchor voice must be named:\n {repr(anchor_voice)}") anchor_voice_insert = Voice(name=anchor_voice.name) mutate(anchor_voice_selection).wrap(anchor_voice_insert) container = Container(simultaneous=True) mutate(anchor_voice_insert).wrap(container) container.insert(0, on_beat_grace_container) on_beat_grace_container._match_anchor_leaf() on_beat_grace_container._set_leaf_durations() insert_duration = abjad_inspect(anchor_voice_insert).duration() grace_container_duration = abjad_inspect( on_beat_grace_container).duration() if insert_duration < grace_container_duration: message = f"grace {repr(grace_container_duration)}" message += f" exceeds anchor {repr(insert_duration)}." raise Exception(message) if font_size is not None: string = rf"\set fontSize = #{font_size}" literal = LilyPondLiteral(string) attach(literal, on_beat_grace_container, tag=_site(1)) if not do_not_beam: beam(on_beat_grace_container[:]) if not do_not_slash: literal = LilyPondLiteral(r"\slash") attach(literal, on_beat_grace_container[0], tag=_site(2)) if not do_not_slur: slur(on_beat_grace_container[:]) voice_number_to_string = { 1: r"\voiceOne", 2: r"\voiceTwo", 3: r"\voiceThree", 4: r"\voiceFour", } first_grace = abjad_inspect(on_beat_grace_container).leaf(0) one_voice_literal = LilyPondLiteral(r"\oneVoice", format_slot="absolute_before") string = voice_number_to_string.get(grace_voice_number, None) if string is not None: literal detach(one_voice_literal, anchor_leaf) attach(LilyPondLiteral(string), first_grace, tag=_site(3)) string = voice_number_to_string.get(anchor_voice_number, None) if string is not None: detach(one_voice_literal, anchor_leaf) attach(LilyPondLiteral(string), anchor_leaf, tag=_site(4)) if not do_not_stop_polyphony: last_anchor_leaf = abjad_inspect(anchor_voice_selection).leaf(-1) next_leaf = abjad_inspect(last_anchor_leaf).leaf(1) if next_leaf is not None: literal = LilyPondLiteral(r"\oneVoice", format_slot="absolute_before") attach(literal, next_leaf, tag=_site(5)) return on_beat_grace_container
def _before_attach(self, argument): if self._ignore_before_attach: return for leaf in iterate(argument).leaves(): detach(Tie, leaf)
def _split_by_durations(self, durations, cyclic=False): from .Chord import Chord from .Note import Note from .Selection import Selection from .Tuplet import Tuplet durations = [Duration(_) for _ in durations] durations = Sequence(durations) leaf_duration = inspect(self).duration() if cyclic: durations = durations.repeat_to_weight(leaf_duration) if sum(durations) < leaf_duration: last_duration = leaf_duration - sum(durations) durations = list(durations) durations.append(last_duration) durations = Sequence(durations) durations = durations.truncate(weight=leaf_duration) originally_tied = inspect(self).has_indicator(Tie) originally_repeat_tied = inspect(self).has_indicator(RepeatTie) result_selections = [] # detach grace containers before_grace_container = self._before_grace_container if before_grace_container is not None: detach(before_grace_container, self) after_grace_container = self._after_grace_container if after_grace_container is not None: detach(after_grace_container, self) # do other things leaf_prolation = inspect(self).parentage().prolation for duration in durations: new_leaf = copy.copy(self) preprolated_duration = duration / leaf_prolation selection = new_leaf._set_duration(preprolated_duration) result_selections.append(selection) result_components = Sequence(result_selections).flatten(depth=-1) result_components = select(result_components) result_leaves = select(result_components).leaves(grace=False) assert all(isinstance(_, Selection) for _ in result_selections) assert all(isinstance(_, Component) for _ in result_components) assert result_leaves.are_leaves() # strip result leaves of all indicators for leaf in result_leaves: detach(object, leaf) # replace leaf with flattened result if inspect(self).parentage().parent is not None: mutate(self).replace(result_components) # move indicators first_result_leaf = result_leaves[0] last_result_leaf = result_leaves[-1] for indicator in inspect(self).indicators(): detach(indicator, self) direction = getattr(indicator, "_time_orientation", enums.Left) if direction is enums.Left: attach(indicator, first_result_leaf) elif direction == enums.Right: attach(indicator, last_result_leaf) else: raise ValueError(direction) # reattach grace containers if before_grace_container is not None: attach(before_grace_container, first_result_leaf) if after_grace_container is not None: attach(after_grace_container, last_result_leaf) # fuse tuplets if isinstance(result_components[0], Tuplet): mutate(result_components).fuse() # tie split notes if isinstance(self, (Note, Chord)) and 1 < len(result_leaves): result_leaves._attach_tie_to_leaves() if originally_repeat_tied and not inspect( result_leaves[0]).has_indicator(RepeatTie): attach(RepeatTie(), result_leaves[0]) if originally_tied and not inspect( result_leaves[-1]).has_indicator(Tie): attach(Tie(), result_leaves[-1]) assert isinstance(result_leaves, Selection) assert all(isinstance(_, Leaf) for _ in result_leaves) return result_leaves
def _move_indicators(self, recipient_component): for wrapper in inspect(self).wrappers(): detach(wrapper, self) attach(wrapper, recipient_component)
def _split_by_durations( self, durations, cyclic=False, tie_split_notes=True, repeat_ties=False ): from .AfterGraceContainer import AfterGraceContainer from .Chord import Chord from .GraceContainer import GraceContainer from .Note import Note from .Selection import Selection from .Tuplet import Tuplet durations = [Duration(_) for _ in durations] durations = Sequence(durations) leaf_duration = inspect(self).duration() if cyclic: durations = durations.repeat_to_weight(leaf_duration) if sum(durations) < leaf_duration: last_duration = leaf_duration - sum(durations) durations = list(durations) durations.append(last_duration) durations = Sequence(durations) durations = durations.truncate(weight=leaf_duration) originally_tied = inspect(self).has_indicator(TieIndicator) originally_repeat_tied = inspect(self).has_indicator(RepeatTie) result_selections = [] grace_container = self._detach_grace_container() after_grace_container = self._detach_after_grace_container() leaf_prolation = inspect(self).parentage().prolation for duration in durations: new_leaf = copy.copy(self) preprolated_duration = duration / leaf_prolation selection = new_leaf._set_duration( preprolated_duration, repeat_ties=repeat_ties ) result_selections.append(selection) result_components = Sequence(result_selections).flatten(depth=-1) result_components = select(result_components) result_leaves = select(result_components).leaves(grace_notes=False) assert all(isinstance(_, Selection) for _ in result_selections) assert all(isinstance(_, Component) for _ in result_components) assert result_leaves.are_leaves() # for leaf in result_leaves: # detach(Tie, leaf) # strip result leaves of all indicators for leaf in result_leaves: detach(object, leaf) # replace leaf with flattened result if self._parent is not None: mutate(self).replace(result_components) # move indicators first_result_leaf = result_leaves[0] last_result_leaf = result_leaves[-1] for indicator in inspect(self).indicators(): detach(indicator, self) direction = getattr(indicator, "_time_orientation", enums.Left) if direction is enums.Left: attach(indicator, first_result_leaf) elif direction == enums.Right: attach(indicator, last_result_leaf) else: raise ValueError(direction) # move grace containers if grace_container is not None: container = grace_container[0] assert isinstance(container, GraceContainer), repr(container) attach(container, first_result_leaf) if after_grace_container is not None: container = after_grace_container[0] prototype = AfterGraceContainer assert isinstance(container, prototype), repr(container) attach(container, last_result_leaf) if isinstance(result_components[0], Tuplet): mutate(result_components).fuse() # tie split notes if ( tie_split_notes and isinstance(self, (Note, Chord)) and 1 < len(result_leaves) ): result_leaves._attach_tie_to_leaves(repeat_ties=repeat_ties) # assert not inspect(result_leaves[0]).has_indicator(RepeatTie) detach(RepeatTie, result_leaves[0]) # assert not inspect(result_leaves[-1]).has_indicator(TieIndicator) detach(TieIndicator, result_leaves[-1]) if originally_repeat_tied: tie = RepeatTie() attach(tie, result_leaves[0]) if originally_tied: tie = TieIndicator() attach(tie, result_leaves[-1]) assert isinstance(result_leaves, Selection) assert all(isinstance(_, Leaf) for _ in result_leaves) return result_leaves
def _detach_grace_container(self): if self._grace_container is not None: return detach(self._grace_container, self)