class ScheduleBlock(name=None, metadata=None, alignment_context=None)[source]

Bases: object

Time-ordered sequence of instructions with alignment context.

ScheduleBlock supports lazy scheduling of context instructions, i.e. their timeslots is always generated at runtime. This indicates we can parametrize instruction durations as well as other parameters. In contrast to Schedule being somewhat static, ScheduleBlock is a dynamic representation of a pulse program.

Pulse Builder

The Qiskit pulse builder is a domain specific language that is developed on top of the schedule block. Use of the builder syntax will improve the workflow of pulse programming. See Pulse Builder for a user guide.

Alignment contexts

A schedule block is always relatively scheduled. Instead of taking individual instructions with absolute execution time t0, the schedule block defines a context of scheduling and instructions under the same context are scheduled in the same manner (alignment). Several contexts are available in Alignments. A schedule block is instantiated with one of these alignment contexts. The default context is AlignLeft, for which all instructions are left-justified, in other words, meaning they use as-soon-as-possible scheduling.

If you need an absolute-time interval in between instructions, you can explicitly insert Delay instructions.

Nested blocks

A schedule block can contain other nested blocks with different alignment contexts. This enables advanced scheduling, where a subset of instructions is locally scheduled in a different manner. Note that a Schedule instance cannot be directly added to a schedule block. To add a Schedule instance, wrap it in a Call instruction. This is implicitly performed when a schedule is added through the Pulse Builder.

Unsupported operations

Because the schedule block representation lacks timeslots, it cannot perform particular Schedule operations such as insert() or shift() that require instruction start time t0. In addition, exclude() and filter() methods are not supported because these operations may identify the target instruction with t0. Except for these operations, ScheduleBlock provides full compatibility with Schedule.


The timeslots-free representation offers much greater flexibility for writing pulse programs. Because ScheduleBlock only cares about the ordering of the child blocks we can add an undefined pulse sequence as a subroutine of the main program. If your program contains the same sequence multiple times, this representation may reduce the memory footprint required by the program construction. Such a subroutine is realized by the special compiler directive Reference that is defined by a unique set of reference key strings to the subroutine. The (executable) subroutine is separately stored in the main program. Appended reference directives are resolved when the main program is executed. Subroutines must be assigned through assign_references() before execution.

Program Scoping

When you call a subroutine from another subroutine, or append a schedule block to another schedule block, the management of references and parameters can be a hard task. Schedule block offers a convenient feature to help with this by automatically scoping the parameters and subroutines.

from qiskit import pulse
from qiskit.circuit.parameter import Parameter

amp1 = Parameter("amp")

with pulse.build() as sched1:
    pulse.play(pulse.Constant(100, amp1), pulse.DriveChannel(0))


The scoped_parameters() method returns all Parameter objects defined in the schedule block. The parameter name is updated to reflect its scope information, i.e. where it is defined. The outer scope is called “root”. Since the “amp” parameter is directly used in the current builder context, it is prefixed with “root”. Note that the Parameter object returned by scoped_parameters() preserves the hidden UUID key, and thus the scoped name doesn’t break references to the original Parameter.

You may want to call this program from another program. In this example, the program is called with the reference key “grand_child”. You can call a subroutine without specifying a substantial program (like sched1 above which we will assign later).

amp2 = Parameter("amp")

with pulse.build() as sched2:
    with pulse.align_right():
        pulse.play(pulse.Constant(200, amp2), pulse.DriveChannel(0))


This only returns “root::amp” because the “grand_child” reference is unknown. Now you assign the actual pulse program to this reference.

sched2.assign_references({("grand_child", ): sched1})
(Parameter(root::amp), Parameter(root::grand_child::amp))

