def _initialize_with_mode_name(self, mode_name): mdi_segment = [] m2 = NamedInterval('m2') M2 = NamedInterval('M2') A2 = NamedInterval('aug2') dorian = [M2, m2, M2, M2, M2, m2, M2] if mode_name == 'dorian': mdi_segment.extend(sequence(dorian).rotate(n=0)) elif mode_name == 'phrygian': mdi_segment.extend(sequence(dorian).rotate(n=-1)) elif mode_name == 'lydian': mdi_segment.extend(sequence(dorian).rotate(n=-2)) elif mode_name == 'mixolydian': mdi_segment.extend(sequence(dorian).rotate(n=-3)) elif mode_name in ('aeolian', 'minor', 'natural minor'): mdi_segment.extend(sequence(dorian).rotate(n=-4)) elif mode_name == 'locrian': mdi_segment.extend(sequence(dorian).rotate(n=-5)) elif mode_name in ('ionian', 'major'): mdi_segment.extend(sequence(dorian).rotate(n=-6)) elif mode_name == 'melodic minor': mdi_segment.extend([M2, m2, M2, M2, M2, M2, m2]) elif mode_name == 'harmonic minor': mdi_segment.extend([M2, m2, M2, M2, m2, A2, m2]) else: message = 'unknown mode name: {!r}.' message = message.format(mode_name) raise ValueError(message) return IntervalSegment( items=mdi_segment, item_class=NamedInterval, )
def _initialize_with_mode_name(self, mode_name): mdi_segment = [] m2 = NamedInterval("m2") M2 = NamedInterval("M2") A2 = NamedInterval("aug2") dorian = [M2, m2, M2, M2, M2, m2, M2] if mode_name == "dorian": mdi_segment.extend(sequence(dorian).rotate(n=0)) elif mode_name == "phrygian": mdi_segment.extend(sequence(dorian).rotate(n=-1)) elif mode_name == "lydian": mdi_segment.extend(sequence(dorian).rotate(n=-2)) elif mode_name == "mixolydian": mdi_segment.extend(sequence(dorian).rotate(n=-3)) elif mode_name in ("aeolian", "minor", "natural minor"): mdi_segment.extend(sequence(dorian).rotate(n=-4)) elif mode_name == "locrian": mdi_segment.extend(sequence(dorian).rotate(n=-5)) elif mode_name in ("ionian", "major"): mdi_segment.extend(sequence(dorian).rotate(n=-6)) elif mode_name == "melodic minor": mdi_segment.extend([M2, m2, M2, M2, M2, M2, m2]) elif mode_name == "harmonic minor": mdi_segment.extend([M2, m2, M2, M2, m2, A2, m2]) else: message = "unknown mode name: {!r}." message = message.format(mode_name) raise ValueError(message) return IntervalSegment(items=mdi_segment, item_class=NamedInterval)
def _fracture_right(self, i): self, left, right = Spanner._fracture_right(self, i) if self.durations: weights = [ inspect(left).duration(), inspect(right).duration(), ] assert sum(self.durations) == sum(weights) split_durations = sequence(self.durations) split_durations = split_durations.split( weights, cyclic=False, overhang=False, ) left_durations, right_durations = split_durations left._durations = left_durations right._durations = right_durations return self, left, right
def _attachment_test_all(self, component_expression): if self._ignore_attachment_test: return True written_pitches = [] if isinstance(component_expression, Component): component_expression = [component_expression] for component in component_expression: if isinstance(component, Note): written_pitches.append(set([component.written_pitch.number])) elif isinstance(component, Chord): numbers = [_.number for _ in component.written_pitches] written_pitches.append(set(numbers)) else: return [ 'Can only tie notes and chords.', f'Not {component!r}.', ] for pair in sequence(written_pitches).nwise(): if not set.intersection(*pair): return [f'Pitch {pair[0]} does not equal pitch {pair[1]}.'] return True
def _split_by_durations( self, durations, cyclic=False, fracture_spanners=False, tie_split_notes=True, repeat_ties=False, ): import abjad durations = [Duration(_) for _ in durations] durations = sequence(durations) leaf_duration = inspect(self).duration() if cyclic: durations = durations.repeat_to_weight(leaf_duration) if sum(durations) < leaf_duration: last_duration = leaf_duration - sum(durations) durations = list(durations) durations.append(last_duration) durations = sequence(durations) durations = durations.truncate(weight=leaf_duration) result_selections = [] # detach grace containers grace_container = self._detach_grace_container() after_grace_container = self._detach_after_grace_container() leaf_prolation = inspect(self).parentage().prolation for duration in durations: new_leaf = copy.copy(self) preprolated_duration = duration / leaf_prolation selection = new_leaf._set_duration( preprolated_duration, repeat_ties=repeat_ties, ) result_selections.append(selection) result_components = sequence(result_selections).flatten(depth=-1) result_components = select(result_components) result_leaves = select(result_components).leaves() assert all(isinstance(_, abjad.Selection) for _ in result_selections) assert all(isinstance(_, Component) for _ in result_components) assert result_leaves.are_leaves() if inspect(self).has_spanner(abjad.Tie): for leaf in result_leaves: detach(abjad.Tie, leaf) # strip result leaves of indicators (other than multipliers) for leaf in result_leaves: multiplier = inspect(leaf).indicator(Multiplier) detach(object, leaf) if multiplier is not None: attach(multiplier, leaf) # replace leaf with flattened result selection = select(self) parent, start, stop = selection._get_parent_and_start_stop_indices() if parent: parent.__setitem__(slice(start, stop + 1), result_components) else: selection._give_dominant_spanners(result_components) selection._withdraw_from_crossing_spanners() # fracture spanners if fracture_spanners: first_selection = result_selections[0] for spanner in inspect(first_selection[-1]).spanners(): index = spanner._index(first_selection[-1]) spanner._fracture(index, direction=enums.Right) last_selection = result_selections[-1] for spanner in inspect(last_selection[0]).spanners(): index = spanner._index(last_selection[0]) spanner._fracture(index, direction=enums.Left) for middle_selection in result_selections[1:-1]: spanners = inspect(middle_selection[0]).spanners() for spanner in spanners: index = spanner._index(middle_selection[0]) spanner._fracture(index, direction=enums.Left) spanners = inspect(middle_selection[-1]).spanners() for spanner in spanners: index = spanner._index(middle_selection[-1]) spanner._fracture(index, direction=enums.Right) # move indicators first_result_leaf = result_leaves[0] last_result_leaf = result_leaves[-1] for indicator in inspect(self).indicators(): if isinstance(indicator, Multiplier): continue detach(indicator, self) direction = getattr(indicator, '_time_orientation', enums.Left) if direction is enums.Left: attach(indicator, first_result_leaf) elif direction == enums.Right: attach(indicator, last_result_leaf) else: raise ValueError(direction) # move grace containers if grace_container is not None: container = grace_container[0] assert isinstance(container, abjad.GraceContainer), repr(container) attach(container, first_result_leaf) if after_grace_container is not None: container = after_grace_container[0] prototype = abjad.AfterGraceContainer assert isinstance(container, prototype), repr(container) attach(container, last_result_leaf) if isinstance(result_components[0], abjad.Tuplet): abjad.mutate(result_components).fuse() # tie split notes if isinstance(self, (abjad.Note, abjad.Chord)) and tie_split_notes: result_leaves._attach_tie_to_leaves(repeat_ties=repeat_ties, ) assert isinstance(result_selections, list), repr(result_selections) assert all(isinstance(_, abjad.Selection) for _ in result_selections) return result_selections
def rhythm( class_, selections, divisions=None, attach_lilypond_voice_commands=None, implicit_scaling=None, pitched_staff=None, simultaneous_selections=None, time_signatures=None, ): r""" Makes rhythm-styled LilyPond file. .. container:: example Makes rhythmic staff: >>> divisions = [(3, 4), (4, 8), (1, 4)] >>> maker = abjad.NoteMaker() >>> selections = [ ... maker(6 * [0], [(1, 8)]), ... maker(8 * [0], [(1, 16)]), ... maker(2 * [0], [(1, 8)]), ... ] >>> for selection in selections: ... abjad.attach(abjad.Beam(), selection[:]) ... >>> lilypond_file = abjad.LilyPondFile.rhythm( ... selections, ... divisions, ... ) >>> abjad.show(lilypond_file) # doctest: +SKIP .. docs:: >>> score = lilypond_file[abjad.Score] >>> abjad.f(score) \new Score << \new GlobalContext { { % measure \time 3/4 s1 * 3/4 } % measure { % measure \time 4/8 s1 * 1/2 } % measure { % measure \time 1/4 s1 * 1/4 } % measure } \new RhythmicStaff { { % measure \time 3/4 c'8 [ c'8 c'8 c'8 c'8 c'8 ] } % measure { % measure \time 4/8 c'16 [ c'16 c'16 c'16 c'16 c'16 c'16 c'16 ] } % measure { % measure \time 1/4 c'8 [ c'8 ] } % measure } >> .. container:: example Set time signatures explicitly: >>> divisions = [(3, 4), (4, 8), (1, 4)] >>> maker = abjad.NoteMaker() >>> selections = [ ... maker(6 * [0], [(1, 8)]), ... maker(8 * [0], [(1, 16)]), ... maker(2 * [0], [(1, 8)]), ... ] >>> for selection in selections: ... abjad.attach(abjad.Beam(), selection[:]) ... >>> lilypond_file = abjad.LilyPondFile.rhythm( ... selections, ... [(6, 8), (4, 8), (2, 8)], ... ) >>> abjad.show(lilypond_file) # doctest: +SKIP .. docs:: >>> score = lilypond_file[abjad.Score] >>> abjad.f(score) \new Score << \new GlobalContext { { % measure \time 6/8 s1 * 3/4 } % measure { % measure \time 4/8 s1 * 1/2 } % measure { % measure \time 2/8 s1 * 1/4 } % measure } \new RhythmicStaff { { % measure \time 6/8 c'8 [ c'8 c'8 c'8 c'8 c'8 ] } % measure { % measure \time 4/8 c'16 [ c'16 c'16 c'16 c'16 c'16 c'16 c'16 ] } % measure { % measure \time 2/8 c'8 [ c'8 ] } % measure } >> .. container:: example Makes pitched staff: >>> divisions = [(3, 4), (4, 8), (1, 4)] >>> maker = abjad.NoteMaker() >>> selections = [ ... maker(6 * [0], [(1, 8)]), ... maker(8 * [0], [(1, 16)]), ... maker(2 * [0], [(1, 8)]), ... ] >>> for selection in selections: ... abjad.attach(abjad.Beam(), selection[:]) ... >>> lilypond_file = abjad.LilyPondFile.rhythm( ... selections, ... divisions, ... pitched_staff=True, ... ) >>> abjad.show(lilypond_file) # doctest: +SKIP .. docs:: >>> abjad.f(lilypond_file[abjad.Score]) \new Score << \new GlobalContext { { % measure \time 3/4 s1 * 3/4 } % measure { % measure \time 4/8 s1 * 1/2 } % measure { % measure \time 1/4 s1 * 1/4 } % measure } \new Staff { { % measure \time 3/4 c'8 [ c'8 c'8 c'8 c'8 c'8 ] } % measure { % measure \time 4/8 c'16 [ c'16 c'16 c'16 c'16 c'16 c'16 c'16 ] } % measure { % measure \time 1/4 c'8 [ c'8 ] } % measure } >> .. container:: example Makes simultaneous voices: >>> divisions = [(3, 4), (4, 8), (1, 4)] >>> maker = abjad.NoteMaker() >>> selections = [ ... maker(6 * [0], [(1, 8)]), ... maker(8 * [0], [(1, 16)]), ... maker(2 * [0], [(1, 8)]), ... ] >>> for selection in selections: ... abjad.attach(abjad.Beam(), selection[:]) ... >>> for note in abjad.iterate(selections).components(abjad.Note): ... note.written_pitch = abjad.NamedPitch("e'") ... >>> selection_1 = selections[0] + selections[1] + selections[2] >>> selections = [ ... maker(12 * [0], [(1, 16)]), ... maker(16 * [0], [(1, 32)]), ... maker(4 * [0], [(1, 16)]), ... ] >>> for selection in selections: ... abjad.attach(abjad.Beam(), selection[:]) ... >>> selection_2 = selections[0] + selections[1] + selections[2] >>> selections = { ... 'Voice 1': selection_1, ... 'Voice 2': selection_2, ... } >>> lilypond_file = abjad.LilyPondFile.rhythm( ... selections, ... divisions, ... ) >>> voice_1 = lilypond_file['Voice 1'] >>> abjad.attach(abjad.LilyPondLiteral(r'\voiceOne'), voice_1) >>> voice_2 = lilypond_file['Voice 2'] >>> abjad.attach(abjad.LilyPondLiteral(r'\voiceTwo'), voice_2) >>> abjad.show(lilypond_file) # doctest: +SKIP .. docs:: >>> abjad.f(lilypond_file[abjad.Score]) \new Score << \new GlobalContext { { % measure \time 3/4 s1 * 3/4 } % measure { % measure \time 4/8 s1 * 1/2 } % measure { % measure \time 1/4 s1 * 1/4 } % measure } \new Staff << \context Voice = "Voice 1" { \voiceOne e'8 [ e'8 e'8 e'8 e'8 e'8 ] e'16 [ e'16 e'16 e'16 e'16 e'16 e'16 e'16 ] e'8 [ e'8 ] } \context Voice = "Voice 2" { \voiceTwo c'16 [ c'16 c'16 c'16 c'16 c'16 c'16 c'16 c'16 c'16 c'16 c'16 ] c'32 [ c'32 c'32 c'32 c'32 c'32 c'32 c'32 c'32 c'32 c'32 c'32 c'32 c'32 c'32 c'32 ] c'16 [ c'16 c'16 c'16 ] } >> >> Returns LilyPond file. """ if isinstance(selections, list): for selection in selections: if not isinstance(selection, Selection): message = f'must be selection: {selection!r}.' raise TypeError(message) elif isinstance(selections, dict): for selection in selections.values(): if not isinstance(selection, Selection): message = f'must be selection: {selection!r}.' raise TypeError(message) else: message = f'must be list or dictionary: {selections!r}.' raise TypeError(message) score = Score() lilypond_file = LilyPondFile.new( score, includes=['default.ily', 'rhythm-maker-docs.ily'], ) if pitched_staff is None: if isinstance(selections, list): selections_ = selections elif isinstance(selections, dict): selections_ = selections.values() else: raise TypeError(selections) for note in iterate(selections_).leaves(Note): if note.written_pitch != NamedPitch("c'"): pitched_staff = True break if isinstance(selections, list): if divisions is None: duration = abjad_inspect(selections).duration() divisions = [duration] time_signatures = time_signatures or divisions maker = MeasureMaker(implicit_scaling=implicit_scaling) measures = maker(time_signatures) if pitched_staff: staff = Staff(measures) else: staff = Staff(measures, lilypond_type='RhythmicStaff') selections = sequence(selections).flatten(depth=-1) selections_ = copy.deepcopy(selections) try: agent = mutate(staff) measures = agent.replace_measure_contents(selections) except StopIteration: if pitched_staff: staff = Staff(selections_) else: staff = Staff( selections_, lilypond_type='RhythmicStaff', ) elif isinstance(selections, dict): voices = [] for voice_name in sorted(selections): selections_ = selections[voice_name] selections_ = sequence(selections_).flatten(depth=-1) selections_ = copy.deepcopy(selections_) voice = Voice(selections_, name=voice_name) if attach_lilypond_voice_commands: voice_name_to_command_string = { 'Voice 1': 'voiceOne', 'Voice 2': 'voiceTwo', 'Voice 3': 'voiceThree', 'Voice 4': 'voiceFour', } command_string = voice_name_to_command_string.get( voice_name, ) if command_string: command = LilyPondLiteral('\\' + command_string) attach(command, voice) voices.append(voice) staff = Staff(voices, is_simultaneous=True) if divisions is None: duration = abjad_inspect(staff).duration() divisions = [duration] else: message = 'must be list or dictionary of selections:' message += f' {selections!r}.' raise TypeError(message) score.append(staff) assert isinstance(divisions, collections.Sequence), repr(divisions) time_signatures = time_signatures or divisions context = Context(lilypond_type='GlobalContext') maker = MeasureMaker(implicit_scaling=implicit_scaling) measures = maker(time_signatures) context.extend(measures) score.insert(0, context) return lilypond_file
def list_related_tempos( self, maximum_numerator=None, maximum_denominator=None, integer_tempos_only=False, ) -> typing.List[typing.Tuple["MetronomeMark", "Ratio"]]: r""" Lists related tempos. .. container:: example Rewrites tempo ``4=58`` by ratios ``n:d`` such that ``1 <= n <= 8`` and ``1 <= d <= 8``. >>> mark = abjad.MetronomeMark((1, 4), 58) >>> pairs = mark.list_related_tempos( ... maximum_numerator=8, ... maximum_denominator=8, ... ) >>> for tempo, ratio in pairs: ... string = f'{tempo!s}\t{ratio!s}' ... print(string) 4=29 1:2 4=33+1/7 4:7 4=34+4/5 3:5 4=36+1/4 5:8 4=38+2/3 2:3 4=41+3/7 5:7 4=43+1/2 3:4 4=46+2/5 4:5 4=48+1/3 5:6 4=49+5/7 6:7 4=50+3/4 7:8 4=58 1:1 4=66+2/7 8:7 4=67+2/3 7:6 4=69+3/5 6:5 4=72+1/2 5:4 4=77+1/3 4:3 4=81+1/5 7:5 4=87 3:2 4=92+4/5 8:5 4=96+2/3 5:3 4=101+1/2 7:4 4=116 2:1 .. container:: example Integer-valued tempos only: >>> mark = abjad.MetronomeMark((1, 4), 58) >>> pairs = mark.list_related_tempos( ... maximum_numerator=16, ... maximum_denominator=16, ... integer_tempos_only=True, ... ) >>> for tempo, ratio in pairs: ... string = f'{tempo!s}\t{ratio!s}' ... print(string) 4=29 1:2 4=58 1:1 4=87 3:2 4=116 2:1 Constrains ratios such that ``1:2 <= n:d <= 2:1``. """ allowable_numerators = range(1, maximum_numerator + 1) allowable_denominators = range(1, maximum_denominator + 1) numbers = [allowable_numerators, allowable_denominators] enumerator = Enumerator(numbers) pairs = enumerator.yield_outer_product() multipliers = [Multiplier(_) for _ in pairs] multipliers = [_ for _ in multipliers if Fraction(1, 2) <= _ <= Fraction(2)] multipliers.sort() multipliers = sequence(multipliers).remove_repeats() pairs = [] for multiplier in multipliers: new_units_per_minute = multiplier * self.units_per_minute if integer_tempos_only and not mathtools.is_integer_equivalent_number( new_units_per_minute ): continue metronome_mark = type(self)( reference_duration=self.reference_duration, units_per_minute=new_units_per_minute, ) ratio = Ratio(multiplier.pair) pair = (metronome_mark, ratio) pairs.append(pair) return pairs
def rhythm( class_, selections, divisions=None, attach_lilypond_voice_commands=None, implicit_scaling=None, pitched_staff=None, simultaneous_selections=None, time_signatures=None, ): r""" Makes rhythm-styled LilyPond file. .. container:: example Makes rhythmic staff: >>> divisions = [(3, 4), (4, 8), (1, 4)] >>> maker = abjad.NoteMaker() >>> selections = [ ... maker(6 * [0], [(1, 8)]), ... maker(8 * [0], [(1, 16)]), ... maker(2 * [0], [(1, 8)]), ... ] >>> for selection in selections: ... abjad.beam(selection[:]) ... >>> lilypond_file = abjad.LilyPondFile.rhythm( ... selections, ... divisions, ... ) >>> abjad.show(lilypond_file) # doctest: +SKIP .. docs:: >>> score = lilypond_file[abjad.Score] >>> abjad.f(score) \new Score << \new GlobalContext { \time 3/4 s1 * 3/4 \time 4/8 s1 * 1/2 \time 1/4 s1 * 1/4 } \new RhythmicStaff { c'8 [ c'8 c'8 c'8 c'8 c'8 ] c'16 [ c'16 c'16 c'16 c'16 c'16 c'16 c'16 ] c'8 [ c'8 ] } >> .. container:: example Set time signatures explicitly: >>> divisions = [(3, 4), (4, 8), (1, 4)] >>> maker = abjad.NoteMaker() >>> selections = [ ... maker(6 * [0], [(1, 8)]), ... maker(8 * [0], [(1, 16)]), ... maker(2 * [0], [(1, 8)]), ... ] >>> for selection in selections: ... abjad.beam(selection[:]) ... >>> lilypond_file = abjad.LilyPondFile.rhythm( ... selections, ... [(6, 8), (4, 8), (2, 8)], ... ) >>> abjad.show(lilypond_file) # doctest: +SKIP .. docs:: >>> score = lilypond_file[abjad.Score] >>> abjad.f(score) \new Score << \new GlobalContext { \time 6/8 s1 * 3/4 \time 4/8 s1 * 1/2 \time 2/8 s1 * 1/4 } \new RhythmicStaff { c'8 [ c'8 c'8 c'8 c'8 c'8 ] c'16 [ c'16 c'16 c'16 c'16 c'16 c'16 c'16 ] c'8 [ c'8 ] } >> .. container:: example Makes pitched staff: >>> divisions = [(3, 4), (4, 8), (1, 4)] >>> maker = abjad.NoteMaker() >>> selections = [ ... maker(6 * [0], [(1, 8)]), ... maker(8 * [0], [(1, 16)]), ... maker(2 * [0], [(1, 8)]), ... ] >>> for selection in selections: ... abjad.beam(selection[:]) ... >>> lilypond_file = abjad.LilyPondFile.rhythm( ... selections, ... divisions, ... pitched_staff=True, ... ) >>> abjad.show(lilypond_file) # doctest: +SKIP .. docs:: >>> abjad.f(lilypond_file[abjad.Score]) \new Score << \new GlobalContext { \time 3/4 s1 * 3/4 \time 4/8 s1 * 1/2 \time 1/4 s1 * 1/4 } \new Staff { c'8 [ c'8 c'8 c'8 c'8 c'8 ] c'16 [ c'16 c'16 c'16 c'16 c'16 c'16 c'16 ] c'8 [ c'8 ] } >> .. container:: example Makes simultaneous voices: >>> divisions = [(3, 4), (4, 8), (1, 4)] >>> maker = abjad.NoteMaker() >>> selections = [ ... maker(6 * [0], [(1, 8)]), ... maker(8 * [0], [(1, 16)]), ... maker(2 * [0], [(1, 8)]), ... ] >>> for selection in selections: ... abjad.beam(selection[:]) ... >>> for note in abjad.iterate(selections).components(abjad.Note): ... note.written_pitch = abjad.NamedPitch("e'") ... >>> selection_1 = selections[0] + selections[1] + selections[2] >>> selections = [ ... maker(12 * [0], [(1, 16)]), ... maker(16 * [0], [(1, 32)]), ... maker(4 * [0], [(1, 16)]), ... ] >>> for selection in selections: ... abjad.beam(selection[:]) ... >>> selection_2 = selections[0] + selections[1] + selections[2] >>> selections = { ... 'Voice_1': selection_1, ... 'Voice_2': selection_2, ... } >>> lilypond_file = abjad.LilyPondFile.rhythm( ... selections, ... divisions, ... ) >>> voice_1 = lilypond_file['Voice_1'] >>> literal = abjad.LilyPondLiteral(r'\voiceOne', "opening") >>> abjad.attach(literal, voice_1) >>> voice_2 = lilypond_file['Voice_2'] >>> literal = abjad.LilyPondLiteral(r'\voiceTwo', "opening") >>> abjad.attach(literal, voice_2) >>> abjad.show(lilypond_file) # doctest: +SKIP .. docs:: >>> abjad.f(lilypond_file[abjad.Score]) \new Score << \new GlobalContext { s1 * 3/4 s1 * 1/2 s1 * 1/4 } \new Staff << \context Voice = "Voice_1" { \voiceOne e'8 [ e'8 e'8 e'8 e'8 e'8 ] e'16 [ e'16 e'16 e'16 e'16 e'16 e'16 e'16 ] e'8 [ e'8 ] } \context Voice = "Voice_2" { \voiceTwo c'16 [ c'16 c'16 c'16 c'16 c'16 c'16 c'16 c'16 c'16 c'16 c'16 ] c'32 [ c'32 c'32 c'32 c'32 c'32 c'32 c'32 c'32 c'32 c'32 c'32 c'32 c'32 c'32 c'32 ] c'16 [ c'16 c'16 c'16 ] } >> >> Returns LilyPond file. """ if isinstance(selections, Selection): pass elif isinstance(selections, list): for selection in selections: if not isinstance(selection, Selection): raise TypeError(f"must be selection: {selection!r}.") elif isinstance(selections, dict): for selection in selections.values(): if not isinstance(selection, Selection): raise TypeError(f"must be selection: {selection!r}.") else: raise TypeError(f"must be list or dictionary: {selections!r}.") score = Score() lilypond_file = LilyPondFile.new( score, includes=["default.ily", "rhythm-maker-docs.ily"] ) if pitched_staff is None: if isinstance(selections, (list, Selection)): selections_ = selections elif isinstance(selections, dict): selections_ = selections.values() else: raise TypeError(selections) for note in select(selections_).notes(): if note.written_pitch != NamedPitch("c'"): pitched_staff = True break chords = select(selections_).chords() if chords: pitched_staff = True if isinstance(selections, (list, Selection)): if divisions is None: duration = abjad_inspect(selections).duration() divisions = [duration] time_signatures = time_signatures or divisions time_signatures = [TimeSignature(_) for _ in time_signatures] if pitched_staff: staff = Staff() else: staff = Staff(lilypond_type="RhythmicStaff") staff.extend(selections) elif isinstance(selections, dict): voices = [] for voice_name in sorted(selections): selections_ = selections[voice_name] selections_ = sequence(selections_).flatten(depth=-1) selections_ = copy.deepcopy(selections_) voice = Voice(selections_, name=voice_name) if attach_lilypond_voice_commands: voice_name_to_command_string = { "Voice_1": "voiceOne", "Voice_2": "voiceTwo", "Voice_3": "voiceThree", "Voice_4": "voiceFour", } command_string = voice_name_to_command_string.get(voice_name) if command_string: command = LilyPondLiteral("\\" + command_string) attach(command, voice) voices.append(voice) staff = Staff(voices, simultaneous=True) if divisions is None: duration = abjad_inspect(staff).duration() divisions = [duration] else: message = "must be list or dictionary of selections:" message += f" {selections!r}." raise TypeError(message) score.append(staff) assert isinstance(divisions, collections.abc.Sequence), repr(divisions) time_signatures = time_signatures or divisions context = Context(lilypond_type="GlobalContext") skips = [] for time_signature in time_signatures: skip = Skip(1) skip.multiplier = time_signature attach(time_signature, skip, context="Score") skips.append(skip) context.extend(skips) score.insert(0, context) return lilypond_file
def rhythm( class_, selections, divisions=None, attach_lilypond_voice_commands=None, implicit_scaling=None, pitched_staff=None, simultaneous_selections=None, time_signatures=None, ): r""" Makes rhythm-styled LilyPond file. .. container:: example Makes rhythmic staff: >>> divisions = [(3, 4), (4, 8), (1, 4)] >>> maker = abjad.NoteMaker() >>> selections = [ ... maker(6 * [0], [(1, 8)]), ... maker(8 * [0], [(1, 16)]), ... maker(2 * [0], [(1, 8)]), ... ] >>> for selection in selections: ... abjad.beam(selection[:]) ... >>> lilypond_file = abjad.LilyPondFile.rhythm( ... selections, ... divisions, ... ) >>> abjad.show(lilypond_file) # doctest: +SKIP .. docs:: >>> score = lilypond_file[abjad.Score] >>> abjad.f(score) \new Score << \new GlobalContext { \time 3/4 s1 * 3/4 \time 4/8 s1 * 1/2 \time 1/4 s1 * 1/4 } \new RhythmicStaff { c'8 [ c'8 c'8 c'8 c'8 c'8 ] c'16 [ c'16 c'16 c'16 c'16 c'16 c'16 c'16 ] c'8 [ c'8 ] } >> .. container:: example Set time signatures explicitly: >>> divisions = [(3, 4), (4, 8), (1, 4)] >>> maker = abjad.NoteMaker() >>> selections = [ ... maker(6 * [0], [(1, 8)]), ... maker(8 * [0], [(1, 16)]), ... maker(2 * [0], [(1, 8)]), ... ] >>> for selection in selections: ... abjad.beam(selection[:]) ... >>> lilypond_file = abjad.LilyPondFile.rhythm( ... selections, ... [(6, 8), (4, 8), (2, 8)], ... ) >>> abjad.show(lilypond_file) # doctest: +SKIP .. docs:: >>> score = lilypond_file[abjad.Score] >>> abjad.f(score) \new Score << \new GlobalContext { \time 6/8 s1 * 3/4 \time 4/8 s1 * 1/2 \time 2/8 s1 * 1/4 } \new RhythmicStaff { c'8 [ c'8 c'8 c'8 c'8 c'8 ] c'16 [ c'16 c'16 c'16 c'16 c'16 c'16 c'16 ] c'8 [ c'8 ] } >> .. container:: example Makes pitched staff: >>> divisions = [(3, 4), (4, 8), (1, 4)] >>> maker = abjad.NoteMaker() >>> selections = [ ... maker(6 * [0], [(1, 8)]), ... maker(8 * [0], [(1, 16)]), ... maker(2 * [0], [(1, 8)]), ... ] >>> for selection in selections: ... abjad.beam(selection[:]) ... >>> lilypond_file = abjad.LilyPondFile.rhythm( ... selections, ... divisions, ... pitched_staff=True, ... ) >>> abjad.show(lilypond_file) # doctest: +SKIP .. docs:: >>> abjad.f(lilypond_file[abjad.Score]) \new Score << \new GlobalContext { \time 3/4 s1 * 3/4 \time 4/8 s1 * 1/2 \time 1/4 s1 * 1/4 } \new Staff { c'8 [ c'8 c'8 c'8 c'8 c'8 ] c'16 [ c'16 c'16 c'16 c'16 c'16 c'16 c'16 ] c'8 [ c'8 ] } >> .. container:: example Makes simultaneous voices: >>> divisions = [(3, 4), (4, 8), (1, 4)] >>> maker = abjad.NoteMaker() >>> selections = [ ... maker(6 * [0], [(1, 8)]), ... maker(8 * [0], [(1, 16)]), ... maker(2 * [0], [(1, 8)]), ... ] >>> for selection in selections: ... abjad.beam(selection[:]) ... >>> for note in abjad.iterate(selections).components(abjad.Note): ... note.written_pitch = abjad.NamedPitch("e'") ... >>> selection_1 = selections[0] + selections[1] + selections[2] >>> selections = [ ... maker(12 * [0], [(1, 16)]), ... maker(16 * [0], [(1, 32)]), ... maker(4 * [0], [(1, 16)]), ... ] >>> for selection in selections: ... abjad.beam(selection[:]) ... >>> selection_2 = selections[0] + selections[1] + selections[2] >>> selections = { ... 'Voice_1': selection_1, ... 'Voice_2': selection_2, ... } >>> lilypond_file = abjad.LilyPondFile.rhythm( ... selections, ... divisions, ... ) >>> voice_1 = lilypond_file['Voice_1'] >>> abjad.attach(abjad.LilyPondLiteral(r'\voiceOne'), voice_1) >>> voice_2 = lilypond_file['Voice_2'] >>> abjad.attach(abjad.LilyPondLiteral(r'\voiceTwo'), voice_2) >>> abjad.show(lilypond_file) # doctest: +SKIP .. docs:: >>> abjad.f(lilypond_file[abjad.Score]) \new Score << \new GlobalContext { s1 * 3/4 s1 * 1/2 s1 * 1/4 } \new Staff << \context Voice = "Voice_1" { \voiceOne e'8 [ e'8 e'8 e'8 e'8 e'8 ] e'16 [ e'16 e'16 e'16 e'16 e'16 e'16 e'16 ] e'8 [ e'8 ] } \context Voice = "Voice_2" { \voiceTwo c'16 [ c'16 c'16 c'16 c'16 c'16 c'16 c'16 c'16 c'16 c'16 c'16 ] c'32 [ c'32 c'32 c'32 c'32 c'32 c'32 c'32 c'32 c'32 c'32 c'32 c'32 c'32 c'32 c'32 ] c'16 [ c'16 c'16 c'16 ] } >> >> Returns LilyPond file. """ if isinstance(selections, list): for selection in selections: if not isinstance(selection, Selection): raise TypeError(f"must be selection: {selection!r}.") elif isinstance(selections, dict): for selection in selections.values(): if not isinstance(selection, Selection): raise TypeError(f"must be selection: {selection!r}.") else: raise TypeError(f"must be list or dictionary: {selections!r}.") score = Score() lilypond_file = LilyPondFile.new( score, includes=["default.ily", "rhythm-maker-docs.ily"] ) if pitched_staff is None: if isinstance(selections, list): selections_ = selections elif isinstance(selections, dict): selections_ = selections.values() else: raise TypeError(selections) for note in iterate(selections_).leaves(Note): if note.written_pitch != NamedPitch("c'"): pitched_staff = True break if isinstance(selections, list): if divisions is None: duration = abjad_inspect(selections).duration() divisions = [duration] time_signatures = time_signatures or divisions time_signatures = [TimeSignature(_) for _ in time_signatures] if pitched_staff: staff = Staff() else: staff = Staff(lilypond_type="RhythmicStaff") staff.extend(selections) elif isinstance(selections, dict): voices = [] for voice_name in sorted(selections): selections_ = selections[voice_name] selections_ = sequence(selections_).flatten(depth=-1) selections_ = copy.deepcopy(selections_) voice = Voice(selections_, name=voice_name) if attach_lilypond_voice_commands: voice_name_to_command_string = { "Voice_1": "voiceOne", "Voice_2": "voiceTwo", "Voice_3": "voiceThree", "Voice_4": "voiceFour", } command_string = voice_name_to_command_string.get( voice_name ) if command_string: command = LilyPondLiteral("\\" + command_string) attach(command, voice) voices.append(voice) staff = Staff(voices, is_simultaneous=True) if divisions is None: duration = abjad_inspect(staff).duration() divisions = [duration] else: message = "must be list or dictionary of selections:" message += f" {selections!r}." raise TypeError(message) score.append(staff) assert isinstance(divisions, collections.abc.Sequence), repr(divisions) time_signatures = time_signatures or divisions context = Context(lilypond_type="GlobalContext") skips = [] for time_signature in time_signatures: skip = Skip(1) skip.multiplier = time_signature attach(time_signature, skip, context="Score") skips.append(skip) context.extend(skips) score.insert(0, context) return lilypond_file