def _get_logical_tie(self): from abjad.tools import selectiontools from abjad.tools import spannertools prototype = (spannertools.Tie, ) for component in self._get_parentage(): tie_spanners = component._get_spanners(prototype) if len(tie_spanners) == 1: tie_spanner = tie_spanners.pop() return selectiontools.LogicalTie(music=tie_spanner._leaves) elif 1 < len(tie_spanners): message = 'multiple tie spanners found.' raise ExtraSpannerError(message) else: return selectiontools.LogicalTie(music=self)
def _get_logical_tie(self): from abjad.tools import selectiontools from abjad.tools import spannertools prototype = (spannertools.Tie, ) for component in self._get_parentage(): tie_spanners = component._get_spanners(prototype) if len(tie_spanners) == 1: tie_spanner = tie_spanners.pop() return selectiontools.LogicalTie( music=tie_spanner._get_leaves()) elif 1 < len(tie_spanners): message = 'parentage of {!r} contains {} tie spanners.' message = message.format(self, len(tie_spanners)) raise Exception(message) else: return selectiontools.LogicalTie(music=self)
def __call__(self, argument): r'''Calls naive attack-point optimizer. Returns none. ''' for logical_tie in iterate(argument).by_logical_tie(reverse=True): sub_logical_ties = [] current_sub_logical_tie = [] for leaf in logical_tie: tempos = leaf._get_indicators(indicatortools.MetronomeMark) if tempos: if current_sub_logical_tie: current_sub_logical_tie = \ selectiontools.LogicalTie(current_sub_logical_tie) sub_logical_ties.append(current_sub_logical_tie) current_sub_logical_tie = [] current_sub_logical_tie.append(leaf) if current_sub_logical_tie: current_sub_logical_tie = selectiontools.LogicalTie(current_sub_logical_tie) sub_logical_ties.append(current_sub_logical_tie) for sub_logical_tie in sub_logical_ties: sub_logical_tie._fuse_leaves_by_immediate_parent()
def __call__(self, logical_ties): r'''Calls hairpin handler on `logical_ties`. Passes silently when `logical_ties` is empty. Returns none. ''' if not logical_ties: return if not isinstance(logical_ties[0], selectiontools.LogicalTie): assert isinstance(logical_ties[0], scoretools.Leaf) logical_ties = [selectiontools.LogicalTie(_) for _ in logical_ties] if (self.span == 'contiguous notes and chords' or isinstance(self.span, (tuple, list))): groups = self._group_contiguous_logical_ties(logical_ties) elif self.span == 'nontrivial ties': groups = [[_] for _ in logical_ties] else: raise ValueError(self.span) if isinstance(self.span, (tuple, list)): if not self.enchain_hairpins: groups = self._partition_groups(groups) else: groups = self._partition_enchained_groups(groups) hairpin_tokens = self.hairpin_tokens for group_index, group in enumerate(groups): notes = [] for logical_tie in group: for note in logical_tie: notes.append(note) if len(notes) == 0: continue total_notes = len(notes) notes_to_span = [] for note_index, note in enumerate(notes): if self._index_matches_patterns(note_index, total_notes): notes_to_span.append(note) if not notes_to_span: continue if self.include_following_rests: last_note = notes_to_span[-1] next_leaf = inspect_(last_note).get_leaf(1) prototype = (scoretools.Rest, scoretools.MultimeasureRest) if isinstance(next_leaf, prototype): notes_to_span.append(next_leaf) if len(notes_to_span) == 1 and self.omit_lone_note_dynamic: continue if len(notes_to_span) == 1 and not self.omit_lone_note_dynamic: hairpin_token = hairpin_tokens[group_index] start_dynamic = hairpin_token[0] if start_dynamic == 'niente': message = 'can not attach niente dynamics to components.' raise Exception(message) dynamic = indicatortools.Dynamic(start_dynamic) attach(dynamic, notes[0]) continue hairpin_token = hairpin_tokens[group_index] if hairpin_token is None: continue if isinstance(hairpin_token, tuple): descriptor = ' '.join([_ for _ in hairpin_token if _]) include_rests = bool(self.include_following_rests) hairpin = spannertools.Hairpin( descriptor=descriptor, include_rests=include_rests, ) attach(hairpin, notes_to_span) # hook to allow callable custom classes like SwellSpecifier else: hairpin_token(notes_to_span) if self.flare: first_note = notes_to_span[0] prototype = scoretools.Note assert isinstance(first_note, prototype), repr(first_note) stencil = schemetools.Scheme('flared-hairpin') override(first_note).hairpin.stencil = stencil
def iterate_rewrite_inputs(expr): r'''Iterates topmost masked logical ties, rest groups and containers in `expr`, masked by `expr`. :: >>> from abjad.tools import metertools >>> from abjad.tools import scoretools :: >>> string = "abj: ! 2/4 c'4 d'4 ~ !" >>> string += "! 4/4 d'8. r16 r8. e'16 ~ " >>> string += "2/3 { e'8 ~ e'8 f'8 ~ } f'4 ~ !" >>> string += "! 4/4 f'8 g'8 ~ g'4 a'4 ~ a'8 b'8 ~ !" >>> string += "! 2/4 b'4 c''4 !" >>> string = string.replace('!', '|') >>> staff = scoretools.Staff(string) .. doctest:: >>> print(format(staff)) \new Staff { { \time 2/4 c'4 d'4 ~ } { \time 4/4 d'8. r16 r8. e'16 ~ \times 2/3 { e'8 ~ e'8 f'8 ~ } f'4 ~ } { f'8 g'8 ~ g'4 a'4 ~ a'8 b'8 ~ } { \time 2/4 b'4 c''4 } } :: >>> for x in metertools.MeterManager.iterate_rewrite_inputs( ... staff[0]): x ... LogicalTie(Note("c'4"),) LogicalTie(Note("d'4"),) :: >>> for x in metertools.MeterManager.iterate_rewrite_inputs( ... staff[1]): x ... LogicalTie(Note("d'8."),) LogicalTie(Rest('r16'), Rest('r8.')) LogicalTie(Note("e'16"),) Tuplet(Multiplier(2, 3), "e'8 ~ e'8 f'8 ~") LogicalTie(Note("f'4"),) :: >>> for x in metertools.MeterManager.iterate_rewrite_inputs( ... staff[2]): x ... LogicalTie(Note("f'8"),) LogicalTie(Note("g'8"), Note("g'4")) LogicalTie(Note("a'4"), Note("a'8")) LogicalTie(Note("b'8"),) :: >>> for x in metertools.MeterManager.iterate_rewrite_inputs( ... staff[3]): x ... LogicalTie(Note("b'4"),) LogicalTie(Note("c''4"),) Returns generator. ''' from abjad.tools import scoretools from abjad.tools import selectiontools from abjad.tools import spannertools last_tie_spanner = None current_leaf_group = None current_leaf_group_is_silent = False for x in expr: if isinstance(x, (scoretools.Note, scoretools.Chord)): this_tie_spanner = x._get_spanners(spannertools.Tie) or None if current_leaf_group is None: current_leaf_group = [] elif current_leaf_group_is_silent or \ this_tie_spanner is None or \ last_tie_spanner != this_tie_spanner: yield selectiontools.LogicalTie(current_leaf_group) current_leaf_group = [] current_leaf_group_is_silent = False current_leaf_group.append(x) last_tie_spanner = this_tie_spanner elif isinstance(x, (scoretools.Rest, scoretools.Skip)): if current_leaf_group is None: current_leaf_group = [] elif not current_leaf_group_is_silent: yield selectiontools.LogicalTie(current_leaf_group) current_leaf_group = [] current_leaf_group_is_silent = True current_leaf_group.append(x) last_tie_spanner = None elif isinstance(x, scoretools.Container): if current_leaf_group is not None: yield selectiontools.LogicalTie(current_leaf_group) current_leaf_group = None last_tie_spanner = None yield x else: message = 'unhandled component: {!r}.' message = message.format(x) raise Exception(message) if current_leaf_group is not None: yield selectiontools.LogicalTie(current_leaf_group)
def recurse( boundary_depth=None, boundary_offsets=None, depth=0, logical_tie=None, ): offsets = metertools.MeterManager.get_offsets_at_depth( depth, offset_inventory, ) #print('DEPTH:', depth) logical_tie_duration = logical_tie._preprolated_duration logical_tie_timespan = logical_tie.get_timespan() logical_tie_start_offset = logical_tie_timespan.start_offset logical_tie_stop_offset = logical_tie_timespan.stop_offset logical_tie_starts_in_offsets = logical_tie_start_offset in offsets logical_tie_stops_in_offsets = logical_tie_stop_offset in offsets if not metertools.MeterManager.is_acceptable_logical_tie( logical_tie_duration=logical_tie_duration, logical_tie_starts_in_offsets=logical_tie_starts_in_offsets, logical_tie_stops_in_offsets=logical_tie_stops_in_offsets, maximum_dot_count=maximum_dot_count, ): #print('UNACCEPTABLE:', logical_tie, logical_tie_start_offset, logical_tie_stop_offset) #print('\t', ' '.join([str(x) for x in offsets])) split_offset = None offsets = metertools.MeterManager.get_offsets_at_depth( depth, offset_inventory, ) # If the logical tie's start aligns, take the latest possible offset. if logical_tie_starts_in_offsets: offsets = reversed(offsets) for offset in offsets: if logical_tie_start_offset < offset < logical_tie_stop_offset: split_offset = offset break #print('\tABS:', split_offset) if split_offset is not None: split_offset -= logical_tie_start_offset #print('\tREL:', split_offset) #print() shards = mutate(logical_tie[:]).split( [split_offset], use_messiaen_style_ties=use_messiaen_style_ties, ) logical_ties = \ [selectiontools.LogicalTie(shard) for shard in shards] for logical_tie in logical_ties: recurse( boundary_depth=boundary_depth, boundary_offsets=boundary_offsets, depth=depth, logical_tie=logical_tie, ) else: #print() recurse( boundary_depth=boundary_depth, boundary_offsets=boundary_offsets, depth=depth + 1, logical_tie=logical_tie, ) elif metertools.MeterManager.is_boundary_crossing_logical_tie( boundary_depth=boundary_depth, boundary_offsets=boundary_offsets, logical_tie_start_offset=logical_tie_start_offset, logical_tie_stop_offset=logical_tie_stop_offset, ): #print('BOUNDARY CROSSING', logical_tie, logical_tie_start_offset, logical_tie_stop_offset) offsets = boundary_offsets if logical_tie_start_offset in boundary_offsets: offsets = reversed(boundary_offsets) split_offset = None for offset in offsets: if logical_tie_start_offset < offset < logical_tie_stop_offset: split_offset = offset break assert split_offset is not None #print('\tABS:', split_offset) split_offset -= logical_tie_start_offset #print('\tREL:', split_offset) #print() shards = mutate(logical_tie[:]).split( [split_offset], use_messiaen_style_ties=use_messiaen_style_ties, ) logical_ties = \ [selectiontools.LogicalTie(shard) for shard in shards] for logical_tie in logical_ties: recurse( boundary_depth=boundary_depth, boundary_offsets=boundary_offsets, depth=depth, logical_tie=logical_tie, ) else: #print('ACCEPTABLE:', logical_tie, logical_tie_start_offset, logical_tie_stop_offset) #print('\t', ' '.join([str(x) for x in offsets])) #print() logical_tie[:]._fuse()