diff --git a/qctrlopencontrols/driven_controls/driven_control.py b/qctrlopencontrols/driven_controls/driven_control.py index 49f5684f..6d8c301e 100644 --- a/qctrlopencontrols/driven_controls/driven_control.py +++ b/qctrlopencontrols/driven_controls/driven_control.py @@ -531,88 +531,6 @@ def export(self, coordinates=CYLINDRICAL, dimensionless_rabi_rate=True): return plot_dictionary - def get_plot_formatted_arrays(self, coordinates=CARTESIAN, dimensionless_rabi_rate=True): - """ Gets arrays for plotting a driven control. - - Parameters - ---------- - dimensionless_rabi_rate: boolean - If True, calculates the dimensionless values for segments - coordinates : string - Indicated the type of segments that need to be transformed can be 'cartesian' or - 'cylindrical'. - - Returns - ------- - dict - A dict with keywords depending on the chosen coordinates. For 'cylindrical', we have - 'rabi_rate', 'azimuthal_angle', 'detuning' and 'times', and for 'cartesian' we have - 'amplitude_x', 'amplitude_y', 'detuning' and 'times'. - - Notes - ----- - The plot data can have repeated times and for amplitudes, 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. - - Raises - ------ - 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: - control_segments = np.vstack(( - self.amplitude_x / normalizer, - self.amplitude_y / normalizer, - self.detunings, - self.durations)).T - elif coordinates == CYLINDRICAL: - 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 = {} - if coordinates == CARTESIAN: - plot_dictionary = { - 'amplitudes_x': plot_amplitude_x, - 'amplitudes_y': plot_amplitude_y, - 'detunings': plot_amplitude_z, - 'times': plot_time} - - if coordinates == CYLINDRICAL: - plot_dictionary = { - 'rabi_rates': plot_amplitude_x, - 'azimuthal_angles': plot_amplitude_y, - 'detunings': plot_amplitude_z, - 'times': plot_time} - return plot_dictionary - def __str__(self): """Prepares a friendly string format for a Driven Control """ diff --git a/qctrlopencontrols/dynamic_decoupling_sequences/dynamic_decoupling_sequence.py b/qctrlopencontrols/dynamic_decoupling_sequences/dynamic_decoupling_sequence.py index 5d71e132..2fc2db4b 100644 --- a/qctrlopencontrols/dynamic_decoupling_sequences/dynamic_decoupling_sequence.py +++ b/qctrlopencontrols/dynamic_decoupling_sequences/dynamic_decoupling_sequence.py @@ -170,68 +170,6 @@ def export(self): return plot_dictionary - def get_plot_formatted_arrays(self, plot_format=MATPLOTLIB): - """Gets arrays for plotting a pulse. - - Parameters - ---------- - plot_format : string, optional - Indicates the format of the plot; Defaults to `matplotlib` - - Returns - ------- - dict - A dict with keywords 'rabi_rotations', 'azimuthal_angles', - 'detuning_rotations' and 'times'. - - Raises - ------ - ArgumentsValueError - Raised if `plot_format` is not recognized. - """ - - if plot_format != MATPLOTLIB: - raise ArgumentsValueError("Open Controls currently supports `matplotlib` " - "data format only.", - {'data_format': plot_format}) - - offsets = self.offsets - number_of_offsets = self.number_of_offsets - - plot_data = dict() - - rabi_rotations = self.rabi_rotations - azimuthal_angles = self.azimuthal_angles - detuning_rotations = self.detuning_rotations - - rabi_rotations = np.reshape(rabi_rotations, (-1, 1)) - azimuthal_angles = np.reshape(azimuthal_angles, (-1, 1)) - detuning_rotations = np.reshape(detuning_rotations, (-1, 1)) - - plot_times = offsets[:, np.newaxis] - plot_times = np.repeat(plot_times, 3, axis=1) - - multiplier = np.array([0, 1, 0]) - multiplier = multiplier[np.newaxis, :] - multiplier = np.repeat(multiplier, number_of_offsets, axis=0) - multiplier = multiplier[np.newaxis, :] - - rabi_rotations = rabi_rotations * multiplier - azimuthal_angles = azimuthal_angles * multiplier - detuning_rotations = detuning_rotations * multiplier - - plot_times = plot_times.flatten() - rabi_rotations = rabi_rotations.flatten() - azimuthal_angles = azimuthal_angles.flatten() - detuning_rotations = detuning_rotations.flatten() - - plot_data['rabi_rotations'] = rabi_rotations - plot_data['azimuthal_angles'] = azimuthal_angles - plot_data['detuning_rotations'] = detuning_rotations - plot_data['times'] = plot_times - - return plot_data - def __repr__(self): """Returns a string representation for the object. The returned string looks like a valid Python expression that could be used to recreate the object, including default arguments. diff --git a/tests/test_driven_controls.py b/tests/test_driven_controls.py index 564987f9..487f58ae 100644 --- a/tests/test_driven_controls.py +++ b/tests/test_driven_controls.py @@ -197,19 +197,20 @@ def test_plot_data(): durations=_durations ) - x_amplitude = [0., np.pi, np.pi, 0., 0., 0., 0., 0.] - y_amplitude = [0., 0., 0., 2*np.pi, 2*np.pi, -np.pi, -np.pi, 0.] - z_amplitude = [0., 0., 0., 1., 1., 0., 0., 0.] - times = [0., 0., 1., 1., 2.25, 2.25, 3.75, 3.75] + x_amplitude = [np.pi, 0., 0.] + y_amplitude = [0., 2*np.pi, -np.pi] - plot_data = driven_control.get_plot_formatted_arrays( + plot_data = driven_control.export( dimensionless_rabi_rate=False, coordinates='cartesian' ) - assert np.allclose(plot_data['times'], times) - assert np.allclose(plot_data['amplitudes_x'], x_amplitude) - assert np.allclose(plot_data['amplitudes_y'], y_amplitude) - assert np.allclose(plot_data['detunings'], z_amplitude) + assert np.allclose([point['duration'] for point in plot_data['X amplitude']], _durations) + assert np.allclose([point['duration'] for point in plot_data['Y amplitude']], _durations) + assert np.allclose([point['duration'] for point in plot_data['Detuning']], _durations) + + assert np.allclose([point['value'] for point in plot_data['X amplitude']], x_amplitude) + assert np.allclose([point['value'] for point in plot_data['Y amplitude']], y_amplitude) + assert np.allclose([point['value'] for point in plot_data['Detuning']], _detunings) def test_pretty_print(): diff --git a/tests/test_dynamical_decoupling.py b/tests/test_dynamical_decoupling.py index 50fb21b0..b3a3fc3e 100644 --- a/tests/test_dynamical_decoupling.py +++ b/tests/test_dynamical_decoupling.py @@ -133,28 +133,6 @@ def test_sequence_plot(): _azimuthal_angle = np.array([0, 0, 0, 0, 0]) _detuning_rotations = np.array([0, 0, 0, 0, 0]) - _plot_times = np.array([0, 0, 0, - 0.25, 0.25, 0.25, - 0.5, 0.5, 0.5, - 0.75, 0.75, 0.75, - 1., 1., 1.]) - _plot_rabi_rotations = np.array([0, 0, 0, - 0, np.pi, 0, - 0, 0, 0, - 0, np.pi, 0, - 0, 0, 0]) - _plot_azimuthal_angles = np.array([0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0]) - - _plot_detuning_rotations = np.array([0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0]) - seq = DynamicDecouplingSequence( duration=1.0, offsets=_offsets, @@ -162,18 +140,20 @@ def test_sequence_plot(): azimuthal_angles=_azimuthal_angle, detuning_rotations=_detuning_rotations) - plot_data = seq.get_plot_formatted_arrays() - plot_rabi, plot_azimuthal, plot_detuning, plot_times = ( - plot_data['rabi_rotations'], - plot_data['azimuthal_angles'], - plot_data['detuning_rotations'], - plot_data['times'] - ) + plot_data = seq.export() + + _plot_rabi_offsets = [pulse['offset'] for pulse in plot_data['Rabi']] + _plot_detuning_offsets = [pulse['offset'] for pulse in plot_data['Detuning']] + _plot_rabi_rotations = [pulse['rotation'] for pulse in plot_data['Rabi']] + _plot_detuning_rotations = [pulse['rotation'] for pulse in plot_data['Detuning']] + + assert np.allclose(_plot_rabi_offsets, _offsets) + assert np.allclose(_plot_detuning_offsets, _offsets) + + assert np.allclose(np.abs(_plot_rabi_rotations), _rabi_rotations) + assert np.allclose(np.angle(_plot_rabi_rotations), _azimuthal_angle) - assert np.allclose(_plot_rabi_rotations, plot_rabi) - assert np.allclose(_plot_azimuthal_angles, plot_azimuthal) - assert np.allclose(_plot_detuning_rotations, plot_detuning) - assert np.allclose(_plot_times, plot_times) + assert np.allclose(_plot_detuning_rotations, _detuning_rotations) # with both X and Y pi _offsets = np.array([0, 0.25, 0.5, 0.75, 1.00]) @@ -181,28 +161,6 @@ def test_sequence_plot(): _azimuthal_angle = np.array([0, np.pi/2, 0, np.pi/2, 0]) _detuning_rotations = np.array([0, 0, 0, 0, 0]) - _plot_rabi_rotations = np.array([0, 0, 0, - 0, np.pi, 0, - 0, 0, 0, - 0, np.pi, 0, - 0, 0, 0]) - _plot_azimuthal_angles = np.array([0, 0, 0, - 0, np.pi/2, 0, - 0, 0, 0, - 0, np.pi/2, 0, - 0, 0, 0]) - - _plot_detuning_rotations = np.array([0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0, - 0, 0, 0]) - - _plot_times = np.array([0, 0, 0, - 0.25, 0.25, 0.25, - 0.5, 0.5, 0.5, - 0.75, 0.75, 0.75, - 1., 1., 1.]) seq = DynamicDecouplingSequence( duration=1.0, offsets=_offsets, @@ -210,18 +168,20 @@ def test_sequence_plot(): azimuthal_angles=_azimuthal_angle, detuning_rotations=_detuning_rotations) - plot_data = seq.get_plot_formatted_arrays() - plot_rabi, plot_azimuthal, plot_detuning, plot_times = ( - plot_data['rabi_rotations'], - plot_data['azimuthal_angles'], - plot_data['detuning_rotations'], - plot_data['times'] - ) + plot_data = seq.export() + + _plot_rabi_offsets = [pulse['offset'] for pulse in plot_data['Rabi']] + _plot_detuning_offsets = [pulse['offset'] for pulse in plot_data['Detuning']] + _plot_rabi_rotations = [pulse['rotation'] for pulse in plot_data['Rabi']] + _plot_detuning_rotations = [pulse['rotation'] for pulse in plot_data['Detuning']] + + assert np.allclose(_plot_rabi_offsets, _offsets) + assert np.allclose(_plot_detuning_offsets, _offsets) + + assert np.allclose(np.abs(_plot_rabi_rotations), _rabi_rotations) + assert np.allclose(np.angle(_plot_rabi_rotations), _azimuthal_angle) - assert np.allclose(_plot_rabi_rotations, plot_rabi) - assert np.allclose(_plot_azimuthal_angles, plot_azimuthal) - assert np.allclose(_plot_detuning_rotations, plot_detuning) - assert np.allclose(_plot_times, plot_times) + assert np.allclose(_plot_detuning_rotations, _detuning_rotations) def test_pretty_string_format():