Feature/qd sensor sweep level 2#482
Conversation
KU-QM
left a comment
There was a problem hiding this comment.
A few comments and some discussion points
| # Sweep the sensor bias voltage | ||
| readout_len = sensor.readout_resonator.operations["readout"].length | ||
| # sensor.physical_channel.set_dc_offset(offset=offset) | ||
| sensor.voltage_sequence.step_to_voltages( |
There was a problem hiding this comment.
If the sensor object is already a VoltageControlMixin, then it should be able to directly step_to_voltages({...}) without the intermediate voltage_sequence. Might be more intuitive for those who want to debug
There was a problem hiding this comment.
I guess that it has to be a VoltageControlMixin no?
I tested it an it works, except for the ramp_to_zero method which is not part of sensor, shouldn't we add it?
| align() | ||
|
|
||
| for i, sensor in multiplexed_sensors.items(): | ||
| sensor.voltage_sequence.ramp_to_zero() |
There was a problem hiding this comment.
Instead of ramping directly to zero, perhaps we should do sensor.apply_compensation_pulse(ramp_to_zero = True)
There was a problem hiding this comment.
The weird thing is that the auto-completion is not suggesting the API attached to sensor.voltage_sequence. If we want users to do it, I believe that we should fix it because otherwise there is no easy way to know which methods are accessible from which component. It probably comes from sensors.batch.
qualibration_graphs/quantum_dots/calibrations/loss_divincenzo/05a_sensor_gate_sweep_opx.py
Outdated
Show resolved
Hide resolved
| dc_lists = {} | ||
| for sensor in sensors: # TODO: Issue with qcodes driver? | ||
| dc_lists[sensor.name] = node.machine.qdac.channel(sensor.physical_channel.qdac_spec.qdac_output_port).dc_list( | ||
| voltages=bias_offsets, |
There was a problem hiding this comment.
At some point in this section, you'd probably have to do node.machine.connect_to_external_source(external_qdac = True) to instantiate machine.qdac, and if the machine has the qdac_ip in the network, it should directly connect via the qcodes driver. To be replaced with in-house in future, but can keep the api here the same.
For a more intuitive api, should we integrate the connect_to_external_source call in the machine.connect() function? It can look in its network to see if qdac_ip exists, and conditionally connect to external source
| continue | ||
|
|
||
| optimal_offset = 0.0 # find_optimal_offset(node.results["ds_fit"], sensor.name) | ||
| sensor.physical_channel.offset_parameter(optimal_offset) |
There was a problem hiding this comment.
I think we should use VirtualDCSet, so that a virtual point can be used instead of setting it directly via the physical channel
machine.virtual_dc_sets[virtual_gate_set_id].set_voltages({sensor.name : optimal_offset})
| # Set up the DC lists to load into the QDAC. | ||
| dc_lists = {} | ||
| for sensor in sensors: # TODO: Issue with qcodes driver? | ||
| dc_lists[sensor.name] = node.machine.qdac.channel(sensor.physical_channel.qdac_spec.qdac_output_port).dc_list( |
There was a problem hiding this comment.
Is the sweep going to be virtual? This goes for the charge stability node too, but perhaps we need to load multiple dc_lists for the physical outputs of the virtual channels. Here is a snippet of what I did in qua-dashboards:
def _find_physical_dc_lists(
self,
qdac_sweep_axis: VoltageSweepAxis,
) -> Dict[str, Union[List, np.ndarray]]:
"""Use the sweep axis abnd scab mode to yield a dictionary of physical dc_lists to use for the Qdac"""
axis_name = qdac_sweep_axis.name
axis_values = qdac_sweep_axis.sweep_values_with_offset
_, y_idxs = self.scan_mode.get_idxs(x_points = 1, y_points = len(axis_values))
ordered_axis_values = axis_values[y_idxs]
dc_set = self.dc_set
full_physical_dicts = {name: [] for name in dc_set.channels.keys()}
for value in ordered_axis_values:
virtual_dict = {axis_name: float(value)}
physical_dict = dc_set.resolve_voltages(virtual_dict)
for physical_gate in dc_set.channels.keys():
full_physical_dicts[physical_gate].append(physical_dict[physical_gate])
return {name: np.array(l) for name, l in full_physical_dicts.items()}
def _prepare_qdac_sweeps(
self,
) -> None:
"""
Prepares the DC list attributes for the QDAC channel. This function assumes the use of the
Qdac2 driver from qcodes_contrib_drivers. This also assumes that the VoltageGate objects have
their QdacSpec objects configured with the qdac_output_port and opx_trigger_out.
"""
if not isinstance(self.y_axis, VoltageSweepAxis):
raise ValueError("Qdac Sweep Axis must be mode 'Voltage'")
self._last_dc_list_y_offset = self.y_axis.offset_parameter.get_latest()
physical_dc_lists = self._find_physical_dc_lists(self.y_axis)
for name, voltages in physical_dc_lists.items():
dc_list = self.qdac.channel(self.dc_set.channels[name].qdac_spec.qdac_output_port).dc_list(
voltages = voltages,
dwell_s = self.qdac_dwell_time_us/1e6,
stepped = True,
)
dc_list.start_on_external(trigger = self.qdac_ext_trigger_input_port)
Sensor gate sweep with OPX and QDAC to level 2