def _do_tie_consecutive_notes(self, divisions): if not self.tie_consecutive_notes: return leaves = select(divisions).by_leaf() for leaf in leaves: detach(spannertools.Tie, leaf) pairs = itertools.groupby(leaves, lambda _: _.__class__) def _get_pitches(component): if isinstance(component, scoretools.Note): return component.written_pitch elif isinstance(component, scoretools.Chord): return component.written_pitches else: raise TypeError(component) for class_, group in pairs: group = list(group) if not isinstance(group[0], (scoretools.Note, scoretools.Chord)): continue subpairs = itertools.groupby(group, lambda _: _get_pitches(_)) for pitches, subgroup in subpairs: subgroup = list(subgroup) if len(subgroup) == 1: continue tie = spannertools.Tie() assert tie._attachment_test_all(subgroup) attach(tie, subgroup)
def _scale(self, multiplier=None): from abjad.tools import indicatortools if multiplier is None: return multiplier = durationtools.Multiplier(multiplier) old_time_signature = self.time_signature if mathtools.is_nonnegative_integer_power_of_two(multiplier) and \ 1 <= multiplier: old_numerator = old_time_signature.numerator old_denominator = old_time_signature.denominator new_denominator = old_denominator // multiplier.numerator pair = (old_numerator, new_denominator) new_time_signature = indicatortools.TimeSignature(pair) else: old_denominator = old_time_signature.denominator old_duration = old_time_signature.duration new_duration = multiplier * old_duration new_time_signature = \ self._duration_and_possible_denominators_to_time_signature( new_duration, [old_denominator], multiplier.denominator, ) detach(indicatortools.TimeSignature, self) attach(new_time_signature, self) contents_multiplier_denominator = \ mathtools.greatest_power_of_two_less_equal(multiplier.denominator) pair = (multiplier.numerator, contents_multiplier_denominator) contents_multiplier = durationtools.Multiplier(*pair) self._scale_contents(contents_multiplier)
def _get_span_events(self, leaf): annotations = leaf._get_indicators(dict) detach(dict, leaf) annotations = [x for x in annotations if 'post events' in x] if annotations: return annotations[0]['post events'] return {}
def _make_music(self, duration_pairs, seeds): from abjad.tools import rhythmmakertools selections = [] specifier = self.duration_spelling_specifier if specifier is None: specifier = rhythmmakertools.DurationSpellingSpecifier() for duration_pair in duration_pairs: selection = scoretools.make_leaves( pitches=0, durations=[duration_pair], decrease_durations_monotonically=\ specifier.decrease_durations_monotonically, forbidden_written_duration=\ specifier.forbidden_written_duration, ) selections.append(selection) beam_specifier = self.beam_specifier if beam_specifier is None: beam_specifier = rhythmmakertools.BeamSpecifier() if beam_specifier.beam_divisions_together: for component in iterate(selections).by_class(): detach(spannertools.Beam, component) beam = spannertools.MultipartBeam() leaves = iterate(selections).by_class(scoretools.Leaf) leaves = list(leaves) attach(beam, leaves) elif beam_specifier.beam_each_division: for selection in selections: beam = spannertools.MultipartBeam() attach(beam, selection) return selections
def _get_span_events(self, leaf): annotations = leaf._get_indicators(indicatortools.Annotation) detach(indicatortools.Annotation, leaf) annotations = [x for x in annotations if x.name == 'post events'] if annotations: return annotations[0].value return {}
def _apply_output_masks(self, selections): from abjad.tools import rhythmmakertools if not self.output_masks: return selections new_selections = [] duration_spelling_specifier = self.duration_spelling_specifier or \ rhythmmakertools.DurationSpellingSpecifier() decrease_durations_monotonically = \ duration_spelling_specifier.decrease_durations_monotonically forbidden_written_duration = \ duration_spelling_specifier.forbidden_written_duration length = len(selections) output_masks = self.output_masks for i, selection in enumerate(selections): if not any(_._matches_index(i, length) for _ in output_masks): new_selections.append(selection) continue duration = selection.get_duration() new_selection = scoretools.make_leaves( [None], [duration], decrease_durations_monotonically=\ decrease_durations_monotonically, forbidden_written_duration=forbidden_written_duration, ) for component in iterate(selection).by_class(): detach(spannertools.Tie, component) new_selections.append(new_selection) return new_selections
def _set_duration(self, new_duration, use_messiaen_style_ties=False): from abjad.tools import scoretools from abjad.tools import spannertools new_duration = durationtools.Duration(new_duration) # change LilyPond multiplier if leaf already has LilyPond multiplier if self._get_indicators(durationtools.Multiplier): detach(durationtools.Multiplier, self) multiplier = new_duration.__div__(self.written_duration) attach(multiplier, self) return [self] # change written duration if new duration is assignable try: self.written_duration = new_duration return [self] except AssignabilityError: pass # make new notes or tuplets if new duration is nonassignable components = scoretools.make_notes( 0, new_duration, use_messiaen_style_ties=use_messiaen_style_ties, ) if isinstance(components[0], scoretools.Leaf): tied_leaf_count = len(components) - 1 tied_leaves = tied_leaf_count * self all_leaves = [self] + tied_leaves for x, component in zip(all_leaves, components): x.written_duration = component.written_duration self._splice(tied_leaves, grow_spanners=True) parentage = self._get_parentage() if not parentage._get_spanners(spannertools.Tie): #if spannertools.Tie._attachment_test(self): tie = spannertools.Tie() if tie._attachment_test(self): tie = spannertools.Tie( use_messiaen_style_ties=use_messiaen_style_ties, ) attach(tie, all_leaves) return all_leaves else: assert isinstance(components[0], scoretools.Tuplet) tuplet = components[0] components = tuplet[:] tied_leaf_count = len(components) - 1 tied_leaves = tied_leaf_count * self all_leaves = [self] + tied_leaves for x, component in zip(all_leaves, components): x.written_duration = component.written_duration self._splice(tied_leaves, grow_spanners=True) if not self._get_spanners(spannertools.Tie): #if spannertools.Tie._attachment_test(self): tie = spannertools.Tie() if tie._attachment_test(self): tie = spannertools.Tie( use_messiaen_style_ties=use_messiaen_style_ties, ) attach(tie, all_leaves) tuplet_multiplier = tuplet.multiplier scoretools.Tuplet(tuplet_multiplier, all_leaves) return [tuplet]
def _apply_output_masks(self, selections): from abjad.tools import rhythmmakertools if not self.output_masks: return selections new_selections = [] if self.duration_spelling_specifier is None: duration_spelling_specifier = \ rhythmmakertools.DurationSpellingSpecifier() decrease_durations_monotonically = \ duration_spelling_specifier.decrease_durations_monotonically forbidden_written_duration = \ duration_spelling_specifier.forbidden_written_duration length = len(selections) output_masks = self.output_masks for i, selection in enumerate(selections): if not any(_._matches_index(i, length) for _ in output_masks): new_selections.append(selection) continue duration = selection.get_duration() new_selection = scoretools.make_leaves( [None], [duration], decrease_durations_monotonically=\ decrease_durations_monotonically, forbidden_written_duration=forbidden_written_duration, ) for component in iterate(selection).by_class(): detach(spannertools.Tie, component) new_selections.append(new_selection) return new_selections
def move_full_measure_tuplet_prolation_to_measure_time_signature(expr): r'''Moves prolation of full-measure tuplet to time signature of measure. Measures usually become non-power-of-two as as result. .. container:: example :: >>> tuplet = scoretools.FixedDurationTuplet(Duration(2, 8), "c'8 d'8 e'8") >>> measure = Measure((2, 8), [tuplet]) >>> measure.implicit_scaling = True >>> scoretools.move_full_measure_tuplet_prolation_to_measure_time_signature(measure) .. doctest:: >>> print(format(measure)) { \time 3/12 \scaleDurations #'(2 . 3) { c'8 d'8 e'8 } } Returns none. ''' from abjad.tools import indicatortools from abjad.tools import scoretools for measure in iterate(expr).by_class(scoretools.Measure): if len(measure) == 1: if isinstance(measure[0], scoretools.Tuplet): tuplet = measure[0] tuplet_multiplier = tuplet.multiplier tuplet_denominator = tuplet_multiplier.denominator reduced_denominator = mathtools.remove_powers_of_two( tuplet_denominator) time_signature = measure.time_signature time_signature_rational = durationtools.Duration( time_signature.numerator, time_signature.denominator) numerator = time_signature_rational.numerator * reduced_denominator denominator = time_signature_rational.denominator * reduced_denominator time_signature = indicatortools.TimeSignature( (numerator, denominator)) detach(indicatortools.TimeSignature, measure) attach(time_signature, measure) if time_signature.has_non_power_of_two_denominator: measure.implicit_scaling = True time_signature_multiplier = \ measure.time_signature.implied_prolation written_adjustment = tuplet_multiplier.__div__( time_signature_multiplier) tuplet._extract() measure._scale_contents(written_adjustment)
def _apply_division_masks(self, selections, rotation): from abjad.tools import rhythmmakertools if not self.division_masks: return selections new_selections = [] duration_spelling_specifier = self._get_duration_spelling_specifier() decrease_durations_monotonically = \ duration_spelling_specifier.decrease_durations_monotonically forbidden_written_duration = \ duration_spelling_specifier.forbidden_written_duration tie_specifier = self._get_tie_specifier() length = len(selections) division_masks = self.division_masks for i, selection in enumerate(selections): matching_division_mask = division_masks.get_matching_pattern( i, length, rotation=rotation, ) if not matching_division_mask: new_selections.append(selection) continue duration = selection.get_duration() if isinstance( matching_division_mask, rhythmmakertools.SustainMask, ): new_selection = scoretools.make_leaves( [0], [duration], decrease_durations_monotonically=\ decrease_durations_monotonically, forbidden_written_duration=forbidden_written_duration, use_messiaen_style_ties=\ tie_specifier.use_messiaen_style_ties, ) else: use_multimeasure_rests = getattr( matching_division_mask, 'use_multimeasure_rests', False, ) new_selection = scoretools.make_leaves( [None], [duration], decrease_durations_monotonically=\ decrease_durations_monotonically, forbidden_written_duration=forbidden_written_duration, use_multimeasure_rests=use_multimeasure_rests, ) for component in iterate(selection).by_class(): detach(spannertools.Tie, component) new_selections.append(new_selection) return new_selections
def _remove_and_shrink_durated_parent_containers(self): from abjad.tools import indicatortools from abjad.tools import scoretools prolated_leaf_duration = self._get_duration() parentage = self._get_parentage(include_self=False) prolations = parentage._prolations current_prolation, i = durationtools.Duration(1), 0 parent = self._parent while parent is not None and not parent.is_simultaneous: current_prolation *= prolations[i] if isinstance(parent, scoretools.FixedDurationTuplet): candidate_new_parent_dur = ( parent.target_duration - current_prolation * self.written_duration) if durationtools.Duration(0) < candidate_new_parent_dur: parent.target_duration = candidate_new_parent_dur elif isinstance(parent, scoretools.Measure): indicator = parent._get_indicator(indicatortools.TimeSignature) parent_time_signature = indicator old_prolation = parent_time_signature.implied_prolation naive_time_signature = (parent_time_signature.duration - prolated_leaf_duration) better_time_signature = mathtools.NonreducedFraction( naive_time_signature) better_time_signature = better_time_signature.with_denominator( parent_time_signature.denominator) better_time_signature = indicatortools.TimeSignature( better_time_signature) detach(indicatortools.TimeSignature, parent) attach(better_time_signature, parent) indicator = parent._get_indicator(indicatortools.TimeSignature) parent_time_signature = indicator new_prolation = parent_time_signature.implied_prolation adjusted_prolation = old_prolation / new_prolation for x in parent: if isinstance(x, scoretools.FixedDurationTuplet): x.target_duration *= adjusted_prolation else: if adjusted_prolation != 1: new_target = \ x._preprolated_duration * adjusted_prolation scoretools.FixedDurationTuplet(new_target, [x]) parent = parent._parent i += 1 parentage = self._get_parentage(include_self=False) parent = self._parent if parent: index = parent.index(self) del (parent[index]) for x in parentage: if not len(x): x._extract() else: break
def _conditionally_adjust_time_signature(self, old_denominator): if self.automatically_adjust_time_signature: naive_time_signature = self._preprolated_duration better_time_signature = \ mathtools.NonreducedFraction(naive_time_signature) better_time_signature = \ better_time_signature.with_denominator(old_denominator) better_time_signature = \ indicatortools.TimeSignature(better_time_signature) detach(indicatortools.TimeSignature, self) attach(better_time_signature, self)
def _apply_division_masks(self, selections, rotation=None): from abjad.tools import rhythmmakertools if not self.division_masks: return selections new_selections = [] duration_spelling_specifier = self._get_duration_spelling_specifier() decrease_durations_monotonically = \ duration_spelling_specifier.decrease_durations_monotonically forbidden_written_duration = \ duration_spelling_specifier.forbidden_written_duration tie_specifier = self._get_tie_specifier() length = len(selections) division_masks = self.division_masks for i, selection in enumerate(selections): matching_division_mask = division_masks.get_matching_pattern( i, length, rotation=rotation, ) if not matching_division_mask: new_selections.append(selection) continue duration = selection.get_duration() if isinstance( matching_division_mask, rhythmmakertools.SustainMask, ): new_selection = scoretools.make_leaves( [0], [duration], decrease_durations_monotonically=\ decrease_durations_monotonically, forbidden_written_duration=forbidden_written_duration, use_messiaen_style_ties=\ tie_specifier.use_messiaen_style_ties, ) else: use_multimeasure_rests = getattr( matching_division_mask, 'use_multimeasure_rests', False, ) new_selection = scoretools.make_leaves( [None], [duration], decrease_durations_monotonically=\ decrease_durations_monotonically, forbidden_written_duration=forbidden_written_duration, use_multimeasure_rests=use_multimeasure_rests, ) for component in iterate(selection).by_class(): detach(spannertools.Tie, component) new_selections.append(new_selection) return new_selections
def _do_tie_consecutive_notes(self, divisions): if not self.tie_consecutive_notes: return leaves = list(iterate(divisions).by_leaf()) for leaf in leaves: detach(spannertools.Tie, leaf) pairs = itertools.groupby(leaves, lambda _: _.__class__) for class_, group in pairs: group = list(group) if isinstance(group[0], scoretools.Note): if 1 < len(group): attach(spannertools.Tie(), group)
def set_measure_denominator_and_adjust_numerator(measure, denominator): r'''Set `measure` time signature `denominator` and multiply time signature numerator accordingly: :: >>> measure = Measure((3, 8), "c'8 d'8 e'8") >>> beam = spannertools.Beam() >>> attach(beam, measure[:]) .. doctest:: >>> print(format(measure)) { \time 3/8 c'8 [ d'8 e'8 ] } :: >>> scoretools.set_measure_denominator_and_adjust_numerator(measure, 16) Measure((6, 16), "c'8 d'8 e'8") .. doctest:: >>> print(format(measure)) { \time 6/16 c'8 [ d'8 e'8 ] } Leave `measure` contents unchanged. Return `measure`. ''' from abjad.tools import scoretools if isinstance(measure, scoretools.Measure): # to allow iteration inside zero-update loop old_time_signature = measure.time_signature old_time_signature_pair = (old_time_signature.numerator, old_time_signature.denominator) new_time_signature = mathtools.NonreducedFraction( old_time_signature_pair) new_time_signature = new_time_signature.with_denominator(denominator) new_time_signature = indicatortools.TimeSignature(new_time_signature) detach(indicatortools.TimeSignature, measure) attach(new_time_signature, measure) return measure
def move_full_measure_tuplet_prolation_to_measure_time_signature(expr): r'''Moves prolation of full-measure tuplet to time signature of measure. Measures usually become non-power-of-two as as result. .. container:: example :: >>> tuplet = scoretools.FixedDurationTuplet(Duration(2, 8), "c'8 d'8 e'8") >>> measure = Measure((2, 8), [tuplet]) >>> measure.implicit_scaling = True >>> scoretools.move_full_measure_tuplet_prolation_to_measure_time_signature(measure) .. doctest:: >>> print format(measure) { \time 3/12 \scaleDurations #'(2 . 3) { c'8 d'8 e'8 } } Returns none. ''' from abjad.tools import indicatortools from abjad.tools import scoretools for measure in iterate(expr).by_class(scoretools.Measure): if len(measure) == 1: if isinstance(measure[0], scoretools.Tuplet): tuplet = measure[0] tuplet_multiplier = tuplet.multiplier tuplet_denominator = tuplet_multiplier.denominator reduced_denominator = mathtools.remove_powers_of_two(tuplet_denominator) time_signature = measure.time_signature time_signature_rational = durationtools.Duration( time_signature.numerator, time_signature.denominator) numerator = time_signature_rational.numerator * reduced_denominator denominator = time_signature_rational.denominator * reduced_denominator time_signature = indicatortools.TimeSignature((numerator, denominator)) detach(indicatortools.TimeSignature, measure) attach(time_signature, measure) if time_signature.has_non_power_of_two_denominator: measure.implicit_scaling = True time_signature_multiplier = \ measure.time_signature.implied_prolation written_adjustment = tuplet_multiplier / time_signature_multiplier tuplet._extract() measure._scale_contents(written_adjustment)
def _get_span_events(self, leaf): annotations = leaf._get_indicators(indicatortools.Annotation) detach(indicatortools.Annotation, leaf) if annotations: spanners_annotations = [x for x in annotations if x.name == "spanners"] if 1 == len(spanners_annotations): return spanners_annotations[0].value elif 1 < len(spanners_annotations): message = "multiple span events lists attached to {}." message = message.format(leaf) raise Exception(message) return []
def _remove_and_shrink_durated_parent_containers(self): from abjad.tools import indicatortools from abjad.tools import scoretools prolated_leaf_duration = self._get_duration() parentage = self._get_parentage(include_self=False) prolations = parentage._prolations current_prolation, i = durationtools.Duration(1), 0 parent = self._parent while parent is not None and not parent.is_simultaneous: current_prolation *= prolations[i] if isinstance(parent, scoretools.FixedDurationTuplet): candidate_new_parent_dur = (parent.target_duration - current_prolation * self.written_duration) if durationtools.Duration(0) < candidate_new_parent_dur: parent.target_duration = candidate_new_parent_dur elif isinstance(parent, scoretools.Measure): indicator = parent._get_indicator(indicatortools.TimeSignature) parent_time_signature = indicator old_prolation = parent_time_signature.implied_prolation naive_time_signature = ( parent_time_signature.duration - prolated_leaf_duration) better_time_signature = mathtools.NonreducedFraction( naive_time_signature) better_time_signature = better_time_signature.with_denominator( parent_time_signature.denominator) better_time_signature = indicatortools.TimeSignature( better_time_signature) detach(indicatortools.TimeSignature, parent) attach(better_time_signature, parent) indicator = parent._get_indicator(indicatortools.TimeSignature) parent_time_signature = indicator new_prolation = parent_time_signature.implied_prolation adjusted_prolation = old_prolation / new_prolation for x in parent: if isinstance(x, scoretools.FixedDurationTuplet): x.target_duration *= adjusted_prolation else: if adjusted_prolation != 1: new_target = \ x._preprolated_duration * adjusted_prolation scoretools.FixedDurationTuplet(new_target, [x]) parent = parent._parent i += 1 parentage = self._get_parentage(include_self=False) parent = self._parent if parent: index = parent.index(self) del(parent[index]) for x in parentage: if not len(x): x._extract() else: break
def set_measure_denominator_and_adjust_numerator(measure, denominator): r'''Set `measure` time signature `denominator` and multiply time signature numerator accordingly: :: >>> measure = Measure((3, 8), "c'8 d'8 e'8") >>> beam = spannertools.Beam() >>> attach(beam, measure.select_leaves()) .. doctest:: >>> print format(measure) { \time 3/8 c'8 [ d'8 e'8 ] } :: >>> scoretools.set_measure_denominator_and_adjust_numerator(measure, 16) Measure((6, 16), "c'8 d'8 e'8") .. doctest:: >>> print format(measure) { \time 6/16 c'8 [ d'8 e'8 ] } Leave `measure` contents unchanged. Return `measure`. ''' from abjad.tools import scoretools if isinstance(measure, scoretools.Measure): # to allow iteration inside zero-update loop old_time_signature = measure.time_signature old_time_signature_pair = ( old_time_signature.numerator, old_time_signature.denominator) new_time_signature = mathtools.NonreducedFraction(old_time_signature_pair) new_time_signature = new_time_signature.with_denominator(denominator) new_time_signature = indicatortools.TimeSignature(new_time_signature) detach(indicatortools.TimeSignature, measure) attach(new_time_signature, measure) return measure
def _cleanup(self, parsed): container = scoretools.Container() for x in parsed: container.append(x) parsed = container leaves = parsed.select_leaves(allow_discontiguous_leaves=True) if leaves: self._apply_spanners(leaves) for leaf in leaves: detach(indicatortools.Annotation, leaf) if 1 < self._toplevel_component_count: return parsed return parsed[0]
def _get_span_events(self, leaf): annotations = leaf._get_indicators(indicatortools.Annotation) detach(indicatortools.Annotation, leaf) if annotations: spanners_annotations = [ x for x in annotations if x.name == 'spanners'] if 1 == len(spanners_annotations): return spanners_annotations[0].value elif 1 < len(spanners_annotations): message = 'multiple span events lists attached to {}.' message = message.format(leaf) raise Exception(message) return []
def _divide(self, pitch=None): from abjad.tools import scoretools from abjad.tools import markuptools from abjad.tools import pitchtools pitch = pitch or pitchtools.NamedPitch('b', 3) pitch = pitchtools.NamedPitch(pitch) treble = copy.copy(self) bass = copy.copy(self) detach(markuptools.Markup, treble) detach(markuptools.Markup, bass) if isinstance(treble, scoretools.Note): if treble.written_pitch < pitch: treble = scoretools.Rest(treble) elif isinstance(treble, scoretools.Rest): pass elif isinstance(treble, scoretools.Chord): for note_head in reversed(treble.note_heads): if note_head.written_pitch < pitch: treble.note_heads.remove(note_head) else: raise TypeError if isinstance(bass, scoretools.Note): if pitch <= bass.written_pitch: bass = scoretools.Rest(bass) elif isinstance(bass, scoretools.Rest): pass elif isinstance(bass, scoretools.Chord): for note_head in reversed(bass.note_heads): if pitch <= note_head.written_pitch: bass.note_heads.remove(note_head) else: raise TypeError treble = self._cast_defective_chord(treble) bass = self._cast_defective_chord(bass) up_markup = self._get_markup(direction=Up) up_markup = [copy.copy(markup) for markup in up_markup] down_markup = self._get_markup(direction=Down) down_markup = [copy.copy(markup) for markup in down_markup] for markup in up_markup: markup(treble) for markup in down_markup: markup(bass) return treble, bass
def _copy_with_indicators_but_without_children_or_spanners(self): from abjad.tools import indicatortools new = type(self)(*self.__getnewargs__()) # only the following line differs from Container detach(indicatortools.TimeSignature, new) if getattr(self, '_lilypond_grob_name_manager', None) is not None: new._lilypond_grob_name_manager = copy.copy(override(self)) if getattr(self, '_lilypond_setting_name_manager', None) is not None: new._lilypond_setting_name_manager = copy.copy(set_(self)) for indicator in self._get_indicators(): new_indicator = copy.copy(indicator) attach(new_indicator, new) new.is_simultaneous = self.is_simultaneous return new
def _cleanup(self, parsed): import abjad container = scoretools.Container() for x in parsed: container.append(x) parsed = container leaves = abjad.select(parsed).leaves() if leaves: self._apply_spanners(leaves) for leaf in leaves: detach(dict, leaf) if 1 < self._toplevel_component_count: return parsed return parsed[0]
def _do_tie_across_divisions(self, divisions): from abjad.tools import rhythmmakertools if not self.tie_across_divisions: return if self.strip_ties: return if self.tie_consecutive_notes: return length = len(divisions) tie_across_divisions = self.tie_across_divisions if isinstance(tie_across_divisions, bool): tie_across_divisions = [tie_across_divisions] if not isinstance(tie_across_divisions, patterntools.Pattern): tie_across_divisions = patterntools.Pattern.from_vector( tie_across_divisions) pairs = sequencetools.iterate_sequence_nwise(divisions) rest_prototype = (scoretools.Rest, scoretools.MultimeasureRest) for i, pair in enumerate(pairs): if not tie_across_divisions.matches_index(i, length): continue division_one, division_two = pair leaf_one = next(iterate(division_one).by_class( prototype=scoretools.Leaf, reverse=True, )) leaf_two = next(iterate(division_two).by_class( prototype=scoretools.Leaf, )) leaves = [leaf_one, leaf_two] if isinstance(leaf_one, rest_prototype): continue if isinstance(leaf_two, rest_prototype): continue prototype = (scoretools.Note, scoretools.Chord) if not all(isinstance(x, prototype) for x in leaves): continue logical_tie_one = inspect_(leaf_one).get_logical_tie() logical_tie_two = inspect_(leaf_two).get_logical_tie() for tie in inspect_(leaf_one).get_spanners(spannertools.Tie): detach(tie, leaf_one) for tie in inspect_(leaf_two).get_spanners(spannertools.Tie): detach(tie, leaf_two) combined_logical_tie = logical_tie_one + logical_tie_two tie_spanner = spannertools.Tie( use_messiaen_style_ties=self.use_messiaen_style_ties, ) tie_spanner._unconstrain_contiguity() attach(tie_spanner, combined_logical_tie) tie_spanner._constrain_contiguity()
def __mul__(self, n): r'''Copies component `n` times and detaches spanners. Returns list of new components. ''' from abjad.tools import spannertools result = mutate(self).copy(n=n) for component in iterate(result).by_class(): detach(spannertools.Spanner, component) if isinstance(result, type(self)): result = [result] else: result = list(result) result = selectiontools.Selection(result) return result
def _divide(self, pitch=None): from abjad.tools import markuptools treble = copy.copy(self) bass = copy.copy(self) detach(markuptools.Markup, treble) detach(markuptools.Markup, bass) up_markup = self._get_markup(direction=Up) up_markup = [copy.copy(markup) for markup in up_markup] down_markup = self._get_markup(direction=Down) down_markup = [copy.copy(markup) for markup in down_markup] for markup in up_markup: markup(treble) for markup in down_markup: markup(bass) return treble, bass
def _copy_with_indicators_but_without_children_or_spanners(self): from abjad.tools import indicatortools new = type(self)(*self.__getnewargs__()) # only the following line differs from Container detach(indicatortools.TimeSignature, new) if getattr(self, '_lilypond_grob_name_manager', None) is not None: new._lilypond_grob_name_manager = copy.copy(override(self)) if getattr(self, '_lilypond_setting_name_manager', None) is not None: new._lilypond_setting_name_manager = copy.copy(set_(self)) for indicator in self._get_indicators(): new_indicator = copy.copy(indicator) attach(new_indicator, new) new.is_simultaneous = self.is_simultaneous new.implicit_scaling = self.implicit_scaling return new
def _do_tie_across_divisions(self, divisions): if not self.tie_across_divisions: return if self.strip_ties: return if self.tie_consecutive_notes: return length = len(divisions) tie_across_divisions = self.tie_across_divisions if isinstance(tie_across_divisions, bool): tie_across_divisions = [tie_across_divisions] if not isinstance(tie_across_divisions, patterntools.Pattern): tie_across_divisions = patterntools.Pattern.from_vector( tie_across_divisions) pairs = sequencetools.iterate_sequence_nwise(divisions) rest_prototype = (scoretools.Rest, scoretools.MultimeasureRest) for i, pair in enumerate(pairs): if not tie_across_divisions.matches_index(i, length): continue division_one, division_two = pair leaf_one = next( iterate(division_one).by_class( prototype=scoretools.Leaf, reverse=True, )) leaf_two = next( iterate(division_two).by_class(prototype=scoretools.Leaf, )) leaves = [leaf_one, leaf_two] if isinstance(leaf_one, rest_prototype): continue if isinstance(leaf_two, rest_prototype): continue prototype = (scoretools.Note, scoretools.Chord) if not all(isinstance(x, prototype) for x in leaves): continue logical_tie_one = inspect_(leaf_one).get_logical_tie() logical_tie_two = inspect_(leaf_two).get_logical_tie() for tie in inspect_(leaf_one).get_spanners(spannertools.Tie): detach(tie, leaf_one) for tie in inspect_(leaf_two).get_spanners(spannertools.Tie): detach(tie, leaf_two) combined_logical_tie = logical_tie_one + logical_tie_two tie_spanner = spannertools.Tie( use_messiaen_style_ties=self.use_messiaen_style_ties, ) tie_spanner._unconstrain_contiguity() if tie_spanner._attachment_test_all(combined_logical_tie): attach(tie_spanner, combined_logical_tie) tie_spanner._constrain_contiguity()
def _notate_leaves( self, grace_handler=None, voice=None, ): for leaf in iterate(voice).by_leaf(): if leaf._has_indicator(indicatortools.Annotation): annotation = leaf._get_indicator(indicatortools.Annotation) pitches, grace_container = grace_handler(annotation.value) if not pitches: new_leaf = scoretools.Rest(leaf) elif 1 < len(pitches): new_leaf = scoretools.Chord(leaf) new_leaf.written_pitches = pitches else: new_leaf = scoretools.Note(leaf) new_leaf.written_pitch = pitches[0] if grace_container: attach(grace_container, new_leaf) tie = spannertools.Tie() if tie._attachment_test(new_leaf): attach(tie, new_leaf) mutate(leaf).replace(new_leaf) else: previous_leaf = leaf._get_leaf(-1) if isinstance(previous_leaf, scoretools.Rest): new_leaf = type(previous_leaf)( leaf.written_duration, ) elif isinstance(previous_leaf, scoretools.Note): new_leaf = type(previous_leaf)( previous_leaf.written_pitch, leaf.written_duration, ) else: new_leaf = type(previous_leaf)( previous_leaf.written_pitch, leaf.written_duration, ) mutate(leaf).replace(new_leaf) tie = inspect_(previous_leaf).get_spanner(spannertools.Tie) if tie is not None: tie._append(new_leaf) if leaf._has_indicator(indicatortools.Tempo): tempo = leaf._get_indicator(indicatortools.Tempo) detach(indicatortools.Tempo, leaf) attach(tempo, new_leaf)
def _notate_leaves( self, grace_handler=None, voice=None, ): for leaf in voice.select_leaves(): if leaf._has_indicator(indicatortools.Annotation): annotation = leaf._get_indicator(indicatortools.Annotation) pitches, grace_container = grace_handler(annotation.value) if not pitches: new_leaf = scoretools.Rest(leaf) elif 1 < len(pitches): new_leaf = scoretools.Chord(leaf) new_leaf.written_pitches = pitches else: new_leaf = scoretools.Note(leaf) new_leaf.written_pitch = pitches[0] if grace_container: attach(grace_container, new_leaf) tie = spannertools.Tie() if tie._attachment_test(new_leaf): attach(tie, new_leaf) mutate(leaf).replace(new_leaf) else: previous_leaf = leaf._get_leaf(-1) if isinstance(previous_leaf, scoretools.Rest): new_leaf = type(previous_leaf)( leaf.written_duration, ) elif isinstance(previous_leaf, scoretools.Note): new_leaf = type(previous_leaf)( previous_leaf.written_pitch, leaf.written_duration, ) else: new_leaf = type(previous_leaf)( previous_leaf.written_pitch, leaf.written_duration, ) mutate(leaf).replace(new_leaf) tie = inspect_(previous_leaf).get_spanner(spannertools.Tie) if tie is not None: tie._append(new_leaf) if leaf._has_indicator(indicatortools.Tempo): tempo = leaf._get_indicator(indicatortools.Tempo) detach(indicatortools.Tempo, leaf) attach(tempo, new_leaf)
def _make_ties_across_divisions(self, music): if not self.tie_across_divisions: return if self.tie_across_divisions == True: for division_one, division_two in \ sequencetools.iterate_sequence_nwise(music): leaf_one = next(iterate(division_one).by_class( prototype=scoretools.Leaf, reverse=True)) leaf_two = next(iterate(division_two).by_class( prototype=scoretools.Leaf)) leaves = [leaf_one, leaf_two] prototype = (scoretools.Note, scoretools.Chord) if not all(isinstance(x, prototype) for x in leaves): continue logical_tie_one = inspect_(leaf_one).get_logical_tie() logical_tie_two = inspect_(leaf_two).get_logical_tie() for tie in inspect_(leaf_one).get_spanners(spannertools.Tie): detach(tie, leaf_one) for tie in inspect_(leaf_two).get_spanners(spannertools.Tie): detach(tie, leaf_two) combined_logical_tie = logical_tie_one + logical_tie_two attach(spannertools.Tie(), combined_logical_tie) elif isinstance(self.tie_across_divisions, (tuple, list)): tie_across_divisions = datastructuretools.CyclicTuple( self.tie_across_divisions ) pairs = sequencetools.iterate_sequence_nwise(music) for i, pair in enumerate(pairs): indicator = tie_across_divisions[i] if not bool(indicator): continue division_one, division_two = pair leaf_one = next(iterate(division_one).by_class( prototype=scoretools.Leaf, reverse=True, )) leaf_two = next(iterate(division_two).by_class( prototype=scoretools.Leaf, )) leaves = [leaf_one, leaf_two] prototype = (scoretools.Note, scoretools.Chord) if not all(isinstance(x, prototype) for x in leaves): continue logical_tie_one = inspect_(leaf_one).get_logical_tie() logical_tie_two = inspect_(leaf_two).get_logical_tie() for tie in inspect_(leaf_one).get_spanners(spannertools.Tie): detach(tie, leaf_one) for tie in inspect_(leaf_two).get_spanners(spannertools.Tie): detach(tie, leaf_two) combined_logical_tie = logical_tie_one + logical_tie_two attach(spannertools.Tie(), combined_logical_tie) else: raise TypeError(self.tie_across_divisions)
def _make_ties_across_divisions(self, music): if not self.tie_across_divisions: return if self.tie_across_divisions == True: for division_one, division_two in \ sequencetools.iterate_sequence_nwise(music): leaf_one = next( iterate(division_one).by_class(prototype=scoretools.Leaf, reverse=True)) leaf_two = next( iterate(division_two).by_class(prototype=scoretools.Leaf)) leaves = [leaf_one, leaf_two] prototype = (scoretools.Note, scoretools.Chord) if not all(isinstance(x, prototype) for x in leaves): continue logical_tie_one = inspect_(leaf_one).get_logical_tie() logical_tie_two = inspect_(leaf_two).get_logical_tie() for tie in inspect_(leaf_one).get_spanners(spannertools.Tie): detach(tie, leaf_one) for tie in inspect_(leaf_two).get_spanners(spannertools.Tie): detach(tie, leaf_two) combined_logical_tie = logical_tie_one + logical_tie_two attach(spannertools.Tie(), combined_logical_tie) elif isinstance(self.tie_across_divisions, (tuple, list)): tie_across_divisions = datastructuretools.CyclicTuple( self.tie_across_divisions) pairs = sequencetools.iterate_sequence_nwise(music) for i, pair in enumerate(pairs): indicator = tie_across_divisions[i] if not bool(indicator): continue division_one, division_two = pair leaf_one = next( iterate(division_one).by_class( prototype=scoretools.Leaf, reverse=True, )) leaf_two = next( iterate(division_two).by_class( prototype=scoretools.Leaf, )) leaves = [leaf_one, leaf_two] prototype = (scoretools.Note, scoretools.Chord) if not all(isinstance(x, prototype) for x in leaves): continue logical_tie_one = inspect_(leaf_one).get_logical_tie() logical_tie_two = inspect_(leaf_two).get_logical_tie() for tie in inspect_(leaf_one).get_spanners(spannertools.Tie): detach(tie, leaf_one) for tie in inspect_(leaf_two).get_spanners(spannertools.Tie): detach(tie, leaf_two) combined_logical_tie = logical_tie_one + logical_tie_two attach(spannertools.Tie(), combined_logical_tie) else: raise TypeError(self.tie_across_divisions)
def _make_ties_across_divisions(self, divisions): from abjad.tools import rhythmmakertools if not self.tie_across_divisions: return length = len(divisions) tie_across_divisions = self.tie_across_divisions if isinstance(tie_across_divisions, bool): tie_across_divisions = [tie_across_divisions] if not isinstance(tie_across_divisions, rhythmmakertools.BooleanPattern): tie_across_divisions = \ rhythmmakertools.BooleanPattern.from_sequence( tie_across_divisions) pairs = sequencetools.iterate_sequence_nwise(divisions) for i, pair in enumerate(pairs): if not tie_across_divisions.matches_index(i, length): continue division_one, division_two = pair leaf_one = next(iterate(division_one).by_class( prototype=scoretools.Leaf, reverse=True, )) leaf_two = next(iterate(division_two).by_class( prototype=scoretools.Leaf, )) leaves = [leaf_one, leaf_two] prototype = (scoretools.Note, scoretools.Chord) if not all(isinstance(x, prototype) for x in leaves): continue logical_tie_one = inspect_(leaf_one).get_logical_tie() logical_tie_two = inspect_(leaf_two).get_logical_tie() for tie in inspect_(leaf_one).get_spanners(spannertools.Tie): detach(tie, leaf_one) for tie in inspect_(leaf_two).get_spanners(spannertools.Tie): detach(tie, leaf_two) combined_logical_tie = logical_tie_one + logical_tie_two tie_spanner = spannertools.Tie( use_messiaen_style_ties=self.use_messiaen_style_ties, ) tie_spanner._unconstrain_contiguity() attach(tie_spanner, combined_logical_tie) tie_spanner._constrain_contiguity()
def _apply_logical_tie_masks(self, selections): from abjad.tools import rhythmmakertools if self.logical_tie_masks is None: return selections # wrap every selection in a temporary container; # this allows the call to mutate().replace() to work containers = [] for selection in selections: container = scoretools.Container(selection) attach('temporary container', container) containers.append(container) logical_ties = iterate(selections).by_logical_tie() logical_ties = list(logical_ties) total_logical_ties = len(logical_ties) for index, logical_tie in enumerate(logical_ties[:]): matching_mask = self.logical_tie_masks.get_matching_pattern( index, total_logical_ties, ) if not isinstance(matching_mask, rhythmmakertools.SilenceMask): continue if isinstance(logical_tie.head, scoretools.Rest): continue for leaf in logical_tie: rest = scoretools.Rest(leaf.written_duration) inspector = inspect_(leaf) if inspector.has_indicator(durationtools.Multiplier): multiplier = inspector.get_indicator( durationtools.Multiplier, ) multiplier = durationtools.Multiplier(multiplier) attach(multiplier, rest) mutate(leaf).replace([rest]) detach(spannertools.Tie, rest) # remove every temporary container and recreate selections new_selections = [] for container in containers: inspector = inspect_(container) assert inspector.get_indicator(str) == 'temporary container' new_selection = mutate(container).eject_contents() new_selections.append(new_selection) return new_selections
def move_measure_prolation_to_full_measure_tuplet(expr): '''Move measure prolation to full-measure tuplet. Turn non-power-of-two measures into power-of-two measures containing a single fixed-duration tuplet. Note that not all non-power-of-two measures can be made power-of-two. Returns None because processes potentially many measures. ''' from abjad.tools import indicatortools from abjad.tools import scoretools for measure in iterate(expr).by_class(scoretools.Measure): effective_time_signature = measure.time_signature if effective_time_signature.has_non_power_of_two_denominator: # find time signature and contents multipliers time_signature_multiplier = effective_time_signature.implied_prolation contents_multiplier = \ measure._get_likely_multiplier_of_components(measure[:]) # update non-power-of-two time signature to power-of-two power_of_two_time_signature = effective_time_signature.with_power_of_two_denominator( contents_multiplier) detach(indicatortools.TimeSignature, measure) attach(power_of_two_time_signature, measure) # find target duration and create tuplet target_duration = time_signature_multiplier * measure._contents_duration tuplet = scoretools.FixedDurationTuplet(target_duration, measure[:]) # scale tuplet contents, if helpful if contents_multiplier is not None: numerator = contents_multiplier.numerator denominator = contents_multiplier.denominator pair = (denominator, numerator) inverse_multiplier = durationtools.Multiplier(*pair) tuplet._scale_contents(inverse_multiplier)
def remove_markup_from_leaves_in_expr(expr): r'''Remove markup from leaves in `expr`: :: >>> staff = Staff("c'8 d'8 e'8 f'8") >>> labeltools.label_leaves_in_expr_with_pitch_class_numbers(staff) >>> print(format(staff)) \new Staff { c'8 _ \markup { \small 0 } d'8 _ \markup { \small 2 } e'8 _ \markup { \small 4 } f'8 _ \markup { \small 5 } } :: >>> show(staff) # doctest: +SKIP :: >>> labeltools.remove_markup_from_leaves_in_expr(staff) >>> print(format(staff)) \new Staff { c'8 d'8 e'8 f'8 } :: >>> show(staff) # doctest: +SKIP Returns none. ''' from abjad.tools import markuptools for leaf in iterate(expr).by_class(scoretools.Leaf): detach(markuptools.Markup, leaf)
def _make_ties_across_divisions(music): for division_one, division_two in \ sequencetools.iterate_sequence_nwise(music): leaf_one = iterate(division_one).by_class( prototype=scoretools.Leaf, reverse=True, ).next() leaf_two = iterate(division_two).by_class( prototype=scoretools.Leaf, ).next() leaves = [leaf_one, leaf_two] prototype = (scoretools.Note, scoretools.Chord) if not all(isinstance(x, prototype) for x in leaves): continue logical_tie_one = inspect_(leaf_one).get_logical_tie() logical_tie_two = inspect_(leaf_two).get_logical_tie() for tie in inspect_(leaf_one).get_spanners(spannertools.Tie): detach(tie, leaf_one) for tie in inspect_(leaf_two).get_spanners(spannertools.Tie): detach(tie, leaf_two) combined_logical_tie = logical_tie_one + logical_tie_two attach(spannertools.Tie(), combined_logical_tie)
def _divide(self, pitch=None): from abjad.tools import markuptools from abjad.tools import pitchtools from abjad.tools import scoretools pitch = pitch or pitchtools.NamedPitch('b', 3) pitch = pitchtools.NamedPitch(pitch) treble = copy.copy(self) bass = copy.copy(self) detach(markuptools.Markup, treble) detach(markuptools.Markup, bass) if treble.written_pitch < pitch: treble = scoretools.Rest(treble) if pitch <= bass.written_pitch: bass = scoretools.Rest(bass) up_markup = self._get_markup(direction=Up) up_markup = [copy.copy(markup) for markup in up_markup] down_markup = self._get_markup(direction=Down) down_markup = [copy.copy(markup) for markup in down_markup] for markup in up_markup: markup(treble) for markup in down_markup: markup(bass) return treble, bass
def _split( self, durations, cyclic=False, fracture_spanners=False, tie_split_notes=True, use_messiaen_style_ties=False, ): from abjad.tools import pitchtools from abjad.tools import selectiontools from abjad.tools import scoretools from abjad.tools import spannertools durations = [durationtools.Duration(x) for x in durations] if cyclic: durations = sequencetools.repeat_sequence_to_weight( durations, self._get_duration()) durations = [durationtools.Duration(x) for x in durations] if sum(durations) < self._get_duration(): last_duration = self._get_duration() - sum(durations) durations.append(last_duration) sequencetools.truncate_sequence( durations, weight=self._get_duration(), ) result = [] leaf_prolation = self._get_parentage(include_self=False).prolation timespan = self._get_timespan() start_offset = timespan.start_offset for duration in durations: new_leaf = copy.copy(self) preprolated_duration = duration / leaf_prolation shard = new_leaf._set_duration( preprolated_duration, use_messiaen_style_ties=use_messiaen_style_ties, ) for x in shard: if isinstance(x, scoretools.Leaf): x_duration = x.written_duration * leaf_prolation else: x_duration = x.multiplied_duration * leaf_prolation stop_offset = x_duration + start_offset x._start_offset = start_offset x._stop_offset = stop_offset x._timespan = timespantools.Timespan( start_offset=start_offset, stop_offset=stop_offset, ) start_offset = stop_offset shard = [x._get_parentage().root for x in shard] result.append(shard) flattened_result = sequencetools.flatten_sequence(result) flattened_result = selectiontools.Selection(flattened_result) prototype = (spannertools.Tie,) parentage = self._get_parentage() if parentage._get_spanners(prototype=prototype): selection = select(flattened_result) for component in selection: # TODO: make top-level detach() work here for spanner in component._get_spanners(prototype): spanner._sever_all_components() #detach(prototype, component) # replace leaf with flattened result selection = selectiontools.Selection(self) parent, start, stop = selection._get_parent_and_start_stop_indices() if parent: parent.__setitem__(slice(start, stop + 1), flattened_result) else: selection._give_dominant_spanners(flattened_result) selection._withdraw_from_crossing_spanners() # fracture spanners if fracture_spanners: first_shard = result[0] for spanner in first_shard[-1]._get_spanners(): index = spanner._index(first_shard[-1]) spanner._fracture(index, direction=Right) last_shard = result[-1] for spanner in last_shard[0]._get_spanners(): index = spanner._index(last_shard[0]) spanner._fracture(index, direction=Left) for middle_shard in result[1:-1]: for spanner in middle_shard[0]._get_spanners(): index = spanner._index(middle_shard[0]) spanner._fracture(index, direction=Left) for spanner in middle_shard[-1]._get_spanners(): index = spanner._index(middle_shard[-1]) spanner._fracture(index, direction=Right) # adjust first leaf first_leaf = flattened_result[0] self._detach_grace_containers(kind='after') # adjust any middle leaves for middle_leaf in flattened_result[1:-1]: middle_leaf._detach_grace_containers(kind='grace') self._detach_grace_containers(kind='after') detach(object, middle_leaf) # adjust last leaf last_leaf = flattened_result[-1] last_leaf._detach_grace_containers(kind='grace') detach(object, last_leaf) # tie split notes, rests and chords as specified if pitchtools.Pitch.is_pitch_carrier(self) and tie_split_notes: flattened_result_leaves = iterate(flattened_result).by_class( scoretools.Leaf) # TODO: implement Selection._attach_tie_spanner_to_leaves() for leaf_pair in sequencetools.iterate_sequence_nwise( flattened_result_leaves): selection = selectiontools.Selection(leaf_pair) selection._attach_tie_spanner_to_leaf_pair( use_messiaen_style_ties=use_messiaen_style_ties, ) # return result return result
def _detach_all_beams(self, divisions): for component in iterate(divisions).by_class(): detach(spannertools.Beam, component)
def _detach_grace_containers(self, kind=None): grace_containers = self._get_grace_containers(kind=kind) for grace_container in grace_containers: detach(grace_container, self) return grace_containers
def _move_indicators(self, recipient_component): for indicator in self._get_indicators(unwrap=False): detach(indicator, self) attach(indicator, recipient_component)
def _split( self, durations, cyclic=False, fracture_spanners=False, tie_split_notes=True, use_messiaen_style_ties=False, ): from abjad.tools import pitchtools from abjad.tools import selectiontools from abjad.tools import scoretools from abjad.tools import spannertools durations = [durationtools.Duration(x) for x in durations] if cyclic: durations = sequencetools.repeat_sequence_to_weight( durations, self._get_duration()) durations = [durationtools.Duration(x) for x in durations] if sum(durations) < self._get_duration(): last_duration = self._get_duration() - sum(durations) durations.append(last_duration) sequencetools.truncate_sequence( durations, weight=self._get_duration(), ) result = [] leaf_prolation = self._get_parentage(include_self=False).prolation timespan = self._get_timespan() start_offset = timespan.start_offset for duration in durations: new_leaf = copy.copy(self) preprolated_duration = duration / leaf_prolation shard = new_leaf._set_duration( preprolated_duration, use_messiaen_style_ties=use_messiaen_style_ties, ) for x in shard: if isinstance(x, scoretools.Leaf): x_duration = x.written_duration * leaf_prolation else: x_duration = x.multiplied_duration * leaf_prolation stop_offset = x_duration + start_offset x._start_offset = start_offset x._stop_offset = stop_offset x._timespan = timespantools.Timespan( start_offset=start_offset, stop_offset=stop_offset, ) start_offset = stop_offset shard = [x._get_parentage().root for x in shard] result.append(shard) flattened_result = sequencetools.flatten_sequence(result) flattened_result = selectiontools.SliceSelection(flattened_result) prototype = (spannertools.Tie,) parentage = self._get_parentage() if parentage._get_spanners(prototype=prototype): selection = select(flattened_result) for component in selection: # TODO: make top-level detach() work here for spanner in component._get_spanners(prototype): spanner._sever_all_components() #detach(prototype, component) # replace leaf with flattened result selection = selectiontools.SliceSelection(self) parent, start, stop = selection._get_parent_and_start_stop_indices() if parent: parent.__setitem__(slice(start, stop + 1), flattened_result) else: selection._give_dominant_spanners(flattened_result) selection._withdraw_from_crossing_spanners() # fracture spanners if fracture_spanners: first_shard = result[0] for spanner in first_shard[-1]._get_spanners(): index = spanner._index(first_shard[-1]) spanner._fracture(index, direction=Right) last_shard = result[-1] for spanner in last_shard[0]._get_spanners(): index = spanner._index(last_shard[0]) spanner._fracture(index, direction=Left) for middle_shard in result[1:-1]: for spanner in middle_shard[0]._get_spanners(): index = spanner._index(middle_shard[0]) spanner._fracture(index, direction=Left) for spanner in middle_shard[-1]._get_spanners(): index = spanner._index(middle_shard[-1]) spanner._fracture(index, direction=Right) # adjust first leaf first_leaf = flattened_result[0] self._detach_grace_containers(kind='after') # adjust any middle leaves for middle_leaf in flattened_result[1:-1]: middle_leaf._detach_grace_containers(kind='grace') self._detach_grace_containers(kind='after') detach(object, middle_leaf) # adjust last leaf last_leaf = flattened_result[-1] last_leaf._detach_grace_containers(kind='grace') detach(object, last_leaf) # tie split notes, rests and chords as specified if pitchtools.Pitch.is_pitch_carrier(self) and tie_split_notes: flattened_result_leaves = iterate(flattened_result).by_class( scoretools.Leaf) # TODO: implement SliceSelection._attach_tie_spanner_to_leaves() for leaf_pair in sequencetools.iterate_sequence_nwise( flattened_result_leaves): selection = selectiontools.ContiguousSelection(leaf_pair) selection._attach_tie_spanner_to_leaf_pair( use_messiaen_style_ties=use_messiaen_style_ties, ) # return result return result