3.6.14. qupulse.pulses.pulse_template

This module defines the abstract PulseTemplate class which is the basis of any pulse model in the qupulse.

Classes:
  • PulseTemplate: Represents the parametrized general structure of a pulse.

  • AtomicPulseTemplate: PulseTemplate that does imply any control flow disruptions and can be

    directly translated into a waveform.

Classes

AtomicPulseTemplate(*, identifier, measurements)

A PulseTemplate that does not imply any control flow disruptions and can be directly translated into a waveform.

PulseTemplate(*, identifier[, metadata])

A PulseTemplate represents the parametrized general structure of a pulse.

Exceptions

DoubleParameterNameException(templateA, ...)

MetadataComparison

UnknownVolatileParameter

class AtomicPulseTemplate(*, identifier: str | None, measurements: List[Tuple[str, Expression | str | Real, Expression | str | Real]] | None, metadata: TemplateMetadata | dict = None)[source]

Bases: PulseTemplate, MeasurementDefiner

A PulseTemplate that does not imply any control flow disruptions and can be directly translated into a waveform.

Implies that no AtomicPulseTemplate object is interruptable.

Initializes a Serializable.

Parameters:

identifier – An optional, non-empty identifier for this Serializable. If set, this Serializable will always be stored as a separate data item and never be embedded.

Raises:

ValueError – If identifier is the empty string

abstractmethod build_waveform(parameters: Mapping[str, Real], channel_mapping: Dict[str | int, str | int | None]) Waveform | None[source]

Translate this PulseTemplate into a waveform according to the given parameters.

Subclasses of AtomicPulseTemplate must check for ParameterConstraintViolation errors in their build_waveform implementation and raise corresponding exceptions.