Now you get two parameters “root::amp” and “root::grand_child::amp”. The second parameter name indicates it is defined within the referred program “grand_child”. The program calling the “grand_child” has a reference program description which is accessed through ScheduleBlock.references.

  - ('grand_child',): ScheduleBlock(Play(Constant(duration=100, amp=amp,...

Finally, you may want to call this program from another program. Here we try a different approach to define subroutine. Namely, we call a subroutine from the root program with the actual program sched2.

amp3 = Parameter("amp")

with pulse.build() as main:
    pulse.play(pulse.Constant(300, amp3), pulse.DriveChannel(0))
    pulse.call(sched2, name="child")

(Parameter(root::amp), Parameter(root::child::amp), Parameter(root::child::grand_child::amp))

This implicitly creates a reference named “child” within the root program and assigns sched2 to it. You get three parameters “root::amp”, “root::child::amp”, and “root::child::grand_child::amp”. As you can see, each parameter name reflects the layer of calls from the root program. If you know the scope of a parameter, you can directly get the parameter object using ScheduleBlock.search_parameters() as follows.


You can use a regular expression to specify the scope. The following returns the parameters defined within the scope of “ground_child” regardless of its parent scope. This is sometimes convenient if you want to extract parameters from a deeply nested program.


Note that the root program is only aware of its direct references.

  - ('child',): ScheduleBlock(ScheduleBlock(ScheduleBlock(Play(Con...

As you can see the main program cannot directly assign a subroutine to the “grand_child” because this subroutine is not called within the root program, i.e. it is indirectly called by “child”. However, the returned ReferenceManager is a dict-like object, and you can still reach to “grand_child” via the “child” program with the following chained dict access.

main.references[("child", )].references[("grand_child", )]

Note that ScheduleBlock.parameters and ScheduleBlock.scoped_parameters() still collect all parameters also from the subroutine once it’s assigned.

Create an empty schedule block.

  • name (Optional[str]) – Name of this schedule. Defaults to an autogenerated string if not provided.

  • metadata (Optional[dict]) – Arbitrary key value metadata to associate with the schedule. This gets stored as free-form data in a dict in the metadata attribute. It will not be directly used in the schedule.

  • alignment_context (AlignmentKind) – AlignmentKind instance that manages scheduling of instructions in this block.


TypeError – if metadata is not a dict.



Return a new schedule block with block appended to the context block.


Assign the parameters in this schedule according to the input.


Assign schedules to references.


Return the time of the end of the last instruction over the supplied channels.


Plot the schedule.


Return a Schedule with only the instructions from this Schedule failing at least one of the provided filters. This method is the complement of py:meth:~self.filter, so that::.


Return a new Schedule with only the instructions from this ScheduleBlock which pass though the provided filters; i.e. an instruction will be retained iff every function in filter_funcs returns True, the instruction occurs on a channel type contained in channels, the instruction type is contained in instruction_types, and the period over which the instruction operates is fully contained in one specified in time_ranges or intervals.


Get parameter object bound to this schedule by string name.


Create new schedule object with metadata of another schedule object.


Return True iff the instruction is parameterized.


Return True iff the current schedule block contains reference to subroutine.


Return True if all durations are assigned.


Return a ScheduleBlock with the old component replaced with a new component.


Return unassigned parameters with scoped names.


Search parameter with regular expression.



Return alignment instance that allocates block component to generate schedule.


Get the block elements added to self.


The sequence of elements is returned in order of addition. Because the first element is schedule first, e.g. FIFO, the returned sequence is roughly time-ordered. However, in the parallel alignment context, especially in the as-late-as-possible scheduling, or AlignRight context, the actual timing of when the instructions are issued is unknown until the ScheduleBlock is scheduled and converted into a Schedule.

Return type

Tuple[Union[ScheduleBlock, Instruction], ...]


Returns channels that this schedule block uses.

Return type



Duration of this schedule block.

Return type


instances_counter = count(9)

Get the time-ordered instructions from self.

Return type

Tuple[Tuple[int, Instruction]]


The user provided metadata associated with the schedule.

User provided dict of metadata for the schedule. The metadata contents do not affect the semantics of the program but are used to influence the execution of the schedule. It is expected to be passed between all transforms of the schedule and that providers will associate any schedule metadata with the results it returns from the execution of that schedule.

Return type

Dict[str, Any]


Return name of this schedule

Return type



Return unassigned parameters with raw names.

Return type


prefix = 'block'

Return a reference manager of the current scope.

Return type