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.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 __call__(self) -> Score: r""" Calls two-staff piano score template. .. container:: example REGRESSION. Attaches piano to piano group (rather than just staff): >>> template = abjad.TwoStaffPianoScoreTemplate() >>> score = template() >>> piano_staff = score['Piano_Staff'] >>> rh_voice = score['RH_Voice'] >>> lh_voice = score['LH_Voice'] >>> rh_voice.append("g'4") >>> lh_voice.append("c4") >>> wrappers = template.attach_defaults(score) >>> abjad.show(score) # doctest: +SKIP .. docs:: >>> abjad.f(score, strict=60) \context Score = "Two_Staff_Piano_Score" %! abjad.TwoStaffPianoScoreTemplate.__call__ << %! abjad.TwoStaffPianoScoreTemplate.__call__ \context GlobalContext = "Global_Context" %! abjad.ScoreTemplate._make_global_context << %! abjad.ScoreTemplate._make_global_context \context GlobalRests = "Global_Rests" %! abjad.ScoreTemplate._make_global_context { %! abjad.ScoreTemplate._make_global_context } %! abjad.ScoreTemplate._make_global_context \context GlobalSkips = "Global_Skips" %! abjad.ScoreTemplate._make_global_context { %! abjad.ScoreTemplate._make_global_context } %! abjad.ScoreTemplate._make_global_context >> %! abjad.ScoreTemplate._make_global_context \context PianoStaff = "Piano_Staff" %! abjad.TwoStaffPianoScoreTemplate.__call__ << %! abjad.TwoStaffPianoScoreTemplate.__call__ \context Staff = "RH_Staff" %! abjad.TwoStaffPianoScoreTemplate.__call__ { %! abjad.TwoStaffPianoScoreTemplate.__call__ \context Voice = "RH_Voice" %! abjad.TwoStaffPianoScoreTemplate.__call__ { %! abjad.TwoStaffPianoScoreTemplate.__call__ g'4 } %! abjad.TwoStaffPianoScoreTemplate.__call__ } %! abjad.TwoStaffPianoScoreTemplate.__call__ \context Staff = "LH_Staff" %! abjad.TwoStaffPianoScoreTemplate.__call__ { %! abjad.TwoStaffPianoScoreTemplate.__call__ \context Voice = "LH_Voice" %! abjad.TwoStaffPianoScoreTemplate.__call__ { %! abjad.TwoStaffPianoScoreTemplate.__call__ \clef "bass" %! abjad.ScoreTemplate.attach_defaults c4 } %! abjad.TwoStaffPianoScoreTemplate.__call__ } %! abjad.TwoStaffPianoScoreTemplate.__call__ >> %! abjad.TwoStaffPianoScoreTemplate.__call__ >> %! abjad.TwoStaffPianoScoreTemplate.__call__ >>> wrapper = abjad.inspect(rh_voice[0]).wrapper(abjad.Instrument) >>> wrapper.context 'PianoStaff' """ tag = "abjad.TwoStaffPianoScoreTemplate.__call__" # GLOBAL CONTEXT global_context = self._make_global_context() # RH STAFF rh_voice = Voice(name="RH_Voice", tag=tag) rh_staff = Staff([rh_voice], name="RH_Staff", tag=tag) # LH STAFF lh_voice = Voice(name="LH_Voice", tag=tag) lh_staff = Staff([lh_voice], name="LH_Staff", tag=tag) annotate(lh_staff, "default_clef", Clef("bass")) # PIANO STAFF staff_group = StaffGroup( [rh_staff, lh_staff], lilypond_type="PianoStaff", name="Piano_Staff", tag=tag, ) annotate(staff_group, "default_instrument", Piano()) # SCORE score = Score( [global_context, staff_group], name="Two_Staff_Piano_Score", tag=tag, ) return score