def make_unordered_cells_sequence(): result = [] harmonic_walk = sequencetools.flatten_sequence(manifolds.etc.pitch.harmonic_walk) pitch_fields = manifolds.etc.pitch.pitch_fields timeslot_pitch_to_field_cell = \ manifolds.etc.pitch._helpers.timeslot_pitch_to_field_cell len_walk = len(harmonic_walk) len_fields = len(pitch_fields) lcm = mathtools.least_common_multiple(len_walk, len_fields) assert lcm == 120 harmonic_walk = sequencetools.repeat_list_to_length(harmonic_walk, lcm) for timeslot, pitch in enumerate(harmonic_walk): field_cell = timeslot_pitch_to_field_cell(timeslot, Pitch(pitch)) result.append(field_cell) assert len(result) == 120 assert len(sequencetools.flatten_sequence(result)) == 504 return result
def get_segment_desired_duration_in_seconds(self, segment_index, total_seconds): segment_proportions = self[segment_index] segment_total = sum(sequencetools.flatten_sequence( segment_proportions)) ratio = durationtools.Multiplier(segment_total, self.total) desired_duration_in_seconds = ratio * total_seconds return desired_duration_in_seconds
def _make_score( self, rhythm_maker, division_list, score_number_markup, ): lists = rhythm_maker(division_list) music = sequencetools.flatten_sequence(lists) measures = scoretools.make_spacer_skip_measures(division_list) time_signature_context = scoretools.Context( measures, context_name='TimeSignatureContext', name='TimeSignatureContext', ) measures = scoretools.make_spacer_skip_measures(division_list) staff = scoretools.Staff(measures) set_(staff).instrument_name = score_number_markup staff.context_name = 'RhythmicStaff' staff.name = 'Note-entry staff' measures = mutate(staff).replace_measure_contents(music) score = scoretools.Score() score.append(time_signature_context) score.append(staff) self._add_final_bar_line(score) self._check_score(score) return score
def test_scoretools_make_repeated_skips_from_time_signatures_01(): r'''Make repeated rests from list of integer pairs. ''' rests = scoretools.make_repeated_rests_from_time_signatures([(2, 8), (3, 32)]) assert len(rests) == 2 rests = sequencetools.flatten_sequence(rests) staff = Staff(rests) r''' \new Staff { r8 r8 r32 r32 r32 } ''' assert format(staff) == stringtools.normalize( r''' \new Staff { r8 r8 r32 r32 r32 } ''' ) assert inspect_(staff).is_well_formed()
def test_scoretools_make_repeated_rests_from_time_signatures_01(): r'''Make repeated rests from list of integer pairs. ''' rests = scoretools.make_repeated_rests_from_time_signatures( [(2, 8), (3, 32)]) assert len(rests) == 2 rests = sequencetools.flatten_sequence(rests) staff = Staff(rests) r''' \new Staff { r8 r8 r32 r32 r32 } ''' assert systemtools.TestManager.compare( staff, r''' \new Staff { r8 r8 r32 r32 r32 } ''' ) assert inspect_(staff).is_well_formed()
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 meters = [metertools.Meter(_) for _ in meters] durations = [durationtools.Duration(_) for _ in meters] music = sequencetools.flatten_sequence(selections) assert isinstance(music, list), repr(music) total_duration = sum(durations) music_duration = sum(inspect_(_).get_duration() for _ in music) assert total_duration == music_duration voice = scoretools.Voice(music) mutate(voice[:]).split( durations=durations, tie_split_notes=True, use_messiaen_style_ties=use_messiaen_style_ties, ) selections = list(voice[:]) return selections
def _flatten_at_indices_helper(sequence, indices, classes, depth): from abjad.tools import sequencetools if classes is None: classes = (list, tuple) if not isinstance(sequence, classes): raise TypeError() ltype = type(sequence) len_l = len(sequence) indices = [x if 0 <= x else len_l + x for x in indices] result = [] for i, element in enumerate(sequence): if i in indices: try: flattened = sequencetools.flatten_sequence( element, classes=classes, depth=depth, ) result.extend(flattened) except: result.append(element) else: result.append(element) result = ltype(result) return result
def increase_sequence_elements_at_indices_by_addenda(sequence, addenda, indices): '''Increase `sequence` by `addenda` at `indices`: :: >>> sequence = [1, 1, 2, 3, 5, 5, 1, 2, 5, 5, 6] :: >>> sequencetools.increase_sequence_elements_at_indices_by_addenda( ... sequence, [0.5, 0.5], [0, 4, 8]) [1.5, 1.5, 2, 3, 5.5, 5.5, 1, 2, 5.5, 5.5, 6] Returns list. ''' from abjad.tools import sequencetools # assert no overlaps tmp = sequencetools.flatten_sequence([range(i, len(addenda)) for i in indices]) assert len(tmp) == len(set(tmp)) result = sequence[:] for i in indices: for j in range(len(addenda)): result[i+j] += addenda[j] return result
def __init__( self, calculation_rate=None, decay_scale=1, frequency_offset=0, frequency_scale=1, source=None, specifications=None, ): frequencies, amplitudes, decay_times = specifications assert len(frequencies) if not amplitudes: amplitudes = [1.0] * len(frequencies) elif not isinstance(amplitudes, collections.Sequence): amplitudes = [amplitudes] * len(frequencies) if not decay_times: decay_times = [1.0] * len(frequencies) elif not isinstance(decay_times, collections.Sequence): decay_times = [decay_times] * len(frequencies) specifications = sequencetools.zip_sequences( [frequencies, amplitudes, decay_times]) specifications = sequencetools.flatten_sequence(specifications) specifications = tuple(specifications) UGen.__init__( self, calculation_rate=calculation_rate, decay_scale=decay_scale, frequency_offset=frequency_offset, frequency_scale=frequency_scale, source=source, specifications=specifications, )
def to_osc_message(self, with_textual_osc_command=False): if with_textual_osc_command: request_id = self.request_command else: request_id = int(self.request_id) buffer_id = int(self.buffer_id) contents = [ request_id, buffer_id, self.command_name, self.flags, ] if self.command_name in ( 'cheby', 'sine1', ): coefficients = self.amplitudes elif self.command_name == 'sine2': coefficients = zip( self.amplitudes, self.frequencies, ) coefficients = tuple(coefficients) elif self.command_name == 'sine3': coefficients = zip( self.amplitudes, self.frequencies, self.phases, ) coefficients = tuple(coefficients) coefficients = sequencetools.flatten_sequence(coefficients) contents.extend(coefficients) message = osctools.OscMessage(*contents) return message
def _make_score( self, rhythm_maker, division_list, score_number_markup, ): lists = rhythm_maker(division_list) selections = sequencetools.flatten_sequence(lists) measures = scoretools.make_spacer_skip_measures(division_list) time_signature_context = scoretools.Context( measures, context_name='TimeSignatureContext', name='TimeSignatureContext', ) measures = scoretools.make_spacer_skip_measures(division_list) staff = scoretools.Staff(measures) set_(staff).instrument_name = score_number_markup staff.context_name = 'RhythmicStaff' staff.name = 'Note-entry staff' measures = mutate(staff).replace_measure_contents(selections) score = scoretools.Score() score.append(time_signature_context) score.append(staff) self._add_final_bar_line(score) self._check_score(score) return score
def _make_secondary_divisions( self, divisions, split_divisions_by_counts, ): if not split_divisions_by_counts: return divisions[:] numerators = [ division.numerator for division in divisions ] secondary_numerators = sequencetools.split_sequence( numerators, split_divisions_by_counts, cyclic=True, overhang=True, ) secondary_numerators = \ sequencetools.flatten_sequence(secondary_numerators) denominator = divisions[0].denominator secondary_divisions = [ (n, denominator) for n in secondary_numerators ] return secondary_divisions
def __init__( self, divisions=None, instrument=None, name=None, rhythm_maker=None, stages=None, time_signatures=None ): assert(isinstance(instrument, instrumenttools.Instrument)) assert(time_signatures is not None) self.divisions = divisions self._instrument = instrument self._name = name self.rhythm_maker = rhythm_maker if isinstance(stages, int): self.stages = (stages,) else: self._stages = stages self.time_signatures = sequencetools.flatten_sequence(time_signatures) # check that divisions and time signatures are the same duration if self.divisions is not None: divisions_fractions = [Duration(pair) for pair in divisions] divisions_sum = sum(divisions_fractions) time_sigs_fractions = [Duration(pair) for pair in self.time_signatures] time_sigs_sum = sum(time_sigs_fractions) assert divisions_sum == time_sigs_sum
def test_scoretools_make_repeated_skips_from_time_signatures_01(): r'''Make repeated rests from list of integer pairs. ''' rests = scoretools.make_repeated_rests_from_time_signatures([(2, 8), (3, 32)]) assert len(rests) == 2 rests = sequencetools.flatten_sequence(rests) staff = Staff(rests) r''' \new Staff { r8 r8 r32 r32 r32 } ''' assert format(staff) == stringtools.normalize(r''' \new Staff { r8 r8 r32 r32 r32 } ''') assert inspect_(staff).is_well_formed()
def spackle(m, grid, mask): '''Creates subdivision grid under m; subdivides sections in mask. ''' grid = baca.tools.helianthate(grid, 1, 1) grid = sequencetools.repeat_to_length(grid, len(m.leaves)) positions = [range(x[0], x[1] + 1) for x in mask] sequencetools.flatten_sequence(positions) positions = [ pair[-1] if pair[0] in positions else 0 for pair in enumerate(grid) ] #sekka.etc.transforms.subdivide(m, positions) baca.tools.abjad_subdivide(m, positions)
def test_notetools_make_repeated_notes_from_time_signatures_01(): r'''Make repeated notes from list of integer pairs. ''' notes = notetools.make_repeated_notes_from_time_signatures([(2, 8), (3, 32)], pitch = "d''") assert len(notes) == 2 notes = sequencetools.flatten_sequence(notes) staff = Staff(notes) r''' \new Staff { d''8 d''8 d''32 d''32 d''32 } ''' assert testtools.compare( staff, r''' \new Staff { d''8 d''8 d''32 d''32 d''32 } ''' ) assert inspect(staff).is_well_formed()
def test_rhythmmakertools_OutputIncisedRestRhythmMaker_03(): prefix_talea, prefix_lengths = [], [0] suffix_talea, suffix_lengths = [], [0] talea_denominator = 4 maker = rhythmmakertools.OutputIncisedRestRhythmMaker( prefix_talea, prefix_lengths, suffix_talea, suffix_lengths, talea_denominator) divisions = [(5, 8), (5, 8), (5, 8)] leaf_lists = maker(divisions) leaves = sequencetools.flatten_sequence(leaf_lists) staff = Staff(measuretools.make_measures_with_full_measure_spacer_skips(divisions)) measuretools.replace_contents_of_measures_in_expr(staff, leaves) measuretools.set_always_format_time_signature_of_measures_in_expr(staff) r''' \new Staff { { \time 5/8 r2 r8 } { \time 5/8 r2 r8 } { \time 5/8 r2 r8 } } ''' assert testtools.compare( staff, r''' \new Staff { { \time 5/8 r2 r8 } { \time 5/8 r2 r8 } { \time 5/8 r2 r8 } } ''' )
def make_harmonic_walk_sections(): harmonic_walk = manifolds.etc.pitch.harmonic_walk harmonic_walk = sequencetools.flatten_sequence(harmonic_walk) lengths = manifolds.etc.pitch.harmonic_walk_lengths sections = sequencetools.partition_by_lengths(harmonic_walk, lengths) sections = [tuple(x) for x in sections] return sections
def __call__(self, expr): r'''Calls flatten division callback on `expr`. Returns list of divisions or list of division lists. ''' return sequencetools.flatten_sequence( expr, depth=self.depth, )
def __call__(self, expr): r'''Iterates tuple `expr`. .. todo:: Does this always return a tuple of selections? ''' assert isinstance(expr, tuple), repr(tuple) return sequencetools.flatten_sequence( expr, depth=self.depth, )
def make_harmonic_walk(): field_4 = manifolds.etc.pitch.pitch_fields[3] assert field_4 == ( -20, -16, -12, -10, -8, -7, -5, -2, -0.5, 0, 2, 3, 6, 9, 10, 13, 15, 20, 21, 25, 29, 30, 31) ## later dubbed 'polar values' walk = [ 13, 15, 21, 10, -12, -10, -0.5, -8, -7, 6, -2, 2, 3, 0, 9, -16, 29, -5, 30, -20, 20, 31, 25 ] assert tuple(sorted(walk)) == field_4 ''' for i in range(1, 16): divisors = mathtools.divisors(16 * i) z_divisors = [x for x in divisors if not 16 in mathtools.divisors(x)] print '%s\t%s\t%s' % (i, 16 * i, z_divisors) 1 16 [1, 2, 4, 8] 2 32 [1, 2, 4, 8] 3 48 [1, 2, 3, 4, 6, 8, 12, 24] 4 64 [1, 2, 4, 8] 5 80 [1, 2, 4, 5, 8, 10, 20, 40] 6 96 [1, 2, 3, 4, 6, 8, 12, 24] 7 112 [1, 2, 4, 7, 8, 14, 28, 56] 8 128 [1, 2, 4, 8] 9 144 [1, 2, 3, 4, 6, 8, 9, 12, 18, 24, 36, 72] 10 160 [1, 2, 4, 5, 8, 10, 20, 40] 11 176 [1, 2, 4, 8, 11, 22, 44, 88] 12 192 [1, 2, 3, 4, 6, 8, 12, 24] 13 208 [1, 2, 4, 8, 13, 26, 52, 104] 14 224 [1, 2, 4, 7, 8, 14, 28, 56] 15 240 [1, 2, 3, 4, 5, 6, 8, 10, 12, 15, 20, 24, 30, 40, 60, 120] ''' indicators = [] for i in range(23): if i % 5 == 0: indicators.append((i, 1, 5)) elif i % 4 == 0: indicators.append((i, 1, 3)) walk = sequencetools.repeat_subruns_to_count(walk, indicators) assert len(walk) == 32 assert len(sequencetools.flatten_sequence(walk)) == 60 return walk
def test_rhythmmakertools_OutputBurnishedTaleaRhythmMaker___call___04(): talea, talea_denominator, prolation_addenda = [1], 8, [] lefts, middles, rights = [-1], [0], [-1] left_lengths, right_lengths = [1], [2] maker = rhythmmakertools.OutputBurnishedTaleaRhythmMaker( talea, talea_denominator, prolation_addenda, lefts, middles, rights, left_lengths, right_lengths) divisions = [(8, 8)] music = maker(divisions) music = sequencetools.flatten_sequence(music) staff = Staff(measuretools.make_measures_with_full_measure_spacer_skips(divisions)) measuretools.replace_contents_of_measures_in_expr(staff, music) r''' \new Staff { { \time 8/8 r8 c'8 c'8 c'8 c'8 c'8 r8 r8 } } ''' assert testtools.compare( staff, r''' \new Staff { { \time 8/8 r8 c'8 c'8 c'8 c'8 c'8 r8 r8 } } ''' )
def make_lilypond_file(music, divisions, implicit_scaling=False): r'''Makes LilyPond file. .. container:: :: >>> maker = rhythmmakertools.EvenRunRhythmMaker(1) >>> divisions = [(3, 4), (4, 8), (1, 4)] >>> music = maker(divisions) >>> lilypond_file = rhythmmakertools.make_lilypond_file( ... music, ... divisions, ... ) >>> show(lilypond_file) # doctest: +SKIP Used in rhythm-maker docs. Returns LilyPond file. ''' assert isinstance(music, list), repr(music) prototype = (selectiontools.Selection, scoretools.Tuplet) assert all(isinstance(x, prototype) for x in music), repr(music) assert isinstance(divisions, (tuple, list)), repr(divisions) score = scoretools.Score() lilypond_file = \ lilypondfiletools.make_floating_time_signature_lilypond_file(score) context = scoretools.Context(context_name='TimeSignatureContext') measures = scoretools.make_spacer_skip_measures( divisions, implicit_scaling=implicit_scaling, ) context.extend(measures) score.append(context) measures = scoretools.make_spacer_skip_measures( divisions, implicit_scaling=implicit_scaling, ) staff = scoretools.Staff(measures) staff.context_name = 'RhythmicStaff' music = sequencetools.flatten_sequence(music) measures = mutate(staff).replace_measure_contents(music) score.append(staff) return lilypond_file
def __init__(self): self.cur_marimba_descent_pitch_index = 0 self.cur_pitch_1_index = 0 self.cur_pitch_2_index = 0 self.cur_sargasso_pitch_index = 0 self.cur_serration_pitch_index = 0 self.cur_white_vocalization_index = 0 self.known_tropes = {} white_vocalizations = baca.tools.helianthate( [['s', 's', 'š'], ['f', 'f', 's', 'š']], 1, 1) white_vocalizations = sequencetools.flatten_sequence( white_vocalizations) white_vocalizations = sequencetools.CyclicTuple(white_vocalizations) self.white_vocalizations = white_vocalizations
def _make_secondary_duration_pairs( self, duration_pairs, secondary_divisions): if not secondary_divisions: return duration_pairs[:] numerators = [duration_pair.numerator for duration_pair in duration_pairs] secondary_numerators = sequencetools.split_sequence_by_weights( numerators, secondary_divisions, cyclic=True, overhang=True) secondary_numerators = \ sequencetools.flatten_sequence(secondary_numerators) denominator = duration_pairs[0].denominator secondary_duration_pairs = \ [(n, denominator) for n in secondary_numerators] return secondary_duration_pairs
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 increase_elements(sequence, addenda, indices=None): '''Increases `sequence` cyclically by `addenda`. .. container:: example Increases elements cyclically by ``10`` and ``-10`` in alternation: :: >>> sequencetools.increase_elements(range(10), [10, -10]) [10, -9, 12, -7, 14, -5, 16, -3, 18, -1] .. container:: example Increases elements by ``0.5`` at indices 0, 4 and 8 and at one element following each: :: >>> sequence = [1, 1, 2, 3, 5, 5, 1, 2, 5, 5, 6] >>> sequencetools.increase_elements( ... sequence, [0.5, 0.5], indices=[0, 4, 8]) [1.5, 1.5, 2, 3, 5.5, 5.5, 1, 2, 5.5, 5.5, 6] Returns list. ''' from abjad.tools import sequencetools prototype = (collections.Sequence, types.GeneratorType) if not isinstance(sequence, prototype): raise TypeError(sequence) if indices is None: result = [] for i, element in enumerate(sequence): new = element + addenda[i % len(addenda)] result.append(new) else: # assert no overlaps tmp = [tuple(range(i, len(addenda))) for i in indices] tmp = sequencetools.flatten_sequence(tmp) assert len(tmp) == len(set(tmp)) result = sequence[:] for i in indices: for j in range(len(addenda)): result[i + j] += addenda[j] return result
def add_division_lists_to_score(self): from experimental.tools import musicexpressiontools for voice in iterate(self.score).by_class(scoretools.Voice): voice_division_list = \ musicexpressiontools.DivisionList([], voice_name=voice.name) voice_proxy = \ self.score_specification.voice_data_structures_by_voice[ voice.name] expressions = \ voice_proxy.payload_expressions_by_attribute['divisions'] divisions = [x.payload.divisions for x in expressions] divisions = sequencetools.flatten_sequence(divisions, depth=1) for division in divisions: division = copy.deepcopy(division) voice_division_list.divisions.append(division) voice_proxy._voice_division_list = voice_division_list
def _gallery_input_block_to_score(self, block): from abjad.tools import sequencetools maker = type(self)(**block.input_) lists = maker(block.divisions) music = sequencetools.flatten_sequence(lists) measures = scoretools.make_spacer_skip_measures(block.divisions) time_signature_context = scoretools.Context( measures, context_name='TimeSignatureContext', name='TimeSignatureContext', ) measures = scoretools.make_spacer_skip_measures(block.divisions) staff = scoretools.RhythmicStaff(measures) measures = mutate(staff).replace_measure_contents(music) score = scoretools.Score() score.append(time_signature_context) score.append(staff) return score
def _make_secondary_divisions( self, divisions, split_divisions_by_counts, ): if not split_divisions_by_counts: return divisions[:] numerators = [division.numerator for division in divisions] secondary_numerators = sequencetools.split_sequence( numerators, split_divisions_by_counts, cyclic=True, overhang=True, ) secondary_numerators = \ sequencetools.flatten_sequence(secondary_numerators) denominator = divisions[0].denominator secondary_divisions = [(n, denominator) for n in secondary_numerators] return secondary_divisions
def register(self, pitch_classes): '''Registers `pitch_classes` by pitch set. .. container:: example :: >>> pitch_set = pitchtools.PitchSet( ... items=[10, 19, 20, 23, 24, 26, 27, 29, 30, 33, 37, 40], ... item_class=pitchtools.NumberedPitch, ... ) >>> pitch_classes = [10, 0, 2, 6, 8, 7, 5, 3, 1, 9, 4, 11] >>> pitches = pitch_set.register(pitch_classes) >>> for pitch in pitches: ... pitch NumberedPitch(10) NumberedPitch(24) NumberedPitch(26) NumberedPitch(30) NumberedPitch(20) NumberedPitch(19) NumberedPitch(29) NumberedPitch(27) NumberedPitch(37) NumberedPitch(33) NumberedPitch(40) NumberedPitch(23) Returns list of zero or more numbered pitches. ''' if isinstance(pitch_classes, list): result = [ [_ for _ in self if _.pitch_number % 12 == pc] for pc in [x % 12 for x in pitch_classes] ] result = sequencetools.flatten_sequence(result) elif isinstance(pitch_classes, int): result = [p for p in pitch_classes if p % 12 == pitch_classes][0] else: message = 'must be pitch-class or list of pitch-classes.' raise TypeError(message) return result
def interlace_sequences(*sequences): '''Interlaces `sequences`. :: >>> k = range(100, 103) >>> l = range(200, 201) >>> m = range(300, 303) >>> n = range(400, 408) >>> sequencetools.interlace_sequences(k, l, m, n) [100, 200, 300, 400, 101, 301, 401, 102, 302, 402, 403, 404, 405, 406, 407] Returns list. ''' from abjad.tools import sequencetools result = sequencetools.zip_sequences(sequences, truncate=False) result = sequencetools.flatten_sequence(result, depth=1) return result
def register_pitch_class_numbers_by_pitch_number_aggregate( pitch_class_numbers, aggregate): '''Register `pitch_class_numbers` by pitch-number `aggregate`: :: >>> pitchtools.register_pitch_class_numbers_by_pitch_number_aggregate( ... [10, 0, 2, 6, 8, 7, 5, 3, 1, 9, 4, 11], ... [10, 19, 20, 23, 24, 26, 27, 29, 30, 33, 37, 40]) [10, 24, 26, 30, 20, 19, 29, 27, 37, 33, 40, 23] Returns list of zero or more pitch numbers. ''' if isinstance(pitch_class_numbers, list): result = [[p for p in aggregate if p % 12 == pc] for pc in [x % 12 for x in pitch_class_numbers]] result = sequencetools.flatten_sequence(result) elif isinstance(pitch_class_numbers, int): result = [p for p in aggregate if p % 12 == pitch_class_numbers][0] else: message = 'must be pitch-class number or list of pitch-class numbers.' raise TypeError(message) return result
def interlace_sequences(sequences): '''Interlaces `sequences`. .. container:: example **Example 1.** Interlaces generators: :: >>> sequences = [] >>> sequences.append(range(100, 103)) >>> sequences.append(range(200, 201)) >>> sequences.append(range(300, 303)) >>> sequences.append(range(400, 408)) >>> sequencetools.interlace_sequences(sequences) [100, 200, 300, 400, 101, 301, 401, 102, 302, 402, 403, 404, 405, 406, 407] .. container:: example **Example 2.** Interlaces tuples: :: >>> sequences = [] >>> sequences.append(tuple(range(100, 103))) >>> sequences.append(tuple(range(200, 201))) >>> sequences.append(tuple(range(300, 303))) >>> sequences.append(tuple(range(400, 408))) >>> sequencetools.interlace_sequences(sequences) [100, 200, 300, 400, 101, 301, 401, 102, 302, 402, 403, 404, 405, 406, 407] .. container:: example **Example 3.** Interlaces lists: :: >>> sequences = [] >>> sequences.append(list(range(100, 103))) >>> sequences.append(list(range(200, 201))) >>> sequences.append(list(range(300, 303))) >>> sequences.append(list(range(400, 408))) >>> sequencetools.interlace_sequences(sequences) [100, 200, 300, 400, 101, 301, 401, 102, 302, 402, 403, 404, 405, 406, 407] .. container:: example **Example 4.** Interlaces strings: :: >>> sequences = [] >>> sequences.append('first') >>> sequences.append('second') >>> sequencetools.interlace_sequences(sequences) ['f', 's', 'i', 'e', 'r', 'c', 's', 'o', 't', 'n', 'd'] Returns list. ''' from abjad.tools import sequencetools for sequence in sequences: if not isinstance(sequence, collections.Iterable): message = 'must be iterable: {!r}.' message = message.format(sequence) raise Exception(message) result = sequencetools.zip_sequences(sequences, truncate=False) result = sequencetools.flatten_sequence(result, depth=1) assert isinstance(result, list), repr(result) return result
def partition_sequence_by_ratio_of_weights(sequence, weights): '''Partitions `sequence` by ratio of `weights`. :: >>> sequencetools.partition_sequence_by_ratio_of_weights( ... [1] * 10, [1, 1, 1]) [[1, 1, 1], [1, 1, 1, 1], [1, 1, 1]] :: >>> sequencetools.partition_sequence_by_ratio_of_weights( ... [1] * 10, [1, 1, 1, 1]) [[1, 1, 1], [1, 1], [1, 1, 1], [1, 1]] :: >>> sequencetools.partition_sequence_by_ratio_of_weights( ... [1] * 10, [2, 2, 3]) [[1, 1, 1], [1, 1, 1], [1, 1, 1, 1]] :: >>> sequencetools.partition_sequence_by_ratio_of_weights( ... [1] * 10, [3, 2, 2]) [[1, 1, 1, 1], [1, 1, 1], [1, 1, 1]] :: >>> sequencetools.partition_sequence_by_ratio_of_weights( ... [1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2], [1, 1]) [[1, 1, 1, 1, 1, 1, 2, 2], [2, 2, 2, 2]] :: >>> sequencetools.partition_sequence_by_ratio_of_weights( ... [1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2], [1, 1, 1]) [[1, 1, 1, 1, 1, 1], [2, 2, 2], [2, 2, 2]] Weights of parts of returned list equal `weights_ratio` proportions with some rounding magic. Returns list of lists. ''' from abjad.tools import sequencetools if not isinstance(sequence, collections.Sequence): message = 'must be sequence: {!r}.' message = message.format(sequence) raise Exception(message) list_weight = mathtools.weight(sequence) weights_parts = mathtools.partition_integer_by_ratio(list_weight, weights) cumulative_weights = mathtools.cumulative_sums(weights_parts, start=None) result = [] sublist = [] result.append(sublist) current_cumulative_weight = cumulative_weights.pop(0) for n in sequence: if not isinstance(n, (int, float, fractions.Fraction)): message = 'must be number: {!r}.' message = message.format(n) raise TypeError(message) sublist.append(n) while current_cumulative_weight <= \ mathtools.weight(sequencetools.flatten_sequence(result)): try: current_cumulative_weight = cumulative_weights.pop(0) sublist = [] result.append(sublist) except IndexError: break return result
def partition_sequence_by_weights( sequence, weights, cyclic=False, overhang=False, allow_part_weights=Exact, ): r'''Partitions `sequence` by `weights` exactly. :: >>> sequence = [3, 3, 3, 3, 4, 4, 4, 4, 5] .. container:: example **Example 1.** Partition sequence once by weights exactly without overhang: :: >>> sequencetools.partition_sequence_by_weights( ... sequence, ... [3, 9], ... cyclic=False, ... overhang=False, ... ) [[3], [3, 3, 3]] .. container:: example **Example 2.** Partition sequence once by weights exactly with overhang: :: >>> sequencetools.partition_sequence_by_weights( ... sequence, ... [3, 9], ... cyclic=False, ... overhang=True, ... ) [[3], [3, 3, 3], [4, 4, 4, 4, 5]] .. container:: example **Example 3.** Partition sequence cyclically by weights exactly without overhang: :: >>> sequencetools.partition_sequence_by_weights( ... sequence, ... [12], ... cyclic=True, ... overhang=False, ... ) [[3, 3, 3, 3], [4, 4, 4]] .. container:: example **Example 4.** Partition sequence cyclically by weights exactly with overhang: :: >>> sequencetools.partition_sequence_by_weights( ... sequence, ... [12], ... cyclic=True, ... overhang=True, ... ) [[3, 3, 3, 3], [4, 4, 4], [4, 5]] :: >>> sequence = [3, 3, 3, 3, 4, 4, 4, 4, 5, 5] .. container:: example **Example 1.** Partition sequence once by weights at most without overhang: :: >>> sequencetools.partition_sequence_by_weights( ... sequence, ... [10, 4], ... cyclic=False, ... overhang=False, ... allow_part_weights=Less, ... ) [[3, 3, 3], [3]] .. container:: example **Example 2.** Partition sequence once by weights at most with overhang: :: >>> sequencetools.partition_sequence_by_weights( ... sequence, ... [10, 4], ... cyclic=False, ... overhang=True, ... allow_part_weights=Less, ... ) [[3, 3, 3], [3], [4, 4, 4, 4, 5, 5]] .. container:: example **Example 3.** Partition sequence cyclically by weights at most without overhang: :: >>> sequencetools.partition_sequence_by_weights( ... sequence, ... [10, 5], ... cyclic=True, ... overhang=False, ... allow_part_weights=Less, ... ) [[3, 3, 3], [3], [4, 4], [4], [4, 5], [5]] .. container:: example **Example 4.** Partition sequence cyclically by weights at most with overhang: :: >>> sequencetools.partition_sequence_by_weights( ... sequence, ... [10, 5], ... cyclic=True, ... overhang=True, ... allow_part_weights=Less, ... ) [[3, 3, 3], [3], [4, 4], [4], [4, 5], [5]] :: >>> sequence = [3, 3, 3, 3, 4, 4, 4, 4, 5, 5] .. container:: example **Example 1.** Partition sequence once by weights at least without overhang: :: >>> sequencetools.partition_sequence_by_weights( ... sequence, ... [10, 4], ... cyclic=False, ... overhang=False, ... allow_part_weights=More, ... ) [[3, 3, 3, 3], [4]] .. container:: example **Example 2.** Partition sequence once by weights at least with overhang: :: >>> sequencetools.partition_sequence_by_weights( ... sequence, ... [10, 4], ... cyclic=False, ... overhang=True, ... allow_part_weights=More, ... ) [[3, 3, 3, 3], [4], [4, 4, 4, 5, 5]] .. container:: example **Example 3.** Partition sequence cyclically by weights at least without overhang: :: >>> sequencetools.partition_sequence_by_weights( ... sequence, ... [10, 4], ... cyclic=True, ... overhang=False, ... allow_part_weights=More, ... ) [[3, 3, 3, 3], [4], [4, 4, 4], [5]] .. container:: example **Example 4.** Partition sequence cyclically by weights at least with overhang: :: >>> sequencetools.partition_sequence_by_weights( ... sequence, ... [10, 4], ... cyclic=True, ... overhang=True, ... allow_part_weights=More, ... ) [[3, 3, 3, 3], [4], [4, 4, 4], [5], [5]] Returns list sequence objects. ''' from abjad.tools import sequencetools if allow_part_weights == Exact: candidate = sequencetools.split_sequence( sequence, weights, cyclic=cyclic, overhang=overhang, ) flattened_candidate = sequencetools.flatten_sequence(candidate) if flattened_candidate == sequence[:len(flattened_candidate)]: return candidate else: message = 'can not partition exactly.' raise Exception(message) elif allow_part_weights == More: if not cyclic: return _partition_sequence_once_by_weights_at_least( sequence, weights, overhang=overhang) else: return _partition_sequence_cyclically_by_weights_at_least( sequence, weights, overhang=overhang) elif allow_part_weights == Less: if not cyclic: return _partition_sequence_once_by_weights_at_most( sequence, weights, overhang=overhang, ) else: return _partition_sequence_cyclically_by_weights_at_most( sequence, weights, overhang=overhang, ) else: message = 'not an ordinal value constant: {!r}.' message = message.format(allow_part_weights) raise ValueError(message)
def _split( self, durations, cyclic=False, fracture_spanners=False, tie_split_notes=True, use_messiaen_style_ties=False, ): from abjad.tools import pitchtools from abjad.tools import selectiontools from abjad.tools import scoretools from abjad.tools import spannertools durations = [durationtools.Duration(x) for x in durations] if cyclic: durations = sequencetools.repeat_sequence_to_weight( durations, self._get_duration()) durations = [durationtools.Duration(x) for x in durations] if sum(durations) < self._get_duration(): last_duration = self._get_duration() - sum(durations) durations.append(last_duration) sequencetools.truncate_sequence( durations, weight=self._get_duration(), ) result = [] leaf_prolation = self._get_parentage(include_self=False).prolation timespan = self._get_timespan() start_offset = timespan.start_offset for duration in durations: new_leaf = copy.copy(self) preprolated_duration = duration / leaf_prolation shard = new_leaf._set_duration( preprolated_duration, use_messiaen_style_ties=use_messiaen_style_ties, ) for x in shard: if isinstance(x, scoretools.Leaf): x_duration = x.written_duration * leaf_prolation else: x_duration = x.multiplied_duration * leaf_prolation stop_offset = x_duration + start_offset x._start_offset = start_offset x._stop_offset = stop_offset x._timespan = timespantools.Timespan( start_offset=start_offset, stop_offset=stop_offset, ) start_offset = stop_offset shard = [x._get_parentage().root for x in shard] result.append(shard) flattened_result = sequencetools.flatten_sequence(result) flattened_result = selectiontools.SliceSelection(flattened_result) prototype = (spannertools.Tie,) parentage = self._get_parentage() if parentage._get_spanners(prototype=prototype): selection = select(flattened_result) for component in selection: # TODO: make top-level detach() work here for spanner in component._get_spanners(prototype): spanner._sever_all_components() #detach(prototype, component) # replace leaf with flattened result selection = selectiontools.SliceSelection(self) parent, start, stop = selection._get_parent_and_start_stop_indices() if parent: parent.__setitem__(slice(start, stop + 1), flattened_result) else: selection._give_dominant_spanners(flattened_result) selection._withdraw_from_crossing_spanners() # fracture spanners if fracture_spanners: first_shard = result[0] for spanner in first_shard[-1]._get_spanners(): index = spanner._index(first_shard[-1]) spanner._fracture(index, direction=Right) last_shard = result[-1] for spanner in last_shard[0]._get_spanners(): index = spanner._index(last_shard[0]) spanner._fracture(index, direction=Left) for middle_shard in result[1:-1]: for spanner in middle_shard[0]._get_spanners(): index = spanner._index(middle_shard[0]) spanner._fracture(index, direction=Left) for spanner in middle_shard[-1]._get_spanners(): index = spanner._index(middle_shard[-1]) spanner._fracture(index, direction=Right) # adjust first leaf first_leaf = flattened_result[0] self._detach_grace_containers(kind='after') # adjust any middle leaves for middle_leaf in flattened_result[1:-1]: middle_leaf._detach_grace_containers(kind='grace') self._detach_grace_containers(kind='after') detach(object, middle_leaf) # adjust last leaf last_leaf = flattened_result[-1] last_leaf._detach_grace_containers(kind='grace') detach(object, last_leaf) # tie split notes, rests and chords as specified if pitchtools.Pitch.is_pitch_carrier(self) and tie_split_notes: flattened_result_leaves = iterate(flattened_result).by_class( scoretools.Leaf) # TODO: implement SliceSelection._attach_tie_spanner_to_leaves() for leaf_pair in sequencetools.iterate_sequence_nwise( flattened_result_leaves): selection = selectiontools.ContiguousSelection(leaf_pair) selection._attach_tie_spanner_to_leaf_pair( use_messiaen_style_ties=use_messiaen_style_ties, ) # return result return result
def make_lilypond_file( selections, divisions, implicit_scaling=None, pitched_staff=None, time_signatures=None, ): r'''Makes LilyPond file. .. container:: **Example 1.** :: >>> maker = rhythmmakertools.EvenRunRhythmMaker(exponent=1) >>> divisions = [(3, 4), (4, 8), (1, 4)] >>> selections = maker(divisions) >>> lilypond_file = rhythmmakertools.make_lilypond_file( ... selections, ... divisions, ... ) >>> show(lilypond_file) # doctest: +SKIP Used in rhythm-maker docs. Returns LilyPond file. ''' assert isinstance(selections, list), repr(selections) prototype = selectiontools.Selection assert all(isinstance(_, prototype) for _ in selections), repr(selections) assert isinstance(divisions, (tuple, list)), repr(divisions) time_signatures = time_signatures or divisions score = scoretools.Score() lilypond_file = \ lilypondfiletools.make_floating_time_signature_lilypond_file(score) context = scoretools.Context(context_name='TimeSignatureContext') measures = scoretools.make_spacer_skip_measures( time_signatures, implicit_scaling=implicit_scaling, ) context.extend(measures) score.append(context) measures = scoretools.make_spacer_skip_measures( time_signatures, implicit_scaling=implicit_scaling, ) if pitched_staff: staff = scoretools.Staff(measures) else: staff = scoretools.Staff(measures, context_name='RhythmicStaff') selections = sequencetools.flatten_sequence(selections) selections_ = copy.deepcopy(selections) try: measures = mutate(staff).replace_measure_contents(selections) except StopIteration: if pitched_staff: staff = scoretools.Staff(selections_) else: staff = scoretools.Staff(selections_, context_name='RhythmicStaff') score.append(staff) return lilypond_file
def pitches(self): r'''Pitches in pitch array. Returns tuple. ''' return sequencetools.flatten_sequence(self.pitches_by_row)
def __graph__(self, **kwargs): r'''Gets Graphviz format of meter. .. container:: example **Example 1.** Graphs ``7/4``: :: >>> meter = metertools.Meter((7, 4)) >>> meter_graph = meter.__graph__() >>> graph(meter_graph) # doctest: +SKIP .. doctest:: >>> print(str(meter_graph)) digraph G { graph [bgcolor=transparent, fontname=Arial, penwidth=2, truecolor=true]; node [fontname=Arial, fontsize=12, penwidth=2]; edge [penwidth=2]; node_0 [label="7/4", shape=triangle]; node_1 [label="3/4", shape=triangle]; node_2 [label="1/4", shape=box]; node_3 [label="1/4", shape=box]; node_4 [label="1/4", shape=box]; node_5 [label="2/4", shape=triangle]; node_6 [label="1/4", shape=box]; node_7 [label="1/4", shape=box]; node_8 [label="2/4", shape=triangle]; node_9 [label="1/4", shape=box]; node_10 [label="1/4", shape=box]; subgraph cluster_cluster_offsets { graph [style=rounded]; node_11_0 [color=white, fillcolor=black, fontcolor=white, fontname="Arial bold", label="{ <f_0_0> 0 | <f_0_1> +++ }", shape=Mrecord, style=filled]; node_11_1 [color=white, fillcolor=black, fontcolor=white, fontname="Arial bold", label="{ <f_0_0> 1/4 | <f_0_1> + }", shape=Mrecord, style=filled]; node_11_2 [color=white, fillcolor=black, fontcolor=white, fontname="Arial bold", label="{ <f_0_0> 1/2 | <f_0_1> + }", shape=Mrecord, style=filled]; node_11_3 [color=white, fillcolor=black, fontcolor=white, fontname="Arial bold", label="{ <f_0_0> 3/4 | <f_0_1> ++ }", shape=Mrecord, style=filled]; node_11_4 [color=white, fillcolor=black, fontcolor=white, fontname="Arial bold", label="{ <f_0_0> 1 | <f_0_1> + }", shape=Mrecord, style=filled]; node_11_5 [color=white, fillcolor=black, fontcolor=white, fontname="Arial bold", label="{ <f_0_0> 5/4 | <f_0_1> ++ }", shape=Mrecord, style=filled]; node_11_6 [color=white, fillcolor=black, fontcolor=white, fontname="Arial bold", label="{ <f_0_0> 3/2 | <f_0_1> + }", shape=Mrecord, style=filled]; node_11_7 [label="{ <f_0_0> 7/4 | <f_0_1> +++ }", shape=Mrecord]; } node_0 -> node_1; node_0 -> node_5; node_0 -> node_8; node_1 -> node_2; node_1 -> node_3; node_1 -> node_4; node_2 -> node_11_0 [style=dotted]; node_2 -> node_11_1 [style=dotted]; node_3 -> node_11_1 [style=dotted]; node_3 -> node_11_2 [style=dotted]; node_4 -> node_11_2 [style=dotted]; node_4 -> node_11_3 [style=dotted]; node_5 -> node_6; node_5 -> node_7; node_6 -> node_11_3 [style=dotted]; node_6 -> node_11_4 [style=dotted]; node_7 -> node_11_4 [style=dotted]; node_7 -> node_11_5 [style=dotted]; node_8 -> node_9; node_8 -> node_10; node_9 -> node_11_5 [style=dotted]; node_9 -> node_11_6 [style=dotted]; node_10 -> node_11_6 [style=dotted]; node_10 -> node_11_7 [style=dotted]; } Returns Graphviz graph. ''' def make_offset_node( offset, leaf_one=None, leaf_two=None, is_last=False, ): if not is_last: offset_node = documentationtools.GraphvizNode(attributes={ 'shape': 'Mrecord', 'style': 'filled', 'color': 'white', 'fontname': 'Arial bold', 'fontcolor': 'white', 'fillcolor': 'black', }, ) else: offset_node = documentationtools.GraphvizNode(attributes={ 'shape': 'Mrecord', }, ) offset_field = documentationtools.GraphvizField( label=str(offset), ) weight_field = documentationtools.GraphvizField(label='+' * offsets[offset], ) group = documentationtools.GraphvizGroup() group.extend([offset_field, weight_field]) offset_node.append(group) offset_subgraph.append(offset_node) leaf_one_node = node_mapping[leaf_one] edge = documentationtools.GraphvizEdge( attributes={'style': 'dotted'}, ) edge.attach(leaf_one_node, offset_node) if leaf_two: leaf_two_node = node_mapping[leaf_two] edge = documentationtools.GraphvizEdge( attributes={'style': 'dotted'}, ) edge.attach(leaf_two_node, offset_node) from abjad.tools import metertools offsets = metertools.MetricAccentKernel.count_offsets_in_expr( sequencetools.flatten_sequence(self.depthwise_offset_inventory)) graph = documentationtools.GraphvizGraph( name='G', attributes={ 'bgcolor': 'transparent', 'fontname': 'Arial', 'penwidth': 2, 'truecolor': True, }, edge_attributes={ 'penwidth': 2, }, node_attributes={ 'fontname': 'Arial', 'fontsize': 12, 'penwidth': 2, }, ) node_mapping = {} for node in self._root_node.nodes: graphviz_node = documentationtools.GraphvizNode() graphviz_node.attributes['label'] = str(node.preprolated_duration) if isinstance(node, rhythmtreetools.RhythmTreeContainer): graphviz_node.attributes['shape'] = 'triangle' else: graphviz_node.attributes['shape'] = 'box' graph.append(graphviz_node) node_mapping[node] = graphviz_node if node.parent is not None: documentationtools.GraphvizEdge().attach( node_mapping[node.parent], node_mapping[node], ) leaves = self._root_node.leaves offset = leaves[0].start_offset offset_subgraph = documentationtools.GraphvizSubgraph( name='cluster_offsets', attributes={ 'style': 'rounded', }, ) graph.append(offset_subgraph) make_offset_node(offset, leaves[0]) for one, two in sequencetools.iterate_sequence_nwise(leaves): offset = one.stop_offset make_offset_node(offset, one, two) offset = leaves[-1].stop_offset make_offset_node(offset, leaves[-1], is_last=True) return graph
def flatten(self, classes=None, depth=-1, indices=None): r'''Flattens sequence. .. container:: example **Example 1.** Flattens sequence completely: :: >>> sequence = Sequence((1, [2, 3, [4]], 5, [6, 7, [8]])) >>> sequence.flatten() Sequence((1, 2, 3, 4, 5, 6, 7, 8)) .. container:: example **Example 2.** Flattens `sequence` to depth ``1``: :: >>> sequence = Sequence((1, [2, 3, [4]], 5, [6, 7, [8]])) >>> sequence.flatten(depth=1) Sequence((1, 2, 3, [4], 5, 6, 7, [8])) .. container:: example **Example 3.** Flattens `sequence` to depth ``2``: :: >>> sequence = Sequence((1, [2, 3, [4]], 5, [6, 7, [8]])) >>> sequence.flatten(depth=2) Sequence((1, 2, 3, 4, 5, 6, 7, 8)) .. container:: example **Example 4.** Flattens `sequence` at `indices`: :: >>> sequence = Sequence((1, [2, 3, [4]], 5, [6, 7, [8]])) >>> sequence.flatten(indices=[3]) Sequence((1, [2, 3, [4]], 5, 6, 7, 8)) .. container:: example **Example 5.** Flattens `sequence` at negative `indices`: :: >>> sequence = Sequence((1, [2, 3, [4]], 5, [6, 7, [8]])) >>> sequence.flatten(indices=[-1]) Sequence((1, [2, 3, [4]], 5, 6, 7, 8)) .. container:: example **Example 6.** Flattens only tuples in `sequence`: :: >>> sequence = Sequence(('ab', 'cd', ('ef', 'gh'), ('ij', 'kl'))) >>> sequence.flatten(classes=(tuple,)) Sequence(('ab', 'cd', 'ef', 'gh', 'ij', 'kl')) Returns new sequence. ''' from abjad.tools import sequencetools items = sequencetools.flatten_sequence( self._items[:], classes=classes, depth=depth, indices=indices, ) result = type(self)(items) return result
def increase_elements(sequence, addenda, indices=None): '''Increases `sequence` cyclically by `addenda`. .. container:: example **Example 1a.** Increases range elements by ``10`` and ``-10`` in alternation: :: >>> sequencetools.increase_elements(range(10), [10, -10]) [10, -9, 12, -7, 14, -5, 16, -3, 18, -1] **Example 1b.** Increases list elements by 10 and -10 in alternation: :: >>> sequencetools.increase_elements(list(range(10)), [10, -10]) [10, -9, 12, -7, 14, -5, 16, -3, 18, -1] **Example 1c.** Increases tuple elements by 10 and -10 in alternation: :: >>> sequencetools.increase_elements(tuple(range(10)), [10, -10]) [10, -9, 12, -7, 14, -5, 16, -3, 18, -1] .. container:: example **Example 2.** Increases pairs of elements by ``0.5`` starting at indices 0, 4, 8: :: >>> sequence = [1, 1, 2, 3, 5, 5, 1, 2, 5, 5, 6] >>> addenda = [0.5, 0.5] >>> indices = [0, 4, 8] >>> sequencetools.increase_elements(sequence, addenda, indices) [1.5, 1.5, 2, 3, 5.5, 5.5, 1, 2, 5.5, 5.5, 6] Returns list. ''' from abjad.tools import sequencetools sequence = list(sequence) if indices is None: result = [] for i, element in enumerate(sequence): new = element + addenda[i % len(addenda)] result.append(new) else: # assert no overlaps tmp = [tuple(range(i, len(addenda))) for i in indices] tmp = sequencetools.flatten_sequence(tmp) assert len(tmp) == len(set(tmp)) result = sequence[:] for i in indices: for j in range(len(addenda)): result[i + j] += addenda[j] assert isinstance(result, list) return result