Skip to content

Commit

Permalink
Merge pull request #155 from QDevil/master
Browse files Browse the repository at this point in the history
QDAC2: Generalise virtual sweep
  • Loading branch information
astafan8 authored Sep 12, 2022
2 parents 301c25c + 96be844 commit ecd012f
Show file tree
Hide file tree
Showing 5 changed files with 200 additions and 64 deletions.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

86 changes: 69 additions & 17 deletions qcodes_contrib_drivers/drivers/QDevil/QDAC2.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from typing import Any, NewType, Sequence, List, Dict, Tuple, Optional
from packaging.version import parse

# Version 0.16.0
# Version 0.17.0
#
# Guiding principles for this driver for QDevil QDAC-II
# -----------------------------------------------------
Expand Down Expand Up @@ -1544,7 +1544,7 @@ def waveform(self, values: Sequence[float]) -> None:
self._parent.write_floats(f'trac:data "{self.name}",', values)


class Sweep_2D_Context:
class Virtual_Sweep_Context:

def __init__(self, arrangement: 'Arrangement_Context', sweep: np.ndarray,
start_sweep_trigger: Optional[str], inner_step_time_s: float,
Expand Down Expand Up @@ -1679,8 +1679,24 @@ def initiate_correction(self, gate: str, factors: Sequence[float]):
self._correction[index] = factors

def set_virtual_voltage(self, gate: str, voltage: float) -> None:
index = self._gate_index(gate)
"""Set virtual voltage on specific gate
The actual voltage that the gate will receive depends on the
correction matrix.
Args:
gate (str): Name of gate
voltage (float): Voltage corresponding to no correction
"""
try:
index = self._gate_index(gate)
except KeyError:
raise ValueError(f'No gate named "{gate}"')
self._virtual_voltages[index] = voltage
actual_V = self.actual_voltages()[index]
channel_number = self._channels[index]
self._qdac.channel(channel_number).dc_constant_V(actual_V)


def add_correction(self, gate: str, factors: Sequence[float]) -> None:
"""Update how much a particular gate influences the other gates
Expand Down Expand Up @@ -1745,45 +1761,81 @@ def get_trigger_by_name(self, name: str) -> QDac2Trigger_Context:
print(f'Internal triggers: {list(self._internal_triggers.keys())}')
raise

def virtual_sweep(self, gate: str, voltages: Sequence[float],
start_sweep_trigger: Optional[str] = None,
step_time_s: float = 1e-5,
step_trigger: Optional[str] = None
) -> Virtual_Sweep_Context:
"""Sweep a gate to create a 1D sweep
Args:
gate (str): Name of sweeping gate
voltages (Sequence[float]): Virtual sweep voltages
outer_gate (str): Name of slow-changing (outer) gate
start_sweep_trigger (None, optional): Trigger that starts sweep
step_time_s (float, optional): Delay between voltage changes
step_trigger (None, optional): Trigger that marks each step
Returns:
Virtual_Sweep_Context: context manager
"""
sweep = self._calculate_1d_values(gate, voltages)
return Virtual_Sweep_Context(self, sweep, start_sweep_trigger,
step_time_s, step_trigger)

def _calculate_1d_values(self, gate: str, voltages: Sequence[float]
) -> np.ndarray:
original_voltage = self.virtual_voltage(gate)
index = self._gate_index(gate)
sweep = []
for v in voltages:
self._virtual_voltages[index] = v
sweep.append(self.actual_voltages())
self._virtual_voltages[index] = original_voltage
return np.array(sweep)


def virtual_sweep2d(self, inner_gate: str, inner_voltages: Sequence[float],
outer_gate: str, outer_voltages: Sequence[float],
start_sweep_trigger: Optional[str] = None,
inner_step_time_s: float = 1e-5,
inner_step_trigger: Optional[str] = None
) -> Sweep_2D_Context:
) -> Virtual_Sweep_Context:
"""Sweep two gates to create a 2D sweep
Args:
inner_gate (str): Name of fast-changing (inner) gate
inner_voltages (Sequence[float]): Inner gate voltages
inner_voltages (Sequence[float]): Inner gate virtual voltages
outer_gate (str): Name of slow-changing (outer) gate
outer_voltages (Sequence[float]): Outer gate voltages
outer_voltages (Sequence[float]): Outer gate virtual voltages
start_sweep_trigger (None, optional): Trigger that starts sweep
inner_step_time_s (float, optional): Delay between voltage changes
inner_step_trigger (None, optional): Trigger that marks each step
Returns:
Sweep_2D_Context: context manager
Virtual_Sweep_Context: context manager
"""
sweep = self._calculate_sweep_values(inner_gate, inner_voltages,
sweep = self._calculate_2d_values(inner_gate, inner_voltages,
outer_gate, outer_voltages)
return Sweep_2D_Context(self, sweep, start_sweep_trigger,
return Virtual_Sweep_Context(self, sweep, start_sweep_trigger,
inner_step_time_s, inner_step_trigger)

def _calculate_sweep_values(self, inner_gate: str,
inner_voltages: Sequence[float],
outer_gate: str,
outer_voltages: Sequence[float]) -> np.ndarray:
def _calculate_2d_values(self, inner_gate: str,
inner_voltages: Sequence[float],
outer_gate: str,
outer_voltages: Sequence[float]) -> np.ndarray:
original_fast_voltage = self.virtual_voltage(inner_gate)
original_slow_voltage = self.virtual_voltage(outer_gate)
outer_index = self._gate_index(outer_gate)
inner_index = self._gate_index(inner_gate)
sweep = []
for slow_V in outer_voltages:
self.set_virtual_voltage(outer_gate, slow_V)
self._virtual_voltages[outer_index] = slow_V
for fast_V in inner_voltages:
self.set_virtual_voltage(inner_gate, fast_V)
self._virtual_voltages[inner_index] = fast_V
sweep.append(self.actual_voltages())
self.set_virtual_voltage(inner_gate, original_fast_voltage)
self.set_virtual_voltage(outer_gate, original_slow_voltage)
self._virtual_voltages[inner_index] = original_fast_voltage
self._virtual_voltages[outer_index] = original_slow_voltage
return np.array(sweep)

def _gate_index(self, gate: str) -> int:
Expand Down
2 changes: 2 additions & 0 deletions qcodes_contrib_drivers/tests/QDevil/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ Simulated instrument:
$ source venv/bin/activate
$ pytest qcodes_contrib_drivers/tests/QDevil/test_sim_qdac2_*.py

To silence warnings, use `-W ignore::DeprecationWarning`.

Real instrument:

$ source venv/bin/activate
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,41 @@ def test_arrangement_default_correction(qdac): # noqa
np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1]]))


def test_arrangement_default_actuals(qdac): # noqa
def test_arrangement_set_virtual_voltage_non_exiting_gate(qdac): # noqa
arrangement = qdac.arrange(gates={'plunger': 1})
# -----------------------------------------------------------------------
with pytest.raises(ValueError) as error:
arrangement.set_virtual_voltage('sensor', 1.0)
# -----------------------------------------------------------------------
assert 'No gate named "sensor"' in repr(error)


def test_arrangement_set_virtual_voltage_effectuated_immediately(qdac): # noqa
arrangement = qdac.arrange(gates={'plunger1': 1, 'plunger2': 2, 'plunger3': 3})
qdac.start_recording_scpi()
# -----------------------------------------------------------------------
arrangement.set_virtual_voltage('plunger2', 0.5)
# -----------------------------------------------------------------------
commands = qdac.get_recorded_scpi_commands()
assert commands == ['sour2:volt:mode fix', 'sour2:volt 0.5']


def test_arrangement_default_actuals_1d(qdac): # noqa
arrangement = qdac.arrange(gates={'plunger1': 1, 'plunger2': 2})
arrangement.set_virtual_voltage('plunger2', 1.0)
# -----------------------------------------------------------------------
sweep = arrangement.virtual_sweep(
gate='plunger1',
voltages=np.linspace(-0.1, 0.1, 5),
step_time_s=2e-5)
# -----------------------------------------------------------------------
assert np.allclose(sweep.actual_values_V('plunger1'),
[-0.1, -0.05, 0.0, 0.05, 0.1])
assert np.allclose(sweep.actual_values_V('plunger2'),
[1.0, 1.0, 1.0, 1.0, 1.0])


def test_arrangement_default_actuals_2d(qdac): # noqa
arrangement = qdac.arrange(gates={'plunger1': 1, 'plunger2': 2, 'plunger3': 3})
# -----------------------------------------------------------------------
sweep = arrangement.virtual_sweep2d(
Expand Down Expand Up @@ -186,6 +220,14 @@ def test_stability_diagram_external(qdac): # noqa
assert commands == [
'outp:trig4:sour int1',
'outp:trig4:widt 1e-06',
'sour3:volt:mode fix',
'sour3:volt 0.1',
'sour6:volt:mode fix',
'sour6:volt 0.176',
'sour7:volt:mode fix',
'sour7:volt 0.383',
'sour8:volt:mode fix',
'sour8:volt 0.69693',
'sour3:dc:mark:sst 1',
# Sensor 1
'sour3:dc:trig:sour hold',
Expand Down

0 comments on commit ecd012f

Please sign in to comment.