Source code for zhinst.toolkit.sequence
"""Custom sequence code class."""
from zhinst.toolkit.waveform import Waveforms
from zhinst.toolkit.command_table import CommandTable
import re
import typing as t
[docs]class Sequence:
r"""A representation of a ZI sequencer code.
This class enables a compact representation of a sequence for a Zurich
Instruments device. Although a sequencer code can be represented by a
simple string this class offers the following advantages:
* Define a constants dictionary. The constants will be added
automatically to the top of the resulting sequencer code and helps
to prevent the use of fstrings (which require the escaping of {})
* Link Waveforms to the sequence. This adds the waveform placeholder
definitions to the top of the resulting sequencer code.
Note:
This class is only for convenience. The same functionality can be
achieved with a simple string.
Args:
code: Sequencer code (default = None).
constants: A dictionary of constants to be added to the top of the
resulting sequencer code. (default = None).
waveforms: Waveforms that will be used in the sequence.
Example:
>>> waveforms = Waveforms()
>>> waveforms[0] = (0.5*np.ones(1008), -0.2*np.ones(1008), np.ones(1008))
>>> sequencer = Sequence()
>>> sequencer.constants["PULSE_WIDTH"] = 10e-9 #ns
>>> sequencer.waveforms = waveforms
>>> sequencer.code = \"\"\"\
// Hello World
repeat(5)
...
\"\"\"
>>> str(sequencer)
// Constants
const PULSE_WIDTH = 10e-9;
// Waveforms declaration
assignWaveIndex(placeholder(1008, true, false), placeholder(1008, \
false, false), 0);
assignWaveIndex(placeholder(1008, false, false), placeholder(1008, \
false, false), 2);
// Hello World
repeat(5)
...
"""
def __init__(
self,
code: str = None,
*,
constants: t.Dict[str, float] = None,
waveforms: Waveforms = None,
command_table: CommandTable = None,
):
self._partial_seq = code if code else ""
self._constants = constants if constants else {}
self._waveforms = waveforms
self._command_table = command_table
def __str__(self) -> str:
return self.to_string()
[docs] def to_string(self, *, waveform_snippet: bool = True) -> str:
"""Convert the object into a string.
Args:
waveform_snippet: Flag if the waveform declaration should be added
to the top of the resulting sequence. (default = True).
Returns:
String representation of the sequence.
"""
sequence = self._partial_seq
if waveform_snippet and self._waveforms:
sequence = (
"// Waveforms declaration\n"
+ self._waveforms.get_sequence_snippet()
+ "\n"
+ sequence
)
new_constants = {}
for key, value in self._constants.items():
constant_regex = re.compile(rf"(const {key} *= *)(.*);")
if constant_regex.search(sequence):
sequence = constant_regex.sub(rf"\g<1>{value};", sequence)
else:
new_constants[key] = value
if len(new_constants) > 0:
sequence = (
"// Constants\n"
+ "\n".join(
[f"const {key} = {value};" for key, value in new_constants.items()]
)
+ "\n"
+ sequence
)
return sequence
@property
def code(self) -> str:
"""Code of the Sequence."""
return self._partial_seq
@code.setter
def code(self, value: str) -> None:
"""Code of the Sequence."""
self._partial_seq = value
@property
def constants(self) -> t.Dict[str, float]:
"""Constants of the Sequence."""
return self._constants
@constants.setter
def constants(self, value: t.Dict[str, float]) -> None:
"""Constants of the Sequence."""
self._constants = value
@property
def waveforms(self) -> Waveforms:
"""Waveforms of the Sequence."""
return self._waveforms
@waveforms.setter
def waveforms(self, value: Waveforms) -> None:
"""Waveforms of the Sequence."""
self._waveforms = value
@property
def command_table(self) -> CommandTable:
"""Command table of the Sequence."""
return self._command_table
@command_table.setter
def command_table(self, value: CommandTable) -> None:
"""Command table of the Sequence."""
self._command_table = value