Skip to content

Commit 9898395

Browse files
authored
feat!: Export controls and sequences as dict of arrays (#289)
Changes: - Export controls and decoupling sequences as dictionaries with arrays, to be compatible with the Q-CTRL Visualizer 7.0.0. - Tweak and rerun example notebooks with latest Visualizer version. BREAKING CHANGE: `DrivenControl.export` and `DynamicDecouplingSequence.export` now export each item as a dictionary of arrays (rather than a list of dictionaries).
1 parent cf36d21 commit 9898395

File tree

6 files changed

+62
-111
lines changed

6 files changed

+62
-111
lines changed

examples/creating-a-driven-control.ipynb

Lines changed: 10 additions & 15 deletions
Large diffs are not rendered by default.

examples/creating-a-dynamical-decoupling-sequence.ipynb

Lines changed: 7 additions & 25 deletions
Large diffs are not rendered by default.

qctrlopencontrols/driven_controls/driven_control.py

Lines changed: 21 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -554,7 +554,7 @@ def export(
554554
self, coordinates=Coordinate.CYLINDRICAL.value, dimensionless_rabi_rate=True
555555
) -> dict[str, Any]:
556556
"""
557-
Returns a dictionary formatted for plotting using the ``qctrl-visualizer`` package.
557+
Returns a dictionary formatted for plotting using the Q-CTRL Visualizer package.
558558
559559
Parameters
560560
----------
@@ -569,7 +569,7 @@ def export(
569569
-------
570570
dict
571571
Dictionary with plot data that can be used by the `plot_controls`
572-
method of the ``qctrl-visualizer`` package. It has keywords 'Rabi rate'
572+
method of the Q-CTRL Visualizer package. It has keywords 'Rabi rate'
573573
and 'Detuning' for 'cylindrical' coordinates and 'X amplitude', 'Y amplitude',
574574
and 'Detuning' for 'cartesian' coordinates.
575575
"""
@@ -587,30 +587,29 @@ def export(
587587

588588
plot_dictionary = {}
589589

590-
plot_x = self.amplitude_x / normalizer
591-
plot_y = self.amplitude_y / normalizer
592-
plot_r = self.rabi_rates / normalizer
593-
plot_theta = self.azimuthal_angles
594-
plot_durations = self.durations
595-
plot_detunings = self.detunings
596-
597590
if coordinates == Coordinate.CARTESIAN.value:
598-
plot_dictionary["X amplitude"] = [
599-
{"value": v, "duration": t} for v, t in zip(plot_x, plot_durations)
600-
]
601-
plot_dictionary["Y amplitude"] = [
602-
{"value": v, "duration": t} for v, t in zip(plot_y, plot_durations)
603-
]
591+
plot_dictionary["X amplitude"] = {
592+
"values": self.amplitude_x / normalizer,
593+
"durations": self.durations,
594+
}
595+
plot_dictionary["Y amplitude"] = {
596+
"values": self.amplitude_y / normalizer,
597+
"durations": self.durations,
598+
}
604599

605600
if coordinates == Coordinate.CYLINDRICAL.value:
606-
plot_dictionary["Rabi rate"] = [
607-
{"value": r * np.exp(1.0j * theta), "duration": t}
608-
for r, theta, t in zip(plot_r, plot_theta, plot_durations)
609-
]
601+
values = (self.rabi_rates / normalizer) * np.exp(
602+
1.0j * self.azimuthal_angles
603+
)
604+
plot_dictionary["Rabi rate"] = {
605+
"values": values,
606+
"durations": self.durations,
607+
}
610608

611-
plot_dictionary["Detuning"] = [
612-
{"value": v, "duration": t} for v, t in zip(plot_detunings, plot_durations)
613-
]
609+
plot_dictionary["Detuning"] = {
610+
"values": self.detunings,
611+
"durations": self.durations,
612+
}
614613

615614
return plot_dictionary
616615

qctrlopencontrols/dynamic_decoupling_sequences/dynamic_decoupling_sequence.py

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -132,27 +132,22 @@ def __init__(
132132

133133
def export(self) -> dict[str, Any]:
134134
"""
135-
Returns a dictionary for plotting using the qctrl-visualizer package.
135+
Returns a dictionary for plotting using the Q-CTRL Visualizer package.
136136
137137
Returns
138138
-------
139139
dict
140-
Dictionary with plot data that can be used by the plot_sequences
141-
method of the qctrl-visualizer package. It has keywords 'Rabi'
140+
Dictionary with plot data that can be used by the `plot_sequences`
141+
method of the Q-CTRL Visualizer package. It has keywords 'Rabi'
142142
and 'Detuning'.
143143
"""
144144

145145
return {
146-
"Rabi": [
147-
{"rotation": rabi * np.exp(1.0j * theta), "offset": offset}
148-
for rabi, theta, offset in zip(
149-
self.rabi_rotations, self.azimuthal_angles, self.offsets
150-
)
151-
],
152-
"Detuning": [
153-
{"rotation": rotation, "offset": offset}
154-
for rotation, offset in zip(self.detuning_rotations, self.offsets)
155-
],
146+
"Rabi": {
147+
"rotations": self.rabi_rotations * np.exp(1.0j * self.azimuthal_angles),
148+
"offsets": self.offsets,
149+
},
150+
"Detuning": {"rotations": self.detuning_rotations, "offsets": self.offsets},
156151
}
157152

158153
def __repr__(self):

tests/test_driven_controls.py

Lines changed: 6 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -261,23 +261,13 @@ def test_plot_data():
261261
dimensionless_rabi_rate=False, coordinates="cartesian"
262262
)
263263

264-
assert np.allclose(
265-
[point["duration"] for point in plot_data["X amplitude"]], _durations
266-
)
267-
assert np.allclose(
268-
[point["duration"] for point in plot_data["Y amplitude"]], _durations
269-
)
270-
assert np.allclose(
271-
[point["duration"] for point in plot_data["Detuning"]], _durations
272-
)
264+
assert np.allclose(plot_data["X amplitude"]["durations"], _durations)
265+
assert np.allclose(plot_data["Y amplitude"]["durations"], _durations)
266+
assert np.allclose(plot_data["Detuning"]["durations"], _durations)
273267

274-
assert np.allclose(
275-
[point["value"] for point in plot_data["X amplitude"]], x_amplitude
276-
)
277-
assert np.allclose(
278-
[point["value"] for point in plot_data["Y amplitude"]], y_amplitude
279-
)
280-
assert np.allclose([point["value"] for point in plot_data["Detuning"]], _detunings)
268+
assert np.allclose(plot_data["X amplitude"]["values"], x_amplitude)
269+
assert np.allclose(plot_data["Y amplitude"]["values"], y_amplitude)
270+
assert np.allclose(plot_data["Detuning"]["values"], _detunings)
281271

282272

283273
def test_pretty_print():

tests/test_dynamical_decoupling.py

Lines changed: 10 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -156,18 +156,13 @@ def test_sequence_plot():
156156

157157
plot_data = seq.export()
158158

159-
_plot_rabi_offsets = [pulse["offset"] for pulse in plot_data["Rabi"]]
160-
_plot_detuning_offsets = [pulse["offset"] for pulse in plot_data["Detuning"]]
161-
_plot_rabi_rotations = [pulse["rotation"] for pulse in plot_data["Rabi"]]
162-
_plot_detuning_rotations = [pulse["rotation"] for pulse in plot_data["Detuning"]]
159+
assert np.allclose(plot_data["Rabi"]["offsets"], _offsets)
160+
assert np.allclose(plot_data["Detuning"]["offsets"], _offsets)
163161

164-
assert np.allclose(_plot_rabi_offsets, _offsets)
165-
assert np.allclose(_plot_detuning_offsets, _offsets)
162+
assert np.allclose(np.abs(plot_data["Rabi"]["rotations"]), _rabi_rotations)
163+
assert np.allclose(np.angle(plot_data["Rabi"]["rotations"]), _azimuthal_angle)
166164

167-
assert np.allclose(np.abs(_plot_rabi_rotations), _rabi_rotations)
168-
assert np.allclose(np.angle(_plot_rabi_rotations), _azimuthal_angle)
169-
170-
assert np.allclose(_plot_detuning_rotations, _detuning_rotations)
165+
assert np.allclose(plot_data["Detuning"]["rotations"], _detuning_rotations)
171166

172167
# with both X and Y pi
173168
_offsets = np.array([0, 0.25, 0.5, 0.75, 1.00])
@@ -185,18 +180,13 @@ def test_sequence_plot():
185180

186181
plot_data = seq.export()
187182

188-
_plot_rabi_offsets = [pulse["offset"] for pulse in plot_data["Rabi"]]
189-
_plot_detuning_offsets = [pulse["offset"] for pulse in plot_data["Detuning"]]
190-
_plot_rabi_rotations = [pulse["rotation"] for pulse in plot_data["Rabi"]]
191-
_plot_detuning_rotations = [pulse["rotation"] for pulse in plot_data["Detuning"]]
192-
193-
assert np.allclose(_plot_rabi_offsets, _offsets)
194-
assert np.allclose(_plot_detuning_offsets, _offsets)
183+
assert np.allclose(plot_data["Rabi"]["offsets"], _offsets)
184+
assert np.allclose(plot_data["Detuning"]["offsets"], _offsets)
195185

196-
assert np.allclose(np.abs(_plot_rabi_rotations), _rabi_rotations)
197-
assert np.allclose(np.angle(_plot_rabi_rotations), _azimuthal_angle)
186+
assert np.allclose(np.abs(plot_data["Rabi"]["rotations"]), _rabi_rotations)
187+
assert np.allclose(np.angle(plot_data["Rabi"]["rotations"]), _azimuthal_angle)
198188

199-
assert np.allclose(_plot_detuning_rotations, _detuning_rotations)
189+
assert np.allclose(plot_data["Detuning"]["rotations"], _detuning_rotations)
200190

201191

202192
def test_pretty_string_format():

0 commit comments

Comments
 (0)