Parameters:
  • parameters (Dict(str -> Parameter)) – A mapping of parameter names to real numbers.

  • channel_mapping (Dict(ChannelID -> ChannelID) – A mapping of Channel IDs

Returns:

Waveform object represented by this PulseTemplate object or None, if this object

does not represent a valid waveform of finite length.

property final_values: Dict[str | int, ExpressionScalar]

Values of defined channels at t == self.duration

property initial_values: Dict[str | int, ExpressionScalar]

Values of defined channels at t == 0

property integral: Dict[str | int, ExpressionScalar]

Implements PulseTemplate.integral.

property measurement_names: Set[str]

Return the names of measurements that are directly declared on self. Does _not_ visit eventual child objects.

with_parallel_atomic(*parallel: AtomicPulseTemplate) AtomicPulseTemplate[source]
exception DoubleParameterNameException(templateA: PulseTemplate, templateB: PulseTemplate, names: Set[str])[source]

Bases: Exception

class PulseTemplate(*, identifier: str | None, metadata: TemplateMetadata | dict = None)[source]

Bases: Serializable

A PulseTemplate represents the parametrized general structure of a pulse.

A PulseTemplate described a pulse in an abstract way: It defines the structure of a pulse but might leave some timings or voltage levels undefined, thus declaring parameters. This allows to reuse a PulseTemplate for several pulses which have the same overall structure and differ only in concrete values for the parameters. Obtaining an actual pulse which can be executed by specifying values for these parameters is called instantiation of the PulseTemplate and achieved by invoking the sequencing process.

Initializes a Serializable.

Parameters:

identifier – An optional, non-empty identifier for this Serializable. If set, this Serializable will always be stored as a separate data item and never be embedded.

Raises:

ValueError – If identifier is the empty string

create_program(*, parameters: Mapping[str, Expression | str | Number] | None = None, measurement_mapping: Mapping[str, str | None] | None = None, channel_mapping: Mapping[str | int, str | int | None] | None = None, global_transformation: Transformation | None = None, to_single_waveform: Set[str | PulseTemplate] = None, volatile: Set[str] | str = None, program_builder: ProgramBuilder = None) Program | None[source]

Translates this PulseTemplate into a program Loop.

The returned Loop represents the PulseTemplate with all parameter values instantiated provided as dictated by the parameters argument. Optionally, channels and measurements defined in the PulseTemplate can be renamed/mapped via the channel_mapping and measurement_mapping arguments.

Parameters:
  • parameters – A mapping of parameter names to Parameter objects.

  • measurement_mapping – A mapping of measurement window names. Windows that are mapped to None are omitted.

  • channel_mapping – A mapping of channel names. Channels that are mapped to None are omitted.

  • global_transformation – This transformation is applied to every waveform

  • to_single_waveform – A set of pulse templates (or identifiers) which are directly translated to a waveform. This might change how transformations are applied. TODO: clarify

  • volatile – Everything in the final program that depends on these parameters is marked as volatile

  • program_builder – This program builder is used to build the return value. If None default_program_builder is used.

Returns:

A Loop object corresponding to this PulseTemplate.

abstract property defined_channels: Set[str | int]

Returns the number of hardware output channels this PulseTemplate defines.

abstract property duration: ExpressionScalar

An expression for the duration of this PulseTemplate.

property final_values: Dict[str | int, ExpressionScalar]

Values of defined channels at t == self.duration

get_serialization_data(serializer: Serializer | None = None) Dict[str, Any][source]

Returns all data relevant for serialization as a dictionary containing only base types.

Implementation hint: In the old serialization routines, if the Serializable contains complex objects which are itself Serializables, a serialized representation for these MUST be obtained by calling the dictify() method of serializer. The reason is that serializer may decide to either return a dictionary to embed or only a reference to the Serializable subelement. This is DEPRECATED behavior as of May 2018. In the new routines, this will happen automatically and every Serializable is only responsible for returning it’s own data and leave nested Serializables in object form.

For the transition time where both implementations are available, implementations of this method should support the old and new routines, using the presence of the serializer argument to differentiate between both. Don’t make use of the implementation in this base class when implementing this method for the old routines.

Parameters:

serializer (Serializer) – DEPRECATED (May 2018).A Serializer instance used to serialize complex subelements of this Serializable.

Returns:

A dictionary of Python base types (strings, integers, lists/tuples containing these,

etc..) which fully represent the relevant properties of this Serializable for storing and later reconstruction as a Python object.

property initial_values: Dict[str | int, ExpressionScalar]

Values of defined channels at t == 0

abstract property integral: Dict[str | int, ExpressionScalar]

Returns an expression giving the integral over the pulse.

abstract property measurement_names: Set[str]

The set of measurement identifiers in this pulse template.

property metadata: TemplateMetadata

The metadata is intended for information which does not concern the pulse itself but rather its usage.

Here is the place for program builder optimization hints or tags that are not targeted at qupulse. Currently, qupulse itself only uses the TemplateMetadata.to_single_waveform attribute to allow dynamic atomicity during translation.

As it is no property of the pulse itself, it is ignored for hashing and equality checks.

property num_channels: int

The number of channels this PulseTemplate defines

pad_selected_subtemplates_to(to_new_duration: ~qupulse.expressions.ExpressionLike | ~typing.Callable[[~qupulse.expressions.sympy.Expression], ~qupulse.expressions.ExpressionLike], selector: ~typing.Callable[[~qupulse.pulses.pulse_template.PulseTemplate], bool] = None, spt_kwargs: ~typing.Mapping[str, ~typing.Any] = None, identity_map: ~typing.Callable[[str | None], str | None] = <function PulseTemplate.<lambda>>)[source]

Pad all subtemplates for which the selector returns true with the given padding strategy. If no selector is specified, all atomic subtemplates are padded. Padding non-atomic pulse templates is generally non-sensical when the subtemplates are padded.

By default newly created SequencePT`s have the metadata field `to_single_waveform set to “always”. Overwrite pt_kwargs to supply other metadata arguments.

If you need more customization, you can use PulseTemplate.with_mapped_subtemplates().

!!! Note: This method needs to create new pulse templates and removes all parent tempates identifiers

Parameters:
  • to_new_duration – Specity how to pad. See pad_to().

  • selector – Select which subtemplates to pad.

  • spt_kwargs – Passed to newly created sequence pulse templates required for padding. By default {"metadata": {"to_single_waveform": "always"}} is passed to make them atomic.

  • identity_map – Provide a function to map the identifiers of composite templates whos subtemplates are padded.

Returns:

A new pulse template if any subtemplate needed to be padded.

pad_to(to_new_duration: ExpressionLike | Callable[[Expression], ExpressionLike], spt_kwargs: Mapping[str, Any] = None, pt_kwargs: Mapping[str, Any] = None) PulseTemplate[source]

Pad this pulse template to the given duration. The target duration can be numeric, symbolic or a callable that returns a new duration from the current duration.

Examples

# pad to a fixed duration >>> padded_1 = my_pt.pad_to(1000)

# pad to a fixed sample coun >>> padded_2 = my_pt.pad_to(‘sample_rate * 1000’)

# pad to the next muliple of 16 samples with a symbolic sample rate >>> padded_3 = my_pt.pad_to(to_next_multiple(‘sample_rate’, 16))

# pad to the next muliple of 16 samples with a fixed sample rate of 1 GHz >>> padded_4 = my_pt.pad_to(to_next_multiple(1, 16))

Parameters:
  • to_new_duration – Duration or callable that maps the current duration to the new duration

  • spt_kwargs – Keyword arguments for an optionally newly created sequence pulse template.

  • pt_kwargs – Deprecated! Similar to spt_kwargs but enforces sequence pt creation even if no padding required.

Returns:

A pulse template that has the duration given by to_new_duration. It can be self if the duration is already as required. It is never self if pt_kwargs is non-empty (deprecated feated).

abstract property parameter_names: Set[str]

The set of names of parameters required to instantiate this PulseTemplate.

property to_single_waveform: Literal['always'] | None

This property describes whether this pulse template is translated into a single waveform.

‘always’: It is always translated into a single waveform. None: It depends on the create_program arguments and the pulse template itself.

with_appended(*appended: PulseTemplate)[source]

Create a SequencePT that represents a sequence of this pulse template and appended

You can also use the @ operator to do this or call qupulse.pulses.SequencePT.concatenate() directly.

with_iteration(loop_idx: str, loop_range) PulseTemplate[source]

Create a ForLoopPT with the given index and range.

Examples

>>> from qupulse.pulses import ConstantPT
... const = ConstantPT('t_hold', {'x': 'start_x + i_x * step_x', 'y': 'start_y + i_y * step_y'})
... scan_2d = const.with_iteration('i_x', 'n_x').with_iteration('i_y', 'n_y')
with_mapped_subtemplates(map_fn: ~typing.Callable[[~qupulse.pulses.pulse_template.PulseTemplate], ~qupulse.pulses.pulse_template.PulseTemplate], *, identifier_map: ~typing.Callable[[str | None], str | None] = <function PulseTemplate.<lambda>>, always_new_template: bool = False, recursion_strategy: ~typing.Literal['pre', 'post', 'self'] = 'pre') PulseTemplate[source]

Return a new pulse template with all subtemplates mapped by map_fn.

If map_fn returns the same object for all subtemplates no new pulse template is created unless always_new_template is true.

If a new template is created the identifier of the old template is passed to ìdentifier_map to determine the new identifier. It is the same by default.

By default, this function visits all subtemplates recursively. The recursion_strategy determines the order of recursion and map_fn calls. For the default ‘pre’ the recursive subtemplates are mapped first before the direct subtemplates are mapped. For ‘post’ the direct subtemplates are mapped first before the recursive subtemplates are visited. For ‘self’ there is no recursion, i.e. the potential recursion can be implemented in map_fn itself.

This helper function is useful for modification of pulse templates without having to worry about the internal structure.

The pulse registry feature is not yet supported by the method. When you need it, please open an issue on github.

Parameters:
  • map_fn – The function to be applied to the subtemplates according to the recursion strategy.

  • identifier_map – This function is called to map the identifiers of pulse templates that need to be newly created because their subtemplates changed.

  • always_new_template – If True, a new pulse template will be created even if the mapped subtemplates are identical.

  • recursion_strategy – Either ‘pre’, ‘post’ or ‘self’. - ‘pre’: All recursive subtemplates are mapped before the map_fn is applied. - ‘post’: All recursive subtemplates are mapped after the map_fn is applied. - ‘Self’: The recursion needs to be done by the map_fn if required.

Returns:

A pulse template with mapped subtemplates.

with_mapping(*mapping_tuple_args: Mapping, **mapping_kwargs: Mapping) PulseTemplate[source]

Map parameters / channel names / measurement names. You may either specify the mappings as positional arguments XOR as keyword arguments. Positional arguments are forwarded to from_tuple() which automatically determines the “type” of the mappings. Keyword arguments must be one of the keyword arguments of MappingPT.

Parameters:
  • *mapping_tuple_args – Mappings for parameters / channel names / measurement names

  • **mapping_kwargs – Mappings for parameters / channel names / measurement names

Examples

Equivalent ways to rename a channel and map a parameter value >>> from qupulse.pulses import FunctionPT … fpt = FunctionPT(‘sin(f * t)’, duration_expression=10, channel=’A’) … mapped = fpt.with_mapping({‘f’: 0.1}, {‘A’: ‘B’}) … mapped.defined_channels {‘B’}

>>> from qupulse.pulses import FunctionPT
... fpt = FunctionPT('sin(f * t)', duration_expression=10, channel='A')
... mapped = fpt.with_mapping(parameter_mapping={'f': 0.1}, channel_mapping={'A': 'B'})
... mapped.defined_channels
{'B'}
Returns:

A newly created mapping pulse template

with_parallel_channels(values: Mapping[str | int, ExpressionLike]) PulseTemplate[source]

Create a new pulse template that sets the given channels to the corresponding values.

See ParallelChannelPulseTemplate for implementation details and restictions.

Examples

>>> from qupulse.pulses import FunctionPT
... fpt = FunctionPT('sin(0.1 * t)', duration_expression=10)
... fpt_and_marker = fpt.with_parallel_channels({'marker': 1})
Parameters:

values – Values to be set for each channel.

Returns:

A newly created pulse template.

with_repetition(repetition_count: ExpressionLike) PulseTemplate[source]

Repeat this pulse template repetition_count times via a RepetitionPulseTemplate.

Examples

>>> from qupulse.pulses import FunctionPT
... fpt = FunctionPT('sin(0.1 * t)', duration_expression=10)
... repeated = fpt.with_repetition('n_periods')
Parameters:

repetition_count – Amount of times this pulse template is repeated in the return value.

Returns:

A newly created pulse template.

with_time_reversal() PulseTemplate[source]

Reverse this pulse template by creating a TimeReversalPT.

Examples

>>> from qupulse.pulses import FunctionPT
... forward = FunctionPT('sin(f * t)', duration_expression=10, channel='A')
... backward = fpt.with_time_reversal()
... forward_and_backward = forward @ backward
exception UnknownVolatileParameter[source]

Bases: RuntimeWarning