def partition_by_ratio_of_durations(self, ratio): r'''Partition payload expression by ratio of durations. :: >>> result = \ ... payload_expression.partition_by_ratio_of_durations((1, 1)) :: >>> for element in result: ... print element.storage_format musicexpressiontools.IterablePayloadExpression( payload=((4, 16),) ) musicexpressiontools.IterablePayloadExpression( payload=((2, 16),) ) Returns newly constructed payload expression. ''' element_durations = [self._duration_helper(x) for x in self.payload] element_tokens = self._durations_to_integers(element_durations) token_parts = sequencetools.partition_sequence_by_ratio_of_weights( element_tokens, ratio) part_lengths = [len(x) for x in token_parts] duration_parts = sequencetools.partition_sequence_by_counts( element_durations, part_lengths) element_parts = sequencetools.partition_sequence_by_counts( self.payload, part_lengths) result = [] for part in element_parts: part = self.new(payload=part) result.append(part) return result
def _beat_list_to_grouped_beat_list(self, beat_list): assert isinstance(beat_list, (list, tuple)), repr(beat_list) beat_list_ = [] for beat in beat_list: if hasattr(beat, 'duration'): beat = durationtools.Division(beat.duration) else: beat = durationtools.Division(beat) beat_list_.append(beat) beat_list = beat_list_ total_duration = sum(beat_list) total_duration = durationtools.Duration(total_duration) if (total_duration.is_assignable and self.fuse_assignable_total_duration): return [[durationtools.Division(total_duration)]] if self.counts is None: beat_group = list(beat_list) grouped_beat_list = [beat_group] return grouped_beat_list grouped_beat_list = sequencetools.partition_sequence_by_counts( beat_list, counts=self.counts, cyclic=True, overhang=False, ) beats_included = sum([len(_) for _ in grouped_beat_list]) if beats_included == len(beat_list): return grouped_beat_list remainder_length = len(beat_list) - beats_included if self.remainder_direction == Left: grouped_beat_list = sequencetools.partition_sequence_by_counts( beat_list[remainder_length:], counts=self.counts, cyclic=True, overhang=False ) remainder = beat_list[:remainder_length] if self.append_remainder: grouped_beat_list[0] = remainder + grouped_beat_list[0] else: grouped_beat_list.insert(0, remainder) else: grouped_beat_list = sequencetools.partition_sequence_by_counts( beat_list[:-remainder_length], counts=self.counts, cyclic=True, overhang=False ) remainder = beat_list[-remainder_length:] if self.append_remainder: grouped_beat_list[-1] = grouped_beat_list[-1] + remainder else: grouped_beat_list.append(remainder) return grouped_beat_list
def _beat_list_to_grouped_beat_list(self, beat_list): assert isinstance(beat_list, (list, tuple)), repr(beat_list) beat_list_ = [] for beat in beat_list: if hasattr(beat, 'duration'): beat = durationtools.Division(beat.duration) else: beat = durationtools.Division(beat) beat_list_.append(beat) beat_list = beat_list_ total_duration = sum(beat_list) total_duration = durationtools.Duration(total_duration) if (total_duration.is_assignable and self.fuse_assignable_total_duration): return [[durationtools.Division(total_duration)]] if self.counts is None: beat_group = list(beat_list) grouped_beat_list = [beat_group] return grouped_beat_list grouped_beat_list = sequencetools.partition_sequence_by_counts( beat_list, counts=self.counts, cyclic=True, overhang=False, ) beats_included = sum([len(_) for _ in grouped_beat_list]) if beats_included == len(beat_list): return grouped_beat_list remainder_length = len(beat_list) - beats_included if self.remainder_direction == Left: grouped_beat_list = sequencetools.partition_sequence_by_counts( beat_list[remainder_length:], counts=self.counts, cyclic=True, overhang=False) remainder = beat_list[:remainder_length] if self.append_remainder: grouped_beat_list[0] = remainder + grouped_beat_list[0] else: grouped_beat_list.insert(0, remainder) else: grouped_beat_list = sequencetools.partition_sequence_by_counts( beat_list[:-remainder_length], counts=self.counts, cyclic=True, overhang=False) remainder = beat_list[-remainder_length:] if self.append_remainder: grouped_beat_list[-1] = grouped_beat_list[-1] + remainder else: grouped_beat_list.append(remainder) return grouped_beat_list
def make_spanner_score_02(self): r'''Make 200-note voice with durated complex beam spanner on every 20 notes. :: 2.12 (r9710) initialization: 250,954 function calls 2.12 (r9724) initialization: 248,717 function calls 2.12 (r9703) LilyPond format: 495,768 function calls 2.12 (r9710) LilyPond format: 496,572 function calls 2.12 (r9724) LilyPond format: 511,471 function calls ''' from abjad.tools import scoretools from abjad.tools import sequencetools from abjad.tools import spannertools from abjad.tools import topleveltools voice = scoretools.Voice(200 * scoretools.Note("c'16")) for part in sequencetools.partition_sequence_by_counts( voice[:], [20], cyclic=True, ): beam = spannertools.DuratedComplexBeam() topleveltools.attach(beam, part) return voice
def partition_by_ratio_of_durations(self, ratio): r'''Partition start-positioned payload expression by ratio of durations. Operates in place and returns newly constructed inventory. ''' from experimental.tools import musicexpressiontools element_durations = [ self._get_duration_of_expr(leaf) for leaf in self.elements ] integers = self._durations_to_integers(element_durations) parts = sequencetools.partition_sequence_by_ratio_of_weights( integers, ratio) part_lengths = [len(part) for part in parts] parts = sequencetools.partition_sequence_by_counts( self.elements, part_lengths) durations = [self._get_duration_of_list(part) for part in parts] payload_parts = self._split_payload_at_offsets(durations) start_offsets = mathtools.cumulative_sums(durations)[:-1] start_offsets = [ self.start_offset + start_offset for start_offset in start_offsets ] payload_expressions = \ musicexpressiontools.TimespanScopedSingleContextSetExpressionInventory() for payload_part, start_offset in zip(payload_parts, start_offsets): timespan = timespantools.Timespan(start_offset) payload_expression = type(self)( [], start_offset=timespan.start_offset, voice_name=self.voice_name, ) payload_expression._payload = payload_part payload_expressions.append(payload_expression) return payload_expressions
def partition_by_ratio_of_durations(self, ratio): r'''Partition start-positioned payload expression by ratio of durations. Operates in place and returns newly constructed inventory. ''' from experimental.tools import musicexpressiontools element_durations = [ self._get_duration_of_expr(leaf) for leaf in self.elements] integers = self._durations_to_integers(element_durations) parts = sequencetools.partition_sequence_by_ratio_of_weights( integers, ratio) part_lengths = [len(part) for part in parts] parts = sequencetools.partition_sequence_by_counts( self.elements, part_lengths) durations = [self._get_duration_of_list(part) for part in parts] payload_parts = self._split_payload_at_offsets(durations) start_offsets = mathtools.cumulative_sums(durations)[:-1] start_offsets = [ self.start_offset + start_offset for start_offset in start_offsets] payload_expressions = \ musicexpressiontools.TimespanScopedSingleContextSetExpressionInventory() for payload_part, start_offset in zip(payload_parts, start_offsets): timespan = timespantools.Timespan(start_offset) payload_expression = type(self)( [], start_offset=timespan.start_offset, voice_name=self.voice_name, ) payload_expression._payload = payload_part payload_expressions.append(payload_expression) return payload_expressions
def new(sources): from supriya.tools import synthdeftools from supriya.tools import ugentools flattened_sources = [] for source in sources: if isinstance(source, synthdeftools.UGenArray): flattened_sources.extend(source) else: flattened_sources.append(source) sources = synthdeftools.UGenArray(flattened_sources) summed_sources = [] parts = sequencetools.partition_sequence_by_counts( sources, [4], cyclic=True, overhang=True, ) for part in parts: if len(part) == 4: summed_sources.append(ugentools.Sum4(*part)) elif len(part) == 3: summed_sources.append(ugentools.Sum3(*part)) elif len(part) == 2: summed_sources.append(part[0] + part[1]) else: summed_sources.append(part[0]) if len(summed_sources) == 1: return summed_sources[0] return Mix.new(summed_sources)
def _burnish_all_division_parts(self, divisions, quintuplet): lefts, middles, rights, left_lengths, right_lengths=quintuplet lefts_index, rights_index = 0, 0 burnished_divisions = [] for division_index, division in enumerate(divisions): left_length = left_lengths[division_index] left = lefts[lefts_index:lefts_index+left_length] lefts_index += left_length right_length = right_lengths[division_index] right = rights[rights_index:rights_index+right_length] rights_index += right_length available_left_length = len(division) left_length = min([left_length, available_left_length]) available_right_length = len(division) - left_length right_length = min([right_length, available_right_length]) middle_length = len(division) - left_length - right_length left = left[:left_length] middle = middle_length * [middles[division_index]] right = right[:right_length] left_part, middle_part, right_part = \ sequencetools.partition_sequence_by_counts( division, [left_length, middle_length, right_length], cyclic=False, overhang=False, ) left_part = self._burnish_division_part(left_part, left) middle_part = self._burnish_division_part(middle_part, middle) right_part = self._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 make_spanner_score_03(self): r'''Make 200-note voice with durated complex beam spanner on every 100 notes. :: 2.12 (r9710) initialization: 251,606 function calls 2.12 (r9724) initialization: 249,369 function calls 2.12 (r9703) LilyPond format: 509,752 function calls 2.12 (r9710) LilyPond format: 510,556 function calls 2.12 (r9724) LilyPond format: 525,463 function calls ''' from abjad.tools import scoretools from abjad.tools import sequencetools from abjad.tools import spannertools from abjad.tools import topleveltools voice = scoretools.Voice(200 * scoretools.Note("c'16")) for part in sequencetools.partition_sequence_by_counts( voice[:], [100], cyclic=True, ): beam = spannertools.DuratedComplexBeam() topleveltools.attach(beam, part) return voice
def make_hairpin_score_03(self): r'''Make 200-note voice with crescendo spanner on every 100 notes. :: 2.12 (r9726) initialization: 249,363 function calls 2.12 (r9726) initialization: 249,363 function calls 2.12 (r9726) LilyPond format: 133,898 function calls 2.12 (r9728) LilyPond format: 128,948 function calls ''' from abjad.tools import scoretools from abjad.tools import sequencetools from abjad.tools import spannertools from abjad.tools import topleveltools voice = scoretools.Voice(200 * scoretools.Note("c'16")) for part in sequencetools.partition_sequence_by_counts( voice[:], [100], cyclic=True, ): crescendo = spannertools.Crescendo() topleveltools.attach(crescendo, part) return voice
def make_spanner_score_01(self): r'''Make 200-note voice with durated complex beam spanner on every 4 notes. :: 2.12 (r9710) initialization: 248,654 function calls 2.12 (r9724) initialization: 248,660 function calls 2.12 (r9703) LilyPond format: 425,848 function calls 2.12 (r9710) LilyPond format: 426,652 function calls 2.12 (r9724) LilyPond format: 441,884 function calls ''' from abjad.tools import scoretools from abjad.tools import sequencetools from abjad.tools import spannertools from abjad.tools import topleveltools voice = scoretools.Voice(200 * scoretools.Note("c'16")) for part in sequencetools.partition_sequence_by_counts( voice[:], [4], cyclic=True, ): beam = spannertools.DuratedComplexBeam() topleveltools.attach(beam, part) return voice
def make_bound_hairpin_score_03(self): r'''Make 200-note voice with p-to-f bound crescendo spanner on every 100 notes. :: 2.12 (r9726) initialization: 267,417 function calls 2.12 (r9726) LilyPond format: 116,534 function calls ''' from abjad.tools import indicatortools from abjad.tools import scoretools from abjad.tools import sequencetools from abjad.tools import spannertools from abjad.tools import topleveltools voice = scoretools.Voice(200 * scoretools.Note("c'16")) for part in sequencetools.partition_sequence_by_counts( voice[:], [100], cyclic=True, ): crescendo = spannertools.Crescendo() topleveltools.attach(crescendo, part) dynamic = indicatortools.Dynamic('p') topleveltools.attach(dynamic, part[0]) dynamic = indicatortools.Dynamic('r') topleveltools.attach(dynamic, part[-1]) return voice
def make_score_with_indicators_01(self): r'''Make 200-note voice with dynamic on every 20th note: :: 2.12 (r9704) initialization: 630,433 function calls 2.12 (r9710) initialization: 235,120 function calls 2.12 r(9726) initialization: 235,126 function calls 2.12 (r9704) LilyPond format: 136,637 function calls 2.12 (r9710) LilyPond format: 82,730 function calls 2.12 (r9726) LilyPond format: 88,382 function calls ''' from abjad.tools import indicatortools from abjad.tools import scoretools from abjad.tools import sequencetools from abjad.tools import topleveltools staff = scoretools.Staff(200 * scoretools.Note("c'16")) for part in sequencetools.partition_sequence_by_counts( staff[:], [20], cyclic=True, ): dynamic = indicatortools.Dynamic('f') topleveltools.attach(dynamic, part[0]) return staff
def make_score_with_indicators_02(self): r'''Make 200-note staff with dynamic on every 4th note. :: 2.12 (r9704) initialization: 4,632,761 function calls 2.12 (r9710) initialization: 327,280 function calls 2.12 (r9726) initialization: 325,371 function calls 2.12 (r9704) LilyPond format: 220,277 function calls 2.12 (r9710) LilyPond format: 84,530 function calls 2.12 (r9726) LilyPond format: 90,056 function calls ''' from abjad.tools import indicatortools from abjad.tools import scoretools from abjad.tools import sequencetools from abjad.tools import topleveltools staff = scoretools.Staff(200 * scoretools.Note("c'16")) for part in sequencetools.partition_sequence_by_counts( staff[:], [4], cyclic=True, ): dynamic = indicatortools.Dynamic('f') topleveltools.attach(dynamic, part[0]) return staff
def partition_sequence_by_ratio_of_lengths(sequence, lengths): '''Partitions `sequence` by ratio of `lengths`. :: >>> sequence = tuple(range(10)) :: >>> sequencetools.partition_sequence_by_ratio_of_lengths( ... sequence, ... [1, 1, 2], ... ) [(0, 1, 2), (3, 4), (5, 6, 7, 8, 9)] Uses rounding magic to avoid fractional part lengths. Returns list of `sequence` objects. ''' from abjad.tools import sequencetools lengths = mathtools.partition_integer_by_ratio(len(sequence), lengths) return sequencetools.partition_sequence_by_counts( sequence, lengths, cyclic=False, overhang=False, )
def format_datagram(cls, datagram): result = [] result.append('size {}'.format(len(datagram))) index = 0 while index < len(datagram): chunk = datagram[index:index + 16] line = '{: >4} '.format(index) hex_blocks = [] ascii_block = '' for chunk in sequencetools.partition_sequence_by_counts( chunk, [4], cyclic=True): hex_block = [] for byte in chunk: char = int(byte) if 31 < char < 127: char = chr(char) else: char = '.' ascii_block += char hexed = hex(byte)[2:].zfill(2) hex_block.append(hexed) hex_block = ' '.join(hex_block) hex_blocks.append(hex_block) hex_blocks = ' '.join(hex_blocks) ascii_block = '|{}|'.format(ascii_block) hex_blocks = '{: <53}'.format(hex_blocks) line += hex_blocks line += ascii_block result.append(line) index += 16 result = '\n'.join(result) return result
def __call__(self, expr): r'''Calls retrogression on `expr`. .. container:: example **Example 1.** Retrograde pitch classes. :: >>> operator_ = pitchtools.Retrogression() >>> pitch_classes = pitchtools.PitchClassSegment([0, 1, 4, 7]) >>> operator_(pitch_classes) PitchClassSegment([7, 4, 1, 0]) .. container:: example **Example 2.** Does not retrograde single pitches or pitch-classes. :: >>> operator_ = pitchtools.Retrogression() >>> pitch_class = pitchtools.NumberedPitchClass(6) >>> operator_(pitch_class) NumberedPitchClass(6) .. container:: example **Example 3.** Periodic retrogression. :: >>> operator_ = pitchtools.Retrogression(period=3) >>> pitches = pitchtools.PitchSegment("c' d' e' f' g' a' b' c''") >>> operator_(pitches) PitchSegment(["e'", "d'", "c'", "a'", "g'", "f'", "c''", "b'"]) Returns new object with type equal to that of `expr`. ''' from abjad.tools import pitchtools if isinstance(expr, (pitchtools.Pitch, pitchtools.PitchClass)): return expr if not isinstance(expr, ( pitchtools.PitchSegment, pitchtools.PitchClassSegment, )): expr = pitchtools.PitchSegment(expr) if not self.period: return type(expr)(reversed(expr)) result = new(expr, items=()) for shard in sequencetools.partition_sequence_by_counts( expr, [self.period], cyclic=True, overhang=True, ): shard = type(expr)(shard) shard = type(expr)(reversed(shard)) result = result + shard return result
def __call__(self, logical_ties, timespan=None, offset=0): r'''Calls note and chord hairpin handler on `logical_ties` with `offset`. Returns none. ''' 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)): new_groups = [] for group in groups: leaves = iterate(group).by_class(scoretools.Leaf) leaves = list(leaves) shards = sequencetools.partition_sequence_by_counts( leaves, counts=self.span, cyclic=True, ) new_groups.extend(shards) groups = new_groups groups = [[_] for _ in groups] 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 (len(notes_to_span) == 1 and not self.attach_start_dynamic_to_lone_notes): continue if (len(notes_to_span) == 1 and self.attach_start_dynamic_to_lone_notes): hairpin_token = self.hairpin_token[group_index] start_dynamic = hairpin_token[0] dynamic = indicatortools.Dynamic(start_dynamic) attach(dynamic, notes[0]) continue hairpin_token = self.hairpin_token[group_index] descriptor = ' '.join([_ for _ in hairpin_token if _]) hairpin = spannertools.Hairpin( descriptor=descriptor, include_rests=False, ) attach(hairpin, notes_to_span)
def _handle_input_levels(self, message): contents = message.contents[2:] peak_levels = [] rms_levels = [] for peak, rms in sequencetools.partition_sequence_by_counts( contents, counts=[2], cyclic=True): peak_levels.append(peak) rms_levels.append(rms) self._input_meter_peak_levels = tuple(peak_levels) self._input_meter_rms_levels = tuple(rms_levels)
def partition_sequence_by_ratio_of_lengths(sequence, ratio): '''Partitions `sequence` by `ratio` of lengths. .. container:: example **Example 1.** Partitions sequence by ``1:1:1`` ratio: :: >>> sequence = list(range(10)) >>> sequencetools.partition_sequence_by_ratio_of_lengths( ... sequence, ... [1, 1, 1], ... ) [[0, 1, 2], [3, 4, 5, 6], [7, 8, 9]] Returns list of lists. .. container:: example **Example 2.** Partitions sequence by ``1:1:2`` ratio: :: >>> sequence = tuple(range(10)) >>> sequencetools.partition_sequence_by_ratio_of_lengths( ... sequence, ... [1, 1, 2], ... ) [(0, 1, 2), (3, 4), (5, 6, 7, 8, 9)] Returns list of tuples. Uses the rounding magic implemented in ``mathtools.partition_integer_by_ratio()`` to avoid fractional part lengths. Returns list of `sequence` objects. ''' from abjad.tools import sequencetools if sequence is None: callback = sequencetools.PartitionByRatioOfLengthsCallback( ratio=ratio, ) return callback ratio = mathtools.Ratio(ratio) counts = mathtools.partition_integer_by_ratio(len(sequence), ratio) return sequencetools.partition_sequence_by_counts( sequence, counts, cyclic=False, overhang=Exact, )
def partition_by_ratio_of_durations(self, ratio): r'''Partition payload expression by ratio of durations. :: >>> result = \ ... payload_expression.partition_by_ratio_of_durations((1, 1)) :: >>> for element in result: ... print(format(element)) musicexpressiontools.IterablePayloadExpression( payload=( (4, 16), ), ) musicexpressiontools.IterablePayloadExpression( payload=( (2, 16), ), ) Returns newly constructed payload expression. ''' element_durations = [self._duration_helper(x) for x in self.payload] element_tokens = self._durations_to_integers(element_durations) token_parts = sequencetools.partition_sequence_by_ratio_of_weights( element_tokens, ratio) part_lengths = [len(x) for x in token_parts] duration_parts = sequencetools.partition_sequence_by_counts( element_durations, part_lengths) element_parts = sequencetools.partition_sequence_by_counts( self.payload, part_lengths) result = [] for part in element_parts: part = new(self, payload=part) result.append(part) return result
def __str__(self): r'''Gets string representation of OSC object. :: size 164 0 2f 64 5f 72 65 63 76 00 2c 62 62 00 00 00 00 6b |/d_recv.,bb....k| 16 53 43 67 66 00 00 00 02 00 01 04 74 65 73 74 00 |SCgf.......test.| 32 00 00 02 43 dc 00 00 00 00 00 00 00 00 00 00 00 |...C............| 48 00 00 00 00 00 00 02 06 53 69 6e 4f 73 63 02 00 |........SinOsc..| 64 00 00 02 00 00 00 01 00 00 ff ff ff ff 00 00 00 |................| 80 00 ff ff ff ff 00 00 00 01 02 03 4f 75 74 02 00 |...........Out..| 96 00 00 02 00 00 00 00 00 00 ff ff ff ff 00 00 00 |................| 112 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 24 |...............$| 128 2f 73 5f 6e 65 77 00 00 2c 73 69 69 69 00 00 00 |/s_new..,siii...| 144 74 65 73 74 00 00 00 00 00 00 03 e9 00 00 00 00 |test............| 160 00 00 00 01 |....| ''' datagram = bytearray(self.to_datagram()) result = [] result.append('size {}'.format(len(datagram))) index = 0 while index < len(datagram): chunk = datagram[index:index + 16] line = '{: >4} '.format(index) hex_blocks = [] ascii_block = '' for chunk in sequencetools.partition_sequence_by_counts( chunk, [4], cyclic=True): hex_block = [] for byte in chunk: char = int(byte) if 31 < char < 127: char = chr(char) else: char = '.' ascii_block += char hexed = hex(byte)[2:].zfill(2) hex_block.append(hexed) hex_block = ' '.join(hex_block) hex_blocks.append(hex_block) hex_blocks = ' '.join(hex_blocks) ascii_block = '|{}|'.format(ascii_block) hex_blocks = '{: <53}'.format(hex_blocks) line += hex_blocks line += ascii_block result.append(line) index += 16 result = '\n'.join(result) return result
def _partition_groups(self, groups): new_groups = [] for group in groups: leaves = iterate(group).by_class(scoretools.Leaf) leaves = list(leaves) shards = sequencetools.partition_sequence_by_counts( leaves, counts=self.span, cyclic=True, ) new_groups.extend(shards) groups = new_groups groups = [[_] for _ in groups] return groups
def _split_at_measure_boundaries( selections, meters, use_messiaen_style_ties=False, ): from abjad.tools import metertools from abjad.tools import scoretools from abjad.tools import sequencetools from abjad.tools.topleveltools import inspect_ from abjad.tools.topleveltools import mutate from abjad.tools.topleveltools import select meters = [metertools.Meter(_) for _ in meters] durations = [durationtools.Duration(_) for _ in meters] selections = sequencetools.flatten_sequence(selections) assert isinstance(selections, list), repr(selections) meter_duration = sum(durations) music_duration = sum(inspect_(_).get_duration() for _ in selections) if not meter_duration == music_duration: message = 'Duration of meters is {!s}' message += ' but duration of selections is {!s}:' message = message.format(meter_duration, music_duration) message += '\nmeters: {}.'.format(meters) message += '\nmusic: {}.'.format(selections) raise Exception(message) voice = scoretools.Voice(selections) mutate(voice[:]).split( durations=durations, tie_split_notes=True, use_messiaen_style_ties=use_messiaen_style_ties, ) #raise Exception(voice) #selections = list(voice[:]) #return selections components = mutate(voice).eject_contents() component_durations = [inspect_(_).get_duration() for _ in components] parts = sequencetools.partition_sequence_by_weights( component_durations, weights=durations, allow_part_weights=Exact, ) part_lengths = [len(_) for _ in parts] parts = sequencetools.partition_sequence_by_counts( components, counts=part_lengths, overhang=Exact, ) selections = [select(_) for _ in parts] return selections
def partition(meter_list, weights_ratio, tempi): new_meter_list = [int(2 * x) for x in meter_list] assert sum(new_meter_list) == 2 * sum(meter_list) parts = sequencetools.partition_sequence_by_ratio_of_weights( new_meter_list, weights_ratio) counts = [len(x) for x in parts] #parts = sequencetools.partition_sequence_once_by_counts_without_overhang( # meter_list, counts) parts = sequencetools.partition_sequence_by_counts( meter_list, counts, cyclic=False, overhang=False, ) parts = sequencetools.zip_sequences([parts, tempi], cyclic=True) return parts
def _partition_selections(self, music): period = self.division_period or 1 selections = [ select(list(iterate(_).by_leaf())) for _ in music ] parts = sequencetools.partition_sequence_by_counts( selections, [period], cyclic=True, overhang=True) if len(parts[-1]) < period and 1 < len(parts): part = parts.pop() parts[-1].extend(part) selections = [] for part in parts: selection = part[0] for next_selection in part[1:]: selection = selection + next_selection selections.append(selection) return selections
def __call__(self, expr, rotation=None): r'''Calls ratio selector callback on `expr`. Returns tuple of selections. ''' assert isinstance(expr, tuple), repr(expr) assert len(expr) == 1, repr(expr) assert isinstance(expr[0], selectiontools.Selection), repr(expr) selection = expr[0] counts = mathtools.partition_integer_by_ratio( len(selection), self.ratio, ) selections = sequencetools.partition_sequence_by_counts( selection, counts=counts, ) return tuple(selections)
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 _handle_output_levels(self, message): contents = message.contents[2:] peak_levels = [] rms_levels = [] for peak, rms in sequencetools.partition_sequence_by_counts( contents, counts=[2], cyclic=True): peak_levels.append(peak) rms_levels.append(rms) self._output_meter_peak_levels = tuple(peak_levels) self._output_meter_rms_levels = tuple(rms_levels) systemtools.PubSub.notify( 'server-meters', { 'input_meter_peak_levels': self._input_meter_peak_levels, 'input_meter_rms_levels': self._input_meter_rms_levels, 'output_meter_peak_levels': self._output_meter_peak_levels, 'output_meter_rms_levels': self._output_meter_rms_levels, }, )
def partition_to_avoid_octave_adjacencies(l, direction): '''Partition to avoid octave adjacencies. ''' assert direction in ('left', 'right') result = [[]] part = result[-1] for x in l: if not isinstance(x, (int, float, Fraction)): raise ValueError if x % 12 in [y % 12 for y in part]: first_value = [y for y in part if y % 12 == x % 12][0] first_index = part.index(first_value) ## partition current part into left and middle subparts old_part = part[:first_index+1] disputed_part = part[first_index+1:] new_part = [] ## divvy up disputed part left, right = mathtools.partition_integer_into_halves( len(disputed_part), bigger = direction) disputed_parts = sequencetools.partition_sequence_by_counts( disputed_part, [left, right], cyclic=False, overhang=False) left_disputed_part, right_disputed_part = disputed_parts assert len(left_disputed_part) == left assert len(right_disputed_part) == right old_part.extend(left_disputed_part) new_part.extend(right_disputed_part) ## replace last sublist in result with old, trimmed part result[-1] = old_part ## append new part to result result.append(new_part) part = result[-1] part.append(x) result = [tuple(x) for x in result] return result
def _add_ties(self, result): from abjad.tools import selectiontools leaves = list(iterationtools.iterate_leaves_in_expr(result)) written_durations = [leaf.written_duration for leaf in leaves] weights = [durationtools.Duration(numerator, self.talea_denominator) for numerator in self.talea] parts = sequencetools.partition_sequence_by_weights_exactly( written_durations, weights=weights, cyclic=True, overhang=True) counts = [len(part) for part in parts] parts = sequencetools.partition_sequence_by_counts(leaves, counts) spanner_classes = (spannertools.TieSpanner,) for part in parts: part = selectiontools.SliceSelection(part) tie_spanner = spannertools.TieSpanner() # this is voodoo to temporarily neuter the contiguity constraint tie_spanner._contiguity_constraint = None for component in part: for spanner in component._get_spanners( spanner_classes=spanner_classes): spanner.detach() tie_spanner.extend(part)
def __call__(self, expr, rotation=None): r'''Iterates tuple `expr`. Returns tuple in which each item is a selection or component. ''' assert isinstance(expr, tuple), repr(expr) if rotation is None: rotation = 0 rotation = int(rotation) result = [] counts = self.counts if self.rotate: counts = sequencetools.rotate_sequence(counts, -rotation) for subexpr in expr: groups = sequencetools.partition_sequence_by_counts( subexpr, [abs(_) for _ in counts], cyclic=self.cyclic, overhang=self.overhang, ) if self.overhang and self.fuse_overhang and 1 < len(groups): last_count = counts[(len(groups) - 1) % len(counts)] if len(groups[-1]) != last_count: last_group = groups.pop() groups[-1] += last_group subresult = [] for i, group in enumerate(groups): count = counts[i] if count < 0: continue items = selectiontools.Selection(group) subresult.append(items) if self.nonempty and not subresult: group = selectiontools.Selection(groups[0]) subresult.append(group) result.extend(subresult) if self.rotate: counts = sequencetools.rotate_sequence(counts, -1) return tuple(result)
def partition_sequence_extended_to_counts(sequence, counts, overhang=True): """Partition sequence extended to counts. .. container:: example **Example 1.** Partition sequence extended to counts with overhang: :: >>> sequencetools.partition_sequence_extended_to_counts( ... (1, 2, 3, 4), ... (6, 6, 6), ... overhang=True, ... ) [(1, 2, 3, 4, 1, 2), (3, 4, 1, 2, 3, 4), (1, 2, 3, 4, 1, 2), (3, 4)] .. container:: example **Example 2.** Partition sequence extended to coutns without overhang: :: >>> sequencetools.partition_sequence_extended_to_counts( ... (1, 2, 3, 4), ... (6, 6, 6), ... overhang=False, ... ) [(1, 2, 3, 4, 1, 2), (3, 4, 1, 2, 3, 4), (1, 2, 3, 4, 1, 2)] Returns sequence of sequence objects. """ from abjad.tools import sequencetools n = int(math.ceil(float(sum(counts)) / len(sequence))) sequence = sequencetools.repeat_sequence_n_times(sequence, n) return sequencetools.partition_sequence_by_counts(sequence, counts, cyclic=False, overhang=overhang)
def make_spanner_score_05(self): r'''Make 200-note voice with slur spanner on every 20 notes. :: 2.12 (r9724) initialization: 248,567 function calls 2.12 (r9703) LilyPond format: 122,177 function calls 2.12 (r9724) LilyPond format: 107,486 function calls ''' from abjad.tools import scoretools from abjad.tools import sequencetools from abjad.tools import spannertools from abjad.tools import topleveltools voice = scoretools.Voice(200 * scoretools.Note("c'16")) for part in sequencetools.partition_sequence_by_counts( voice[:], [20], cyclic=True, ): slur = spannertools.Slur() topleveltools.attach(slur, part) return voice
def make_spanner_score_09(self): r'''Make 200-note voice with (vanilla) beam spanner on every 100 notes. :: 2.12 (r9724) initialization: 249,339 function calls 2.12 (r9703) LilyPond format: 121,497 function calls 2.12 (r9724) LilyPond format: 128,494 function calls ''' from abjad.tools import scoretools from abjad.tools import sequencetools from abjad.tools import spannertools from abjad.tools import topleveltools voice = scoretools.Voice(200 * scoretools.Note("c'16")) for part in sequencetools.partition_sequence_by_counts( voice[:], [100], cyclic=True, ): beam = spannertools.Beam() topleveltools.attach(beam, part) return voice
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 __call__(self, divisions=None): r'''Calls fuse-by-counts division callback. .. container:: example **Example 1.** Returns divisions unfused: :: >>> division_maker = makertools.DivisionMaker() >>> division_maker = division_maker.fuse_by_counts() :: >>> input_divisions = [(2, 8), (2, 8), (4, 8), (4, 8), (2, 4)] >>> divisions = division_maker(input_divisions) >>> divisions [Division(2, 8), Division(2, 8), Division(4, 8), Division(4, 8), Division(2, 4)] :: >>> rhythm_maker = rhythmmakertools.NoteRhythmMaker() >>> music = rhythm_maker(divisions) >>> lilypond_file = rhythmmakertools.make_lilypond_file( ... music, ... divisions, ... time_signatures=input_divisions, ... ) >>> show(lilypond_file) # doctest: +SKIP .. doctest:: >>> staff = rhythm_maker._get_rhythmic_staff(lilypond_file) >>> f(staff) \new RhythmicStaff { { \time 2/8 c'4 } { c'4 } { \time 4/8 c'2 } { c'2 } { \time 2/4 c'2 } } .. container:: example **Example 2.** Fuses divisions two at a time: :: >>> division_maker = makertools.DivisionMaker() >>> division_maker = division_maker.fuse_by_counts( ... counts=[2], ... ) :: >>> input_divisions = [(2, 8), (2, 8), (4, 8), (4, 8), (2, 4)] >>> divisions = division_maker(input_divisions) >>> divisions [Division(4, 8), Division(8, 8), Division(2, 4)] :: >>> rhythm_maker = rhythmmakertools.NoteRhythmMaker() >>> music = rhythm_maker(divisions) >>> lilypond_file = rhythmmakertools.make_lilypond_file( ... music, ... divisions, ... time_signatures=input_divisions, ... ) >>> show(lilypond_file) # doctest: +SKIP .. doctest:: >>> staff = rhythm_maker._get_rhythmic_staff(lilypond_file) >>> f(staff) \new RhythmicStaff { c'2 c'1 c'2 } .. container:: example **Example 3a.** Fuses divisions two at a time. Then splits fused divisions by ``3/16`` durations. Remainders to the right: :: >>> division_maker = makertools.DivisionMaker() >>> division_maker = division_maker.fuse_by_counts( ... counts=[2], ... ) >>> division_maker = division_maker.split_by_durations( ... durations=[Duration(3, 16)], ... remainder=Right, ... ) :: >>> input_divisions = [(2, 8), (2, 8), (4, 8), (4, 8), (2, 4)] >>> division_lists = division_maker(input_divisions) >>> for division_list in division_lists: ... division_list [Division(3, 16), Division(3, 16), Division(1, 8)] [Division(3, 16), Division(3, 16), Division(3, 16), Division(3, 16), Division(3, 16), Division(1, 16)] [Division(3, 16), Division(3, 16), Division(1, 8)] :: >>> rhythm_maker = rhythmmakertools.NoteRhythmMaker() >>> divisions = sequencetools.flatten_sequence(division_lists) >>> music = rhythm_maker(divisions) >>> lilypond_file = rhythmmakertools.make_lilypond_file( ... music, ... divisions, ... time_signatures=input_divisions, ... ) >>> show(lilypond_file) # doctest: +SKIP .. doctest:: >>> staff = rhythm_maker._get_rhythmic_staff(lilypond_file) >>> f(staff) \new RhythmicStaff { c'8. c'8. c'8 c'8. c'8. c'8. c'8. c'8. c'16 c'8. c'8. c'8 } **Example 3b.** Remainders to the left: :: >>> division_maker = makertools.DivisionMaker() >>> division_maker = division_maker.fuse_by_counts( ... counts=[2], ... ) >>> division_maker = division_maker.split_by_durations( ... durations=[Duration(3, 16)], ... remainder=Left, ... ) :: >>> input_divisions = [(2, 8), (2, 8), (4, 8), (4, 8), (2, 4)] >>> division_lists = division_maker(input_divisions) >>> for division_list in division_lists: ... division_list [Division(1, 8), Division(3, 16), Division(3, 16)] [Division(1, 16), Division(3, 16), Division(3, 16), Division(3, 16), Division(3, 16), Division(3, 16)] [Division(1, 8), Division(3, 16), Division(3, 16)] :: >>> rhythm_maker = rhythmmakertools.NoteRhythmMaker() >>> divisions = sequencetools.flatten_sequence(division_lists) >>> music = rhythm_maker(divisions) >>> lilypond_file = rhythmmakertools.make_lilypond_file( ... music, ... divisions, ... time_signatures=input_divisions, ... ) >>> show(lilypond_file) # doctest: +SKIP .. doctest:: >>> staff = rhythm_maker._get_rhythmic_staff(lilypond_file) >>> f(staff) \new RhythmicStaff { c'8 c'8. c'8. c'16 c'8. c'8. c'8. c'8. c'8. c'8 c'8. c'8. } .. container:: example **Example 4.** Fuses all divisions: :: >>> division_maker = makertools.DivisionMaker() >>> division_maker = division_maker.fuse_by_counts( ... counts=mathtools.Infinity, ... ) :: >>> input_divisions = [(2, 8), (2, 8), (4, 8), (4, 8), (2, 4)] >>> divisions = division_maker(input_divisions) >>> divisions [Division(16, 8)] :: >>> rhythm_maker = rhythmmakertools.NoteRhythmMaker() >>> music = rhythm_maker(divisions) >>> lilypond_file = rhythmmakertools.make_lilypond_file( ... music, ... divisions, ... time_signatures=input_divisions, ... ) >>> show(lilypond_file) # doctest: +SKIP .. doctest:: >>> staff = rhythm_maker._get_rhythmic_staff(lilypond_file) >>> f(staff) \new RhythmicStaff { c'\breve } .. container:: example **Example 5a.** Fuses all divisions. Then splits fused divisions by ``3/8`` durations: Remainder at right: :: >>> division_maker = makertools.DivisionMaker() >>> division_maker = division_maker.fuse_by_counts( ... counts=mathtools.Infinity, ... ) >>> division_maker = division_maker.split_by_durations( ... durations=[Duration(3, 16)], ... remainder=Right, ... ) :: >>> input_divisions = [(2, 8), (2, 8), (4, 8), (4, 8), (2, 4)] >>> division_lists = division_maker(input_divisions) >>> for division_list in division_lists: ... division_list [Division(3, 16), Division(3, 16), Division(3, 16), Division(3, 16), Division(3, 16), Division(3, 16), Division(3, 16), Division(3, 16), Division(3, 16), Division(3, 16), Division(1, 8)] :: >>> rhythm_maker = rhythmmakertools.NoteRhythmMaker() >>> divisions = sequencetools.flatten_sequence(division_lists) >>> music = rhythm_maker(divisions) >>> lilypond_file = rhythmmakertools.make_lilypond_file( ... music, ... divisions, ... time_signatures=input_divisions, ... ) >>> show(lilypond_file) # doctest: +SKIP .. doctest:: >>> staff = rhythm_maker._get_rhythmic_staff(lilypond_file) >>> f(staff) \new RhythmicStaff { c'8. c'8. c'8. c'8. c'8. c'8. c'8. c'8. c'8. c'8. c'8 } **Example 5b.** Remainder at left: :: >>> division_maker = makertools.DivisionMaker() >>> division_maker = division_maker.fuse_by_counts( ... counts=mathtools.Infinity, ... ) >>> division_maker = division_maker.split_by_durations( ... durations=[Duration(3, 16)], ... remainder=Left, ... ) :: >>> input_divisions = [(2, 8), (2, 8), (4, 8), (4, 8), (2, 4)] >>> division_lists = division_maker(input_divisions) >>> for division_list in division_lists: ... division_list [Division(1, 8), Division(3, 16), Division(3, 16), Division(3, 16), Division(3, 16), Division(3, 16), Division(3, 16), Division(3, 16), Division(3, 16), Division(3, 16), Division(3, 16)] :: >>> rhythm_maker = rhythmmakertools.NoteRhythmMaker() >>> divisions = sequencetools.flatten_sequence(division_lists) >>> music = rhythm_maker(divisions) >>> lilypond_file = rhythmmakertools.make_lilypond_file( ... music, ... divisions, ... time_signatures=input_divisions, ... ) >>> show(lilypond_file) # doctest: +SKIP .. doctest:: >>> staff = rhythm_maker._get_rhythmic_staff(lilypond_file) >>> f(staff) \new RhythmicStaff { c'8 c'8. c'8. c'8. c'8. c'8. c'8. c'8. c'8. c'8. c'8. } .. container:: example **Example 6.** Empty input: :: >>> input_divisions = [] >>> division_lists = division_maker(input_divisions) >>> for division_list in division_lists: ... division_list Returns list of division lists. ''' divisions = divisions or () divisions = self._coerce_divisions(divisions) if not divisions: pass elif (self.counts == mathtools.Infinity or self.counts == mathtools.Infinity()): divisions = [sum(divisions)] elif self.counts: parts = sequencetools.partition_sequence_by_counts( divisions, self.counts, cyclic=self.cyclic, overhang=True, ) divisions = [sum(_) for _ in parts] divisions = [durationtools.Division(_) for _ in divisions] if self.secondary_division_maker is None: return divisions division_lists = [] for division in divisions: if self.secondary_division_maker is not None: division_list = self.secondary_division_maker([division])[0] else: division_list = [division] division_list = [durationtools.Division(_) for _ in division_list] division_lists.append(division_list) return division_lists
def partition_by_counts(self, counts, cyclic=False, overhang=False): r'''Partitions sequence by `counts`. .. container:: example **Example 1.** Partitions sequence once by counts without overhang: :: >>> sequence_ = Sequence(range(10)) >>> sequence_.partition_by_counts( ... [3], ... cyclic=False, ... overhang=False, ... ) Sequence((Sequence((0, 1, 2)),)) .. container:: example **Example 2.** Partitions sequence once by counts without overhang: :: >>> sequence_ = Sequence(range(16)) >>> sequence_.partition_by_counts( ... [4, 3], ... cyclic=False, ... overhang=False, ... ) Sequence((Sequence((0, 1, 2, 3)), Sequence((4, 5, 6)))) .. container:: example **Example 3.** Partitions sequence cyclically by counts without overhang: :: >>> sequence_ = Sequence(range(10)) >>> sequence_.partition_by_counts( ... [3], ... cyclic=True, ... overhang=False, ... ) Sequence((Sequence((0, 1, 2)), Sequence((3, 4, 5)), Sequence((6, 7, 8)))) .. container:: example **Example 4.** Partitions sequence cyclically by counts without overhang: :: >>> sequence_ = Sequence(range(16)) >>> result = sequence_.partition_by_counts( ... [4, 3], ... cyclic=True, ... overhang=False, ... ) >>> for part in result: ... part Sequence((0, 1, 2, 3)) Sequence((4, 5, 6)) Sequence((7, 8, 9, 10)) Sequence((11, 12, 13)) .. container:: example **Example 5.** Partitions sequence once by counts with overhang: :: >>> sequence_ = Sequence(range(10)) >>> sequence_.partition_by_counts( ... [3], ... cyclic=False, ... overhang=True, ... ) Sequence((Sequence((0, 1, 2)), Sequence((3, 4, 5, 6, 7, 8, 9)))) .. container:: example **Example 6.** Partitions sequence once by counts with overhang: :: >>> sequence_ = Sequence(range(16)) >>> result = sequence_.partition_by_counts( ... [4, 3], ... cyclic=False, ... overhang=True, ... ) >>> for part in result: ... part Sequence((0, 1, 2, 3)) Sequence((4, 5, 6)) Sequence((7, 8, 9, 10, 11, 12, 13, 14, 15)) .. container:: example **Example 7.** Partitions sequence cyclically by counts with overhang: :: >>> sequence_ = Sequence(range(10)) >>> result = sequence_.partition_by_counts( ... [3], ... cyclic=True, ... overhang=True, ... ) >>> for part in result: ... part Sequence((0, 1, 2)) Sequence((3, 4, 5)) Sequence((6, 7, 8)) Sequence((9,)) .. container:: example **Example 8.** Partitions sequence cyclically by counts with overhang: :: >>> sequence_ = Sequence(range(16)) >>> result = sequence_.partition_by_counts( ... [4, 3], ... cyclic=True, ... overhang=True, ... ) >>> for part in result: ... part Sequence((0, 1, 2, 3)) Sequence((4, 5, 6)) Sequence((7, 8, 9, 10)) Sequence((11, 12, 13)) Sequence((14, 15)) .. container:: example **Example 9.** Partitions sequence once by counts and asserts that sequence partitions exactly (with no overhang): :: >>> sequence_ = Sequence(range(10)) >>> sequence_.partition_by_counts( ... [2, 3, 5], ... cyclic=False, ... overhang=Exact, ... ) Sequence((Sequence((0, 1)), Sequence((2, 3, 4)), Sequence((5, 6, 7, 8, 9)))) .. container:: example **Example 10.** Partitions sequence cyclically by counts and asserts that sequence partitions exactly: :: >>> sequence_ = Sequence(range(10)) >>> result = sequence_.partition_by_counts( ... [2], ... cyclic=True, ... overhang=Exact, ... ) >>> for part in result: ... part Sequence((0, 1)) Sequence((2, 3)) Sequence((4, 5)) Sequence((6, 7)) Sequence((8, 9)) Exact partitioning means partitioning with no overhang. .. container:: example **Example 11.** Partitions string: :: >>> sequence_ = Sequence('some text') >>> sequence_.partition_by_counts( ... [3], ... cyclic=False, ... overhang=True, ... ) Sequence((Sequence(('s', 'o', 'm')), Sequence(('e', ' ', 't', 'e', 'x', 't')))) Returns nested sequence. ''' from abjad.tools import sequencetools items = self._items[:] subsequences = [] parts = sequencetools.partition_sequence_by_counts( items, counts, cyclic=cyclic, overhang=overhang, ) parts = [type(self)(_) for _ in parts] sequence = type(self)(parts) return sequence
def make_rhythm_region_expressions_for_voice(self, voice_name): from experimental.tools import musicexpressiontools voice_proxy = \ self.score_specification.voice_data_structures_by_voice[voice_name] division_payload_expressions = \ voice_proxy.payload_expressions_by_attribute['divisions'] voice_proxy = \ self.score_specification.single_context_set_expressions_by_context[voice_name] expressions = \ voice_proxy.timespan_delimited_single_context_set_expressions_by_attribute['rhythm'] timespan_delimited_single_context_rhythm_set_expressions = expressions voice_proxy = \ self.score_specification.voice_data_structures_by_voice[voice_name] voice_division_list = voice_proxy.voice_division_list if not voice_division_list: return [] division_region_durations = \ [x.timespan.duration for x in division_payload_expressions] timespan_delimited_single_context_rhythm_set_expression_durations = [ x.target_timespan.duration for x in timespan_delimited_single_context_rhythm_set_expressions ] assert sum(division_region_durations) == \ sum(timespan_delimited_single_context_rhythm_set_expression_durations) timespan_delimited_single_context_rhythm_set_expression_merged_durations = \ self._merge_duration_sequences( division_region_durations, timespan_delimited_single_context_rhythm_set_expression_durations) # assert that rhythm set expressions cover rhythm regions exactly assert sequencetools.partition_sequence_by_weights( timespan_delimited_single_context_rhythm_set_expression_merged_durations, timespan_delimited_single_context_rhythm_set_expression_durations) rhythm_region_start_division_duration_lists = \ self._partition_sequence_by_backgrounded_weights( voice_division_list.divisions, timespan_delimited_single_context_rhythm_set_expression_merged_durations) #self._debug_values(rhythm_region_start_division_duration_lists, 'rrsddls') assert len(rhythm_region_start_division_duration_lists) == \ len(timespan_delimited_single_context_rhythm_set_expression_merged_durations) rhythm_region_start_division_counts = \ [len(l) for l in rhythm_region_start_division_duration_lists] rhythm_region_division_lists = \ sequencetools.partition_sequence_by_counts( voice_division_list.divisions, rhythm_region_start_division_counts, cyclic=False, overhang=False) rhythm_region_division_lists = [ musicexpressiontools.DivisionList(x, voice_name=voice_name) for x in rhythm_region_division_lists ] assert len(rhythm_region_division_lists) == \ len(timespan_delimited_single_context_rhythm_set_expression_merged_durations) #self._debug_values(rhythm_region_division_lists, 'rrdls') rhythm_region_durations = \ [x.duration for x in rhythm_region_division_lists] #self._debug(rhythm_region_durations, 'rrds') cumulative_sums = \ mathtools.cumulative_sums(rhythm_region_durations) rhythm_region_start_offsets = cumulative_sums[:-1] rhythm_region_start_offsets = \ [durationtools.Offset(x) for x in rhythm_region_start_offsets] timespan_delimited_single_context_rhythm_set_expression_duration_pairs = [ (x, x.target_timespan.duration) for x in timespan_delimited_single_context_rhythm_set_expressions ] merged_duration_timespan_delimited_single_context_rhythm_set_expression_pairs = \ self._pair_duration_sequence_elements_with_input_pair_values( timespan_delimited_single_context_rhythm_set_expression_merged_durations, timespan_delimited_single_context_rhythm_set_expression_duration_pairs) # the first column in pairs is not used for anything further at all is discarded timespan_delimited_single_context_rhythm_set_expressions = [ x[-1] for x in merged_duration_timespan_delimited_single_context_rhythm_set_expression_pairs ] assert len(timespan_delimited_single_context_rhythm_set_expressions) == \ len(rhythm_region_division_lists) rhythm_region_expressions = [] for timespan_delimited_single_context_rhythm_set_expression, \ rhythm_region_start_offset, rhythm_region_division_list in zip( timespan_delimited_single_context_rhythm_set_expressions, rhythm_region_start_offsets, rhythm_region_division_lists): #self._debug(timespan_delimited_single_context_rhythm_set_expression, 'tsscrsx') rhythm_region_expression = \ timespan_delimited_single_context_rhythm_set_expression.evaluate( rhythm_region_division_list, rhythm_region_start_offset, voice_name) rhythm_region_expressions.append(rhythm_region_expression) #self._debug_values(rhythm_region_expressions, 'rrxs') rhythm_region_expressions = \ self.merge_prolonging_rhythm_region_expressions( rhythm_region_expressions) #self._debug_values(rhythm_region_expressions, 'rrxs') return rhythm_region_expressions
def from_score(score, populate=True): r'''Makes pitch array from `score`. .. container:: example **Example 1.** Makes empty pitch array from score: :: >>> score = Score([]) >>> score.append(Staff("c'8 d'8 e'8 f'8")) >>> score.append(Staff("c'4 d'4")) >>> score.append( ... Staff( ... scoretools.FixedDurationTuplet( ... Duration(2, 8), "c'8 d'8 e'8") * 2)) .. doctest:: >>> print(format(score)) \new Score << \new Staff { c'8 d'8 e'8 f'8 } \new Staff { c'4 d'4 } \new Staff { \times 2/3 { c'8 d'8 e'8 } \times 2/3 { c'8 d'8 e'8 } } >> :: >>> show(score) # doctest: +SKIP :: >>> array = pitchtools.PitchArray.from_score( ... score, populate=False) :: >>> print(array) [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] .. container:: example **Example 2.** Makes populated pitch array from `score`: :: >>> score = Score([]) >>> score.append(Staff("c'8 d'8 e'8 f'8")) >>> score.append(Staff("c'4 d'4")) >>> score.append( ... Staff( ... scoretools.FixedDurationTuplet( ... Duration(2, 8), "c'8 d'8 e'8") * 2)) .. doctest:: >>> print(format(score)) \new Score << \new Staff { c'8 d'8 e'8 f'8 } \new Staff { c'4 d'4 } \new Staff { \times 2/3 { c'8 d'8 e'8 } \times 2/3 { c'8 d'8 e'8 } } >> :: >>> show(score) # doctest: +SKIP :: >>> array = pitchtools.PitchArray.from_score( ... score, populate=True) :: >>> print(array) [c' ] [d' ] [e' ] [f' ] [c' ] [d' ] [c'] [d' ] [e'] [c'] [d' ] [e'] Returns pitch array. ''' from abjad.tools import pitchtools from abjad.tools import scoretools time_intervals = \ PitchArray._get_composite_offset_difference_series_from_leaves_in_expr( score) array_width = len(time_intervals) array_depth = len(score) pitch_array = PitchArray(array_depth, array_width) items = scoretools.make_multiplied_quarter_notes( [0], time_intervals) for leaf_iterable, pitch_array_row in \ zip(score, pitch_array.rows): durations = [] for leaf in iterate(leaf_iterable).by_class(scoretools.Leaf): durations.append(leaf._get_duration()) parts = mutate(items).split( durations, cyclic=False, fracture_spanners=False, ) part_lengths = [len(part) for part in parts] cells = pitch_array_row.cells grouped_cells = sequencetools.partition_sequence_by_counts( cells, part_lengths, cyclic=False, overhang=False, ) for group in grouped_cells: pitch_array_row.merge(group) leaves = iterate(leaf_iterable).by_class(scoretools.Leaf) if populate: for cell, leaf in zip(pitch_array_row.cells, leaves): cell.pitches.extend( pitchtools.list_named_pitches_in_expr(leaf)) return pitch_array