<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
Step1:  Encapsulation, part 1
Step3:  2. A function to attach time signatures
Another block of code split notes and rests at measure boundaries and attached time signatures. Let's encapsulate that in its own function
Step5:  3. A function to pitch notes
The next block of code looped through notes, and pitched them. It can be a function, too
Step7:  4. A function to attach articulations and dynamics
We then looped through runs of notes and chords, attaching articulations and dynamics
Step9:  5. A function to call the other functions
What do we gain from encapsulation like this? We can now create a single function to call the others, clarifying the structure of our thinking
Step10:  Now we define input and call just one function to make our staff
<ASSISTANT_TASK:>
Python Code:
def make_notes_and_rests(counts, denominator, time_signatures):
    
    Makes notes and rests with repeating pattern of durations.
    
    Output sums to time signatures.
    
    Returns staff.
    
    durations = [_.duration for _ in time_signatures]
    total_duration = sum(durations)
    talea = rmakers.Talea(counts, denominator)
    talea_index = 0
    leaves = []
    current_duration = abjad.Duration(0)
    while current_duration < total_duration:
        leaf_duration = talea[talea_index]
        if 0 < leaf_duration: 
            pitch = abjad.NamedPitch("c'")
        else:
            pitch = None
            leaf_duration = abs(leaf_duration)
        if total_duration < (leaf_duration + current_duration):
            leaf_duration = total_duration - current_duration
        leaves_ = abjad.LeafMaker()([pitch], [leaf_duration])
        leaves.extend(leaves_)
        current_duration += leaf_duration
        talea_index += 1
    staff = abjad.Staff(leaves)
    return staff
Explanation: Encapsulation, part 1: functions
The last notebook gave us a series of steps that generate music, but they clearly divide into several blocks of code that accomplish different tasks. Wouldn't it be nice to use the structure of the code to document our thinking? In this notebook we'll encapsulate our code in a collection of functions.
1. A function to make notes and rests
Our first block of code made notes and rests. Let's encapsulate that code into its own function:
End of explanation
def impose_time_signatures(staff, time_signatures):
    
    Splits notes and rests at measure boundaries, attached time signatures, rewrites meter.
    
    selections = abjad.mutate.split(staff[:], time_signatures, cyclic=True)
    for time_signature, selection in zip(time_signatures, selections):
        abjad.attach(time_signature, selection[0])
    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)
Explanation: 2. A function to attach time signatures
Another block of code split notes and rests at measure boundaries and attached time signatures. Let's encapsulate that in its own function:
End of explanation
def pitch_notes(staff, pitches):
    
    Pitches notes.
    
    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
Explanation: 3. A function to pitch notes
The next block of code looped through notes, and pitched them. It can be a function, too:
End of explanation
def attach_indicators(staff):
    
    Attaches articulations and dynamics to runs.
    
    for run in abjad.select(staff).runs():
        articulation = abjad.Articulation("tenuto")
        abjad.attach(articulation, run[0])
        if 3 <= len(run):
            abjad.hairpin("p < f", run)
        else:
            dynamic = abjad.Dynamic("ppp")
            abjad.attach(dynamic, run[0])
    abjad.override(staff).dynamic_line_spanner.staff_padding = 4
Explanation: 4. A function to attach articulations and dynamics
We then looped through runs of notes and chords, attaching articulations and dynamics:
End of explanation
def make_staff(counts, denominator, time_signatures, pitches):
    
    Makes notes and rests, pitches notes and attaches articulations and dynamics.
    
    Returns staff.
    
    staff = make_notes_and_rests(counts, denominator, time_signatures)
    impose_time_signatures(staff, time_signatures)
    pitch_notes(staff, pitches)
    attach_indicators(staff)
    return staff
Explanation: 5. A function to call the other functions
What do we gain from encapsulation like this? We can now create a single function to call the others, clarifying the structure of our thinking:
End of explanation
pairs = [(4, 4), (3, 4), (7, 16), (6, 8)]
time_signatures = [abjad.TimeSignature(_) for _ in pairs]
counts = [1, 2, -3, 4]
denominator = 16
string = "d' fs' a' d'' g' ef'"
pitches = abjad.CyclicTuple(string.split())
staff = make_staff(counts, denominator, time_signatures, pitches)
abjad.show(staff)
Explanation: Now we define input and call just one function to make our staff:
End of explanation
<END_TASK>