<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 Designing a music-generating class
The rhythm-makers we studied yesterday help us think about rhythm in a formal way. Today we'll extend the rhythm-makers' pattern with pitches, articulations and dynamics. In this notebook we'll develop the code we need; in the next notebook we'll encapsulate our work in a class.
Making notes and rests
We start by re-implementing the basic note-making functionality of the talea rhythm-maker "by hand." Beginning with a talea object that models a cycle of durations
Step1:  We can ask our talea for as many durations as we want. (Taleas output nonreduced fractions instead of durations. This is to allow talea output to model either durations or time signatures, depending on the application.) We include some negative values, which we will later interpret as rests. We can ask our talea for ten durations like this
Step2:  Let's use our talea to make notes and rests, stopping when the duration of the accumulated notes and rests sums to that of the four time signatures defined above
Step3:  To attach the four time signatures defined above, we must split our notes and rests at measure boundaries. Then we can attach a time signature to the first note or rest in each of the four selections that result
Step4:  Then we group our notes and rests by measure, and metrically respell each group
Step5:  Pitching notes
We can pitch our notes however we like. First we define a cycle of pitches
Step6:  Then we loop through pitched logical ties, pitching notes as we go
Step7:  Attaching articulations and dynamics
Abjad's run selector selects notes and chords, separated by rests
Step8:  We can use Abjad's run selector to loop through the runs in our music, attaching articulations and dynamics along the way
<ASSISTANT_TASK:>
Python Code:
pairs = [(4, 4), (3, 4), (7, 16), (6, 8)]
time_signatures = [abjad.TimeSignature(_) for _ in pairs]
durations = [_.duration for _ in time_signatures]
time_signature_total = sum(durations)
counts = [1, 2, -3, 4]
denominator = 16
talea = rmakers.Talea(counts, denominator)
talea_index = 0
Explanation: Designing a music-generating class
The rhythm-makers we studied yesterday help us think about rhythm in a formal way. Today we'll extend the rhythm-makers' pattern with pitches, articulations and dynamics. In this notebook we'll develop the code we need; in the next notebook we'll encapsulate our work in a class.
Making notes and rests
We start by re-implementing the basic note-making functionality of the talea rhythm-maker "by hand." Beginning with a talea object that models a cycle of durations:
End of explanation
talea[:10]
Explanation: We can ask our talea for as many durations as we want. (Taleas output nonreduced fractions instead of durations. This is to allow talea output to model either durations or time signatures, depending on the application.) We include some negative values, which we will later interpret as rests. We can ask our talea for ten durations like this:
End of explanation
events = []
accumulated_duration = abjad.Duration(0)
while accumulated_duration < time_signature_total:
    duration = talea[talea_index]
    if 0 < duration: 
        pitch = abjad.NamedPitch("c'")
    else:
        pitch = None
        duration = abs(duration)
    if time_signature_total < (duration + accumulated_duration):
        duration = time_signature_total - accumulated_duration
    events_ = abjad.LeafMaker()([pitch], [duration])
    events.extend(events_)
    accumulated_duration += duration
    talea_index += 1
staff = abjad.Staff(events)
abjad.show(staff)
Explanation: Let's use our talea to make notes and rests, stopping when the duration of the accumulated notes and rests sums to that of the four time signatures defined above:
End of explanation
selections = abjad.mutate.split(staff[:], time_signatures, cyclic=True)
for time_signature, selection in zip(time_signatures, selections):
    first_leaf = abjad.get.leaf(selection, 0)
    abjad.attach(time_signature, first_leaf)
abjad.show(staff)
Explanation: To attach the four time signatures defined above, we must split our notes and rests at measure boundaries. Then we can attach a time signature to the first note or rest in each of the four selections that result:
End of explanation
measure_selections = abjad.select(staff).leaves().group_by_measure()
for time_signature, measure_selection in zip(time_signatures, measure_selections):
    abjad.Meter.rewrite_meter(measure_selection, time_signature)
abjad.show(staff)
Explanation: Then we group our notes and rests by measure, and metrically respell each group:
End of explanation
string = "d' fs' a' d'' g' ef'"
strings = string.split()
pitches = abjad.CyclicTuple(strings)
Explanation: Pitching notes
We can pitch our notes however we like. First we define a cycle of pitches:
End of explanation
plts = abjad.select(staff).logical_ties(pitched=True)
for i, plt in enumerate(plts):
    pitch = pitches[i]
    for note in plt:
        note.written_pitch = pitch
abjad.show(staff)
Explanation: Then we loop through pitched logical ties, pitching notes as we go:
End of explanation
for selection in abjad.select(staff).runs():
    print(selection)
Explanation: Attaching articulations and dynamics
Abjad's run selector selects notes and chords, separated by rests:
End of explanation
for selection in abjad.select(staff).runs():
    articulation = abjad.Articulation("tenuto")
    abjad.attach(articulation, selection[0])
    if 3 <= len(selection):
        abjad.hairpin("p < f", selection)
    else:
        dynamic = abjad.Dynamic("ppp")
        abjad.attach(dynamic, selection[0])
abjad.override(staff).dynamic_line_spanner.staff_padding = 4
abjad.show(staff)
Explanation: We can use Abjad's run selector to loop through the runs in our music, attaching articulations and dynamics along the way:
End of explanation
<END_TASK>