Skip to content

Commit

Permalink
improving gui
Browse files Browse the repository at this point in the history
  • Loading branch information
b-vanstraaten committed Jul 23, 2024
1 parent 4a821f0 commit 8d4d2c1
Show file tree
Hide file tree
Showing 11 changed files with 163 additions and 66 deletions.
Binary file removed docs/source/figures/GUI.png
Binary file not shown.
3 changes: 3 additions & 0 deletions docs/source/introduction.rst
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ stability diagram of a closed five dot quantum recreated with permission from `[

|recreations|

The code to reproduces these plots can be found in the examples folder of the QArray repository, named
figure_4b.py and figure_4d.py respectively.

.. |arXiv| image:: https://img.shields.io/badge/arXiv-2404.04994-Green.svg
.. |PyPI| image:: https://img.shields.io/pypi/v/qarray
.. |GitHub Workflow Status| image:: https://github.com/b-vanstraaten/qarray/actions/workflows/windows_tests.yaml//badge.svg
Expand Down
File renamed without changes.
File renamed without changes.
8 changes: 4 additions & 4 deletions examples/gui.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@
]

Cgd = [
[1., 0, 0, 0],
[0, 1., 0, 0.0],
[0, 0, 1., 0],
[0, 0, 0, 1]
[1., 0, 0, 0, 0],
[0, 1., 0, 0.0, 0],
[0, 0, 1., 0, 0],
[0, 0, 0, 1, 1]
]


Expand Down
14 changes: 13 additions & 1 deletion qarray/DotArrays/DotArray.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from ._helper_functions import (check_algorithm_and_implementation,
check_and_warn_user, convert_to_maxwell)
from .ground_state import _ground_state_open, _ground_state_closed
from ..functions import _optimal_Vg, compute_threshold
from ..functions import _optimal_Vg, compute_threshold, compute_optimal_virtual_gate_matrix
from ..latching_models import LatchingBaseModel
from ..qarray_types import Cdd as CddType # to avoid name clash with dataclass cdd
from ..qarray_types import CgdNonMaxwell, CddNonMaxwell, VectorList, Cgd_holes, Cgd_electrons, PositiveValuedMatrix, \
Expand Down Expand Up @@ -276,6 +276,18 @@ def do2d_closed(self, x_gate: int | str, x_min: float, x_max: float, x_points: i
vg = self.gate_voltage_composer.do2d(x_gate, x_min, x_max, x_points, y_gate, y_min, y_max, y_points)
return self.ground_state_closed(vg, n_charges)

def compute_optimal_virtual_gate_matrix(self):
"""
Computes the optimal virtual gate matrix for the dot array and sets it as the virtual gate matrix
in the gate voltage composer.
The virtual gate matrix is computed as the pseudo inverse of the dot to dot capacitance matrix times the dot to gate capacitance matrix.
returns np.ndarray: the virtual gate matrix
"""
virtual_gate_matrix = compute_optimal_virtual_gate_matrix(self.cdd_inv, self.cgd)
self.gate_voltage_composer.virtual_gate_matrix = virtual_gate_matrix
return virtual_gate_matrix

def run_gui(self, port=27182, print_compute_time: bool = False):
"""
Expand Down
2 changes: 1 addition & 1 deletion qarray/DotArrays/GateVoltageComposer.py
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ def meshgrid_virtual(self, dots: List[int | str], arrays: List[np.ndarray]) -> n
V = np.meshgrid(*arrays)

# setting the voltages
for dot in range(self.n_gate):
for dot in range(self.n_dot):
# if the gate is not in the gates list then set it to the current voltage
if dot not in dots:
Vd[..., dot] = 0
Expand Down
4 changes: 2 additions & 2 deletions qarray/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@

from .DotArrays import (DotArray, GateVoltageComposer, ChargeSensedDotArray)
from .functions import (_optimal_Vg, dot_occupation_changes, charge_state_contrast,
charge_state_to_scalar)
charge_state_to_scalar, compute_optimal_virtual_gate_matrix)
from .latching_models import *
from .noise_models import *

__all__ = [
'DotArray', 'GateVoltageComposer', 'ChargeSensedDotArray',
'_optimal_Vg', 'dot_occupation_changes', 'charge_state_contrast',
'charge_state_to_scalar',
'charge_state_to_scalar', 'compute_optimal_virtual_gate_matrix',
]

submodules = ['latching_models', 'noise_models']
23 changes: 23 additions & 0 deletions qarray/functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,29 @@
Vector)


def compute_optimal_virtual_gate_matrix(
cdd_inv: CddInv, cgd: Cgd_holes, rcond: float = 1e-4) -> np.ndarray:
"""
Function to compute the optimal virtual gate matrix.
:param cdd_inv: the inverse of the dot to dot capacitance matrix
:param cgd: the dot to gate capacitance matrix
:param rcond: the rcond parameter for the pseudo inverse
:return: the optimal virtual gate matrix
"""
n_dot = cdd_inv.shape[0]
n_gate = cgd.shape[1]
virtual_gate_matrix = -np.linalg.pinv(cdd_inv @ cgd, rcond=rcond)

# if the number of dots is less than the number of gates then we pad with zeros
if n_dot < n_gate:
virtual_gate_matrix = np.pad(virtual_gate_matrix, ((0, 0), (0, n_gate - n_dot)), mode='constant')

return virtual_gate_matrix



def charge_state_to_scalar(n: Tetrad | np.ndarray) -> int:
"""
Function to convert the charge state to a unique index, using the binary representation.
Expand Down
165 changes: 112 additions & 53 deletions qarray/gui/gui.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,88 +32,122 @@ def run_gui(model, port=27182, run=True, print_compute_time=False):
n_gate = model.n_gate

# Create the gate options
gate_options = create_gate_options(model.n_gate)
gate_options = create_gate_options(model.n_gate, model.n_dot)

# Convert the matrices to DataFrames for display in the tables
Cdd = pd.DataFrame(model.Cdd, dtype=float, columns=[f'D{i + 1}' for i in range(n_dot)])
Cgd = pd.DataFrame(model.Cgd, dtype=float, columns=[f'P{i + 1}' for i in range(n_gate)])

Cdd[''] = [f'D{i + 1}' for i in range(n_dot)]
Cgd[''] = [f'D{i + 1}' for i in range(n_dot)]

# making the '' column the first column
Cdd = Cdd[[''] + [col for col in Cdd.columns if col != '']]
Cgd = Cgd[[''] + [col for col in Cgd.columns if col != '']]

virtual_gate_matrix = model.compute_optimal_virtual_gate_matrix()
virtual_gate_matrix = np.round(virtual_gate_matrix, 3)
virtual_gate_matrix = pd.DataFrame(virtual_gate_matrix, dtype=float, columns=[f'vP{i + 1}' for i in range(n_gate)])

app.layout = html.Div([
# First Row: Tables
html.Div([
html.Div([
html.H4("C dot-dot"),
dash_table.DataTable(
id='editable-table1',
columns=[{"name": i, "id": i, "type": "numeric"} for i in Cdd.columns],
data=Cdd.reset_index().astype(float).to_dict('records'),
columns=[{"name": i, "id": i} for i in Cdd.columns],
data=Cdd.reset_index().to_dict('records'),
editable=True,
style_cell_conditional=[
{
'if': {'column_id': Cdd.columns[0]},
'backgroundColor': '#fafafa' # Light gray color for shading
}
]
)
], style={'display': 'inline-block', 'width': '40%', 'margin-right': '2%', 'vertical-align': 'top'}),
], style={'width': '32%', 'margin-right': '2%'}),

html.Div([
html.H4("C gate-dot"),
dash_table.DataTable(
id='editable-table2',
columns=[{"name": i, "id": i, "type": "numeric"} for i in Cgd.columns],
data=Cgd.reset_index().astype(float).to_dict('records'),
columns=[{"name": i, "id": i} for i in Cgd.columns],
data=Cgd.reset_index().to_dict('records'),
editable=True,
style_cell_conditional=[
{
'if': {'column_id': Cgd.columns[0]},
'backgroundColor': '#fafafa' # Light gray color for shading
}
]
)
], style={'width': '32%', 'margin-right': '2%'}),

html.Div([
html.H4("Virtual gate matrix"),
dash_table.DataTable(
id='virtual-gate-matrix',
columns=[{"name": i, "id": i, "type": "numeric"} for i in virtual_gate_matrix.columns],
data=virtual_gate_matrix.reset_index().astype(float).to_dict('records'),
editable=True
)
], style={'display': 'inline-block', 'width': '40%', 'margin-right': '2%', 'vertical-align': 'top'}),
], style={'width': '32%'}),

], style={'text-align': 'left', 'margin-bottom': '20px', 'display': 'flex',
'justify-content': 'space-between'}),
], style={'display': 'flex', 'justify-content': 'space-between', 'margin-bottom': '20px'}),

# Second Row: Sweep Options and DAC values
html.Div([
html.Div([
html.H4("x sweep options"),
html.H4("X sweep options"),
dcc.Dropdown(
id='dropdown-menu-x',
placeholder='x gate',
placeholder='X gate',
options=gate_options,
value='P1'
),
dcc.Input(
id='input-scalar-x1',
type='number',
placeholder='x_amplitude',
placeholder='X amplitude',
value=5,
style={'margin-left': '10px'}
),
dcc.Input(
id='input-scalar-x2',
type='number',
placeholder='x_resolution',
placeholder='X resolution',
value=200,
style={'margin-left': '10px'}
),
], style={'display': 'inline-block', 'width': '30%', 'margin-right': '2%', 'vertical-align': 'top'}),
], style={'width': '24%', 'margin-right': '2%'}),

html.Div([
html.H4("y sweep options"),
html.H4("Y sweep options"),
dcc.Dropdown(
id='dropdown-menu-y',
placeholder='y gate',
placeholder='Y gate',
options=gate_options,
value=f"P{model.n_gate}"
),
dcc.Input(
id='input-scalar1',
type='number',
placeholder='y_amplitude',
placeholder='Y amplitude',
value=5,
style={'margin-left': '10px'}
),
dcc.Input(
id='input-scalar2',
type='number',
placeholder='y_resolution',
placeholder='Y resolution',
value=200,
style={'margin-left': '10px'}
),
], style={'display': 'inline-block', 'width': '30%', 'margin-right': '2%', 'vertical-align': 'top'}),
], style={'width': '24%', 'margin-right': '2%'}),

html.Div([
html.H4("Dac values"),
html.H4("DAC values"),
*[
dcc.Input(
id=f'dac_{i}',
Expand All @@ -124,7 +158,19 @@ def run_gui(model, port=27182, run=True, print_compute_time=False):
style={'margin-bottom': '10px', 'display': 'block'}
) for i in range(model.n_gate)
]
], style={'display': 'inline-block', 'width': '30%', 'vertical-align': 'top'}),
], style={'width': '24%'}),

], style={'display': 'flex', 'justify-content': 'space-between', 'margin-bottom': '20px'}),

# Third Row: Plot Options and Heatmap
html.Div([

html.Div([
dcc.Graph(
id='heatmap',
style={'width': '100%', 'margin-left': 'auto', 'margin-right': 'auto'}
)
], style={'width': '78%', 'text-align': 'center'}),

html.Div([
html.H4("Open/Closed options"),
Expand All @@ -134,46 +180,47 @@ def run_gui(model, port=27182, run=True, print_compute_time=False):
options=n_charges_options,
value='any'
),

html.H4("Plot options"),
dcc.Dropdown(
id='plot-options',
placeholder='Whether to plot changes or colours and if so the colour map',
placeholder='Select plot options',
options=plot_options,
value='changes'
),
html.H4("Automatically update virtual gate matrix"),
dcc.Dropdown(
id='automatically-update-virtual-gate-matrix',
placeholder='Auto-update virtual gate matrix',
options=[
{'label': 'True', 'value': 'True'},
{'label': 'False', 'value': 'False'}
],
value='True'
)
], style={'width': '20%', 'margin-right': '2%'}),

], style={'display': 'inline-block', 'width': '30%', 'margin-right': '2%', 'vertical-align': 'top'}),

], style={'text-align': 'left', 'margin-bottom': '20px', 'display': 'flex',
'justify-content': 'space-between'}),

html.Div([
html.Div([
dcc.Graph(
id='heatmap',
style={'width': '100%', 'display': 'block', 'margin-left': 'auto', 'margin-right': 'auto'}
)
], style={'text-align': 'center', 'margin-top': '20px'})
])
], style={'display': 'flex', 'justify-content': 'space-between', 'margin-top': '20px'})
])

@app.callback(
Output('heatmap', 'figure'),
Input('editable-table1', 'data'),
Input('editable-table2', 'data'),
Input('dropdown-menu-x', 'value'),
Input('input-scalar-x1', 'value'),
Input('input-scalar-x2', 'value'),
Input('dropdown-menu-y', 'value'),
Input('input-scalar1', 'value'),
Input('input-scalar2', 'value'),
Input('dropdown-menu-n-charges', 'value'),
Input('plot-options', 'value'),
*[Input(f'dac_{i}', 'value') for i in range(model.n_gate)]
(Output('heatmap', 'figure'),
Output('virtual-gate-matrix', 'data')),
[Input('editable-table1', 'data'),
Input('editable-table2', 'data'),
Input('virtual-gate-matrix', 'data'),
Input('dropdown-menu-x', 'value'),
Input('input-scalar-x1', 'value'),
Input('input-scalar-x2', 'value'),
Input('dropdown-menu-y', 'value'),
Input('input-scalar1', 'value'),
Input('input-scalar2', 'value'),
Input('dropdown-menu-n-charges', 'value'),
Input('plot-options', 'value'),
Input('automatically-update-virtual-gate-matrix', 'value'),
*[Input(f'dac_{i}', 'value') for i in range(model.n_gate)]]
)
def update(Cdd, Cgd, x_gate, x_amplitude, x_resolution, y_gate, y_amplitude, y_resolution,
n_charges, plot_options, *dac_values):
def update(Cdd, Cgd, virtual_gate_matrix, x_gate, x_amplitude, x_resolution, y_gate, y_amplitude, y_resolution,
n_charges, plot_options, automatically_update_virtual_gate_matrix, *dac_values):
"""
Update the heatmap based on the input values.
"""
Expand All @@ -189,8 +236,8 @@ def update(Cdd, Cgd, x_gate, x_amplitude, x_resolution, y_gate, y_amplitude, y_r

try:
# Convert table data back to matrices
Cdd = pd.DataFrame(Cdd).set_index('index').astype(float)
Cgd = pd.DataFrame(Cgd).set_index('index').astype(float)
Cdd = pd.DataFrame(Cdd).drop(columns=['']).set_index('index').astype(float)
Cgd = pd.DataFrame(Cgd).drop(columns=['']).set_index('index').astype(float)
except ValueError:
print('Error the capacitance matrices cannot be converted to float. \n')
return go.Figure()
Expand All @@ -206,6 +253,18 @@ def update(Cdd, Cgd, x_gate, x_amplitude, x_resolution, y_gate, y_amplitude, y_r

model.update_capacitance_matrices(Cdd=cdd_matrix, Cgd=Cgd.to_numpy())

if automatically_update_virtual_gate_matrix == 'True':

virtual_gate_matrix = model.compute_optimal_virtual_gate_matrix()
virtual_gate_matrix = np.round(virtual_gate_matrix, 3)
virtual_gate_matrix = pd.DataFrame(virtual_gate_matrix, dtype=float,
columns=[f'vP{i + 1}' for i in range(n_gate)])
else:
virtual_gate_matrix = pd.DataFrame(virtual_gate_matrix)

model.gate_voltage_composer.virtual_gate_matrix = virtual_gate_matrix.to_numpy()[:, :n_dot]


vg = model.gate_voltage_composer.do2d(
x_gate, -x_amplitude / 2, x_amplitude / 2, x_resolution,
y_gate, -y_amplitude / 2, y_amplitude / 2, y_resolution
Expand Down Expand Up @@ -281,7 +340,7 @@ def update(Cdd, Cgd, x_gate, x_amplitude, x_resolution, y_gate, y_amplitude, y_r
height=600,
)

return fig
return fig, virtual_gate_matrix.to_dict('records')

# Run the server
if run:
Expand Down
Loading

0 comments on commit 8d4d2c1

Please sign in to comment.