From 502ddc43e3360f2b1d5c1780ffe7bb3cd176ea1b Mon Sep 17 00:00:00 2001 From: Rajib Chakravorty Date: Thu, 30 May 2019 16:34:52 +1000 Subject: [PATCH 1/5] removed get_plot_segments public method --- qctrlopencontrols/__init__.py | 2 +- .../driven_controls/driven_control.py | 115 +++++++----------- .../dynamic_decoupling_sequences/__init__.py | 2 +- .../driven_controls.py | 2 +- .../dynamic_decoupling_sequence.py | 4 +- tests/test_dynamical_decoupling.py | 24 ++-- 6 files changed, 63 insertions(+), 86 deletions(-) diff --git a/qctrlopencontrols/__init__.py b/qctrlopencontrols/__init__.py index 4f5fb900..e586f815 100644 --- a/qctrlopencontrols/__init__.py +++ b/qctrlopencontrols/__init__.py @@ -20,7 +20,7 @@ from .dynamic_decoupling_sequences import (DynamicDecouplingSequence, new_predefined_dds, - convert_dds_to_driven_controls) + convert_dds_to_driven_control) from .driven_controls import DrivenControl, new_predefined_driven_control from .qiskit import convert_dds_to_quantum_circuit from .cirq import (convert_dds_to_cirq_circuit, diff --git a/qctrlopencontrols/driven_controls/driven_control.py b/qctrlopencontrols/driven_controls/driven_control.py index 18043bb3..e2d3b4f6 100644 --- a/qctrlopencontrols/driven_controls/driven_control.py +++ b/qctrlopencontrols/driven_controls/driven_control.py @@ -31,54 +31,6 @@ UPPER_BOUND_DURATION, LOWER_BOUND_DURATION) -def get_plot_data_from_segments(segments): - """ - Generates arrays that can be used to produce a plot representing the shape of the driven control - constructed from the segments. - - Parameters - ---------- - segments : list - List of segments formatted as described in qctrlopencontrols.driven_controls.DrivenControl - - Returns - ------- - tuple - Tuple made up of arrays for plotting formatted as - (amplitude_x,amplitude_y,amplitude_z,time) where: - - amplitude_k is the amplitude values. - - times the time corresponding to each amplitude_k coordinate. - Note that plot will have repeated times and for amplitudes, this is because it is - expected that these coordinates are to be used with plotting software that 'joins - the dots' with linear lines between each coordinate. The time array gives the x - values for all the amplitude arrays, which give the y values. - - """ - segment_times = np.insert(np.cumsum(segments[:, 3]), 0, 0.) - coords = len(segment_times) - coord_amplitude_x = np.concatenate([[0.], segments[:, 0], [0.]]) - coord_amplitude_y = np.concatenate([[0.], segments[:, 1], [0.]]) - coord_amplitude_z = np.concatenate([[0.], segments[:, 2], [0.]]) - plot_time = [] - plot_amplitude_x = [] - plot_amplitude_y = [] - plot_amplitude_z = [] - for i in range(coords): - plot_time.append(segment_times[i]) - plot_time.append(segment_times[i]) - plot_amplitude_x.append(coord_amplitude_x[i]) - plot_amplitude_x.append(coord_amplitude_x[i + 1]) - plot_amplitude_y.append(coord_amplitude_y[i]) - plot_amplitude_y.append(coord_amplitude_y[i + 1]) - plot_amplitude_z.append(coord_amplitude_z[i]) - plot_amplitude_z.append(coord_amplitude_z[i + 1]) - - return (np.array(plot_amplitude_x), - np.array(plot_amplitude_y), - np.array(plot_amplitude_z), - np.array(plot_time)) - - class DrivenControl(QctrlObject): #pylint: disable=too-few-public-methods """ Creates a driven control. A driven is a set of segments made up of amplitude vectors @@ -545,28 +497,57 @@ def get_plot_formatted_arrays(self, coordinates=CARTESIAN, dimensionless_rabi_ra ArgumentsValueError Raised when an argument is invalid. """ + if coordinates not in [CARTESIAN, CYLINDRICAL]: + raise ArgumentsValueError( + 'Unsupported coordinates provided: ', + arguments={'coordinates': coordinates}) + + if dimensionless_rabi_rate: normalizer = self.maximum_rabi_rate else: normalizer = 1 if coordinates == CARTESIAN: - (x_amplitudes, y_amplitudes, detunings, times) = get_plot_data_from_segments( - np.vstack((self.amplitude_x / normalizer, self.amplitude_y / normalizer, - self.detunings, self.durations)).T - ) - plot_dictionary = { - 'amplitudes_x': x_amplitudes, - 'amplitudes_y': y_amplitudes, - 'detunings': detunings, - 'times': times - } - + segments = np.vstack((self.amplitude_x / normalizer, + self.amplitude_y / normalizer, + self.detunings, + self.durations)).T elif coordinates == CYLINDRICAL: - (x_plot, y_plot, detunings, times) = get_plot_data_from_segments( - np.vstack((self.rabi_rates / normalizer, self.azimuthal_angles, - self.detunings, self.durations)).T - ) + segments = np.vstack((self.rabi_rates / normalizer, + self.azimuthal_angles, + self.detunings, + self.durations)).T + + segment_times = np.insert(np.cumsum(segments[:, 3]), 0, 0.) + coords = len(segment_times) + coord_amplitude_x = np.concatenate([[0.], segments[:, 0], [0.]]) + coord_amplitude_y = np.concatenate([[0.], segments[:, 1], [0.]]) + coord_amplitude_z = np.concatenate([[0.], segments[:, 2], [0.]]) + plot_time = [] + plot_amplitude_x = [] + plot_amplitude_y = [] + plot_amplitude_z = [] + for i in range(coords): + plot_time.append(segment_times[i]) + plot_time.append(segment_times[i]) + plot_amplitude_x.append(coord_amplitude_x[i]) + plot_amplitude_x.append(coord_amplitude_x[i + 1]) + plot_amplitude_y.append(coord_amplitude_y[i]) + plot_amplitude_y.append(coord_amplitude_y[i + 1]) + plot_amplitude_z.append(coord_amplitude_z[i]) + plot_amplitude_z.append(coord_amplitude_z[i + 1]) + + plot_dictionary = { + 'amplitudes_x': plot_amplitude_x, + 'amplitudes_y': plot_amplitude_y, + 'detunings': plot_amplitude_z, + 'times': plot_time + } + + if coordinates == CYLINDRICAL: + x_plot = plot_amplitude_x + y_plot = plot_amplitude_y x_plot[np.equal(x_plot, -0.0)] = 0. y_plot[np.equal(y_plot, -0.0)] = 0. azimuthal_angles_plot = np.arctan2(y_plot, x_plot) @@ -574,13 +555,9 @@ def get_plot_formatted_arrays(self, coordinates=CARTESIAN, dimensionless_rabi_ra plot_dictionary = { 'rabi_rates': amplitudes_plot, 'azimuthal_angles': azimuthal_angles_plot, - 'detunings': detunings, - 'times': times + 'detunings': plot_amplitude_z, + 'times': plot_time } - else: - raise ArgumentsValueError( - 'Unsupported coordinates provided: ', - arguments={'coordinates': coordinates}) return plot_dictionary diff --git a/qctrlopencontrols/dynamic_decoupling_sequences/__init__.py b/qctrlopencontrols/dynamic_decoupling_sequences/__init__.py index 3d2218a8..a71c2aa7 100644 --- a/qctrlopencontrols/dynamic_decoupling_sequences/__init__.py +++ b/qctrlopencontrols/dynamic_decoupling_sequences/__init__.py @@ -26,4 +26,4 @@ from .dynamic_decoupling_sequence import DynamicDecouplingSequence from .predefined import new_predefined_dds -from .driven_controls import convert_dds_to_driven_controls +from .driven_controls import convert_dds_to_driven_control diff --git a/qctrlopencontrols/dynamic_decoupling_sequences/driven_controls.py b/qctrlopencontrols/dynamic_decoupling_sequences/driven_controls.py index 63c8e820..228dc192 100644 --- a/qctrlopencontrols/dynamic_decoupling_sequences/driven_controls.py +++ b/qctrlopencontrols/dynamic_decoupling_sequences/driven_controls.py @@ -95,7 +95,7 @@ def _check_maximum_rotation_rate( 'allowed_maximum_detuning_rate': UPPER_BOUND_DETUNING_RATE}) -def convert_dds_to_driven_controls( +def convert_dds_to_driven_control( dynamic_decoupling_sequence=None, maximum_rabi_rate=2*np.pi, maximum_detuning_rate=2*np.pi, diff --git a/qctrlopencontrols/dynamic_decoupling_sequences/dynamic_decoupling_sequence.py b/qctrlopencontrols/dynamic_decoupling_sequences/dynamic_decoupling_sequence.py index 3fc10d32..61f13e0c 100644 --- a/qctrlopencontrols/dynamic_decoupling_sequences/dynamic_decoupling_sequence.py +++ b/qctrlopencontrols/dynamic_decoupling_sequences/dynamic_decoupling_sequence.py @@ -27,7 +27,7 @@ QCTRL_EXPANDED, CSV, CYLINDRICAL) from .constants import (UPPER_BOUND_OFFSETS, MATPLOTLIB) -from .driven_controls import convert_dds_to_driven_controls +from .driven_controls import convert_dds_to_driven_control class DynamicDecouplingSequence(QctrlObject): #pylint: disable=too-few-public-methods @@ -292,7 +292,7 @@ def export_to_file(self, filename=None, integration with Q-CTRL BLACK OPAL's 1-Qubit workspace. """ - driven_control = convert_dds_to_driven_controls( + driven_control = convert_dds_to_driven_control( dynamic_decoupling_sequence=self, maximum_rabi_rate=maximum_rabi_rate, maximum_detuning_rate=maximum_detuning_rate, diff --git a/tests/test_dynamical_decoupling.py b/tests/test_dynamical_decoupling.py index b0666dc4..e65ed4cd 100644 --- a/tests/test_dynamical_decoupling.py +++ b/tests/test_dynamical_decoupling.py @@ -22,7 +22,7 @@ import numpy as np from qctrlopencontrols.exceptions import ArgumentsValueError from qctrlopencontrols import ( - DynamicDecouplingSequence, convert_dds_to_driven_controls) + DynamicDecouplingSequence, convert_dds_to_driven_control) def _remove_file(filename): @@ -298,10 +298,10 @@ def test_conversion_to_driven_controls(): _maximum_rabi_rate = 20*np.pi _maximum_detuning_rate = 20*np.pi - driven_control = convert_dds_to_driven_controls(dd_sequence, - maximum_rabi_rate=_maximum_rabi_rate, - maximum_detuning_rate=_maximum_detuning_rate, - name=_name) + driven_control = convert_dds_to_driven_control(dd_sequence, + maximum_rabi_rate=_maximum_rabi_rate, + maximum_detuning_rate=_maximum_detuning_rate, + name=_name) assert np.allclose(driven_control.rabi_rates, np.array( [0., _maximum_rabi_rate, 0., 0., 0., @@ -336,7 +336,7 @@ def test_free_evolution_conversion(): _maximum_rabi_rate = 20 * np.pi _maximum_detuning_rate = 20 * np.pi - driven_control = convert_dds_to_driven_controls( + driven_control = convert_dds_to_driven_control( dd_sequence, maximum_rabi_rate=_maximum_rabi_rate, maximum_detuning_rate=_maximum_detuning_rate, @@ -368,7 +368,7 @@ def test_free_evolution_conversion(): _maximum_rabi_rate = 20 * np.pi _maximum_detuning_rate = 20 * np.pi - driven_control = convert_dds_to_driven_controls( + driven_control = convert_dds_to_driven_control( dd_sequence, maximum_rabi_rate=_maximum_rabi_rate, maximum_detuning_rate=_maximum_detuning_rate, @@ -405,10 +405,11 @@ def test_export_to_file(): _maximum_rabi_rate = 20 * np.pi _maximum_detuning_rate = 20 * np.pi - driven_control = convert_dds_to_driven_controls(dd_sequence, - maximum_rabi_rate=_maximum_rabi_rate, - maximum_detuning_rate=_maximum_detuning_rate, - name=_name) + driven_control = convert_dds_to_driven_control( + dd_sequence, + maximum_rabi_rate=_maximum_rabi_rate, + maximum_detuning_rate=_maximum_detuning_rate, + name=_name) _filename = 'dds_qctrl_cylindrical.csv' driven_control.export_to_file( @@ -448,6 +449,5 @@ def test_export_to_file(): _remove_file('dds_qctrl_cartesian.json') - if __name__ == '__main__': pass From 7f78a2ae33efe613b3e4a5fe09c5b5506233ba4a Mon Sep 17 00:00:00 2001 From: Rajib Chakravorty Date: Thu, 30 May 2019 16:52:33 +1000 Subject: [PATCH 2/5] fixed the modified plot data array method --- qctrlopencontrols/driven_controls/driven_control.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/qctrlopencontrols/driven_controls/driven_control.py b/qctrlopencontrols/driven_controls/driven_control.py index e2d3b4f6..379764a1 100644 --- a/qctrlopencontrols/driven_controls/driven_control.py +++ b/qctrlopencontrols/driven_controls/driven_control.py @@ -502,7 +502,6 @@ def get_plot_formatted_arrays(self, coordinates=CARTESIAN, dimensionless_rabi_ra 'Unsupported coordinates provided: ', arguments={'coordinates': coordinates}) - if dimensionless_rabi_rate: normalizer = self.maximum_rabi_rate else: @@ -538,6 +537,11 @@ def get_plot_formatted_arrays(self, coordinates=CARTESIAN, dimensionless_rabi_ra plot_amplitude_z.append(coord_amplitude_z[i]) plot_amplitude_z.append(coord_amplitude_z[i + 1]) + plot_amplitude_x = np.array(plot_amplitude_x) + plot_amplitude_y = np.array(plot_amplitude_y) + plot_amplitude_z = np.array(plot_amplitude_z) + plot_time = np.array(plot_time) + plot_dictionary = { 'amplitudes_x': plot_amplitude_x, 'amplitudes_y': plot_amplitude_y, From 749bc3c69ee738cf4f9d39aa371a771ef522f738 Mon Sep 17 00:00:00 2001 From: Rajib Chakravorty Date: Fri, 31 May 2019 10:06:54 +1000 Subject: [PATCH 3/5] loop replacedment tested with notebooks --- .../driven_controls/driven_control.py | 55 ++++++++----------- 1 file changed, 23 insertions(+), 32 deletions(-) diff --git a/qctrlopencontrols/driven_controls/driven_control.py b/qctrlopencontrols/driven_controls/driven_control.py index 379764a1..28f0fc37 100644 --- a/qctrlopencontrols/driven_controls/driven_control.py +++ b/qctrlopencontrols/driven_controls/driven_control.py @@ -508,39 +508,30 @@ def get_plot_formatted_arrays(self, coordinates=CARTESIAN, dimensionless_rabi_ra normalizer = 1 if coordinates == CARTESIAN: - segments = np.vstack((self.amplitude_x / normalizer, - self.amplitude_y / normalizer, - self.detunings, - self.durations)).T + control_segments = np.vstack(( + self.amplitude_x / normalizer, + self.amplitude_y / normalizer, + self.detunings, + self.durations)).T elif coordinates == CYLINDRICAL: - segments = np.vstack((self.rabi_rates / normalizer, - self.azimuthal_angles, - self.detunings, - self.durations)).T - - segment_times = np.insert(np.cumsum(segments[:, 3]), 0, 0.) - coords = len(segment_times) - coord_amplitude_x = np.concatenate([[0.], segments[:, 0], [0.]]) - coord_amplitude_y = np.concatenate([[0.], segments[:, 1], [0.]]) - coord_amplitude_z = np.concatenate([[0.], segments[:, 2], [0.]]) - plot_time = [] - plot_amplitude_x = [] - plot_amplitude_y = [] - plot_amplitude_z = [] - for i in range(coords): - plot_time.append(segment_times[i]) - plot_time.append(segment_times[i]) - plot_amplitude_x.append(coord_amplitude_x[i]) - plot_amplitude_x.append(coord_amplitude_x[i + 1]) - plot_amplitude_y.append(coord_amplitude_y[i]) - plot_amplitude_y.append(coord_amplitude_y[i + 1]) - plot_amplitude_z.append(coord_amplitude_z[i]) - plot_amplitude_z.append(coord_amplitude_z[i + 1]) - - plot_amplitude_x = np.array(plot_amplitude_x) - plot_amplitude_y = np.array(plot_amplitude_y) - plot_amplitude_z = np.array(plot_amplitude_z) - plot_time = np.array(plot_time) + control_segments = np.vstack(( + self.rabi_rates / normalizer, + self.azimuthal_angles, + self.detunings, + self.durations)).T + + segment_times = np.insert(np.cumsum(control_segments[:, 3]), 0, 0.) + plot_time = (segment_times[:, np.newaxis] * np.ones((1, 2))).flatten() + plot_amplitude_x = control_segments[:, 0] + plot_amplitude_y = control_segments[:, 1] + plot_amplitude_z = control_segments[:, 2] + + plot_amplitude_x = np.concatenate( + ([0.], (plot_amplitude_x[:, np.newaxis] * np.ones((1, 2))).flatten(), [0.])) + plot_amplitude_y = np.concatenate( + ([0.], (plot_amplitude_y[:, np.newaxis] * np.ones((1, 2))).flatten(), [0.])) + plot_amplitude_z = np.concatenate( + ([0.], (plot_amplitude_z[:, np.newaxis] * np.ones((1, 2))).flatten(), [0.])) plot_dictionary = { 'amplitudes_x': plot_amplitude_x, From 18d3788085c453a929000dff143df8a6fcbab213 Mon Sep 17 00:00:00 2001 From: Rajib Chakravorty Date: Fri, 31 May 2019 12:25:15 +1000 Subject: [PATCH 4/5] returned plot_dictionary from 2 if blocks --- .../driven_controls/driven_control.py | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/qctrlopencontrols/driven_controls/driven_control.py b/qctrlopencontrols/driven_controls/driven_control.py index 28f0fc37..a6de2bad 100644 --- a/qctrlopencontrols/driven_controls/driven_control.py +++ b/qctrlopencontrols/driven_controls/driven_control.py @@ -533,27 +533,27 @@ def get_plot_formatted_arrays(self, coordinates=CARTESIAN, dimensionless_rabi_ra plot_amplitude_z = np.concatenate( ([0.], (plot_amplitude_z[:, np.newaxis] * np.ones((1, 2))).flatten(), [0.])) - plot_dictionary = { - 'amplitudes_x': plot_amplitude_x, - 'amplitudes_y': plot_amplitude_y, - 'detunings': plot_amplitude_z, - 'times': plot_time - } - - if coordinates == CYLINDRICAL: + plot_dictionary = {} + if coordinates == CARTESIAN: + plot_dictionary = { + 'amplitudes_x': plot_amplitude_x, + 'amplitudes_y': plot_amplitude_y, + 'detunings': plot_amplitude_z, + 'times': plot_time} + + elif coordinates == CYLINDRICAL: x_plot = plot_amplitude_x y_plot = plot_amplitude_y x_plot[np.equal(x_plot, -0.0)] = 0. y_plot[np.equal(y_plot, -0.0)] = 0. azimuthal_angles_plot = np.arctan2(y_plot, x_plot) amplitudes_plot = np.sqrt(np.abs(x_plot**2 + y_plot**2)) + plot_dictionary = { 'rabi_rates': amplitudes_plot, 'azimuthal_angles': azimuthal_angles_plot, 'detunings': plot_amplitude_z, - 'times': plot_time - } - + 'times': plot_time} return plot_dictionary def __str__(self): From 47cb297c5c087e98948903143a7340be27ede36e Mon Sep 17 00:00:00 2001 From: Rajib Chakravorty Date: Fri, 31 May 2019 12:33:08 +1000 Subject: [PATCH 5/5] lint friendly version to return plot_dictionary --- qctrlopencontrols/driven_controls/driven_control.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/qctrlopencontrols/driven_controls/driven_control.py b/qctrlopencontrols/driven_controls/driven_control.py index a6de2bad..874de8b6 100644 --- a/qctrlopencontrols/driven_controls/driven_control.py +++ b/qctrlopencontrols/driven_controls/driven_control.py @@ -541,7 +541,8 @@ def get_plot_formatted_arrays(self, coordinates=CARTESIAN, dimensionless_rabi_ra 'detunings': plot_amplitude_z, 'times': plot_time} - elif coordinates == CYLINDRICAL: + if coordinates == CYLINDRICAL: + x_plot = plot_amplitude_x y_plot = plot_amplitude_y x_plot[np.equal(x_plot, -0.0)] = 0.