def _initialize_from_columns(self, columns): from abjad.tools import datastructuretools columns = datastructuretools.CyclicTuple( [datastructuretools.CyclicTuple(column) for column in columns]) rows = [] for row_index in range(len(columns[0])): row = datastructuretools.CyclicTuple( [column[row_index] for column in columns]) rows.append(row) rows = datastructuretools.CyclicTuple(rows) return rows, columns
def _initialize_from_rows(self, rows): from abjad.tools import datastructuretools rows = datastructuretools.CyclicTuple( [datastructuretools.CyclicTuple(row) for row in rows]) columns = [] for column_index in range(len(rows[0])): column = datastructuretools.CyclicTuple( [row[column_index] for row in rows]) columns.append(column) columns = datastructuretools.CyclicTuple(columns) return rows, columns
def _make_music(self, divisions, seeds): #assert not seeds, repr(seeds) if seeds is None: seeds = 0 selections = [] divisions = [durationtools.Division(_) for _ in divisions] denominators = datastructuretools.CyclicTuple(self.denominators) extra_counts_per_division = self.extra_counts_per_division or (0,) extra_counts_per_division = datastructuretools.CyclicTuple( extra_counts_per_division ) for i, division in enumerate(divisions, seeds): # not yet extended to work with non-power-of-two divisions assert mathtools.is_positive_integer_power_of_two( division.denominator), repr(division) denominator = denominators[i] extra_count = extra_counts_per_division[i] basic_duration = durationtools.Duration(1, denominator) unprolated_note_count = None if division < 2 * basic_duration: notes = scoretools.make_notes([0], [division]) else: unprolated_note_count = division / basic_duration unprolated_note_count = int(unprolated_note_count) unprolated_note_count = unprolated_note_count or 1 if 0 < extra_count: modulus = unprolated_note_count extra_count = extra_count % modulus elif extra_count < 0: modulus = int(math.ceil(unprolated_note_count / 2.0)) extra_count = abs(extra_count) % modulus extra_count *= -1 note_count = unprolated_note_count + extra_count durations = note_count * [basic_duration] notes = scoretools.make_notes([0], durations) assert all( _.written_duration.denominator == denominator for _ in notes ) tuplet_duration = durationtools.Duration(division) tuplet = scoretools.FixedDurationTuplet( duration=tuplet_duration, music=notes, ) if unprolated_note_count is not None: preferred_denominator = unprolated_note_count tuplet.preferred_denominator = preferred_denominator selection = selectiontools.Selection(tuplet) selections.append(selection) self._apply_beam_specifier(selections) return selections
def children(self): r'''Children of cyclic payload tree. Returns tuple of zero or more nodes. ''' from abjad.tools import datastructuretools return datastructuretools.CyclicTuple(self._children)
def _get_ratios(self): if self.ratios: ratios = self.ratios else: ratios = (mathtools.Ratio([1]), ) ratios = datastructuretools.CyclicTuple(ratios) return ratios
def _get_depths(self): if self.depths: depths = self.depths else: depths = (1, ) depths = datastructuretools.CyclicTuple(depths) return depths
def execute_against_score(self, score): r'''Execute pitch set expression against `score`. ''' statal_server_cursor = self.source_expression.payload leaves = list(self._iterate_selected_leaves_in_score(score)) assert all( isinstance(leaf, (scoretools.Note, scoretools.Chord)) for leaf in leaves) if self.level is None: level = -1 else: level = self.level if self.node_count is None: node_count = len(leaves) else: node_count = self.node_count pitch_numbers = \ statal_server_cursor(n=node_count, level=level) pitch_numbers = \ datastructuretools.CyclicTuple(pitch_numbers) for i, leaf in enumerate(leaves): #leaf.sounding_pitch = pitch_numbers[i] sounding_pitch = pitch_numbers[i] instrument = leaf._get_effective(instrumenttools.Instrument) if instrument: reference_pitch = instrument.sounding_pitch_of_written_middle_c else: reference_pitch = pitchtools.NamedPitch('C4') t_n = reference_pitch - pitchtools.NamedPitch('C4') written_pitch = pitchtools.transpose_pitch_carrier_by_interval( sounding_pitch, t_n) leaf.written_pitch = written_pitch assert inspect_(leaf).get_sounding_pitch() == sounding_pitch
def __init__( self, attach_start_dynamic_to_lone_notes=True, hairpin_token=None, minimum_duration=None, patterns=None, span='contiguous notes and chords', ): DynamicHandler.__init__(self, minimum_duration=minimum_duration) self._attach_start_dynamic_to_lone_notes = bool( attach_start_dynamic_to_lone_notes) if hairpin_token is None: hairpin_token = [] elif isinstance(hairpin_token, str): hairpin_token = tuple(hairpin_token.split()) assert spannertools.Hairpin._is_hairpin_token(hairpin_token) elif isinstance(hairpin_token, list): tokens = [] for element in hairpin_token: if isinstance(element, str): element = tuple(element.split()) if not spannertools.Hairpin._is_hairpin_token(element): message = 'must be valid hairpin token: {!r}.' message = message.format(element) raise Exception(message) tokens.append(element) hairpin_token = tokens if isinstance(hairpin_token, datastructuretools.CyclicTuple): pass elif isinstance(hairpin_token, list): hairpin_token = datastructuretools.CyclicTuple(hairpin_token) elif isinstance(hairpin_token, tuple): hairpin_token = datastructuretools.CyclicTuple([hairpin_token]) else: raise TypeError(hairpin_token) self._hairpin_token = hairpin_token if patterns is not None: assert isinstance(patterns, (list, tuple)), repr(patterns) self._patterns = patterns strings = ( 'contiguous notes and chords', 'nontrivial ties', ) if span not in strings: assert isinstance(span, (tuple, list)), repr(span) self._span = span
def __call__( self, expr, timespan=None, offset=0, skip_first=0, skip_last=0, ): r'''Calls handler on `expr` with keywords. Returns none. ''' articulation_lists = datastructuretools.CyclicTuple( self.articulation_lists) prototype = (scoretools.Note, scoretools.Chord) notes_and_chords = list(iterate(expr).by_class(prototype)) notes_and_chords = notes_and_chords[skip_first:] if skip_last: notes_and_chords = notes_and_chords[:-skip_last] i = 0 for note_or_chord in notes_and_chords: logical_tie = inspect_(note_or_chord).get_logical_tie() duration = logical_tie.get_duration() articulation_list = articulation_lists[offset + i] if articulation_list is None: i += 1 continue articulation_list = [ indicatortools.Articulation(_) for _ in articulation_list ] if self.minimum_duration is not None: if duration <= self.minimum_duration: continue if self.maximum_duration is not None: if self.maximum_duration < duration: continue if self.minimum_written_pitch is not None: if isinstance(note_or_chord, scoretools.Note): minimum_written_pitch = note_or_chord.written_pitch else: minimum_written_pitch = note_or_chord.writen_pitches[0] if minimum_written_pitch < self.minimum_written_pitch: continue if self.maximum_written_pitch is not None: if isinstance(note_or_chord, scoretools.Note): maximum_written_pitch = note_or_chord.written_pitch else: maximum_written_pitch = note_or_chord.written_pitches[-1] if self.maximum_written_pitch < maximum_written_pitch: continue logical_tie = inspect_(note_or_chord).get_logical_tie() if note_or_chord is logical_tie.head: for articulation in articulation_list: # TODO: make new(articulation) work articulation = copy.copy(articulation) attach(articulation, note_or_chord) i += 1 return expr
def repeat_to_length(self, length): r'''Repeat start-positioned rhythm payload expression to `length`. Example 1. Repeat to `length` less than start-positioned rhythm payload expression: :: >>> payload = [Container("c'8 d'8 e'8 f'8")] >>> expression = \ ... musicexpressiontools.StartPositionedRhythmPayloadExpression( ... payload, Offset(0)) :: >>> result = expression.repeat_to_length(3) :: >>> print(format(expression)) musicexpressiontools.StartPositionedRhythmPayloadExpression( payload=scoretools.Container( "{ c'8 d'8 e'8 }" ), start_offset=durationtools.Offset(0, 1), ) Example 2. Repeat to `length` greater than start-positioned rhythm payload expression: :: >>> payload = [Container("c'8 d'8 e'8 f'8")] >>> expression = \ ... musicexpressiontools.StartPositionedRhythmPayloadExpression( ... payload, Offset(0)) :: >>> result = expression.repeat_to_length(7) :: >>> print(format(expression)) musicexpressiontools.StartPositionedRhythmPayloadExpression( payload=scoretools.Container( "{ c'8 d'8 e'8 f'8 } { c'8 d'8 e'8 }" ), start_offset=durationtools.Offset(0, 1), ) Operates in place and returns start-positioned rhythm payload expression. ''' leaves = datastructuretools.CyclicTuple(self.payload.select_leaves()) leaves = leaves[:length] duration = sum([leaf._get_duration() for leaf in leaves]) return self.repeat_to_duration(duration)
def _burnish_each_division(class_, input_, divisions): left_classes = input_['left_classes'] middle_classes = input_['middle_classes'] right_classes = input_['right_classes'] left_counts = input_['left_counts'] left_counts = left_counts or datastructuretools.CyclicTuple([0]) right_counts = input_['right_counts'] right_counts = right_counts or datastructuretools.CyclicTuple([0]) lefts_index, rights_index = 0, 0 burnished_divisions = [] for division_index, division in enumerate(divisions): left_count = left_counts[division_index] left = left_classes[lefts_index:lefts_index + left_count] lefts_index += left_count right_count = right_counts[division_index] right = right_classes[rights_index:rights_index + right_count] rights_index += right_count available_left_count = len(division) left_count = min([left_count, available_left_count]) available_right_count = len(division) - left_count right_count = min([right_count, available_right_count]) middle_count = len(division) - left_count - right_count left = left[:left_count] if middle_classes: middle = middle_count * [middle_classes[division_index]] else: middle = middle_count * [0] right = right[:right_count] left_part, middle_part, right_part = \ sequencetools.partition_sequence_by_counts( division, [left_count, middle_count, right_count], cyclic=False, overhang=False, ) left_part = class_._burnish_division_part(left_part, left) middle_part = class_._burnish_division_part(middle_part, middle) right_part = class_._burnish_division_part(right_part, right) burnished_division = left_part + middle_part + right_part burnished_divisions.append(burnished_division) unburnished_weights = [mathtools.weight(x) for x in divisions] burnished_weights = [mathtools.weight(x) for x in burnished_divisions] assert burnished_weights == unburnished_weights return burnished_divisions
def _burnish_outer_divisions(self, selections): left_classes = self.burnish_specifier.left_classes left_counts = self.burnish_specifier.left_counts right_classes = self.burnish_specifier.right_classes right_counts = self.burnish_specifier.right_counts if left_counts: assert len(left_counts) == 1, repr(left_counts) left_count = left_counts[0] else: left_count = 0 if right_counts: assert len(right_counts) == 1, repr(right_counts) right_count = right_counts[0] else: right_count = 0 if left_count + right_count <= len(selections): middle_count = len(selections) - (left_count + right_count) elif left_count <= len(selections): right_count = len(selections) - left_count middle_count = 0 else: left_count = len(selections) right_count = 0 middle_count = 0 assert left_count + middle_count + right_count == len(selections) new_selections = [] left_classes = datastructuretools.CyclicTuple(left_classes) for i, selection in enumerate(selections[:left_count]): target_class = left_classes[i] new_selection = self._cast_selection(selection, target_class) new_selections.append(new_selection) if right_count: for selection in selections[left_count:-right_count]: new_selections.append(selection) right_classes = datastructuretools.CyclicTuple(right_classes) for i, selection in enumerate(selections[-right_count:]): target_class = right_classes[i] new_selection = self._cast_selection(selection, target_class) new_selections.append(new_selection) else: for selection in selections[left_count:]: new_selections.append(selection) return new_selections
def __call__(self, logical_ties): r'''Calls handler on `logical_ties`. Returns none. ''' markups = datastructuretools.CyclicTuple(self.markups) for i, logical_tie in enumerate(logical_ties): markup = markups[i] markup = markuptools.Markup(markup) attach(markup, logical_tie.head)
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 _populate_pitches(self, voice, pitch_range): assert isinstance(pitch_range, pitchtools.PitchRange) pitch_numbers = [ x for x in self._test_pitch_numbers if x in pitch_range ] pitch_numbers = sequencetools.remove_repeated_elements(pitch_numbers) pitch_numbers = datastructuretools.CyclicTuple(pitch_numbers) logical_ties = iterate(voice).by_logical_tie(pitched=True) for i, logical_tie in enumerate(logical_ties): pitch_number = pitch_numbers[i] for note in logical_tie: note.written_pitch = pitch_number
def _prepare_input(self, seeds): from abjad.tools import rhythmmakertools helper_functions = self.helper_functions or {} incise_specifier = self.incise_specifier if incise_specifier is None: incise_specifier = rhythmmakertools.InciseSpecifier() prefix_talea = incise_specifier.prefix_talea or () helper = helper_functions.get('prefix_talea') helper = self._none_to_trivial_helper(helper) prefix_talea = helper(prefix_talea, seeds) prefix_talea = datastructuretools.CyclicTuple(prefix_talea) prefix_counts = incise_specifier.prefix_counts or (0,) helper = helper_functions.get('prefix_counts') helper = self._none_to_trivial_helper(helper) prefix_counts = helper(prefix_counts, seeds) prefix_counts = datastructuretools.CyclicTuple(prefix_counts) suffix_talea = incise_specifier.suffix_talea or () helper = helper_functions.get('suffix_talea') helper = self._none_to_trivial_helper(helper) suffix_talea = helper(suffix_talea, seeds) suffix_talea = datastructuretools.CyclicTuple(suffix_talea) suffix_counts = incise_specifier.suffix_counts or (0,) helper = helper_functions.get('suffix_counts') helper = self._none_to_trivial_helper(helper) suffix_counts = helper(suffix_counts, seeds) suffix_counts = datastructuretools.CyclicTuple(suffix_counts) extra_counts_per_division = self.extra_counts_per_division or () helper = helper_functions.get('extra_counts_per_division') helper = self._none_to_trivial_helper(helper) extra_counts_per_division = helper(extra_counts_per_division, seeds) if extra_counts_per_division: extra_counts_per_division = datastructuretools.CyclicTuple( extra_counts_per_division) else: extra_counts_per_division = datastructuretools.CyclicTuple([0]) split_divisions_by_counts = self.split_divisions_by_counts or () helper = helper_functions.get('split_divisions_by_counts') helper = self._none_to_trivial_helper(helper) split_divisions_by_counts = helper(split_divisions_by_counts, seeds) split_divisions_by_counts = datastructuretools.CyclicTuple( split_divisions_by_counts) return ( prefix_talea, prefix_counts, suffix_talea, suffix_counts, extra_counts_per_division, split_divisions_by_counts, )
def __call__(self, expr, timespan=None): r'''Calls handler on `expr`. Returns none. ''' prototype = (scoretools.Note, scoretools.Chord) hash_mark_counts = datastructuretools.CyclicTuple( self.hash_mark_counts) leaves = iterate(expr).by_class(prototype) for i, leaf in enumerate(leaves): hash_mark_count = hash_mark_counts[i] stem_tremolo = indicatortools.StemTremolo(hash_mark_count) attach(stem_tremolo, leaf)
def __init__(self, dynamic_name=None, minimum_duration=None): self._dynamic_name = dynamic_name dynamic_names = () if dynamic_name is not None: assert isinstance(dynamic_name, str), repr(dynamic_name) dynamic_names = dynamic_name.split() for dynamic_name in dynamic_names: assert indicatortools.Dynamic.is_dynamic_name(dynamic_name) dynamic_names = datastructuretools.CyclicTuple(dynamic_names) self._dynamic_names = dynamic_names if minimum_duration is not None: minimum_duration = durationtools.Duration(minimum_duration) self._minimum_duration = minimum_duration
def __getitem__(self, item): r'''Gets nonreduced fraction at `item` cyclically. .. container:: example **Example 1.** Gets item at index: :: >>> talea = rhythmmakertools.Talea( ... counts=(2, 1, 3, 2, 4, 1, 1), ... denominator=16, ... ) :: >>> talea[2] NonreducedFraction(3, 16) .. container:: example **Example 2.** Gets items in slice: :: >>> for nonreduced_fraction in talea[3:9]: ... nonreduced_fraction ... NonreducedFraction(2, 16) NonreducedFraction(4, 16) NonreducedFraction(1, 16) NonreducedFraction(1, 16) NonreducedFraction(2, 16) NonreducedFraction(1, 16) Returns nonreduced fraction or nonreduced fractions. ''' counts = datastructuretools.CyclicTuple(self.counts) if isinstance(item, int): count = counts[item] return mathtools.NonreducedFraction(count, self.denominator) elif isinstance(item, slice): counts = counts[item] result = [ mathtools.NonreducedFraction(count, self.denominator) for count in counts ] return result raise ValueError(item)
def __init__( self, enchain_hairpins=None, flare=None, hairpin_tokens=None, include_following_rests=None, minimum_duration=None, omit_lone_note_dynamic=None, patterns=None, span='contiguous notes and chords', ): if enchain_hairpins is not None: enchain_hairpins = bool(enchain_hairpins) self._enchain_hairpins = enchain_hairpins self._flare = flare hairpin_tokens = hairpin_tokens or [] prototype = (list, tuple) assert isinstance(hairpin_tokens, prototype), repr(hairpin_tokens) tokens = [] for element in hairpin_tokens: if isinstance(element, str): element = tuple(element.split()) if not spannertools.Hairpin._is_hairpin_token(element): message = 'must be valid hairpin token: {!r}.' message = message.format(element) raise Exception(message) tokens.append(element) hairpin_tokens = tokens hairpin_tokens = datastructuretools.CyclicTuple(hairpin_tokens) self._hairpin_tokens = hairpin_tokens if include_following_rests is not None: include_following_rests = bool(include_following_rests) self._include_following_rests = include_following_rests if minimum_duration is not None: minimum_duration = durationtools.Duration(minimum_duration) self._minimum_duration = minimum_duration if omit_lone_note_dynamic is not None: omit_lone_note_dynamic = bool(omit_lone_note_dynamic) self._omit_lone_note_dynamic = omit_lone_note_dynamic if patterns is not None: assert isinstance(patterns, (list, tuple)), repr(patterns) self._patterns = patterns strings = ( 'contiguous notes and chords', 'nontrivial ties', ) if span not in strings: assert isinstance(span, (tuple, list)), repr(span) self._span = span
def __getitem__(self, item): r'''Gets non-reduced fraction at `item` cyclically. Returns non-reduced fraction or non-reduced fractions. ''' counts = datastructuretools.CyclicTuple(self.counts) if isinstance(item, int): count = counts[item] return mathtools.NonreducedFraction(count, self.denominator) elif isinstance(item, slice): counts = counts[item] result = [mathtools.NonreducedFraction(count, self.denominator) for count in counts] return result raise ValueError(item)
def __init__( self, counts=(3, ), cyclic=True, fuse_overhang=False, nonempty=False, overhang=True, rotate=True, ): counts = datastructuretools.CyclicTuple(int(_) for _ in counts) self._counts = counts self._cyclic = bool(cyclic) self._fuse_overhang = bool(fuse_overhang) self._overhang = bool(overhang) self._rotate = bool(rotate) self._nonempty = bool(nonempty)
def _partition_by_enchained_counts(self, leaves, counts): assert isinstance(leaves, list), repr(leaves) counts = datastructuretools.CyclicTuple(counts) shards = [] shard_index = 0 leaf_start_index = 0 total_leaves = len(leaves) while True: current_count = counts[shard_index] leaf_stop_index = leaf_start_index + current_count shard = leaves[leaf_start_index:leaf_stop_index] shards.append(shard) shard_index += 1 leaf_start_index = leaf_stop_index - 1 if total_leaves <= leaf_stop_index: break return shards
def _scale_taleas(self, divisions, talea_denominator, taleas): talea_denominator = talea_denominator or 1 dummy_division = (1, talea_denominator) divisions.append(dummy_division) Duration = durationtools.Duration divisions = Duration.durations_to_nonreduced_fractions(divisions) dummy_division = divisions.pop() lcd = dummy_division.denominator multiplier = lcd / talea_denominator scaled_taleas = [] for talea in taleas: talea = [multiplier * _ for _ in talea] talea = datastructuretools.CyclicTuple(talea) scaled_taleas.append(talea) result = [divisions, lcd] result.extend(scaled_taleas) return tuple(result)
def __call__(self, expr): r'''Calls handler on `expr`. Returns none. ''' prototype = (scoretools.Note, scoretools.Chord) hash_mark_counts = datastructuretools.CyclicTuple( self.hash_mark_counts) leaves = list(iterate(expr).by_class(prototype)) total_length = len(leaves) for i, leaf in enumerate(leaves): if self.pattern is not None: if not self.pattern.matches_index(i, total_length): continue hash_mark_count = hash_mark_counts[i] stem_tremolo = indicatortools.StemTremolo(hash_mark_count) attach(stem_tremolo, leaf)
def _rotate_input(self, helper_functions=None, rotation=None): helper_functions = helper_functions or {} input_ = {} names = ( 'left_classes', 'left_counts', 'middle_classes', 'right_classes', 'right_counts', ) for name in names: value = getattr(self, name) value = value or () helper_function = helper_functions.get(name) helper_function = self._none_to_trivial_helper(helper_function) value = helper_function(value, rotation) value = datastructuretools.CyclicTuple(value) input_[name] = value return input_
def __call__(self, logical_ties, timespan=None, offset=0): r'''Calls handler on `expr` with keywords. Returns none. ''' dynamics = datastructuretools.CyclicTuple(self.dynamics) for i, logical_tie in enumerate(logical_ties): dynamic_name = dynamics[offset + i] if i == 0 and self.always_first_note: pass elif self.minimum_duration is not None: written_duration = durationtools.Duration(0) for note in logical_tie: written_duration += note.written_duration if written_duration < self.minimum_duration: continue #indicatortools.Dynamic(dynamic_name)(note_or_chord) command = indicatortools.LilyPondCommand(dynamic_name, 'right') attach(command, logical_tie.head)
def __call__(self, logical_ties, timespan=None, offset=0): r'''Calls handler on `logical_ties` with `offset`. Returns none. ''' hairpin_tokens = datastructuretools.CyclicTuple(self.hairpin_tokens) logical_tie_groups = self._group_contiguous_logical_ties(logical_ties) for logical_tie_group in logical_tie_groups: pairs = sequencetools.iterate_sequence_nwise( logical_tie_group, n=2, ) for i, pair in enumerate(pairs): hairpin_token = hairpin_tokens[i] descriptor = ' '.join([_ for _ in hairpin_token if _]) hairpin = spannertools.Hairpin( descriptor=descriptor, include_rests=False, ) first_logical_tie, second_logical_tie = pair notes = [] notes.extend(first_logical_tie) notes.append(second_logical_tie.head) attach(hairpin, notes)
def _burnish_outer_divisions(class_, input_, divisions): for list_ in divisions: assert all(isinstance(_, int) for _ in list_), repr(list_) left_classes = input_['left_classes'] middle_classes = input_['middle_classes'] right_classes = input_['right_classes'] left_counts = input_['left_counts'] left_counts = left_counts or datastructuretools.CyclicTuple([0]) right_counts = input_['right_counts'] right_counts = right_counts or datastructuretools.CyclicTuple([0]) burnished_divisions = [] left_count = 0 if left_counts: left_count = left_counts[0] left = left_classes[:left_count] right_count = 0 if right_counts: right_count = right_counts[0] right = right_classes[:right_count] if len(divisions) == 1: available_left_count = len(divisions[0]) left_count = min([left_count, available_left_count]) available_right_count = len(divisions[0]) - left_count right_count = min([right_count, available_right_count]) middle_count = len(divisions[0]) - left_count - right_count left = left[:left_count] if not middle_classes: middle_classes = [1] middle = [middle_classes[0]] middle = middle_count * middle right = right[:right_count] left_part, middle_part, right_part = \ sequencetools.partition_sequence_by_counts( divisions[0], [left_count, middle_count, right_count], cyclic=False, overhang=Exact, ) left_part = class_._burnish_division_part(left_part, left) middle_part = class_._burnish_division_part(middle_part, middle) right_part = class_._burnish_division_part(right_part, right) burnished_division = left_part + middle_part + right_part burnished_divisions.append(burnished_division) else: # first division available_left_count = len(divisions[0]) left_count = min([left_count, available_left_count]) middle_count = len(divisions[0]) - left_count left = left[:left_count] if not middle_classes: middle_classes = [1] middle = [middle_classes[0]] middle = middle_count * middle left_part, middle_part = \ sequencetools.partition_sequence_by_counts( divisions[0], [left_count, middle_count], cyclic=False, overhang=Exact, ) left_part = class_._burnish_division_part(left_part, left) middle_part = class_._burnish_division_part(middle_part, middle) burnished_division = left_part + middle_part burnished_divisions.append(burnished_division) # middle divisions for division in divisions[1:-1]: middle_part = division middle = len(division) * [middle_classes[0]] middle_part = class_._burnish_division_part( middle_part, middle, ) burnished_division = middle_part burnished_divisions.append(burnished_division) # last division: available_right_count = len(divisions[-1]) right_count = min([right_count, available_right_count]) middle_count = len(divisions[-1]) - right_count right = right[:right_count] middle = middle_count * [middle_classes[0]] middle_part, right_part = \ sequencetools.partition_sequence_by_counts( divisions[-1], [middle_count, right_count], cyclic=False, overhang=Exact, ) middle_part = class_._burnish_division_part(middle_part, middle) right_part = class_._burnish_division_part(right_part, right) burnished_division = middle_part + right_part burnished_divisions.append(burnished_division) unburnished_weights = [mathtools.weight(x) for x in divisions] burnished_weights = [mathtools.weight(x) for x in burnished_divisions] #assert burnished_weights == unburnished_weights # TODO: make the following work on Python 3: #assert tuple(burnished_weights) == tuple(unburnished_weights) return burnished_divisions
def _make_cyclic_tuple_generator(iterable): cyclic_tuple = datastructuretools.CyclicTuple(iterable) i = 0 while True: yield cyclic_tuple[i] i += 1