Skip to content

Feature/qd sensor sweep level 2#482

Open
TheoLaudatQM wants to merge 5 commits intofeat/quantum_dotsfrom
feature/qd_sensor_sweep_l2
Open

Feature/qd sensor sweep level 2#482
TheoLaudatQM wants to merge 5 commits intofeat/quantum_dotsfrom
feature/qd_sensor_sweep_l2

Conversation

@TheoLaudatQM
Copy link
Collaborator

Sensor gate sweep with OPX and QDAC to level 2

Copy link

@KU-QM KU-QM left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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(
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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()
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of ramping directly to zero, perhaps we should do sensor.apply_compensation_pulse(ramp_to_zero = True)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

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,
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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(
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants