From 95067640b9ddbb3860e5c2c534730599dec010ee Mon Sep 17 00:00:00 2001 From: Harry Slatyer Date: Fri, 4 Sep 2020 12:19:32 +1000 Subject: [PATCH 01/27] Fix scheme names and make private function names consistent For the private function names I've opted to make them consistent with the scheme names, since those are presumably the most natural ways to refer to them. Plan is to make the private functions public, and document those functions with full details. Eventually we can probably delete the new_predefined_driven_control, although it's fine to stick around for a while for compatibility purposes. https://q-ctrl.atlassian.net/browse/QENG-1118 --- .../driven_controls/predefined.py | 56 ++++++++----------- 1 file changed, 24 insertions(+), 32 deletions(-) diff --git a/qctrlopencontrols/driven_controls/predefined.py b/qctrlopencontrols/driven_controls/predefined.py index 1a3a02da..0014e045 100644 --- a/qctrlopencontrols/driven_controls/predefined.py +++ b/qctrlopencontrols/driven_controls/predefined.py @@ -44,22 +44,22 @@ def new_predefined_driven_control(scheme: str = PRIMITIVE, **kwargs): """ - Create a new driven control + Creates a new driven control based on the given scheme. Parameters ---------- scheme : string, optional - Defaults to None. The name of the driven control type, + Defaults to 'primitive'. The name of the driven control type, supported options are: - 'primitive' - - 'wimperis_1' - - 'solovay_kitaev_1' - - 'compensating_for_off_resonance_with_a_pulse_sequence' - - 'compensating_for_off_resonance_with_a_pulse_sequence_with_wimperis' - - 'compensating_for_off_resonance_with_a_pulse_sequence_with_solovay_kitaev' - - 'walsh_amplitude_modulated_filter_1' - - 'short_composite_rotation_for_undoing_length_over_and_under_shoot' - - 'corpse_in_scrofulous' + - 'BB1' + - 'SK1' + - 'CORPSE' + - 'CORPSE in BB1' + - 'CORPSE in SK1' + - 'WAMF1' + - 'SCROFULOUS' + - 'CORPSE in SCROFULOUS' kwargs : dict, optional options to make the corresponding control type. @@ -78,27 +78,19 @@ def new_predefined_driven_control(scheme: str = PRIMITIVE, **kwargs): if scheme == PRIMITIVE: driven_control = _new_primitive_control(**kwargs) elif scheme == BB1: - driven_control = _new_wimperis_1_control(**kwargs) + driven_control = _new_bb1_control(**kwargs) elif scheme == SK1: - driven_control = _new_solovay_kitaev_1_control(**kwargs) + driven_control = _new_sk1_control(**kwargs) elif scheme == WAMF1: - driven_control = _new_walsh_amplitude_modulated_filter_1_control(**kwargs) + driven_control = _new_wamf1_control(**kwargs) elif scheme == CORPSE: - driven_control = _new_compensating_for_off_resonance_with_a_pulse_sequence_control( - **kwargs - ) + driven_control = _new_corpse_control(**kwargs) elif scheme == CORPSE_IN_BB1: - driven_control = _new_compensating_for_off_resonance_with_a_sequence_with_wimperis_control( - **kwargs - ) + driven_control = _new_corpse_in_bb1_control(**kwargs) elif scheme == CORPSE_IN_SK1: - driven_control = _new_compensating_for_off_resonance_with_a_sequence_with_sk_control( - **kwargs - ) + driven_control = _new_corpse_in_sk1_control(**kwargs) elif scheme == SCROFULOUS: - driven_control = _short_composite_rotation_for_undoing_length_over_under_shoot_control( - **kwargs - ) + driven_control = _new_scrofulous_control(**kwargs) elif scheme == CORPSE_IN_SCROFULOUS: driven_control = _new_corpse_in_scrofulous_control(**kwargs) else: @@ -257,7 +249,7 @@ def _new_primitive_control( ) -def _new_wimperis_1_control( +def _new_bb1_control( rabi_rotation: float, azimuthal_angle: float = 0.0, maximum_rabi_rate: float = 2.0 * np.pi, @@ -312,7 +304,7 @@ def _new_wimperis_1_control( ) -def _new_solovay_kitaev_1_control( +def _new_sk1_control( rabi_rotation: float, azimuthal_angle: float = 0.0, maximum_rabi_rate: float = 2.0 * np.pi, @@ -366,7 +358,7 @@ def _new_solovay_kitaev_1_control( ) -def _short_composite_rotation_for_undoing_length_over_under_shoot_control( +def _new_scrofulous_control( rabi_rotation: float, azimuthal_angle: float = 0.0, maximum_rabi_rate: float = 2.0 * np.pi, @@ -457,7 +449,7 @@ def degrees_to_radians(angle_in_degrees): ) -def _new_compensating_for_off_resonance_with_a_pulse_sequence_control( +def _new_corpse_control( rabi_rotation: float, azimuthal_angle: float = 0.0, maximum_rabi_rate: float = 2.0 * np.pi, @@ -511,7 +503,7 @@ def _new_compensating_for_off_resonance_with_a_pulse_sequence_control( ) -def _new_compensating_for_off_resonance_with_a_sequence_with_wimperis_control( +def _new_corpse_in_bb1_control( rabi_rotation: float, azimuthal_angle: float = 0.0, maximum_rabi_rate: float = 2.0 * np.pi, @@ -579,7 +571,7 @@ def _new_compensating_for_off_resonance_with_a_sequence_with_wimperis_control( ) -def _new_compensating_for_off_resonance_with_a_sequence_with_sk_control( +def _new_corpse_in_sk1_control( rabi_rotation: float, azimuthal_angle: float = 0.0, maximum_rabi_rate: float = 2.0 * np.pi, @@ -745,7 +737,7 @@ def degrees_to_radians(angle_in_degrees): ) -def _new_walsh_amplitude_modulated_filter_1_control( +def _new_wamf1_control( rabi_rotation: float, azimuthal_angle: float = 0.0, maximum_rabi_rate: float = 2.0 * np.pi, From 18f02f30e72aea36dd004ab0263838e068bfad5c Mon Sep 17 00:00:00 2001 From: Harry Slatyer Date: Fri, 4 Sep 2020 14:13:48 +1000 Subject: [PATCH 02/27] Fix some docstring formatting --- .../driven_controls/predefined.py | 11 ++++++---- .../predefined.py | 21 ++++++++++--------- 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/qctrlopencontrols/driven_controls/predefined.py b/qctrlopencontrols/driven_controls/predefined.py index 0014e045..dc420fd4 100644 --- a/qctrlopencontrols/driven_controls/predefined.py +++ b/qctrlopencontrols/driven_controls/predefined.py @@ -49,8 +49,8 @@ def new_predefined_driven_control(scheme: str = PRIMITIVE, **kwargs): Parameters ---------- scheme : string, optional - Defaults to 'primitive'. The name of the driven control type, - supported options are: + The name of the driven control type, supported options are: + - 'primitive' - 'BB1' - 'SK1' @@ -60,13 +60,16 @@ def new_predefined_driven_control(scheme: str = PRIMITIVE, **kwargs): - 'WAMF1' - 'SCROFULOUS' - 'CORPSE in SCROFULOUS' + + Defaults to 'primitive'. + kwargs : dict, optional - options to make the corresponding control type. + Additional keyword argument to create the control. Returns ------- qctrlopencontrols.DrivenControls - Returns a driven control corresponding to the driven_control_type. + A driven control corresponding to `scheme`. Raises ------ diff --git a/qctrlopencontrols/dynamic_decoupling_sequences/predefined.py b/qctrlopencontrols/dynamic_decoupling_sequences/predefined.py index 1d08ca33..02422e54 100644 --- a/qctrlopencontrols/dynamic_decoupling_sequences/predefined.py +++ b/qctrlopencontrols/dynamic_decoupling_sequences/predefined.py @@ -162,31 +162,32 @@ def _add_pre_post_rotations( def new_predefined_dds(scheme=SPIN_ECHO, **kwargs): """ - Create a new instance of one of the predefined - dynamic decoupling sequences. + Creates a new instance of one of the predefined dynamic decoupling sequences. Parameters ---------- scheme : string - The name of the sequence; Defaults to 'Spin echo' - Available options are, + The name of the sequence. The available options are: + - 'Ramsey' - - 'Spin echo', - - 'Carr-Purcell', - - 'Carr-Purcell-Meiboom-Gill', + - 'spin echo' + - 'Carr-Purcell' + - 'Carr-Purcell-Meiboom-Gill' - 'Uhrig single-axis' - 'Periodic single-axis' - 'Walsh single-axis' - - 'Quadratic' + - 'quadratic' - 'X concatenated' - 'XY concatenated' + + Defaults to 'spin echo'. kwargs : dict, optional - Additional keyword argument to create the sequence + Additional keyword argument to create the sequence. Returns ------ qctrlopencontrols.dynamic_decoupling_sequences.DynamicDecouplingSequence - Returns a sequence corresponding to the name + A dynamical decuopling sequence corresponding to `scheme`. Raises ----- From 849defb08221c08fc3a0ec14b4ba3d608fda6369 Mon Sep 17 00:00:00 2001 From: Harry Slatyer Date: Fri, 4 Sep 2020 14:15:34 +1000 Subject: [PATCH 03/27] Consistency --- qctrlopencontrols/driven_controls/predefined.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/qctrlopencontrols/driven_controls/predefined.py b/qctrlopencontrols/driven_controls/predefined.py index dc420fd4..3f6a071d 100644 --- a/qctrlopencontrols/driven_controls/predefined.py +++ b/qctrlopencontrols/driven_controls/predefined.py @@ -49,7 +49,7 @@ def new_predefined_driven_control(scheme: str = PRIMITIVE, **kwargs): Parameters ---------- scheme : string, optional - The name of the driven control type, supported options are: + The name of the driven control type. The available options are: - 'primitive' - 'BB1' @@ -62,7 +62,6 @@ def new_predefined_driven_control(scheme: str = PRIMITIVE, **kwargs): - 'CORPSE in SCROFULOUS' Defaults to 'primitive'. - kwargs : dict, optional Additional keyword argument to create the control. From 6ee2860ea7587139bc3c520d73d12c99f4ebc943 Mon Sep 17 00:00:00 2001 From: Harry Slatyer Date: Fri, 4 Sep 2020 15:16:16 +1000 Subject: [PATCH 04/27] Lots of documentation --- .../driven_controls/driven_control.py | 117 ++++++++++-------- 1 file changed, 68 insertions(+), 49 deletions(-) diff --git a/qctrlopencontrols/driven_controls/driven_control.py b/qctrlopencontrols/driven_controls/driven_control.py index 122bce4f..49c3682c 100644 --- a/qctrlopencontrols/driven_controls/driven_control.py +++ b/qctrlopencontrols/driven_controls/driven_control.py @@ -38,31 +38,52 @@ class DrivenControl: - """ - Creates a driven control. A driven is a set of segments made up of amplitude vectors - and corresponding durations. + r""" + A piecewise-constant driven control for a single qubit. Parameters ---------- rabi_rates : np.ndarray, optional - 1-D array of size nx1 where n is number of segments; - Each entry is the rabi rate for the segment. Defaults to None. + The Rabi rates :math:`\{\Omega_n\}` for each segment, in units of radians per second. Every + element must be non-negative. Represented as a 1D array of length :math:`N`, where :math:`N` + is number of segments. You can omit this field if the Rabi rate is zero on all segments. azimuthal_angles : np.ndarray, optional - 1-D array of size nx1 where n is the number of segments; - Each entry is the azimuthal angle for the segment; Defaults to None. + The azimuthal angles :math:`\{\phi_n\}` for each segment. Represented as a 1D array of + length :math:`N`, where :math:`N` is number of segments. You can omit this field if the + azimuthal angle is zero on all segments. detunings : np.ndarray, optional - 1-D array of size nx1 where n is the number of segments; - Each entry is the detuning angle for the segment; Defaults to None. + The detunings :math:`\{\Delta_n\}` for each segment, in units of radians per second. + Represented as a 1D array of length :math:`N`, where :math:`N` is number of segments. You + can omit this field if the detuning is zero on all segments. durations : np.ndarray, optional - 1-D array of size nx1 where n is the number of segments; - Each entry is the duration of the segment (in seconds); Defaults to None. + The durations :math:`\{\delta t_n\}` for each segment, in units seconds. Every element must + be positive. Represented as a 1D array of length :math:`N`, where :math:`N` is number of + segments. Defaults to an array of ones if omitted. name : string, optional - An optional string to name the driven control. Defaults to None. + An optional string to name the control. Defaults to ``None``. Raises ------ ArgumentsValueError Raised when an argument is invalid. + + Notes + ----- + This class represents a control for a single driven qubit with Hamiltonian: + + .. math:: + + H(t) = \frac{1}{2}\left(\Omega(t) e^{i\phi(t)} \sigma_- + + \Omega(t) e^{-i\phi(t)}\sigma_+\right) + + \frac{1}{2}\Delta(t)\sigma_z, + + where :math:`\Omega(t)` is the Rabi rate, :math:`\phi(t)` is the azimuthal angle (or drive + phase), :math:`\Delta(t)` is the detuning, :math:`\sigma_\pm = (\sigma_x \mp \sigma_y)/2`, + and :math:`\sigma_k` are the Pauli matrices. + + The controls are piecewise-constant, meaning :math:`\Omega(t)=\Omega_n` for + :math:`t_{n-1}\leq t int: Returns ------- int - The number of segments in the driven control. + The number of segments in the driven control, :math:`N`. """ return self.rabi_rates.shape[0] @@ -203,12 +224,12 @@ def number_of_segments(self) -> int: @property def maximum_rabi_rate(self) -> float: """ - Returns the maximum rabi rate of the control. + Returns the maximum Rabi rate of the control. Returns ------- float - The maximum rabi rate of the control. + The maximum Rabi rate of the control, :math:`\max_n \Omega_n`. """ return np.amax(self.rabi_rates) @@ -221,19 +242,19 @@ def maximum_detuning(self) -> float: Returns ------- float - The maximum detuning of the control. + The maximum detuning of the control, :math:`\max_n \Delta_n`. """ return np.amax(self.detunings) @property def amplitude_x(self) -> np.ndarray: """ - Return the X-Amplitude. + Returns the X-Amplitude. Returns ------- np.ndarray - X-Amplitude of each segment. + The X-Amplitude of each segment, :math:`\{\Omega_n \cos \phi_n\}`. """ return self.rabi_rates * np.cos(self.azimuthal_angles) @@ -241,12 +262,12 @@ def amplitude_x(self) -> np.ndarray: @property def amplitude_y(self) -> np.ndarray: """ - Return the Y-Amplitude. + Returns the Y-Amplitude. Returns ------- np.ndarray - Y-Amplitude of each segment. + The Y-Amplitude of each segment, :math:`\{\Omega_n \sin \phi_n\}`. """ return self.rabi_rates * np.sin(self.azimuthal_angles) @@ -254,12 +275,13 @@ def amplitude_y(self) -> np.ndarray: @property def angles(self) -> np.ndarray: """ - Returns the angles. + Returns the Bloch sphere rotation angles. Returns ------- np.ndarray - Angles as 1-D array of floats. + The total Bloch sphere rotation angles on each segment, + :math:`\{(\Omega_n^2+\Delta_n^2)\delta t_n\}`. """ amplitudes = np.sqrt( @@ -271,14 +293,15 @@ def angles(self) -> np.ndarray: @property def directions(self) -> np.ndarray: - """ - Returns the directions. + Returns the Bloch sphere rotation directions. Returns ------- np.ndarray - Directions as 1-D array of floats. + The Bloch sphere rotation direction on each segment, + :math:`\{\mathbf v_n/\|\mathbf v_n\|\}`, where + :math:`\mathbf v_n=(\Omega_n\cos\phi_n, \Omega_n\sin\phi_n, \Delta_n)`. """ amplitudes = np.sqrt( self.amplitude_x ** 2 + self.amplitude_y ** 2 + self.detunings ** 2 @@ -310,13 +333,13 @@ def directions(self) -> np.ndarray: @property def times(self) -> np.ndarray: """ - Returns the time of each segment within the duration - of the control. + Returns the boundary times of the control segments. Returns ------ np.ndarray - Segment times as 1-D array of floats. + The boundary times of the control segments, :math:`\{t_{n-1}\}` (starting with + :math:`t_0=0`). """ return np.insert(np.cumsum(self.durations), 0, 0.0) @@ -324,12 +347,12 @@ def times(self) -> np.ndarray: @property def maximum_duration(self) -> float: """ - Returns the maximum duration of all the control segments. + Returns the duration of the longest control segment. Returns ------- float - The maximum duration of all the control segments. + The duration of the longest control segment, :math:`\max_n \delta t_n`. """ return np.amax(self.durations) @@ -337,12 +360,12 @@ def maximum_duration(self) -> float: @property def minimum_duration(self) -> float: """ - Returns the minimum duration of all the control segments. + Returns the duration of the shortest control segment. Returns ------- float - The minimum duration of all the controls segments. + The duration of the shortest control segment, :math:`\min_n \delta t_n`. """ return np.amin(self.durations) @@ -355,7 +378,7 @@ def duration(self) -> float: Returns ------- float - Total duration of the control. + The total duration of the control, :math:`t_N=\sum_n \delta t_n`. """ return np.sum(self.durations) @@ -480,34 +503,30 @@ def export_to_file( file_type=FileType.CSV.value, coordinates=Coordinate.CYLINDRICAL.value, ): - """Prepares and saves the driven control in a file. + """ + Prepares and saves the driven control in a file. Parameters ---------- - filename : str, optional + filename : str Name and path of the file to save the control into. - Defaults to None file_format : str - Specified file format for saving the control. Defaults to - 'Q-CTRL expanded'; Currently it does not support any other format. - For detail of the `Q-CTRL Expanded Format` consult - `Q-CTRL Control Data Format - ` _. + Specified file format for saving the control. Defaults to 'Q-CTRL expanded'. Currently + does not support any other format. For detail of the Q-CTRL expanded format, see below. file_type : str, optional - One of 'CSV' or 'JSON'; defaults to 'CSV'. + One of 'CSV' or 'JSON'. Defaults to 'CSV'. coordinates : str, optional - Indicates the co-ordinate system requested. Must be one of - 'cylindrical', 'cartesian'; defaults to 'cylindrical' - - References - ---------- - `Q-CTRL Control Data Format - ` _. + The coordinate system in which to save the control. Must be 'cylindrical' or + 'cartesian'. Defaults to 'cylindrical'. Raises ------ ArgumentsValueError Raised if some of the parameters are invalid. + + Notes + ----- + The Q-CTRL expanded format can """ _file_types = [v.value for v in FileType] _file_formats = [v.value for v in FileFormat] From c5302dfcbd0514f3cc1bceb371dba6d0f8ecca82 Mon Sep 17 00:00:00 2001 From: Harry Slatyer Date: Fri, 4 Sep 2020 15:19:46 +1000 Subject: [PATCH 05/27] Fix scaling of amplitudes when exporting controls The amplitudes and Rabi rates are supposed to be given in proportion to the maximum Rabi rate: https://docs.q-ctrl.com/wiki/output-data-formats#q-ctrl-hardware https://q-ctrl.atlassian.net/browse/QENG-1118 --- .../driven_controls/driven_control.py | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/qctrlopencontrols/driven_controls/driven_control.py b/qctrlopencontrols/driven_controls/driven_control.py index 122bce4f..5133e788 100644 --- a/qctrlopencontrols/driven_controls/driven_control.py +++ b/qctrlopencontrols/driven_controls/driven_control.py @@ -388,8 +388,8 @@ def _qctrl_expanded_export_content(self, file_type, coordinates): for segment_idx in range(self.number_of_segments): control_info.append( "{},{},{},{},{}".format( - amplitude_x[segment_idx], - amplitude_y[segment_idx], + amplitude_x[segment_idx] / self.maximum_rabi_rate, + amplitude_y[segment_idx] / self.maximum_rabi_rate, self.detunings[segment_idx], self.durations[segment_idx], self.maximum_rabi_rate, @@ -400,8 +400,8 @@ def _qctrl_expanded_export_content(self, file_type, coordinates): if self.name is not None: control_info["name"] = self.name control_info["maximum_rabi_rate"] = self.maximum_rabi_rate - control_info["amplitude_x"] = list(amplitude_x) - control_info["amplitude_y"] = list(amplitude_y) + control_info["amplitude_x"] = list(amplitude_x / self.maximum_rabi_rate) + control_info["amplitude_y"] = list(amplitude_y / self.maximum_rabi_rate) control_info["detuning"] = list(self.detunings) control_info["duration"] = list(self.durations) @@ -416,9 +416,7 @@ def _qctrl_expanded_export_content(self, file_type, coordinates): control_info.append( "{},{},{},{},{}".format( self.rabi_rates[segment_idx] / self.maximum_rabi_rate, - np.arctan2( - amplitude_y[segment_idx], amplitude_x[segment_idx] - ), + self.azimuthal_angles[segment_idx], self.detunings[segment_idx], self.durations[segment_idx], self.maximum_rabi_rate, @@ -433,9 +431,7 @@ def _qctrl_expanded_export_content(self, file_type, coordinates): control_info["rabi_rates"] = list( self.rabi_rates / self.maximum_rabi_rate ) - control_info["azimuthal_angles"] = list( - np.arctan2(amplitude_y, amplitude_x) - ) + control_info["azimuthal_angles"] = list(self.azimuthal_angles) control_info["detuning"] = list(self.detunings) control_info["duration"] = list(self.durations) From 5928584e5932a8d85ca452609cad2fb02a4ae98a Mon Sep 17 00:00:00 2001 From: Harry Slatyer Date: Fri, 4 Sep 2020 16:03:44 +1000 Subject: [PATCH 06/27] docs docs docs --- .../driven_controls/driven_control.py | 55 +++++++++++++++++-- 1 file changed, 49 insertions(+), 6 deletions(-) diff --git a/qctrlopencontrols/driven_controls/driven_control.py b/qctrlopencontrols/driven_controls/driven_control.py index 7b45af10..a5656cf1 100644 --- a/qctrlopencontrols/driven_controls/driven_control.py +++ b/qctrlopencontrols/driven_controls/driven_control.py @@ -522,7 +522,49 @@ def export_to_file( Notes ----- - The Q-CTRL expanded format can + The Q-CTRL expanded format is designed for direct integration of control solutions into + experimental hardware. The format represents controls as vectors defined for the relevant + operators sampled in time (corresponding to the segmentation of the Rabi rate, azimuthal + angle, and detuning). + + The exact data produced depends on the file type and coordinate system. In all cases, the + data contain four lists of real floating point numbers. Each list has the same length, and + the :math:`n`'th element of each list describes the :math:`n`'th segment of the driven + control. + + For Cartesian coordinates, the four lists are X-amplitude, Y-amplitude, detuning, and + duration. The maximum Rabi rate is also included in the data, and the X-amplitude and + Y-amplitude are normalized to that maximum Rabi rate. + + For cylndrical coordinates, the four lists are Rabi rate, azimuthal angle, detuning, and + duration. The maximum Rabi rate is also included in the data, and the the Rabi rate is + normalized to the maximum Rabi rate. + + For CSV, the data are output as five columns, with one row of titles, followed by rows of + data. The maximum Rabi rate is the same in each row. For JSON, the data are output as a + single object with four appropriately-named arrays, a "maximum_rabi_rate" field giving the + maximum Rabi rate, and optionally a "name" field giving the `name` of the control. + + For example, the CSV cylindrical representation of a control with two segments would be:: + + rabi_rate,azimuthal_angle,detuning,duration,maximum_rabi_rate + 0.8,1.57,3000000.,0.000001,10000000 + 1.0,3.14,-3000000.,0.000002,1000000 + + Note that the Rabi rate on each segment is normalized to the maximum Rabi rate. + + The JSON Cartesian representation of the same control would be:: + + { + "name": "a custom control", + "maximum_rabi_rate": 1000000, + "amplitude_x": [0.0,-1.0], + "amplitude_y": [0.8,0.0], + "detuning": [3000000.0,-3000000.0], + "duration": [0.000001,0.000002], + } + + Note that the amplitudes on each segment are normalized to the maximum Rabi rate. """ _file_types = [v.value for v in FileType] _file_formats = [v.value for v in FileFormat] @@ -563,20 +605,21 @@ def export( self, coordinates=Coordinate.CYLINDRICAL.value, dimensionless_rabi_rate=True ): - """ Returns a dictionary formatted for plotting using the qctrl-visualizer package. + """ + Returns a dictionary formatted for plotting using the qctrl-visualizer package. Parameters ---------- - dimensionless_rabi_rate: boolean - If True, normalizes the Rabi rate so that its largest absolute value is 1. coordinates: string Indicates whether the Rabi frequency should be plotted in terms of its - 'cylindrical' or 'cartesian' components. + 'cylindrical' or 'cartesian' components. Defaults to 'cylindrical'. + dimensionless_rabi_rate: boolean + If ``True``, normalizes the Rabi rate so that its largest absolute value is 1. Returns ------- dict - Dictionary with plot data that can be used by the plot_controls + Dictionary with plot data that can be used by the `plot_controls` method of the qctrl-visualizer package. It has keywords 'Rabi rate' and 'Detuning' for 'cylindrical' coordinates and 'X amplitude', 'Y amplitude', and 'Detuning' for 'cartesian' coordinates. From afcd30d12ed8b0fa688a1a2cb24e77293b1354c9 Mon Sep 17 00:00:00 2001 From: Harry Slatyer Date: Fri, 4 Sep 2020 16:07:06 +1000 Subject: [PATCH 07/27] tweaks --- .../driven_controls/driven_control.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/qctrlopencontrols/driven_controls/driven_control.py b/qctrlopencontrols/driven_controls/driven_control.py index a5656cf1..df49ff99 100644 --- a/qctrlopencontrols/driven_controls/driven_control.py +++ b/qctrlopencontrols/driven_controls/driven_control.py @@ -56,9 +56,9 @@ class DrivenControl: Represented as a 1D array of length :math:`N`, where :math:`N` is number of segments. You can omit this field if the detuning is zero on all segments. durations : np.ndarray, optional - The durations :math:`\{\delta t_n\}` for each segment, in units seconds. Every element must - be positive. Represented as a 1D array of length :math:`N`, where :math:`N` is number of - segments. Defaults to an array of ones if omitted. + The durations :math:`\{\delta t_n\}` for each segment, in units of seconds. Every element + must be positive. Represented as a 1D array of length :math:`N`, where :math:`N` is number + of segments. Defaults to an array of ones if omitted. name : string, optional An optional string to name the control. Defaults to ``None``. @@ -338,7 +338,7 @@ def times(self) -> np.ndarray: Returns ------ np.ndarray - The boundary times of the control segments, :math:`\{t_{n-1}\}` (starting with + The boundary times of the control segments, :math:`\{t_n}\}` (starting with :math:`t_0=0`). """ @@ -538,7 +538,7 @@ def export_to_file( For cylndrical coordinates, the four lists are Rabi rate, azimuthal angle, detuning, and duration. The maximum Rabi rate is also included in the data, and the the Rabi rate is - normalized to the maximum Rabi rate. + normalized to that maximum Rabi rate. For CSV, the data are output as five columns, with one row of titles, followed by rows of data. The maximum Rabi rate is the same in each row. For JSON, the data are output as a @@ -606,7 +606,7 @@ def export( ): """ - Returns a dictionary formatted for plotting using the qctrl-visualizer package. + Returns a dictionary formatted for plotting using the ``qctrl-visualizer`` package. Parameters ---------- @@ -620,7 +620,7 @@ def export( ------- dict Dictionary with plot data that can be used by the `plot_controls` - method of the qctrl-visualizer package. It has keywords 'Rabi rate' + method of the ``qctrl-visualizer`` package. It has keywords 'Rabi rate' and 'Detuning' for 'cylindrical' coordinates and 'X amplitude', 'Y amplitude', and 'Detuning' for 'cartesian' coordinates. From 19e6c01c9f1d04ffbc181b06c8bdfaa42bdd3277 Mon Sep 17 00:00:00 2001 From: Harry Slatyer Date: Fri, 4 Sep 2020 16:08:52 +1000 Subject: [PATCH 08/27] Temporarily add HTML for viewing convenience --- docs/_build/html/qctrlopencontrols.html | 751 ++++++++++++++++++++++++ 1 file changed, 751 insertions(+) create mode 100644 docs/_build/html/qctrlopencontrols.html diff --git a/docs/_build/html/qctrlopencontrols.html b/docs/_build/html/qctrlopencontrols.html new file mode 100644 index 00000000..a29f818f --- /dev/null +++ b/docs/_build/html/qctrlopencontrols.html @@ -0,0 +1,751 @@ + + + + + + + + + + + Q-CTRL Open Controls Python package — Open Controls Python package | Q-CTRL + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + +
+ +
+ + + + + + + + + + + + + + + + + +
+ +
    + +
  • Docs »
  • + +
  • Q-CTRL Open Controls Python package
  • + + + +
+ + +
+
+
+
+ +
+

Q-CTRL Open Controls Python package

+

Top-level package for Q-CTRL Open Controls.

+
+
+class qctrlopencontrols.DrivenControl(rabi_rates: Optional[numpy.ndarray] = None, azimuthal_angles: Optional[numpy.ndarray] = None, detunings: Optional[numpy.ndarray] = None, durations: Optional[numpy.ndarray] = None, name: Optional[str] = None)
+

Bases: object

+

A piecewise-constant driven control for a single qubit.

+
+
Parameters
+
    +
  • rabi_rates (np.ndarray, optional) – The Rabi rates \(\{\Omega_n\}\) for each segment, in units of radians per second. Every +element must be non-negative. Represented as a 1D array of length \(N\), where \(N\) +is number of segments. You can omit this field if the Rabi rate is zero on all segments.

  • +
  • azimuthal_angles (np.ndarray, optional) – The azimuthal angles \(\{\phi_n\}\) for each segment. Represented as a 1D array of +length \(N\), where \(N\) is number of segments. You can omit this field if the +azimuthal angle is zero on all segments.

  • +
  • detunings (np.ndarray, optional) – The detunings \(\{\Delta_n\}\) for each segment, in units of radians per second. +Represented as a 1D array of length \(N\), where \(N\) is number of segments. You +can omit this field if the detuning is zero on all segments.

  • +
  • durations (np.ndarray, optional) – The durations \(\{\delta t_n\}\) for each segment, in units of seconds. Every element +must be positive. Represented as a 1D array of length \(N\), where \(N\) is number +of segments. Defaults to an array of ones if omitted.

  • +
  • name (string, optional) – An optional string to name the control. Defaults to None.

  • +
+
+
Raises
+

ArgumentsValueError – Raised when an argument is invalid.

+
+
+

Notes

+

This class represents a control for a single driven qubit with Hamiltonian:

+
+\[H(t) = \frac{1}{2}\left(\Omega(t) e^{i\phi(t)} \sigma_- + + \Omega(t) e^{-i\phi(t)}\sigma_+\right) + + \frac{1}{2}\Delta(t)\sigma_z,\]
+

where \(\Omega(t)\) is the Rabi rate, \(\phi(t)\) is the azimuthal angle (or drive +phase), \(\Delta(t)\) is the detuning, \(\sigma_\pm = (\sigma_x \mp \sigma_y)/2\), +and \(\sigma_k\) are the Pauli matrices.

+

The controls are piecewise-constant, meaning \(\Omega(t)=\Omega_n\) for +\(t_{n-1}\leq t<t_n\), where \(t_0=0\) and \(t_n=t_{n-1}+\delta t_n\) (and similarly +for \(\phi(t)\) and \(\Delta(t)\)).

+
+
+property amplitude_x
+

Returns the X-Amplitude.

+
+
Returns
+

The X-Amplitude of each segment, \(\{\Omega_n \cos \phi_n\}\).

+
+
Return type
+

np.ndarray

+
+
+
+ +
+
+property amplitude_y
+

Returns the Y-Amplitude.

+
+
Returns
+

The Y-Amplitude of each segment, \(\{\Omega_n \sin \phi_n\}\).

+
+
Return type
+

np.ndarray

+
+
+
+ +
+
+property angles
+

Returns the Bloch sphere rotation angles.

+
+
Returns
+

The total Bloch sphere rotation angles on each segment, +\(\{(\Omega_n^2+\Delta_n^2)\delta t_n\}\).

+
+
Return type
+

np.ndarray

+
+
+
+ +
+
+property directions
+

Returns the Bloch sphere rotation directions.

+
+
Returns
+

The Bloch sphere rotation direction on each segment, +\(\{\mathbf v_n/\|\mathbf v_n\|\}\), where +\(\mathbf v_n=(\Omega_n\cos\phi_n, \Omega_n\sin\phi_n, \Delta_n)\).

+
+
Return type
+

np.ndarray

+
+
+
+ +
+
+property duration
+

Returns the total duration of the control.

+
+
Returns
+

The total duration of the control, \(t_N=\sum_n \delta t_n\).

+
+
Return type
+

float

+
+
+
+ +
+
+export(coordinates='cylindrical', dimensionless_rabi_rate=True)
+

Returns a dictionary formatted for plotting using the qctrl-visualizer package.

+
+
Parameters
+
    +
  • coordinates (string) – Indicates whether the Rabi frequency should be plotted in terms of its +‘cylindrical’ or ‘cartesian’ components. Defaults to ‘cylindrical’.

  • +
  • dimensionless_rabi_rate (boolean) – If True, normalizes the Rabi rate so that its largest absolute value is 1.

  • +
+
+
Returns
+

Dictionary with plot data that can be used by the plot_controls +method of the qctrl-visualizer package. It has keywords ‘Rabi rate’ +and ‘Detuning’ for ‘cylindrical’ coordinates and ‘X amplitude’, ‘Y amplitude’, +and ‘Detuning’ for ‘cartesian’ coordinates.

+
+
Return type
+

dict

+
+
Raises
+

ArgumentsValueError – Raised when an argument is invalid.

+
+
+
+ +
+
+export_to_file(filename=None, file_format='Q-CTRL expanded', file_type='CSV', coordinates='cylindrical')
+

Prepares and saves the driven control in a file.

+
+
Parameters
+
    +
  • filename (str) – Name and path of the file to save the control into.

  • +
  • file_format (str) – Specified file format for saving the control. Defaults to ‘Q-CTRL expanded’. Currently +does not support any other format. For detail of the Q-CTRL expanded format, see below.

  • +
  • file_type (str, optional) – One of ‘CSV’ or ‘JSON’. Defaults to ‘CSV’.

  • +
  • coordinates (str, optional) – The coordinate system in which to save the control. Must be ‘cylindrical’ or +‘cartesian’. Defaults to ‘cylindrical’.

  • +
+
+
Raises
+

ArgumentsValueError – Raised if some of the parameters are invalid.

+
+
+

Notes

+

The Q-CTRL expanded format is designed for direct integration of control solutions into +experimental hardware. The format represents controls as vectors defined for the relevant +operators sampled in time (corresponding to the segmentation of the Rabi rate, azimuthal +angle, and detuning).

+

The exact data produced depends on the file type and coordinate system. In all cases, the +data contain four lists of real floating point numbers. Each list has the same length, and +the \(n\)’th element of each list describes the \(n\)’th segment of the driven +control.

+

For Cartesian coordinates, the four lists are X-amplitude, Y-amplitude, detuning, and +duration. The maximum Rabi rate is also included in the data, and the X-amplitude and +Y-amplitude are normalized to that maximum Rabi rate.

+

For cylndrical coordinates, the four lists are Rabi rate, azimuthal angle, detuning, and +duration. The maximum Rabi rate is also included in the data, and the the Rabi rate is +normalized to that maximum Rabi rate.

+

For CSV, the data are output as five columns, with one row of titles, followed by rows of +data. The maximum Rabi rate is the same in each row. For JSON, the data are output as a +single object with four appropriately-named arrays, a “maximum_rabi_rate” field giving the +maximum Rabi rate, and optionally a “name” field giving the name of the control.

+

For example, the CSV cylindrical representation of a control with two segments would be:

+
rabi_rate,azimuthal_angle,detuning,duration,maximum_rabi_rate
+0.8,1.57,3000000.,0.000001,10000000
+1.0,3.14,-3000000.,0.000002,1000000
+
+
+

Note that the Rabi rate on each segment is normalized to the maximum Rabi rate.

+

The JSON Cartesian representation of the same control would be:

+
{
+    "name": "a custom control",
+    "maximum_rabi_rate": 1000000,
+    "amplitude_x": [0.0,-1.0],
+    "amplitude_y": [0.8,0.0],
+    "detuning": [3000000.0,-3000000.0],
+    "duration": [0.000001,0.000002],
+}
+
+
+

Note that the amplitudes on each segment are normalized to the maximum Rabi rate.

+
+ +
+
+property maximum_detuning
+

Returns the maximum detuning of the control.

+
+
Returns
+

The maximum detuning of the control, \(\max_n \Delta_n\).

+
+
Return type
+

float

+
+
+
+ +
+
+property maximum_duration
+

Returns the duration of the longest control segment.

+
+
Returns
+

The duration of the longest control segment, \(\max_n \delta t_n\).

+
+
Return type
+

float

+
+
+
+ +
+
+property maximum_rabi_rate
+

Returns the maximum Rabi rate of the control.

+
+
Returns
+

The maximum Rabi rate of the control, \(\max_n \Omega_n\).

+
+
Return type
+

float

+
+
+
+ +
+
+property minimum_duration
+

Returns the duration of the shortest control segment.

+
+
Returns
+

The duration of the shortest control segment, \(\min_n \delta t_n\).

+
+
Return type
+

float

+
+
+
+ +
+
+property number_of_segments
+

Returns the number of segments.

+
+
Returns
+

The number of segments in the driven control, \(N\).

+
+
Return type
+

int

+
+
+
+ +
+
+property times
+

Returns the boundary times of the control segments.

+
+
Returns
+

The boundary times of the control segments, \(\{t_n}\}\) (starting with +\(t_0=0\)).

+
+
Return type
+

np.ndarray

+
+
+
+ +
+ +
+
+class qctrlopencontrols.DynamicDecouplingSequence(duration: float = 1.0, offsets: Optional[numpy.ndarray] = None, rabi_rotations: Optional[numpy.ndarray] = None, azimuthal_angles: Optional[numpy.ndarray] = None, detuning_rotations: Optional[numpy.ndarray] = None, name: Optional[str] = None)
+

Bases: object

+

Create a dynamic decoupling sequence. +Can be made of perfect operations, or realistic pulses.

+
+
Parameters
+
    +
  • duration (float) – Defaults to 1. The total time in seconds for the sequence.

  • +
  • offsets (np.ndarray) – Defaults to None. +The times offsets in s for the center of pulses. +If None, defaults to one operation at halfway [0.5].

  • +
  • rabi_rotations (np.ndarray) – Defaults to None. +The rabi rotations at each time offset. +If None, defaults to np.pi at each time offset.

  • +
  • azimuthal_angles (np.ndarray) – Defaults to None. +The azimuthal angles at each time offset. +If None, defaults to 0 at each time offset.

  • +
  • detuning_rotations (np.ndarray) – Defaults to None. +The detuning rotations at each time offset. +If None, defaults to 0 at each time offset.

  • +
  • name (str) – Name of the sequence. Defaults to None.

  • +
+
+
Raises
+

qctrlopencontrols.exceptions.ArgumentsValueError – is raised if one of the inputs is invalid.

+
+
+
+
+export() → Dict
+

Returns a dictionary formatted for plotting using the qctrl-visualizer package.

+
+
Returns
+

Dictionary with plot data that can be used by the plot_sequences +method of the qctrl-visualizer package. It has keywords ‘Rabi’ +and ‘Detuning’.

+
+
Return type
+

dict

+
+
+
+ +
+
+export_to_file(filename: Optional[str] = None, file_format: str = 'Q-CTRL expanded', file_type: str = 'CSV', coordinates: str = 'cylindrical', maximum_rabi_rate: float = 6.283185307179586, maximum_detuning_rate: float = 6.283185307179586) → None
+

Prepares and saves the dynamic decoupling sequence in a file.

+
+
Parameters
+
    +
  • filename (str, optional) – Name and path of the file to save the control into. +Defaults to None

  • +
  • file_format (str) – Specified file format for saving the control. Defaults to +‘Q-CTRL expanded’; Currently it does not support any other format. +For detail of the Q-CTRL Expanded Format consult +Q-CTRL Control Data Format +<https://docs.q-ctrl.com/wiki/output-data-formats#q-ctrl-hardware> _.

  • +
  • file_type (str, optional) – One of ‘CSV’ or ‘JSON’; defaults to ‘CSV’.

  • +
  • coordinates (str, optional) – Indicates the co-ordinate system requested. Must be one of +‘cylindrical’, ‘cartesian’; defaults to ‘cylindrical’

  • +
  • maximum_rabi_rate (float, optional) – Maximum Rabi Rate; Defaults to \(2\pi\)

  • +
  • maximum_detuning_rate (float, optional) – Maximum Detuning Rate; Defaults to \(2\pi\)

  • +
+
+
+

References

+

Q-CTRL Control Data Format +<https://docs.q-ctrl.com/wiki/output-data-formats#q-ctrl-hardware> _.

+
+
Raises
+

ArgumentsValueError – Raised if some of the parameters are invalid.

+
+
+

Notes

+

The sequence is converted to a driven control using the maximum rabi and detuning +rate. The driven control is then exported. This is done to facilitate a coherent +integration with Q-CTRL BLACK OPAL’s 1-Qubit workspace.

+
+ +
+
+property number_of_offsets
+

Returns the number of offsets.

+
+
Returns
+

The number of offsets in the dynamic decoupling sequence

+
+
Return type
+

int

+
+
+
+ +
+ +
+
+qctrlopencontrols.convert_dds_to_driven_control(dynamic_decoupling_sequence: qctrlopencontrols.dynamic_decoupling_sequences.dynamic_decoupling_sequence.DynamicDecouplingSequence = None, maximum_rabi_rate: float = 6.283185307179586, maximum_detuning_rate: float = 6.283185307179586, minimum_segment_duration: float = 0.0, **kwargs) → qctrlopencontrols.driven_controls.driven_control.DrivenControl
+

Creates a Driven Control based on the supplied DDS and other relevant information.

+

Currently, pulses that simultaneously contain Rabi and detuning rotations are not +supported.

+
+
Parameters
+
    +
  • dynamic_decoupling_sequence (qctrlopencontrols.DynamicDecouplingSequence) – The base DDS. Its offsets should be sorted in ascending order in time.

  • +
  • maximum_rabi_rate (float, optional) – Maximum Rabi Rate; Defaults to 2*pi. +Must be greater than 0 and less or equal to UPPER_BOUND_RABI_RATE, if set.

  • +
  • maximum_detuning_rate (float, optional) – Maximum Detuning Rate; Defaults to 2*pi. +Must be greater than 0 and less or equal to UPPER_BOUND_DETUNING_RATE, if set.

  • +
  • minimum_segment_duration (float, optional) – If set, further restricts the duration of every segment of the Driven Controls. +Defaults to 0, in which case it does not affect the duration of the pulses. +Must be greater or equal to 0, if set.

  • +
  • kwargs (dict, optional) – Options to make the corresponding filter type. +I.e. the options for primitive are described in doc for the PrimitivePulse class.

  • +
+
+
Returns
+

The Driven Control that contains the segments +corresponding to the Dynamic Decoupling Sequence operation.

+
+
Return type
+

DrivenControls

+
+
Raises
+

ArgumentsValueError – Raised when an argument is invalid or a valid driven control cannot be + created from the sequence parameters, maximum rabi rate and maximum detuning + rate provided.

+
+
+

Notes

+

Driven pulse is defined as a sequence of control segments. Each segment performs +an operation (rotation around one or more axes). While the dynamic decoupling +sequence operation contains ideal instant operations, the maximum Rabi (detuning) rate +defines a minimum time required to perform a given rotation operation. Therefore, each +operation in sequence is converted to a flat-topped control segment with a finite duration. +Each offset is taken as the mid-point of the control segment and the width of the +segment is determined by (rotation/max_rabi(detuning)_rate).

+

If the sequence contains operations at either of the extreme ends +\(\tau_0=0\) and \(\tau_{n+1}=\tau\) +or finishing after the sequence duration \(t>\tau\)). In these cases, the segments +on either of the extreme ends are shifted appropriately so that their start/end time +falls entirely within the duration of the sequence.

+

Moreover, a check is made to make sure the resulting control segments are non-overlapping.

+

If appropriate control segments cannot be created, the conversion process raises +an ArgumentsValueError.

+
+ +
+
+qctrlopencontrols.new_modulated_gaussian_control(maximum_rabi_rate: float, minimum_segment_duration: float, duration: float, modulation_frequency: float) → qctrlopencontrols.driven_controls.driven_control.DrivenControl
+

Generate a Gaussian driven control sequence modulated by a sinusoidal signal at a specific +frequency.

+

The net effect of this control sequence is an identity gate.

+
+
Parameters
+
    +
  • maximum_rabi_rate (float) – Maximum Rabi rate of the system.

  • +
  • minimum_segment_duration (float) – Minimum length of each segment in the control sequence.

  • +
  • duration (float) – Total duration of the control sequence.

  • +
  • modulation_frequency (float) – Frequency of the modulation sinusoidal signal.

  • +
+
+
Returns
+

A control sequence as an instance of DrivenControl.

+
+
Return type
+

DrivenControl

+
+
+
+ +
+
+qctrlopencontrols.new_predefined_dds(scheme='spin echo', **kwargs)
+

Creates a new instance of one of the predefined dynamic decoupling sequences.

+
+
Parameters
+
    +
  • scheme (string) –

    The name of the sequence. The available options are:

    +
      +
    • ’Ramsey’

    • +
    • ’spin echo’

    • +
    • ’Carr-Purcell’

    • +
    • ’Carr-Purcell-Meiboom-Gill’

    • +
    • ’Uhrig single-axis’

    • +
    • ’Periodic single-axis’

    • +
    • ’Walsh single-axis’

    • +
    • ’quadratic’

    • +
    • ’X concatenated’

    • +
    • ’XY concatenated’

    • +
    +

    Defaults to ‘spin echo’.

    +

  • +
  • kwargs (dict, optional) – Additional keyword argument to create the sequence.

  • +
+
+
Returns
+

A dynamical decuopling sequence corresponding to scheme.

+
+
Return type
+

qctrlopencontrols.dynamic_decoupling_sequences.DynamicDecouplingSequence

+
+
Raises
+

ArgumentsValueError – Raised when an argument is invalid.

+
+
+
+ +
+
+qctrlopencontrols.new_predefined_driven_control(scheme: str = 'primitive', **kwargs)
+

Creates a new driven control based on the given scheme.

+
+
Parameters
+
    +
  • scheme (string, optional) –

    The name of the driven control type. The available options are:

    +
      +
    • ’primitive’

    • +
    • ’BB1’

    • +
    • ’SK1’

    • +
    • ’CORPSE’

    • +
    • ’CORPSE in BB1’

    • +
    • ’CORPSE in SK1’

    • +
    • ’WAMF1’

    • +
    • ’SCROFULOUS’

    • +
    • ’CORPSE in SCROFULOUS’

    • +
    +

    Defaults to ‘primitive’.

    +

  • +
  • kwargs (dict, optional) – Additional keyword argument to create the control.

  • +
+
+
Returns
+

A driven control corresponding to scheme.

+
+
Return type
+

qctrlopencontrols.DrivenControls

+
+
Raises
+

ArgumentsValueError – Raised when an argument is invalid.

+
+
+
+ +
+ + +
+
+
+ + + + +
+ +
+

+ © Copyright 2020 Q-CTRL Pty Ltd & Q-CTRL Inc. All rights reserved. + +

+
+ Built with Sphinx using a theme provided by Read the Docs. + +
+ +
+
+ +
+ +
+ + + + + + + + + + + + \ No newline at end of file From b3f3036ecbe8cc51b4a0d78b1350a8245b505a1a Mon Sep 17 00:00:00 2001 From: Harry Slatyer Date: Fri, 4 Sep 2020 16:11:18 +1000 Subject: [PATCH 09/27] remove html, didn't work --- docs/_build/html/qctrlopencontrols.html | 751 ------------------------ 1 file changed, 751 deletions(-) delete mode 100644 docs/_build/html/qctrlopencontrols.html diff --git a/docs/_build/html/qctrlopencontrols.html b/docs/_build/html/qctrlopencontrols.html deleted file mode 100644 index a29f818f..00000000 --- a/docs/_build/html/qctrlopencontrols.html +++ /dev/null @@ -1,751 +0,0 @@ - - - - - - - - - - - Q-CTRL Open Controls Python package — Open Controls Python package | Q-CTRL - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - -
- - - - - -
- -
- - - - - - - - - - - - - - - - - -
- -
    - -
  • Docs »
  • - -
  • Q-CTRL Open Controls Python package
  • - - - -
- - -
-
-
-
- -
-

Q-CTRL Open Controls Python package

-

Top-level package for Q-CTRL Open Controls.

-
-
-class qctrlopencontrols.DrivenControl(rabi_rates: Optional[numpy.ndarray] = None, azimuthal_angles: Optional[numpy.ndarray] = None, detunings: Optional[numpy.ndarray] = None, durations: Optional[numpy.ndarray] = None, name: Optional[str] = None)
-

Bases: object

-

A piecewise-constant driven control for a single qubit.

-
-
Parameters
-
    -
  • rabi_rates (np.ndarray, optional) – The Rabi rates \(\{\Omega_n\}\) for each segment, in units of radians per second. Every -element must be non-negative. Represented as a 1D array of length \(N\), where \(N\) -is number of segments. You can omit this field if the Rabi rate is zero on all segments.

  • -
  • azimuthal_angles (np.ndarray, optional) – The azimuthal angles \(\{\phi_n\}\) for each segment. Represented as a 1D array of -length \(N\), where \(N\) is number of segments. You can omit this field if the -azimuthal angle is zero on all segments.

  • -
  • detunings (np.ndarray, optional) – The detunings \(\{\Delta_n\}\) for each segment, in units of radians per second. -Represented as a 1D array of length \(N\), where \(N\) is number of segments. You -can omit this field if the detuning is zero on all segments.

  • -
  • durations (np.ndarray, optional) – The durations \(\{\delta t_n\}\) for each segment, in units of seconds. Every element -must be positive. Represented as a 1D array of length \(N\), where \(N\) is number -of segments. Defaults to an array of ones if omitted.

  • -
  • name (string, optional) – An optional string to name the control. Defaults to None.

  • -
-
-
Raises
-

ArgumentsValueError – Raised when an argument is invalid.

-
-
-

Notes

-

This class represents a control for a single driven qubit with Hamiltonian:

-
-\[H(t) = \frac{1}{2}\left(\Omega(t) e^{i\phi(t)} \sigma_- + - \Omega(t) e^{-i\phi(t)}\sigma_+\right) + - \frac{1}{2}\Delta(t)\sigma_z,\]
-

where \(\Omega(t)\) is the Rabi rate, \(\phi(t)\) is the azimuthal angle (or drive -phase), \(\Delta(t)\) is the detuning, \(\sigma_\pm = (\sigma_x \mp \sigma_y)/2\), -and \(\sigma_k\) are the Pauli matrices.

-

The controls are piecewise-constant, meaning \(\Omega(t)=\Omega_n\) for -\(t_{n-1}\leq t<t_n\), where \(t_0=0\) and \(t_n=t_{n-1}+\delta t_n\) (and similarly -for \(\phi(t)\) and \(\Delta(t)\)).

-
-
-property amplitude_x
-

Returns the X-Amplitude.

-
-
Returns
-

The X-Amplitude of each segment, \(\{\Omega_n \cos \phi_n\}\).

-
-
Return type
-

np.ndarray

-
-
-
- -
-
-property amplitude_y
-

Returns the Y-Amplitude.

-
-
Returns
-

The Y-Amplitude of each segment, \(\{\Omega_n \sin \phi_n\}\).

-
-
Return type
-

np.ndarray

-
-
-
- -
-
-property angles
-

Returns the Bloch sphere rotation angles.

-
-
Returns
-

The total Bloch sphere rotation angles on each segment, -\(\{(\Omega_n^2+\Delta_n^2)\delta t_n\}\).

-
-
Return type
-

np.ndarray

-
-
-
- -
-
-property directions
-

Returns the Bloch sphere rotation directions.

-
-
Returns
-

The Bloch sphere rotation direction on each segment, -\(\{\mathbf v_n/\|\mathbf v_n\|\}\), where -\(\mathbf v_n=(\Omega_n\cos\phi_n, \Omega_n\sin\phi_n, \Delta_n)\).

-
-
Return type
-

np.ndarray

-
-
-
- -
-
-property duration
-

Returns the total duration of the control.

-
-
Returns
-

The total duration of the control, \(t_N=\sum_n \delta t_n\).

-
-
Return type
-

float

-
-
-
- -
-
-export(coordinates='cylindrical', dimensionless_rabi_rate=True)
-

Returns a dictionary formatted for plotting using the qctrl-visualizer package.

-
-
Parameters
-
    -
  • coordinates (string) – Indicates whether the Rabi frequency should be plotted in terms of its -‘cylindrical’ or ‘cartesian’ components. Defaults to ‘cylindrical’.

  • -
  • dimensionless_rabi_rate (boolean) – If True, normalizes the Rabi rate so that its largest absolute value is 1.

  • -
-
-
Returns
-

Dictionary with plot data that can be used by the plot_controls -method of the qctrl-visualizer package. It has keywords ‘Rabi rate’ -and ‘Detuning’ for ‘cylindrical’ coordinates and ‘X amplitude’, ‘Y amplitude’, -and ‘Detuning’ for ‘cartesian’ coordinates.

-
-
Return type
-

dict

-
-
Raises
-

ArgumentsValueError – Raised when an argument is invalid.

-
-
-
- -
-
-export_to_file(filename=None, file_format='Q-CTRL expanded', file_type='CSV', coordinates='cylindrical')
-

Prepares and saves the driven control in a file.

-
-
Parameters
-
    -
  • filename (str) – Name and path of the file to save the control into.

  • -
  • file_format (str) – Specified file format for saving the control. Defaults to ‘Q-CTRL expanded’. Currently -does not support any other format. For detail of the Q-CTRL expanded format, see below.

  • -
  • file_type (str, optional) – One of ‘CSV’ or ‘JSON’. Defaults to ‘CSV’.

  • -
  • coordinates (str, optional) – The coordinate system in which to save the control. Must be ‘cylindrical’ or -‘cartesian’. Defaults to ‘cylindrical’.

  • -
-
-
Raises
-

ArgumentsValueError – Raised if some of the parameters are invalid.

-
-
-

Notes

-

The Q-CTRL expanded format is designed for direct integration of control solutions into -experimental hardware. The format represents controls as vectors defined for the relevant -operators sampled in time (corresponding to the segmentation of the Rabi rate, azimuthal -angle, and detuning).

-

The exact data produced depends on the file type and coordinate system. In all cases, the -data contain four lists of real floating point numbers. Each list has the same length, and -the \(n\)’th element of each list describes the \(n\)’th segment of the driven -control.

-

For Cartesian coordinates, the four lists are X-amplitude, Y-amplitude, detuning, and -duration. The maximum Rabi rate is also included in the data, and the X-amplitude and -Y-amplitude are normalized to that maximum Rabi rate.

-

For cylndrical coordinates, the four lists are Rabi rate, azimuthal angle, detuning, and -duration. The maximum Rabi rate is also included in the data, and the the Rabi rate is -normalized to that maximum Rabi rate.

-

For CSV, the data are output as five columns, with one row of titles, followed by rows of -data. The maximum Rabi rate is the same in each row. For JSON, the data are output as a -single object with four appropriately-named arrays, a “maximum_rabi_rate” field giving the -maximum Rabi rate, and optionally a “name” field giving the name of the control.

-

For example, the CSV cylindrical representation of a control with two segments would be:

-
rabi_rate,azimuthal_angle,detuning,duration,maximum_rabi_rate
-0.8,1.57,3000000.,0.000001,10000000
-1.0,3.14,-3000000.,0.000002,1000000
-
-
-

Note that the Rabi rate on each segment is normalized to the maximum Rabi rate.

-

The JSON Cartesian representation of the same control would be:

-
{
-    "name": "a custom control",
-    "maximum_rabi_rate": 1000000,
-    "amplitude_x": [0.0,-1.0],
-    "amplitude_y": [0.8,0.0],
-    "detuning": [3000000.0,-3000000.0],
-    "duration": [0.000001,0.000002],
-}
-
-
-

Note that the amplitudes on each segment are normalized to the maximum Rabi rate.

-
- -
-
-property maximum_detuning
-

Returns the maximum detuning of the control.

-
-
Returns
-

The maximum detuning of the control, \(\max_n \Delta_n\).

-
-
Return type
-

float

-
-
-
- -
-
-property maximum_duration
-

Returns the duration of the longest control segment.

-
-
Returns
-

The duration of the longest control segment, \(\max_n \delta t_n\).

-
-
Return type
-

float

-
-
-
- -
-
-property maximum_rabi_rate
-

Returns the maximum Rabi rate of the control.

-
-
Returns
-

The maximum Rabi rate of the control, \(\max_n \Omega_n\).

-
-
Return type
-

float

-
-
-
- -
-
-property minimum_duration
-

Returns the duration of the shortest control segment.

-
-
Returns
-

The duration of the shortest control segment, \(\min_n \delta t_n\).

-
-
Return type
-

float

-
-
-
- -
-
-property number_of_segments
-

Returns the number of segments.

-
-
Returns
-

The number of segments in the driven control, \(N\).

-
-
Return type
-

int

-
-
-
- -
-
-property times
-

Returns the boundary times of the control segments.

-
-
Returns
-

The boundary times of the control segments, \(\{t_n}\}\) (starting with -\(t_0=0\)).

-
-
Return type
-

np.ndarray

-
-
-
- -
- -
-
-class qctrlopencontrols.DynamicDecouplingSequence(duration: float = 1.0, offsets: Optional[numpy.ndarray] = None, rabi_rotations: Optional[numpy.ndarray] = None, azimuthal_angles: Optional[numpy.ndarray] = None, detuning_rotations: Optional[numpy.ndarray] = None, name: Optional[str] = None)
-

Bases: object

-

Create a dynamic decoupling sequence. -Can be made of perfect operations, or realistic pulses.

-
-
Parameters
-
    -
  • duration (float) – Defaults to 1. The total time in seconds for the sequence.

  • -
  • offsets (np.ndarray) – Defaults to None. -The times offsets in s for the center of pulses. -If None, defaults to one operation at halfway [0.5].

  • -
  • rabi_rotations (np.ndarray) – Defaults to None. -The rabi rotations at each time offset. -If None, defaults to np.pi at each time offset.

  • -
  • azimuthal_angles (np.ndarray) – Defaults to None. -The azimuthal angles at each time offset. -If None, defaults to 0 at each time offset.

  • -
  • detuning_rotations (np.ndarray) – Defaults to None. -The detuning rotations at each time offset. -If None, defaults to 0 at each time offset.

  • -
  • name (str) – Name of the sequence. Defaults to None.

  • -
-
-
Raises
-

qctrlopencontrols.exceptions.ArgumentsValueError – is raised if one of the inputs is invalid.

-
-
-
-
-export() → Dict
-

Returns a dictionary formatted for plotting using the qctrl-visualizer package.

-
-
Returns
-

Dictionary with plot data that can be used by the plot_sequences -method of the qctrl-visualizer package. It has keywords ‘Rabi’ -and ‘Detuning’.

-
-
Return type
-

dict

-
-
-
- -
-
-export_to_file(filename: Optional[str] = None, file_format: str = 'Q-CTRL expanded', file_type: str = 'CSV', coordinates: str = 'cylindrical', maximum_rabi_rate: float = 6.283185307179586, maximum_detuning_rate: float = 6.283185307179586) → None
-

Prepares and saves the dynamic decoupling sequence in a file.

-
-
Parameters
-
    -
  • filename (str, optional) – Name and path of the file to save the control into. -Defaults to None

  • -
  • file_format (str) – Specified file format for saving the control. Defaults to -‘Q-CTRL expanded’; Currently it does not support any other format. -For detail of the Q-CTRL Expanded Format consult -Q-CTRL Control Data Format -<https://docs.q-ctrl.com/wiki/output-data-formats#q-ctrl-hardware> _.

  • -
  • file_type (str, optional) – One of ‘CSV’ or ‘JSON’; defaults to ‘CSV’.

  • -
  • coordinates (str, optional) – Indicates the co-ordinate system requested. Must be one of -‘cylindrical’, ‘cartesian’; defaults to ‘cylindrical’

  • -
  • maximum_rabi_rate (float, optional) – Maximum Rabi Rate; Defaults to \(2\pi\)

  • -
  • maximum_detuning_rate (float, optional) – Maximum Detuning Rate; Defaults to \(2\pi\)

  • -
-
-
-

References

-

Q-CTRL Control Data Format -<https://docs.q-ctrl.com/wiki/output-data-formats#q-ctrl-hardware> _.

-
-
Raises
-

ArgumentsValueError – Raised if some of the parameters are invalid.

-
-
-

Notes

-

The sequence is converted to a driven control using the maximum rabi and detuning -rate. The driven control is then exported. This is done to facilitate a coherent -integration with Q-CTRL BLACK OPAL’s 1-Qubit workspace.

-
- -
-
-property number_of_offsets
-

Returns the number of offsets.

-
-
Returns
-

The number of offsets in the dynamic decoupling sequence

-
-
Return type
-

int

-
-
-
- -
- -
-
-qctrlopencontrols.convert_dds_to_driven_control(dynamic_decoupling_sequence: qctrlopencontrols.dynamic_decoupling_sequences.dynamic_decoupling_sequence.DynamicDecouplingSequence = None, maximum_rabi_rate: float = 6.283185307179586, maximum_detuning_rate: float = 6.283185307179586, minimum_segment_duration: float = 0.0, **kwargs) → qctrlopencontrols.driven_controls.driven_control.DrivenControl
-

Creates a Driven Control based on the supplied DDS and other relevant information.

-

Currently, pulses that simultaneously contain Rabi and detuning rotations are not -supported.

-
-
Parameters
-
    -
  • dynamic_decoupling_sequence (qctrlopencontrols.DynamicDecouplingSequence) – The base DDS. Its offsets should be sorted in ascending order in time.

  • -
  • maximum_rabi_rate (float, optional) – Maximum Rabi Rate; Defaults to 2*pi. -Must be greater than 0 and less or equal to UPPER_BOUND_RABI_RATE, if set.

  • -
  • maximum_detuning_rate (float, optional) – Maximum Detuning Rate; Defaults to 2*pi. -Must be greater than 0 and less or equal to UPPER_BOUND_DETUNING_RATE, if set.

  • -
  • minimum_segment_duration (float, optional) – If set, further restricts the duration of every segment of the Driven Controls. -Defaults to 0, in which case it does not affect the duration of the pulses. -Must be greater or equal to 0, if set.

  • -
  • kwargs (dict, optional) – Options to make the corresponding filter type. -I.e. the options for primitive are described in doc for the PrimitivePulse class.

  • -
-
-
Returns
-

The Driven Control that contains the segments -corresponding to the Dynamic Decoupling Sequence operation.

-
-
Return type
-

DrivenControls

-
-
Raises
-

ArgumentsValueError – Raised when an argument is invalid or a valid driven control cannot be - created from the sequence parameters, maximum rabi rate and maximum detuning - rate provided.

-
-
-

Notes

-

Driven pulse is defined as a sequence of control segments. Each segment performs -an operation (rotation around one or more axes). While the dynamic decoupling -sequence operation contains ideal instant operations, the maximum Rabi (detuning) rate -defines a minimum time required to perform a given rotation operation. Therefore, each -operation in sequence is converted to a flat-topped control segment with a finite duration. -Each offset is taken as the mid-point of the control segment and the width of the -segment is determined by (rotation/max_rabi(detuning)_rate).

-

If the sequence contains operations at either of the extreme ends -\(\tau_0=0\) and \(\tau_{n+1}=\tau\) -or finishing after the sequence duration \(t>\tau\)). In these cases, the segments -on either of the extreme ends are shifted appropriately so that their start/end time -falls entirely within the duration of the sequence.

-

Moreover, a check is made to make sure the resulting control segments are non-overlapping.

-

If appropriate control segments cannot be created, the conversion process raises -an ArgumentsValueError.

-
- -
-
-qctrlopencontrols.new_modulated_gaussian_control(maximum_rabi_rate: float, minimum_segment_duration: float, duration: float, modulation_frequency: float) → qctrlopencontrols.driven_controls.driven_control.DrivenControl
-

Generate a Gaussian driven control sequence modulated by a sinusoidal signal at a specific -frequency.

-

The net effect of this control sequence is an identity gate.

-
-
Parameters
-
    -
  • maximum_rabi_rate (float) – Maximum Rabi rate of the system.

  • -
  • minimum_segment_duration (float) – Minimum length of each segment in the control sequence.

  • -
  • duration (float) – Total duration of the control sequence.

  • -
  • modulation_frequency (float) – Frequency of the modulation sinusoidal signal.

  • -
-
-
Returns
-

A control sequence as an instance of DrivenControl.

-
-
Return type
-

DrivenControl

-
-
-
- -
-
-qctrlopencontrols.new_predefined_dds(scheme='spin echo', **kwargs)
-

Creates a new instance of one of the predefined dynamic decoupling sequences.

-
-
Parameters
-
    -
  • scheme (string) –

    The name of the sequence. The available options are:

    -
      -
    • ’Ramsey’

    • -
    • ’spin echo’

    • -
    • ’Carr-Purcell’

    • -
    • ’Carr-Purcell-Meiboom-Gill’

    • -
    • ’Uhrig single-axis’

    • -
    • ’Periodic single-axis’

    • -
    • ’Walsh single-axis’

    • -
    • ’quadratic’

    • -
    • ’X concatenated’

    • -
    • ’XY concatenated’

    • -
    -

    Defaults to ‘spin echo’.

    -

  • -
  • kwargs (dict, optional) – Additional keyword argument to create the sequence.

  • -
-
-
Returns
-

A dynamical decuopling sequence corresponding to scheme.

-
-
Return type
-

qctrlopencontrols.dynamic_decoupling_sequences.DynamicDecouplingSequence

-
-
Raises
-

ArgumentsValueError – Raised when an argument is invalid.

-
-
-
- -
-
-qctrlopencontrols.new_predefined_driven_control(scheme: str = 'primitive', **kwargs)
-

Creates a new driven control based on the given scheme.

-
-
Parameters
-
    -
  • scheme (string, optional) –

    The name of the driven control type. The available options are:

    -
      -
    • ’primitive’

    • -
    • ’BB1’

    • -
    • ’SK1’

    • -
    • ’CORPSE’

    • -
    • ’CORPSE in BB1’

    • -
    • ’CORPSE in SK1’

    • -
    • ’WAMF1’

    • -
    • ’SCROFULOUS’

    • -
    • ’CORPSE in SCROFULOUS’

    • -
    -

    Defaults to ‘primitive’.

    -

  • -
  • kwargs (dict, optional) – Additional keyword argument to create the control.

  • -
-
-
Returns
-

A driven control corresponding to scheme.

-
-
Return type
-

qctrlopencontrols.DrivenControls

-
-
Raises
-

ArgumentsValueError – Raised when an argument is invalid.

-
-
-
- -
- - -
-
-
- - - - -
- -
-

- © Copyright 2020 Q-CTRL Pty Ltd & Q-CTRL Inc. All rights reserved. - -

-
- Built with Sphinx using a theme provided by Read the Docs. - -
- -
-
- -
- -
- - - - - - - - - - - - \ No newline at end of file From 65736380ff4993fa5a06bea366be5ecdaf9f7ef0 Mon Sep 17 00:00:00 2001 From: Harry Slatyer Date: Fri, 4 Sep 2020 16:14:09 +1000 Subject: [PATCH 10/27] raw --- .../driven_controls/driven_control.py | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/qctrlopencontrols/driven_controls/driven_control.py b/qctrlopencontrols/driven_controls/driven_control.py index df49ff99..be63e19c 100644 --- a/qctrlopencontrols/driven_controls/driven_control.py +++ b/qctrlopencontrols/driven_controls/driven_control.py @@ -223,7 +223,7 @@ def number_of_segments(self) -> int: @property def maximum_rabi_rate(self) -> float: - """ + r""" Returns the maximum Rabi rate of the control. Returns @@ -236,7 +236,7 @@ def maximum_rabi_rate(self) -> float: @property def maximum_detuning(self) -> float: - """ + r""" Returns the maximum detuning of the control. Returns @@ -248,7 +248,7 @@ def maximum_detuning(self) -> float: @property def amplitude_x(self) -> np.ndarray: - """ + r""" Returns the X-Amplitude. Returns @@ -261,7 +261,7 @@ def amplitude_x(self) -> np.ndarray: @property def amplitude_y(self) -> np.ndarray: - """ + r""" Returns the Y-Amplitude. Returns @@ -274,7 +274,7 @@ def amplitude_y(self) -> np.ndarray: @property def angles(self) -> np.ndarray: - """ + r""" Returns the Bloch sphere rotation angles. Returns @@ -293,7 +293,7 @@ def angles(self) -> np.ndarray: @property def directions(self) -> np.ndarray: - """ + r""" Returns the Bloch sphere rotation directions. Returns @@ -332,7 +332,7 @@ def directions(self) -> np.ndarray: @property def times(self) -> np.ndarray: - """ + r""" Returns the boundary times of the control segments. Returns @@ -346,7 +346,7 @@ def times(self) -> np.ndarray: @property def maximum_duration(self) -> float: - """ + r""" Returns the duration of the longest control segment. Returns @@ -359,7 +359,7 @@ def maximum_duration(self) -> float: @property def minimum_duration(self) -> float: - """ + r""" Returns the duration of the shortest control segment. Returns @@ -372,7 +372,7 @@ def minimum_duration(self) -> float: @property def duration(self) -> float: - """ + r""" Returns the total duration of the control. Returns From 2246e7e2800133c5772137db63a00350eb01d09e Mon Sep 17 00:00:00 2001 From: Harry Slatyer Date: Fri, 4 Sep 2020 18:27:42 +1000 Subject: [PATCH 11/27] work --- .../driven_controls/driven_control.py | 22 +++++++++---------- .../dynamic_decoupling_sequence.py | 8 +------ qctrlopencontrols/utils.py | 4 ++-- 3 files changed, 13 insertions(+), 21 deletions(-) diff --git a/qctrlopencontrols/driven_controls/driven_control.py b/qctrlopencontrols/driven_controls/driven_control.py index be63e19c..b2a81314 100644 --- a/qctrlopencontrols/driven_controls/driven_control.py +++ b/qctrlopencontrols/driven_controls/driven_control.py @@ -527,10 +527,9 @@ def export_to_file( operators sampled in time (corresponding to the segmentation of the Rabi rate, azimuthal angle, and detuning). - The exact data produced depends on the file type and coordinate system. In all cases, the - data contain four lists of real floating point numbers. Each list has the same length, and - the :math:`n`'th element of each list describes the :math:`n`'th segment of the driven - control. + The exact data format depends on the file type and coordinate system. In all cases, the data + contain four lists of real floating point numbers. Each list has the same length, and the + :math:`n`'th element of each list describes the :math:`n`'th segment of the driven control. For Cartesian coordinates, the four lists are X-amplitude, Y-amplitude, detuning, and duration. The maximum Rabi rate is also included in the data, and the X-amplitude and @@ -540,10 +539,13 @@ def export_to_file( duration. The maximum Rabi rate is also included in the data, and the the Rabi rate is normalized to that maximum Rabi rate. - For CSV, the data are output as five columns, with one row of titles, followed by rows of - data. The maximum Rabi rate is the same in each row. For JSON, the data are output as a - single object with four appropriately-named arrays, a "maximum_rabi_rate" field giving the - maximum Rabi rate, and optionally a "name" field giving the `name` of the control. + For CSV, the data are formatted as five columns, with one row of titles, followed by + :math:`N` rows of data. The first four columns contain the relevant Cartesian or cylindrical + data. The fifth column contains the maximum Rabi rate, and has the same value in each row. + + For JSON, the data are formatted as a single object (dictionary) with four array fields, a + "maximum_rabi_rate" field giving the maximum Rabi rate, and optionally a "name" field giving + the `name` of the control. For example, the CSV cylindrical representation of a control with two segments would be:: @@ -551,8 +553,6 @@ def export_to_file( 0.8,1.57,3000000.,0.000001,10000000 1.0,3.14,-3000000.,0.000002,1000000 - Note that the Rabi rate on each segment is normalized to the maximum Rabi rate. - The JSON Cartesian representation of the same control would be:: { @@ -563,8 +563,6 @@ def export_to_file( "detuning": [3000000.0,-3000000.0], "duration": [0.000001,0.000002], } - - Note that the amplitudes on each segment are normalized to the maximum Rabi rate. """ _file_types = [v.value for v in FileType] _file_formats = [v.value for v in FileFormat] diff --git a/qctrlopencontrols/dynamic_decoupling_sequences/dynamic_decoupling_sequence.py b/qctrlopencontrols/dynamic_decoupling_sequences/dynamic_decoupling_sequence.py index de3a723e..969f5aac 100644 --- a/qctrlopencontrols/dynamic_decoupling_sequences/dynamic_decoupling_sequence.py +++ b/qctrlopencontrols/dynamic_decoupling_sequences/dynamic_decoupling_sequence.py @@ -286,8 +286,7 @@ def export_to_file( Specified file format for saving the control. Defaults to 'Q-CTRL expanded'; Currently it does not support any other format. For detail of the `Q-CTRL Expanded Format` consult - `Q-CTRL Control Data Format - ` _. + :py:meth:`DrivenControl.export_to_file`. file_type : str, optional One of 'CSV' or 'JSON'; defaults to 'CSV'. coordinates : str, optional @@ -298,11 +297,6 @@ def export_to_file( maximum_detuning_rate : float, optional Maximum Detuning Rate; Defaults to :math:`2\\pi` - References - ---------- - `Q-CTRL Control Data Format - ` _. - Raises ------ ArgumentsValueError diff --git a/qctrlopencontrols/utils.py b/qctrlopencontrols/utils.py index 1323b5af..a40d553b 100644 --- a/qctrlopencontrols/utils.py +++ b/qctrlopencontrols/utils.py @@ -119,8 +119,8 @@ class FileFormat(Enum): """ Defines exported file format. - Currently only support Q-CTRL expanded format. - See details in https://docs.q-ctrl.com/wiki/output-data-formats#q-ctrl-hardware + Currently only support Q-CTRL expanded format. See :py:meth:`DrivenControl.export_to_file` for + details. """ QCTRL = "Q-CTRL expanded" From 0f7de73ee5a27e5bc13d75fbecf8d700b97099c1 Mon Sep 17 00:00:00 2001 From: Harry Slatyer Date: Sun, 6 Sep 2020 16:26:28 +1000 Subject: [PATCH 12/27] bump From 3ac68b634c0698c2f81a25832648b41cf10d6d16 Mon Sep 17 00:00:00 2001 From: Harry Slatyer Date: Fri, 4 Sep 2020 19:08:26 +1000 Subject: [PATCH 13/27] Update documentation for predefined driven controls Largely based on the wiki, although some of the references have been fixed, and the description of WAMF1 now more accurately matches the code. https://q-ctrl.atlassian.net/browse/QENG-1118 --- .../driven_controls/predefined.py | 478 ++++++++++++++---- 1 file changed, 366 insertions(+), 112 deletions(-) diff --git a/qctrlopencontrols/driven_controls/predefined.py b/qctrlopencontrols/driven_controls/predefined.py index 3f6a071d..c4d5231f 100644 --- a/qctrlopencontrols/driven_controls/predefined.py +++ b/qctrlopencontrols/driven_controls/predefined.py @@ -14,9 +14,6 @@ """ Module for defining commonly used driven controls. - -More information and publication references to all driven controls defined here -can be found at https://docs.q-ctrl.com/wiki/control-library """ from typing import ( @@ -67,7 +64,7 @@ def new_predefined_driven_control(scheme: str = PRIMITIVE, **kwargs): Returns ------- - qctrlopencontrols.DrivenControls + DrivenControl A driven control corresponding to `scheme`. Raises @@ -217,25 +214,34 @@ def _new_primitive_control( maximum_rabi_rate: float = 2.0 * np.pi, **kwargs ) -> DrivenControl: - """ - Primitive driven control. + r""" + Creates a primitive (square) driven control. Parameters ---------- rabi_rotation : float - The total rabi rotation to be performed by the driven control. + The total Rabi rotation :math:`\theta` to be performed by the driven control. maximum_rabi_rate : float, optional - Defaults to 2.*np.pi - The maximum rabi frequency for the driven control. + The maximum Rabi frequency :math:`\Omega_{\rm max}` for the driven control. + Defaults to :math:`2\pi`. azimuthal_angle : float, optional - The azimuthal position of the driven control. Defaults to 0. + The azimuthal angle :math:`\phi` for the rotation. Defaults to 0. kwargs : dict - Other keywords required to make a qctrlopencontrols.DrivenControls. + Other keywords required to make a :py:obj:`DrivenControl`. Returns ------- - qctrlopencontrols.DrivenControl - The driven control. + DrivenControl + The driven control :math:`\{(\delta t_n, \Omega_n, \phi_n, \Delta_n)\}`. + + Notes + ----- + A primitive driven control consists of a single control segment: + + .. csv-table:: + :header: :math:`\\delta t_n`, :math:`\\Omega_n`, :math:`\\phi_n` , :math:`\\Delta_n` + + :math:`\theta/\Omega_{\rm max}`, :math:`\Omega_{\rm max}`, :math:`\phi`, :math:`0` """ (azimuthal_angle, rabi_rotation, maximum_rabi_rate) = _predefined_common_attributes( @@ -257,26 +263,50 @@ def _new_bb1_control( maximum_rabi_rate: float = 2.0 * np.pi, **kwargs ) -> DrivenControl: - """ - Wimperis or BB1 control. + r""" + Creates a BB1 (Wimperis) driven control. + + BB1 driven controls are robust to low-frequency noise sources that perturb the amplitude of + the control field. Parameters ---------- - rabi_rotation : float, optional - The total rabi rotation to be performed by the control. + rabi_rotation : float + The total Rabi rotation :math:`\theta` to be performed by the driven control. maximum_rabi_rate : float, optional - Defaults to 2.*np.pi - The maximum rabi frequency for the control. + The maximum Rabi frequency :math:`\Omega_{\rm max}` for the driven control. + Defaults to :math:`2\pi`. azimuthal_angle : float, optional - Defaults to 0. - The azimuthal position of the control. + The azimuthal angle :math:`\phi` for the rotation. Defaults to 0. kwargs : dict - Other keywords required to make a qctrlopencontrols.DrivenControls. + Other keywords required to make a :py:obj:`DrivenControl`. Returns ------- - qctrlopencontrols.DrivenControl - The driven control. + DrivenControl + The driven control :math:`\{(\delta t_n, \Omega_n, \phi_n, \Delta_n)\}`. + + Notes + ----- + A BB1 driven control [#]_ consists of four control segments: + + .. csv-table:: + :header: :math:`\\delta t_n`, :math:`\\Omega_n`, :math:`\\phi_n` , :math:`\\Delta_n` + + :math:`\theta/\Omega_{\rm max}`, :math:`\Omega_{\rm max}`, :math:`\phi`, :math:`0` + :math:`\pi/\Omega_{\rm max}`, :math:`\Omega_{\rm max}`, :math:`\phi+\phi_*`, :math:`0` + :math:`2\pi/\Omega_{\rm max}`, :math:`\Omega_{\rm max}`, :math:`\phi+3\phi_*`,:math:`0` + :math:`\pi/\Omega_{\rm max}`, :math:`\Omega_{\rm max}`, :math:`\phi+\phi_*`, :math:`0` + + where + + .. math:: + \phi_* = \cos^{-1} \left( -\frac{\theta}{4\pi} \right). + + References + ---------- + .. [#] `S. Wimperis, Journal of Magnetic Resonance, Series A 109, 2 (1994). + `_ """ (azimuthal_angle, rabi_rotation, maximum_rabi_rate) = _predefined_common_attributes( azimuthal_angle, rabi_rotation, maximum_rabi_rate @@ -312,26 +342,51 @@ def _new_sk1_control( maximum_rabi_rate: float = 2.0 * np.pi, **kwargs ) -> DrivenControl: - """ - First-order Solovay-Kitaev control, also known as SK1. + r""" + Creates a first order Solovay-Kitaev (SK1) driven control. + + SK1 driven controls are robust to low-frequency noise sources that perturb the amplitude of + the control field. Parameters ---------- - rabi_rotation : float, optional - The total rabi rotation to be performed by the control. + rabi_rotation : float + The total Rabi rotation :math:`\theta` to be performed by the driven control. maximum_rabi_rate : float, optional - Defaults to 2.*np.pi - The maximum rabi frequency for the control. + The maximum Rabi frequency :math:`\Omega_{\rm max}` for the driven control. + Defaults to :math:`2\pi`. azimuthal_angle : float, optional - Defaults to 0. - The azimuthal position of the control. + The azimuthal angle :math:`\phi` for the rotation. Defaults to 0. kwargs : dict - Other keywords required to make a qctrlopencontrols.DrivenControls. + Other keywords required to make a :py:obj:`DrivenControl`. Returns ------- - qctrlopencontrols.DrivenControl - The driven control. + DrivenControl + The driven control :math:`\{(\delta t_n, \Omega_n, \phi_n, \Delta_n)\}`. + + Notes + ----- + An SK1 driven control [#]_ [#]_ consists of three control segments: + + .. csv-table:: + :header: :math:`\\delta t_n`, :math:`\\Omega_n`, :math:`\\phi_n` , :math:`\\Delta_n` + + :math:`\theta/\Omega_{\rm max}`, :math:`\Omega_{\rm max}`, :math:`\phi`, :math:`0` + :math:`2\pi/\Omega_{\rm max}`, :math:`\Omega_{\rm max}`, :math:`\phi-\phi_*`, :math:`0` + :math:`2\pi/\Omega_{\rm max}`, :math:`\Omega_{\rm max}`, :math:`\phi+\phi_*`, :math:`0` + + where + + .. math:: + \phi_* = \cos^{-1} \left( -\frac{\theta}{4\pi} \right). + + References + ---------- + .. [#] `K. R. Brown, A. W. Harrow, and I. L. Chuang, Physical Review A 70, 052318 (2004). + `_ + .. [#] `K. R. Brown, A. W. Harrow, and I. L. Chuang, Physical Review A 72, 039905 (2005). + `_ """ (azimuthal_angle, rabi_rotation, maximum_rabi_rate) = _predefined_common_attributes( azimuthal_angle, rabi_rotation, maximum_rabi_rate @@ -366,31 +421,59 @@ def _new_scrofulous_control( maximum_rabi_rate: float = 2.0 * np.pi, **kwargs ) -> DrivenControl: - """ - SCROFULOUS control to compensate for pulse length errors. + r""" + Creates a Short Composite ROtation For Undoing Length Over and Under Shoot (SCROFULOUS) driven + control. + + SCROFULOUS driven controls are robust to low-frequency noise sources that perturb the amplitude + of the control field. Parameters ---------- rabi_rotation : float - The total rabi rotation to be performed by the control. + The total Rabi rotation :math:`\theta` to be performed by the driven control. Must be either + :math:`\pi/4`, :math:`\pi/2`, or :math:`\pi`. maximum_rabi_rate : float, optional - Defaults to 2.*np.pi - The maximum rabi frequency for the control. + The maximum Rabi frequency :math:`\Omega_{\rm max}` for the driven control. + Defaults to :math:`2\pi`. azimuthal_angle : float, optional - Defaults to 0. - The azimuthal position of the control. + The azimuthal angle :math:`\phi` for the rotation. Defaults to 0. kwargs : dict - Other keywords required to make a qctrlopencontrols.DrivenControls. + Other keywords required to make a :py:obj:`DrivenControl`. Returns ------- - qctrlopencontrols.DrivenControl - The driven control. + DrivenControl + The driven control :math:`\{(\delta t_n, \Omega_n, \phi_n, \Delta_n)\}`. - Raises - ------ - ArgumentsValueError - Raised when an argument is invalid. + Notes + ----- + A SCROFULOUS driven control [#]_ consists of three control segments: + + .. csv-table:: + :header: :math:`\\delta t_n`, :math:`\\Omega_n`, :math:`\\phi_n` , :math:`\\Delta_n` + + :math:`\theta_1/\Omega_{\rm max}`, :math:`\Omega_\rm{max}`, :math:`\phi+\phi_1`, :math:`0` + :math:`\theta_2/\Omega_{\rm max}`, :math:`\Omega_{\rm max}`, :math:`\phi+\phi_2`, :math:`0` + :math:`\theta_3/\Omega_{\rm max}`, :math:`\Omega_{\rm max}`, :math:`\phi+\phi_3`, :math:`0` + + where + + .. math:: + \theta_1 &= \theta_3 = \mathrm{sinc}^{-1} \left[\frac{2\cos (\theta/2)}{\pi}\right] + + \theta_2 &= \pi + + \phi_1 &= \phi_3 = \cos^{-1}\left[ \frac{-\pi\cos(\theta_1)}{2\theta_1\sin(\theta/2)}\right] + + \phi_2 &= \phi_1 - \cos^{-1} (-\pi/2\theta_1), + + and :math:`\mathrm{sinc}(x)=\sin(x)/x` is the unnormalized sinc function. + + References + ---------- + .. [#] `H. K. Cummins, G. Llewellyn, and J. A. Jones, Physical Review A 67, 042308 (2003). + `_ """ (azimuthal_angle, rabi_rotation, maximum_rabi_rate) = _predefined_common_attributes( azimuthal_angle, rabi_rotation, maximum_rabi_rate @@ -457,26 +540,54 @@ def _new_corpse_control( maximum_rabi_rate: float = 2.0 * np.pi, **kwargs ) -> DrivenControl: - """ - Compensating for off resonance with a pulse sequence, often abbreviated as CORPSE. + r""" + Creates a Compensating for Off-Resonance with a Pulse SEquence (CORPSE) driven control. + + CORPSE driven controls are robust to low-frequency dephasing noise. Parameters ---------- rabi_rotation : float - The total rabi rotation to be performed by the control. + The total Rabi rotation :math:`\theta` to be performed by the driven control. maximum_rabi_rate : float, optional - Defaults to 2*np.pi. - The maximum rabi frequency for the control. + The maximum Rabi frequency :math:`\Omega_{\rm max}` for the driven control. + Defaults to :math:`2\pi`. azimuthal_angle : float, optional - Defaults to 0. - The azimuthal position of the control. + The azimuthal angle :math:`\phi` for the rotation. Defaults to 0. kwargs : dict - Other keywords required to make a qctrlopencontrols.DrivenControls. + Other keywords required to make a :py:obj:`DrivenControl`. Returns ------- - qctrlopencontrols.DrivenControl - The driven control. + DrivenControl + The driven control :math:`\{(\delta t_n, \Omega_n, \phi_n, \Delta_n)\}`. + + Notes + ----- + A CORPSE driven control [#]_ [#]_ consists of three control segments: + + .. csv-table:: + :header: :math:`\\delta t_n`, :math:`\\Omega_n`, :math:`\\phi_n` , :math:`\\Delta_n` + + :math:`\theta_1/\Omega_{\rm max}`, :math:`\Omega_{\rm max}`, :math:`\phi`, :math:`0` + :math:`\theta_2/\Omega_{\rm max}`, :math:`\Omega_{\rm max}`, :math:`\phi+\pi`, :math:`0` + :math:`\theta_3/\Omega_{\rm max}`, :math:`\Omega_{\rm max}`, :math:`\phi`, :math:`0` + + where + + .. math:: + \theta_1 &= 2\pi + \frac{\theta}{2} - \sin^{-1} \left[ \frac{\sin(\theta/2)}{2}\right] + + \theta_2 &= 2\pi - 2\sin^{-1} \left[ \frac{\sin(\theta/2)}{2}\right] + + \theta_3 &= \frac{\theta}{2} - \left[ \frac{\sin(\theta/2)}{2}\right]. + + References + ---------- + .. [#] `H. K. Cummins and J. A. Jones, New Journal of Physics 2 (2000). + `_ + .. [#] `H. K. Cummins, G. Llewellyn, and J. A. Jones, Physical Review A 67, 042308 (2003). + `_ """ (azimuthal_angle, rabi_rotation, maximum_rabi_rate) = _predefined_common_attributes( azimuthal_angle, rabi_rotation, maximum_rabi_rate @@ -511,27 +622,65 @@ def _new_corpse_in_bb1_control( maximum_rabi_rate: float = 2.0 * np.pi, **kwargs ) -> DrivenControl: - """ - Compensating for off resonance with a pulse sequence with an embedded - Wimperis (or BB1) control, also known as CinBB. + r""" + Creates a CORPSE concatenated within BB1 (CORPSE in BB1) driven control. + + CORPSE in BB1 driven controls are robust to both low-frequency noise sources that perturb the + amplitude of the control field and low-frequency dephasing noise. Parameters ---------- rabi_rotation : float - The total rabi rotation to be performed by the control. + The total Rabi rotation :math:`\theta` to be performed by the driven control. maximum_rabi_rate : float, optional - Defaults to 2.*np.pi - The maximum rabi frequency for the control. + The maximum Rabi frequency :math:`\Omega_{\rm max}` for the driven control. + Defaults to :math:`2\pi`. azimuthal_angle : float, optional - Defaults to 0. - The azimuthal position of the control. + The azimuthal angle :math:`\phi` for the rotation. Defaults to 0. kwargs : dict - Other keywords required to make a qctrlopencontrols.DrivenControls. + Other keywords required to make a :py:obj:`DrivenControl`. Returns ------- - qctrlopencontrols.DrivenControl - The driven control. + DrivenControl + The driven control :math:`\{(\delta t_n, \Omega_n, \phi_n, \Delta_n)\}`. + + See Also + -------- + _new_corpse_control, _new_bb1_control + + Notes + ----- + A CORPSE in BB1 driven control [#]_ [#]_ consists of a BB1 control with the first segment + replaced by a CORPSE control, which yields six segments: + + .. csv-table:: + :header: :math:`\\delta t_n`, :math:`\\Omega_n`, :math:`\\phi_n` , :math:`\\Delta_n` + + :math:`\theta_1/\Omega_{\rm max}`, :math:`\Omega_{\rm max}`, :math:`\phi`, :math:`0` + :math:`\theta_2/\Omega_{\rm max}`, :math:`\Omega_{\rm max}`, :math:`\phi+\pi`, :math:`0` + :math:`\theta_3/\Omega_{\rm max}`, :math:`\Omega_{\rm max}`, :math:`\phi`, :math:`0` + :math:`\pi/\Omega_{\rm max}`, :math:`\Omega_{\rm max}`, :math:`\phi+\phi_*`, :math:`0` + :math:`2\pi/\Omega_{\rm max}`, :math:`\Omega_{\rm max}`, :math:`\phi+3\phi_*`, :math:`0` + :math:`\pi/\Omega_{\rm max}`, :math:`\Omega_{\rm max}`, :math:`\phi+\phi_*`, :math:`0` + + where + + .. math:: + \theta_1 &= 2\pi + \frac{\theta}{2} - \sin^{-1} \left[ \frac{\sin(\theta/2)}{2}\right] + + \theta_2 &= 2\pi - 2\sin^{-1} \left[ \frac{\sin(\theta/2)}{2}\right] + + \theta_3 &= \frac{\theta}{2} - \left[ \frac{\sin(\theta/2)}{2}\right] + + \phi_* &= \cos^{-1} \left( -\frac{\theta}{4\pi} \right). + + References + ---------- + .. [#] `M. Bando, T. Ichikawa, Y Kondo, and M. Nakahara, Journal of the Physical Society of + Japan 82, 1 (2012). `_ + .. [#] `C. Kabytayev, T. J. Green, K. Khodjasteh, M. J. Biercuk, L. Viola, and K. R. Brown, + Physical Review A 90, 012316 (2014). `_ """ (azimuthal_angle, rabi_rotation, maximum_rabi_rate) = _predefined_common_attributes( @@ -579,27 +728,64 @@ def _new_corpse_in_sk1_control( maximum_rabi_rate: float = 2.0 * np.pi, **kwargs ) -> DrivenControl: - """ - Compensating for off resonance with a pulse sequence with an - embedded Solovay Kitaev (or SK1) control, also knowns as CinSK. + r""" + Creates a CORPSE concatenated within SK1 (CORPSE in SK1) driven control. + + CORPSE in SK1 driven controls are robust to both low-frequency noise sources that perturb the + amplitude of the control field and low-frequency dephasing noise. Parameters ---------- rabi_rotation : float - The total rabi rotation to be performed by the control. + The total Rabi rotation :math:`\theta` to be performed by the driven control. maximum_rabi_rate : float, optional - Defaults to 2.*np.pi - The maximum rabi frequency for the control. + The maximum Rabi frequency :math:`\Omega_{\rm max}` for the driven control. + Defaults to :math:`2\pi`. azimuthal_angle : float, optional - Defaults to 0. - The azimuthal position of the control. + The azimuthal angle :math:`\phi` for the rotation. Defaults to 0. kwargs : dict - Other keywords required to make a qctrlopencontrols.DrivenControls. + Other keywords required to make a :py:obj:`DrivenControl`. Returns ------- - qctrlopencontrols.DrivenControl - The driven control. + DrivenControl + The driven control :math:`\{(\delta t_n, \Omega_n, \phi_n, \Delta_n)\}`. + + See Also + -------- + _new_corpse_control, _new_sk1_control + + Notes + ----- + A CORPSE in SK1 driven control [#]_ [#]_ consists of an SK1 control with the first segment + replaced by a CORPSE control, which yields five segments: + + .. csv-table:: + :header: :math:`\\delta t_n`, :math:`\\Omega_n`, :math:`\\phi_n` , :math:`\\Delta_n` + + :math:`\theta_1/\Omega_{\rm max}`, :math:`\Omega_{\rm max}`, :math:`\phi`, :math:`0` + :math:`\theta_2/\Omega_{\rm max}`, :math:`\Omega_{\rm max}`, :math:`\phi+\pi`, :math:`0` + :math:`\theta_3/\Omega_{\rm max}`, :math:`\Omega_{\rm max}`, :math:`\phi`, :math:`0` + :math:`2\pi/\Omega_{\rm max}`, :math:`\Omega_{\rm max}`, :math:`\phi-\phi_*`, :math:`0` + :math:`2\pi/\Omega_{\rm max}`, :math:`\Omega_{\rm max}`, :math:`\phi+\phi_*`, :math:`0` + + where + + .. math:: + \theta_1 &= 2\pi + \frac{\theta}{2} - \sin^{-1} \left[ \frac{\sin(\theta/2)}{2}\right] + + \theta_2 &= 2\pi - 2\sin^{-1} \left[ \frac{\sin(\theta/2)}{2}\right] + + \theta_3 &= \frac{\theta}{2} - \left[ \frac{\sin(\theta/2)}{2}\right] + + \phi_* &= \cos^{-1} \left( -\frac{\theta}{4\pi} \right). + + References + ---------- + .. [#] `M. Bando, T. Ichikawa, Y Kondo, and M. Nakahara, Journal of the Physical Society of + Japan 82, 1 (2012). `_ + .. [#] `C. Kabytayev, T. J. Green, K. Khodjasteh, M. J. Biercuk, L. Viola, and K. R. Brown, + Physical Review A 90, 012316 (2014). `_ """ (azimuthal_angle, rabi_rotation, maximum_rabi_rate) = _predefined_common_attributes( azimuthal_angle, rabi_rotation, maximum_rabi_rate @@ -643,40 +829,87 @@ def _new_corpse_in_scrofulous_control( maximum_rabi_rate: float = 2.0 * np.pi, **kwargs ) -> DrivenControl: - """ - CORPSE (Compensating for Off Resonance with a Pulse SEquence) embedded within a - SCROFULOUS (Short Composite ROtation For Undoing Length Over and Under Shoot) control, - also knowns as CinS. + r""" + Creates a CORPSE concatenated within SCROFULOUS (CORPSE in SCROFULOUS) driven control. + + CORPSE in SCROFULOUS driven controls are robust to both low-frequency noise sources that perturb + the amplitude of the control field and low-frequency dephasing noise. Parameters ---------- rabi_rotation : float - The total rabi rotation to be performed by the control. + The total Rabi rotation :math:`\theta` to be performed by the driven control. Must be either + :math:`\pi/4`, :math:`\pi/2`, or :math:`\pi`. maximum_rabi_rate : float, optional - Defaults to 2.*np.pi - The maximum rabi frequency for the control. + The maximum Rabi frequency :math:`\Omega_{\rm max}` for the driven control. + Defaults to :math:`2\pi`. azimuthal_angle : float, optional - Defaults to 0. - The azimuthal position of the control. + The azimuthal angle :math:`\phi` for the rotation. Defaults to 0. kwargs : dict - Other keywords required to make a qctrlopencontrols.DrivenControls. + Other keywords required to make a :py:obj:`DrivenControl`. Returns ------- - qctrlopencontrols.DrivenControl - The driven control. + DrivenControl + The driven control :math:`\{(\delta t_n, \Omega_n, \phi_n, \Delta_n)\}`. - Raises - ------ - ArgumentsValueError - Raised when an argument is invalid. + See Also + -------- + _new_corpse_control, _new_scrofulous_control + + Notes + ----- + A CORPSE in SCROFULOUS driven control [#]_ consists of a SCROFULOUS control with each segment + replaced by a CORPSE control, which yields nine segments: + + .. csv-table:: + :header: :math:`\\delta t_n`, :math:`\\Omega_n`, :math:`\\phi_n` , :math:`\\Delta_n` + + :math:`\Gamma^{\theta_1}_1/\Omega_{\rm max}`, :math:`\Omega_{\rm max}`, :math:`\phi+\phi_1`, :math:`0` + :math:`\Gamma^{\theta_1}_2/\Omega_{\rm max}`, :math:`\Omega_{\rm max}`, :math:`\phi+\phi_1+\pi`, :math:`0` + :math:`\Gamma^{\theta_1}_3/\Omega_{\rm max}`, :math:`\Omega_{\rm max}`, :math:`\phi+\phi_1`, :math:`0` + :math:`\Gamma^{\theta_2}_1/\Omega_{\rm max}`, :math:`\Omega_{\rm max}`, :math:`\phi+\phi_2`, :math:`0` + :math:`\Gamma^{\theta_2}_2/\Omega_{\rm max}`, :math:`\Omega_{\rm max}`, :math:`\phi+\phi_2+\pi`, :math:`0` + :math:`\Gamma^{\theta_2}_3/\Omega_{\rm max}`, :math:`\Omega_{\rm max}`, :math:`\phi+\phi_2`, :math:`0` + :math:`\Gamma^{\theta_3}_1/\Omega_{\rm max}`, :math:`\Omega_{\rm max}`, :math:`\phi+\phi_3`, :math:`0` + :math:`\Gamma^{\theta_3}_2/\Omega_{\rm max}`, :math:`\Omega_{\rm max}`, :math:`\phi+\phi_3+\pi`, :math:`0` + :math:`\Gamma^{\theta_3}_3/\Omega_{\rm max}`, :math:`\Omega_{\rm max}`, :math:`\phi+\phi_3`, :math:`0` + + where + + .. math:: + \theta_1 &= \theta_3 = \mathrm{sinc}^{-1} \left[\frac{2\cos (\theta/2)}{\pi}\right] + + \theta_2 &= \pi + + \phi_1 &= \phi_3 = \cos^{-1}\left[ \frac{-\pi\cos(\theta_1)}{2\theta_1\sin(\theta/2)}\right] + + \phi_2 &= \phi_1 - \cos^{-1} (-\pi/2\theta_1) + + (with :math:`\mathrm{sinc}(x)=\sin(x)/x` the unnormalized sinc function) are the SCROFULOUS + angles, and + + .. math:: + \Gamma^{\theta'}_1 &= 2\pi + \frac{\theta'}{2} - \sin^{-1} \left[ \frac{\sin(\theta'/2)}{2}\right] + + \Gamma^{\theta'}_2 &= 2\pi - 2\sin^{-1} \left[ \frac{\sin(\theta'/2)}{2}\right] + + \Gamma^{\theta'}_3 &= \frac{\theta'}{2} - \left[ \frac{\sin(\theta'/2)}{2}\right] + + are the CORPSE angles corresponding to each SCROFULOUS angle + :math:`\theta'\in\{\theta_1,\theta_2,\theta_3\}`. + + References + ---------- + .. [#] `T. Ichikawa, M. Bando, Y. Kondo, and M. Nakahara, Physical Review A 84, 062311 (2011). + `_ """ (azimuthal_angle, rabi_rotation, maximum_rabi_rate) = _predefined_common_attributes( azimuthal_angle, rabi_rotation, maximum_rabi_rate ) # Create a lookup table for rabi rotation and phase angles, taken from - # the Cummings paper. Note: values in the paper are in degrees. + # the Cummins paper. Note: values in the paper are in degrees. def degrees_to_radians(angle_in_degrees): return angle_in_degrees / 180 * np.pi @@ -745,31 +978,52 @@ def _new_wamf1_control( maximum_rabi_rate: float = 2.0 * np.pi, **kwargs ) -> DrivenControl: - """ - First order Walsh control with amplitude modulation. + r""" + Creates a first-order Walsh amplitude-modulated filter (WAMF1) driven control. + + WAMF1 driven controls are robust to low-frequency dephasing noise. Parameters ---------- rabi_rotation : float - The total rabi rotation to be performed by the control. + The total Rabi rotation :math:`\theta` to be performed by the driven control. Must be either + :math:`\pi/4`, :math:`\pi/2`, or :math:`\pi`. maximum_rabi_rate : float, optional - Defaults to 2.*np.pi - The maximum rabi frequency for the control. + The maximum Rabi frequency :math:`\Omega_{\rm max}` for the driven control. + Defaults to :math:`2\pi`. azimuthal_angle : float, optional - Defaults to 0. - The azimuthal position of the control. + The azimuthal angle :math:`\phi` for the rotation. Defaults to 0. kwargs : dict - Other keywords required to make a qctrlopencontrols.DrivenControls. + Other keywords required to make a :py:obj:`DrivenControl`. Returns ------- - qctrlopencontrols.DrivenControls - The driven control. + DrivenControl + The driven control :math:`\{(\delta t_n, \Omega_n, \phi_n, \Delta_n)\}`. - Raises - ------ - ArgumentsValueError - Raised when an argument is invalid. + Notes + ----- + A WAMF1 [#]_ driven control consists of four control segments: + + .. csv-table:: + :header: :math:`\\delta t_n`, :math:`\\Omega_n`, :math:`\\phi_n` , :math:`\\Delta_n` + + :math:`\theta_+/4\Omega_{\rm max}`, :math:`\Omega_{\rm max}`, :math:`\phi`, :math:`0` + :math:`\theta_+/4\Omega_{\rm max}`, :math:`\Omega_{\rm max}\theta_-/\theta_+`, :math:`\phi`, :math:`0` + :math:`\theta_+/4\Omega_{\rm max}`, :math:`\Omega_{\rm max}\theta_-/\theta_+`, :math:`\phi`, :math:`0` + :math:`\theta_+/4\Omega_{\rm max}`, :math:`\Omega_{\rm max}`, :math:`\phi`, :math:`0` + + where :math:`\theta_\pm = \theta+2\pi k_\theta\pm \delta_\theta`, and the integer + :math:`k_\theta` and offset :math:`\delta_\theta` are optimized numerically in order to maximize + the suppression of dephasing noise. Note that the optimal values depend only on the rotation + angle :math:`\theta`. + + This implementation supports :math:`\theta\in\{\pi/4,\pi/2,\pi\}`. + + References + ---------- + .. [#] `H. Ball and M. J. Biercuk, EPJ Quantum Technology 2, 11 (2015). + `_ """ (azimuthal_angle, rabi_rotation, maximum_rabi_rate) = _predefined_common_attributes( azimuthal_angle, rabi_rotation, maximum_rabi_rate From 00841c1d4fbb425fa7e94c3c8905e678f9ad307f Mon Sep 17 00:00:00 2001 From: Harry Slatyer Date: Sun, 6 Sep 2020 16:54:28 +1000 Subject: [PATCH 14/27] Fix lint errors --- .../driven_controls/predefined.py | 51 ++++++++++++++----- 1 file changed, 39 insertions(+), 12 deletions(-) diff --git a/qctrlopencontrols/driven_controls/predefined.py b/qctrlopencontrols/driven_controls/predefined.py index c4d5231f..619e9180 100644 --- a/qctrlopencontrols/driven_controls/predefined.py +++ b/qctrlopencontrols/driven_controls/predefined.py @@ -446,6 +446,11 @@ def _new_scrofulous_control( DrivenControl The driven control :math:`\{(\delta t_n, \Omega_n, \phi_n, \Delta_n)\}`. + Raises + ------ + ArgumentsValueError + Raised when an argument is invalid. + Notes ----- A SCROFULOUS driven control [#]_ consists of three control segments: @@ -853,6 +858,11 @@ def _new_corpse_in_scrofulous_control( DrivenControl The driven control :math:`\{(\delta t_n, \Omega_n, \phi_n, \Delta_n)\}`. + Raises + ------ + ArgumentsValueError + Raised when an argument is invalid. + See Also -------- _new_corpse_control, _new_scrofulous_control @@ -865,15 +875,24 @@ def _new_corpse_in_scrofulous_control( .. csv-table:: :header: :math:`\\delta t_n`, :math:`\\Omega_n`, :math:`\\phi_n` , :math:`\\Delta_n` - :math:`\Gamma^{\theta_1}_1/\Omega_{\rm max}`, :math:`\Omega_{\rm max}`, :math:`\phi+\phi_1`, :math:`0` - :math:`\Gamma^{\theta_1}_2/\Omega_{\rm max}`, :math:`\Omega_{\rm max}`, :math:`\phi+\phi_1+\pi`, :math:`0` - :math:`\Gamma^{\theta_1}_3/\Omega_{\rm max}`, :math:`\Omega_{\rm max}`, :math:`\phi+\phi_1`, :math:`0` - :math:`\Gamma^{\theta_2}_1/\Omega_{\rm max}`, :math:`\Omega_{\rm max}`, :math:`\phi+\phi_2`, :math:`0` - :math:`\Gamma^{\theta_2}_2/\Omega_{\rm max}`, :math:`\Omega_{\rm max}`, :math:`\phi+\phi_2+\pi`, :math:`0` - :math:`\Gamma^{\theta_2}_3/\Omega_{\rm max}`, :math:`\Omega_{\rm max}`, :math:`\phi+\phi_2`, :math:`0` - :math:`\Gamma^{\theta_3}_1/\Omega_{\rm max}`, :math:`\Omega_{\rm max}`, :math:`\phi+\phi_3`, :math:`0` - :math:`\Gamma^{\theta_3}_2/\Omega_{\rm max}`, :math:`\Omega_{\rm max}`, :math:`\phi+\phi_3+\pi`, :math:`0` - :math:`\Gamma^{\theta_3}_3/\Omega_{\rm max}`, :math:`\Omega_{\rm max}`, :math:`\phi+\phi_3`, :math:`0` + :math:`\Gamma^{\theta_1}_1/\Omega_{\rm max}`, :math:`\Omega_{\rm max}`, " + :math:`\phi+\phi_1`", :math:`0` + :math:`\Gamma^{\theta_1}_2/\Omega_{\rm max}`, :math:`\Omega_{\rm max}`, " + :math:`\phi+\phi_1+\pi`", :math:`0` + :math:`\Gamma^{\theta_1}_3/\Omega_{\rm max}`, :math:`\Omega_{\rm max}`, " + :math:`\phi+\phi_1`", :math:`0` + :math:`\Gamma^{\theta_2}_1/\Omega_{\rm max}`, :math:`\Omega_{\rm max}`, " + :math:`\phi+\phi_2`", :math:`0` + :math:`\Gamma^{\theta_2}_2/\Omega_{\rm max}`, :math:`\Omega_{\rm max}`, " + :math:`\phi+\phi_2+\pi`", :math:`0` + :math:`\Gamma^{\theta_2}_3/\Omega_{\rm max}`, :math:`\Omega_{\rm max}`, " + :math:`\phi+\phi_2`", :math:`0` + :math:`\Gamma^{\theta_3}_1/\Omega_{\rm max}`, :math:`\Omega_{\rm max}`, " + :math:`\phi+\phi_3`", :math:`0` + :math:`\Gamma^{\theta_3}_2/\Omega_{\rm max}`, :math:`\Omega_{\rm max}`, " + :math:`\phi+\phi_3+\pi`", :math:`0` + :math:`\Gamma^{\theta_3}_3/\Omega_{\rm max}`, :math:`\Omega_{\rm max}`, " + :math:`\phi+\phi_3`", :math:`0` where @@ -890,7 +909,8 @@ def _new_corpse_in_scrofulous_control( angles, and .. math:: - \Gamma^{\theta'}_1 &= 2\pi + \frac{\theta'}{2} - \sin^{-1} \left[ \frac{\sin(\theta'/2)}{2}\right] + \Gamma^{\theta'}_1 &= 2\pi + \frac{\theta'}{2} + - \sin^{-1} \left[ \frac{\sin(\theta'/2)}{2}\right] \Gamma^{\theta'}_2 &= 2\pi - 2\sin^{-1} \left[ \frac{\sin(\theta'/2)}{2}\right] @@ -1001,6 +1021,11 @@ def _new_wamf1_control( DrivenControl The driven control :math:`\{(\delta t_n, \Omega_n, \phi_n, \Delta_n)\}`. + Raises + ------ + ArgumentsValueError + Raised when an argument is invalid. + Notes ----- A WAMF1 [#]_ driven control consists of four control segments: @@ -1009,8 +1034,10 @@ def _new_wamf1_control( :header: :math:`\\delta t_n`, :math:`\\Omega_n`, :math:`\\phi_n` , :math:`\\Delta_n` :math:`\theta_+/4\Omega_{\rm max}`, :math:`\Omega_{\rm max}`, :math:`\phi`, :math:`0` - :math:`\theta_+/4\Omega_{\rm max}`, :math:`\Omega_{\rm max}\theta_-/\theta_+`, :math:`\phi`, :math:`0` - :math:`\theta_+/4\Omega_{\rm max}`, :math:`\Omega_{\rm max}\theta_-/\theta_+`, :math:`\phi`, :math:`0` + :math:`\theta_+/4\Omega_{\rm max}`, :math:`\Omega_{\rm max}\theta_-/\theta_+`," + :math:`\phi`", :math:`0` + :math:`\theta_+/4\Omega_{\rm max}`, :math:`\Omega_{\rm max}\theta_-/\theta_+`, " + :math:`\phi`", :math:`0` :math:`\theta_+/4\Omega_{\rm max}`, :math:`\Omega_{\rm max}`, :math:`\phi`, :math:`0` where :math:`\theta_\pm = \theta+2\pi k_\theta\pm \delta_\theta`, and the integer From c80a2c15f0194d5dcf35f760c7338fc5602ae1b0 Mon Sep 17 00:00:00 2001 From: Harry Slatyer Date: Sun, 6 Sep 2020 16:57:40 +1000 Subject: [PATCH 15/27] Make functions public --- qctrlopencontrols/__init__.py | 24 +++++++++++-- .../driven_controls/predefined.py | 36 +++++++++---------- 2 files changed, 39 insertions(+), 21 deletions(-) diff --git a/qctrlopencontrols/__init__.py b/qctrlopencontrols/__init__.py index ea7ff3fb..fa23d99f 100644 --- a/qctrlopencontrols/__init__.py +++ b/qctrlopencontrols/__init__.py @@ -20,8 +20,17 @@ from .driven_controls.driven_control import DrivenControl from .driven_controls.predefined import ( + new_bb1_control, + new_corpse_control, + new_corpse_in_bb1_control, + new_corpse_in_scrofulous_control, + new_corpse_in_sk1_control, new_modulated_gaussian_control, new_predefined_driven_control, + new_primitive_control, + new_scrofulous_control, + new_sk1_control, + new_wamf1_control, ) from .dynamic_decoupling_sequences.dynamic_decoupling_sequence import ( DynamicDecouplingSequence, @@ -30,10 +39,19 @@ from .dynamic_decoupling_sequences.predefined import new_predefined_dds __all__ = [ + "DrivenControl", + "DynamicDecouplingSequence", "convert_dds_to_driven_control", - "new_predefined_dds", + "new_bb1_control", + "new_corpse_control", + "new_corpse_in_bb1_control", + "new_corpse_in_scrofulous_control", + "new_corpse_in_sk1_control", "new_modulated_gaussian_control", + "new_predefined_dds", "new_predefined_driven_control", - "DrivenControl", - "DynamicDecouplingSequence", + "new_primitive_control", + "new_scrofulous_control", + "new_sk1_control", + "new_wamf1_control", ] diff --git a/qctrlopencontrols/driven_controls/predefined.py b/qctrlopencontrols/driven_controls/predefined.py index 3f6a071d..a4a89a88 100644 --- a/qctrlopencontrols/driven_controls/predefined.py +++ b/qctrlopencontrols/driven_controls/predefined.py @@ -78,23 +78,23 @@ def new_predefined_driven_control(scheme: str = PRIMITIVE, **kwargs): # Raise error if the input driven_control_type is not known if scheme == PRIMITIVE: - driven_control = _new_primitive_control(**kwargs) + driven_control = new_primitive_control(**kwargs) elif scheme == BB1: - driven_control = _new_bb1_control(**kwargs) + driven_control = new_bb1_control(**kwargs) elif scheme == SK1: - driven_control = _new_sk1_control(**kwargs) + driven_control = new_sk1_control(**kwargs) elif scheme == WAMF1: - driven_control = _new_wamf1_control(**kwargs) + driven_control = new_wamf1_control(**kwargs) elif scheme == CORPSE: - driven_control = _new_corpse_control(**kwargs) + driven_control = new_corpse_control(**kwargs) elif scheme == CORPSE_IN_BB1: - driven_control = _new_corpse_in_bb1_control(**kwargs) + driven_control = new_corpse_in_bb1_control(**kwargs) elif scheme == CORPSE_IN_SK1: - driven_control = _new_corpse_in_sk1_control(**kwargs) + driven_control = new_corpse_in_sk1_control(**kwargs) elif scheme == SCROFULOUS: - driven_control = _new_scrofulous_control(**kwargs) + driven_control = new_scrofulous_control(**kwargs) elif scheme == CORPSE_IN_SCROFULOUS: - driven_control = _new_corpse_in_scrofulous_control(**kwargs) + driven_control = new_corpse_in_scrofulous_control(**kwargs) else: raise ArgumentsValueError( "Unknown predefined pulse type. See help(new_predefined_driven_control) to display all" @@ -211,7 +211,7 @@ def _derive_segments( return segments -def _new_primitive_control( +def new_primitive_control( rabi_rotation: float, azimuthal_angle: float = 0.0, maximum_rabi_rate: float = 2.0 * np.pi, @@ -251,7 +251,7 @@ def _new_primitive_control( ) -def _new_bb1_control( +def new_bb1_control( rabi_rotation: float, azimuthal_angle: float = 0.0, maximum_rabi_rate: float = 2.0 * np.pi, @@ -306,7 +306,7 @@ def _new_bb1_control( ) -def _new_sk1_control( +def new_sk1_control( rabi_rotation: float, azimuthal_angle: float = 0.0, maximum_rabi_rate: float = 2.0 * np.pi, @@ -360,7 +360,7 @@ def _new_sk1_control( ) -def _new_scrofulous_control( +def new_scrofulous_control( rabi_rotation: float, azimuthal_angle: float = 0.0, maximum_rabi_rate: float = 2.0 * np.pi, @@ -451,7 +451,7 @@ def degrees_to_radians(angle_in_degrees): ) -def _new_corpse_control( +def new_corpse_control( rabi_rotation: float, azimuthal_angle: float = 0.0, maximum_rabi_rate: float = 2.0 * np.pi, @@ -505,7 +505,7 @@ def _new_corpse_control( ) -def _new_corpse_in_bb1_control( +def new_corpse_in_bb1_control( rabi_rotation: float, azimuthal_angle: float = 0.0, maximum_rabi_rate: float = 2.0 * np.pi, @@ -573,7 +573,7 @@ def _new_corpse_in_bb1_control( ) -def _new_corpse_in_sk1_control( +def new_corpse_in_sk1_control( rabi_rotation: float, azimuthal_angle: float = 0.0, maximum_rabi_rate: float = 2.0 * np.pi, @@ -637,7 +637,7 @@ def _new_corpse_in_sk1_control( ) -def _new_corpse_in_scrofulous_control( +def new_corpse_in_scrofulous_control( rabi_rotation: float, azimuthal_angle: float = 0.0, maximum_rabi_rate: float = 2.0 * np.pi, @@ -739,7 +739,7 @@ def degrees_to_radians(angle_in_degrees): ) -def _new_wamf1_control( +def new_wamf1_control( rabi_rotation: float, azimuthal_angle: float = 0.0, maximum_rabi_rate: float = 2.0 * np.pi, From 448676539051cd3221930c7c93d9131b94109f6c Mon Sep 17 00:00:00 2001 From: Harry Slatyer Date: Sun, 6 Sep 2020 16:58:40 +1000 Subject: [PATCH 16/27] Fix see alsos --- qctrlopencontrols/driven_controls/predefined.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/qctrlopencontrols/driven_controls/predefined.py b/qctrlopencontrols/driven_controls/predefined.py index 3d4cca32..c42d4896 100644 --- a/qctrlopencontrols/driven_controls/predefined.py +++ b/qctrlopencontrols/driven_controls/predefined.py @@ -652,7 +652,7 @@ def new_corpse_in_bb1_control( See Also -------- - _new_corpse_control, _new_bb1_control + new_corpse_control, new_bb1_control Notes ----- @@ -758,7 +758,7 @@ def new_corpse_in_sk1_control( See Also -------- - _new_corpse_control, _new_sk1_control + new_corpse_control, new_sk1_control Notes ----- @@ -865,7 +865,7 @@ def new_corpse_in_scrofulous_control( See Also -------- - _new_corpse_control, _new_scrofulous_control + new_corpse_control, new_scrofulous_control Notes ----- From b088caa3e65dbb29d5889772763ee2f85ed64804 Mon Sep 17 00:00:00 2001 From: Harry Slatyer Date: Mon, 7 Sep 2020 10:40:03 +1000 Subject: [PATCH 17/27] Update qctrlopencontrols/utils.py Co-authored-by: Leonardo Andreta de Castro --- qctrlopencontrols/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qctrlopencontrols/utils.py b/qctrlopencontrols/utils.py index a40d553b..5cf76e6b 100644 --- a/qctrlopencontrols/utils.py +++ b/qctrlopencontrols/utils.py @@ -119,7 +119,7 @@ class FileFormat(Enum): """ Defines exported file format. - Currently only support Q-CTRL expanded format. See :py:meth:`DrivenControl.export_to_file` for + Currently only supports the Q-CTRL expanded format. See :py:meth:`DrivenControl.export_to_file` for details. """ From a46738db357fb8247772b234a02eed75d2289745 Mon Sep 17 00:00:00 2001 From: Harry Slatyer Date: Mon, 7 Sep 2020 10:40:37 +1000 Subject: [PATCH 18/27] Update qctrlopencontrols/driven_controls/driven_control.py Co-authored-by: Leonardo Andreta de Castro --- qctrlopencontrols/driven_controls/driven_control.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qctrlopencontrols/driven_controls/driven_control.py b/qctrlopencontrols/driven_controls/driven_control.py index b2a81314..b11c9c07 100644 --- a/qctrlopencontrols/driven_controls/driven_control.py +++ b/qctrlopencontrols/driven_controls/driven_control.py @@ -535,7 +535,7 @@ def export_to_file( duration. The maximum Rabi rate is also included in the data, and the X-amplitude and Y-amplitude are normalized to that maximum Rabi rate. - For cylndrical coordinates, the four lists are Rabi rate, azimuthal angle, detuning, and + For cylindrical coordinates, the four lists are Rabi rate, azimuthal angle, detuning, and duration. The maximum Rabi rate is also included in the data, and the the Rabi rate is normalized to that maximum Rabi rate. From 98e3c2f0a6cfd7cb1392d0e8fecb4ef10f09a62c Mon Sep 17 00:00:00 2001 From: Harry Slatyer Date: Mon, 7 Sep 2020 10:40:49 +1000 Subject: [PATCH 19/27] Update qctrlopencontrols/driven_controls/driven_control.py Co-authored-by: Leonardo Andreta de Castro --- qctrlopencontrols/driven_controls/driven_control.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qctrlopencontrols/driven_controls/driven_control.py b/qctrlopencontrols/driven_controls/driven_control.py index b11c9c07..1fbc4b6d 100644 --- a/qctrlopencontrols/driven_controls/driven_control.py +++ b/qctrlopencontrols/driven_controls/driven_control.py @@ -536,7 +536,7 @@ def export_to_file( Y-amplitude are normalized to that maximum Rabi rate. For cylindrical coordinates, the four lists are Rabi rate, azimuthal angle, detuning, and - duration. The maximum Rabi rate is also included in the data, and the the Rabi rate is + duration. The maximum Rabi rate is also included in the data, and the Rabi rate is normalized to that maximum Rabi rate. For CSV, the data are formatted as five columns, with one row of titles, followed by From 4c6be0eddee918edc53d0ab54bac27d3968c31d5 Mon Sep 17 00:00:00 2001 From: Harry Slatyer Date: Mon, 7 Sep 2020 10:44:25 +1000 Subject: [PATCH 20/27] Lower case amplitudes --- qctrlopencontrols/driven_controls/driven_control.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/qctrlopencontrols/driven_controls/driven_control.py b/qctrlopencontrols/driven_controls/driven_control.py index 1fbc4b6d..93f4f922 100644 --- a/qctrlopencontrols/driven_controls/driven_control.py +++ b/qctrlopencontrols/driven_controls/driven_control.py @@ -249,12 +249,12 @@ def maximum_detuning(self) -> float: @property def amplitude_x(self) -> np.ndarray: r""" - Returns the X-Amplitude. + Returns the x-amplitude. Returns ------- np.ndarray - The X-Amplitude of each segment, :math:`\{\Omega_n \cos \phi_n\}`. + The x-amplitude of each segment, :math:`\{\Omega_n \cos \phi_n\}`. """ return self.rabi_rates * np.cos(self.azimuthal_angles) @@ -262,12 +262,12 @@ def amplitude_x(self) -> np.ndarray: @property def amplitude_y(self) -> np.ndarray: r""" - Returns the Y-Amplitude. + Returns the y-amplitude. Returns ------- np.ndarray - The Y-Amplitude of each segment, :math:`\{\Omega_n \sin \phi_n\}`. + The y-amplitude of each segment, :math:`\{\Omega_n \sin \phi_n\}`. """ return self.rabi_rates * np.sin(self.azimuthal_angles) From 6424e988df9ba0b64a8cb5ff1026c9521ae79e1e Mon Sep 17 00:00:00 2001 From: Harry Slatyer Date: Mon, 7 Sep 2020 10:45:42 +1000 Subject: [PATCH 21/27] Update qctrlopencontrols/driven_controls/driven_control.py Co-authored-by: Leonardo Andreta de Castro --- qctrlopencontrols/driven_controls/driven_control.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qctrlopencontrols/driven_controls/driven_control.py b/qctrlopencontrols/driven_controls/driven_control.py index 1fbc4b6d..50a2137c 100644 --- a/qctrlopencontrols/driven_controls/driven_control.py +++ b/qctrlopencontrols/driven_controls/driven_control.py @@ -508,7 +508,7 @@ def export_to_file( Name and path of the file to save the control into. file_format : str Specified file format for saving the control. Defaults to 'Q-CTRL expanded'. Currently - does not support any other format. For detail of the Q-CTRL expanded format, see below. + does not support any other format. For details of the Q-CTRL expanded format, see Notes. file_type : str, optional One of 'CSV' or 'JSON'. Defaults to 'CSV'. coordinates : str, optional From b5fe04b3c0a8b05e3d7b4dbbc83aaa6c18be2346 Mon Sep 17 00:00:00 2001 From: Harry Slatyer Date: Mon, 7 Sep 2020 10:46:24 +1000 Subject: [PATCH 22/27] Fix maximum Rabi rate in example --- qctrlopencontrols/driven_controls/driven_control.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qctrlopencontrols/driven_controls/driven_control.py b/qctrlopencontrols/driven_controls/driven_control.py index df1bd8e6..d55805b5 100644 --- a/qctrlopencontrols/driven_controls/driven_control.py +++ b/qctrlopencontrols/driven_controls/driven_control.py @@ -551,7 +551,7 @@ def export_to_file( rabi_rate,azimuthal_angle,detuning,duration,maximum_rabi_rate 0.8,1.57,3000000.,0.000001,10000000 - 1.0,3.14,-3000000.,0.000002,1000000 + 1.0,3.14,-3000000.,0.000002,10000000 The JSON Cartesian representation of the same control would be:: From 8d24a7b72239e743b40f76bcbd5efc44da05b1f7 Mon Sep 17 00:00:00 2001 From: Harry Slatyer Date: Mon, 7 Sep 2020 11:07:50 +1000 Subject: [PATCH 23/27] Add information about driven control time evolution --- .../driven_controls/driven_control.py | 25 +++++++++++++++---- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/qctrlopencontrols/driven_controls/driven_control.py b/qctrlopencontrols/driven_controls/driven_control.py index d55805b5..13bc7488 100644 --- a/qctrlopencontrols/driven_controls/driven_control.py +++ b/qctrlopencontrols/driven_controls/driven_control.py @@ -84,6 +84,20 @@ class DrivenControl: The controls are piecewise-constant, meaning :math:`\Omega(t)=\Omega_n` for :math:`t_{n-1}\leq t np.ndarray: ------- np.ndarray The total Bloch sphere rotation angles on each segment, - :math:`\{(\Omega_n^2+\Delta_n^2)\delta t_n\}`. + :math:`\left\{\sqrt{\Omega_n^2+\Delta_n^2}\delta t_n\right\}`. """ amplitudes = np.sqrt( @@ -338,7 +352,7 @@ def times(self) -> np.ndarray: Returns ------ np.ndarray - The boundary times of the control segments, :math:`\{t_n}\}` (starting with + The boundary times of the control segments, :math:`\{t_n\}` (starting with :math:`t_0=0`). """ @@ -608,11 +622,12 @@ def export( Parameters ---------- - coordinates: string + coordinates: string, optional Indicates whether the Rabi frequency should be plotted in terms of its 'cylindrical' or 'cartesian' components. Defaults to 'cylindrical'. - dimensionless_rabi_rate: boolean - If ``True``, normalizes the Rabi rate so that its largest absolute value is 1. + dimensionless_rabi_rate: boolean, optional + If ``True``, normalizes the Rabi rate so that its largest absolute value is 1. Defaults + to ``True``. Returns ------- From 2523c0b7260e3f26ac7743812f012553cdf866fc Mon Sep 17 00:00:00 2001 From: Harry Slatyer Date: Mon, 7 Sep 2020 11:08:23 +1000 Subject: [PATCH 24/27] lint --- qctrlopencontrols/utils.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/qctrlopencontrols/utils.py b/qctrlopencontrols/utils.py index 5cf76e6b..59c420b7 100644 --- a/qctrlopencontrols/utils.py +++ b/qctrlopencontrols/utils.py @@ -119,8 +119,8 @@ class FileFormat(Enum): """ Defines exported file format. - Currently only supports the Q-CTRL expanded format. See :py:meth:`DrivenControl.export_to_file` for - details. + Currently only supports the Q-CTRL expanded format. See :py:meth:`DrivenControl.export_to_file` + for details. """ QCTRL = "Q-CTRL expanded" From aaacade2a19949e9226f282ad18a7e4ca8d0c776 Mon Sep 17 00:00:00 2001 From: Harry Slatyer Date: Mon, 7 Sep 2020 11:20:48 +1000 Subject: [PATCH 25/27] more lint --- qctrlopencontrols/driven_controls/driven_control.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qctrlopencontrols/driven_controls/driven_control.py b/qctrlopencontrols/driven_controls/driven_control.py index 13bc7488..3ec72d60 100644 --- a/qctrlopencontrols/driven_controls/driven_control.py +++ b/qctrlopencontrols/driven_controls/driven_control.py @@ -89,7 +89,7 @@ class DrivenControl: form: .. math:: - + U_n = \exp\left[-i\frac{\theta_n}{2} (\mathbf u_n\cdot\boldsymbol \sigma)\right], where :math:`\theta_n = \sqrt{\Omega_n^2+\Delta_n^2}\delta t_n`, From 8c0013f2ba429a2381d4c28c02ff61aa6383f3e6 Mon Sep 17 00:00:00 2001 From: Harry Slatyer Date: Mon, 7 Sep 2020 11:23:51 +1000 Subject: [PATCH 26/27] uncapitalise non-proper-noun acronym expansions --- qctrlopencontrols/driven_controls/predefined.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/qctrlopencontrols/driven_controls/predefined.py b/qctrlopencontrols/driven_controls/predefined.py index 619e9180..e6df1a04 100644 --- a/qctrlopencontrols/driven_controls/predefined.py +++ b/qctrlopencontrols/driven_controls/predefined.py @@ -422,7 +422,7 @@ def _new_scrofulous_control( **kwargs ) -> DrivenControl: r""" - Creates a Short Composite ROtation For Undoing Length Over and Under Shoot (SCROFULOUS) driven + Creates a short composite rotation for undoing length over and under shoot (SCROFULOUS) driven control. SCROFULOUS driven controls are robust to low-frequency noise sources that perturb the amplitude @@ -546,7 +546,7 @@ def _new_corpse_control( **kwargs ) -> DrivenControl: r""" - Creates a Compensating for Off-Resonance with a Pulse SEquence (CORPSE) driven control. + Creates a compensating for off-Resonance with a pulse sequence (CORPSE) driven control. CORPSE driven controls are robust to low-frequency dephasing noise. From 0db7a26572f419fcb35e600b9d1f3e893ef07164 Mon Sep 17 00:00:00 2001 From: Harry Slatyer Date: Mon, 7 Sep 2020 12:37:18 +1000 Subject: [PATCH 27/27] add comment --- qctrlopencontrols/driven_controls/predefined.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/qctrlopencontrols/driven_controls/predefined.py b/qctrlopencontrols/driven_controls/predefined.py index 32d9ab50..e8e4d409 100644 --- a/qctrlopencontrols/driven_controls/predefined.py +++ b/qctrlopencontrols/driven_controls/predefined.py @@ -43,6 +43,8 @@ def new_predefined_driven_control(scheme: str = PRIMITIVE, **kwargs): """ Creates a new driven control based on the given scheme. + Equivalent to calling the corresponding ``new__control`` function. + Parameters ---------- scheme : string, optional @@ -759,9 +761,6 @@ def new_corpse_in_sk1_control( See Also -------- new_corpse_control, new_sk1_control -======= - _new_corpse_control, _new_sk1_control ->>>>>>> master Notes -----