From f0a9bd9863ebab7d7108fc30a6fdac73e716d368 Mon Sep 17 00:00:00 2001 From: PiergiorgioButtarini Date: Tue, 26 Dec 2023 15:46:13 +0400 Subject: [PATCH 1/2] feat: draft implementation of tof routine for qblox --- src/qibolab/instruments/qblox/acquisition.py | 20 +++++++++++-------- .../instruments/qblox/cluster_qrm_rf.py | 19 +++++++++--------- src/qibolab/instruments/qblox/controller.py | 17 ++++++++-------- 3 files changed, 29 insertions(+), 27 deletions(-) diff --git a/src/qibolab/instruments/qblox/acquisition.py b/src/qibolab/instruments/qblox/acquisition.py index c469a2b148..55b7735d2b 100644 --- a/src/qibolab/instruments/qblox/acquisition.py +++ b/src/qibolab/instruments/qblox/acquisition.py @@ -93,11 +93,17 @@ class DemodulatedAcquisition: It is advisable to have a power level at least higher than 5mV. """ + scope: dict + """Data returned by scope qblox acquisition.""" bins: dict """Binned acquisition data returned by qblox.""" duration: int """Duration of the readout pulse.""" + @property + def raw(self): + return self.scope["acquisition"]["scope"] + @property def integration(self): return self.bins["integration"] @@ -115,16 +121,14 @@ def shots_q(self): return np.array(self.integration["path1"]) / self.duration @property - def averaged_i(self): - """I-component after demodulating and integrating every shot waveform - and then averaging over shots.""" - return np.mean(self.shots_i) + def raw_i(self): + """Average of the raw i waveforms for every readout pulse.""" + return np.array(self.raw["path0"]["data"][0 : self.duration]) @property - def averaged_q(self): - """Q-component after demodulating and integrating every shot waveform - and then averaging over shots.""" - return np.mean(self.shots_q) + def raw_q(self): + """Average of the raw q waveforms for every readout pulse.""" + return np.array(self.raw["path1"]["data"][0 : self.duration]) @property def classified(self): diff --git a/src/qibolab/instruments/qblox/cluster_qrm_rf.py b/src/qibolab/instruments/qblox/cluster_qrm_rf.py index 21ecf90f36..f45f89df7b 100644 --- a/src/qibolab/instruments/qblox/cluster_qrm_rf.py +++ b/src/qibolab/instruments/qblox/cluster_qrm_rf.py @@ -1026,6 +1026,7 @@ def acquire(self): for port in self._output_ports_keys: for sequencer in self._sequencers[port]: # Store scope acquisition data on 'scope_acquisition' acquisition of the default sequencer + # TODO: Maybe this store_scope can be done only if needed to optimize the process! if sequencer.number == self.DEFAULT_SEQUENCERS[port]: self.device.store_scope_acquisition( sequencer.number, "scope_acquisition" @@ -1033,7 +1034,6 @@ def acquire(self): scope = self.device.get_acquisitions(sequencer.number)[ "scope_acquisition" ] - if not hardware_demod_enabled: # Software Demodulation if len(sequencer.pulses.ro_pulses) == 1: pulse = sequencer.pulses.ro_pulses[0] @@ -1052,19 +1052,18 @@ def acquire(self): bins = results[pulse.serial]["acquisition"]["bins"] acquisitions[pulse.qubit] = acquisitions[ pulse.serial - ] = DemodulatedAcquisition(bins, duration) - + ] = DemodulatedAcquisition(scope, bins, duration) # Provide Scope Data for verification (assuming memory reseet is being done) - if len(sequencer.pulses.ro_pulses) == 1: - pulse = sequencer.pulses.ro_pulses[0] - frequency = self.get_if(pulse) - acquisitions[pulse.serial].averaged = AveragedAcquisition( - scope, duration, frequency - ) + # if len(sequencer.pulses.ro_pulses) == 1: + # pulse = sequencer.pulses.ro_pulses[0] + # frequency = self.get_if(pulse) + # acquisitions[pulse.serial].averaged = AveragedAcquisition( + # scope, duration, frequency + # ) # grab only the data required by the platform # TODO: to be updated once the functionality of ExecutionResults is extended - return {key: acquisition.data for key, acquisition in acquisitions.items()} + return {key: acquisition for key, acquisition in acquisitions.items()} def start(self): """Empty method to comply with Instrument interface.""" diff --git a/src/qibolab/instruments/qblox/controller.py b/src/qibolab/instruments/qblox/controller.py index e0ab4d200f..f71310fa5b 100644 --- a/src/qibolab/instruments/qblox/controller.py +++ b/src/qibolab/instruments/qblox/controller.py @@ -201,25 +201,24 @@ def _execute_pulse_sequence( and not module_pulses[name].ro_pulses.is_empty ): results = module.acquire() - existing_keys = set(acquisition_results.keys()) & set(results.keys()) for key, value in results.items(): - if key in existing_keys: - acquisition_results[key].update(value) - else: - acquisition_results[key] = value - + acquisition_results[key] = value # TODO: move to QRM_RF.acquire() shape = tuple(len(sweeper.values) for sweeper in reversed(sweepers)) shots_shape = (nshots,) + shape for ro_pulse in sequence.ro_pulses: if options.acquisition_type is AcquisitionType.DISCRIMINATION: - _res = acquisition_results[ro_pulse.serial][2] + _res = acquisition_results[ro_pulse.serial].classified _res = np.reshape(_res, shots_shape) if options.averaging_mode is not AveragingMode.SINGLESHOT: _res = np.mean(_res, axis=0) + elif options.acquisition_type is AcquisitionType.RAW: + i_raw = acquisition_results[ro_pulse.serial].raw_i + q_raw = acquisition_results[ro_pulse.serial].raw_q + _res = i_raw + 1j * q_raw else: - ires = acquisition_results[ro_pulse.serial][0] - qres = acquisition_results[ro_pulse.serial][1] + ires = acquisition_results[ro_pulse.serial].shots_i + qres = acquisition_results[ro_pulse.serial].shots_q _res = ires + 1j * qres if options.averaging_mode is AveragingMode.SINGLESHOT: _res = np.reshape(_res, shots_shape) From eff2153bb6b625f89f7d974ca270d61fe6318d26 Mon Sep 17 00:00:00 2001 From: PiergiorgioButtarini Date: Wed, 31 Jan 2024 12:31:17 +0400 Subject: [PATCH 2/2] refactor: delete dead code, add control on AcquisitionType.INTEGRATION --- src/qibolab/instruments/qblox/acquisition.py | 10 ---------- src/qibolab/instruments/qblox/cluster_qrm_rf.py | 10 +--------- src/qibolab/instruments/qblox/controller.py | 2 +- 3 files changed, 2 insertions(+), 20 deletions(-) diff --git a/src/qibolab/instruments/qblox/acquisition.py b/src/qibolab/instruments/qblox/acquisition.py index 55b7735d2b..69da4e5e6b 100644 --- a/src/qibolab/instruments/qblox/acquisition.py +++ b/src/qibolab/instruments/qblox/acquisition.py @@ -135,13 +135,3 @@ def classified(self): """List with the results of demodulating, integrating and classifying every shot.""" return np.array(self.bins["threshold"]) - - @property - def data(self): - """Acquisition data to be returned to the platform. - - Ignores the data available in acquisition results and returns - only i and q voltages. - """ - # TODO: to be updated once the functionality of ExecutionResults is extended - return (self.shots_i, self.shots_q, self.classified) diff --git a/src/qibolab/instruments/qblox/cluster_qrm_rf.py b/src/qibolab/instruments/qblox/cluster_qrm_rf.py index 788444415d..ea5e5a8251 100644 --- a/src/qibolab/instruments/qblox/cluster_qrm_rf.py +++ b/src/qibolab/instruments/qblox/cluster_qrm_rf.py @@ -1004,15 +1004,7 @@ def acquire(self): acquisitions[pulse.qubit] = acquisitions[ pulse.serial ] = DemodulatedAcquisition(scope, bins, duration) - # Provide Scope Data for verification (assuming memory reseet is being done) - # if len(sequencer.pulses.ro_pulses) == 1: - # pulse = sequencer.pulses.ro_pulses[0] - # frequency = self.get_if(pulse) - # acquisitions[pulse.serial].averaged = AveragedAcquisition( - # scope, duration, frequency - # ) - - # grab only the data required by the platform + # TODO: to be updated once the functionality of ExecutionResults is extended return {key: acquisition for key, acquisition in acquisitions.items()} diff --git a/src/qibolab/instruments/qblox/controller.py b/src/qibolab/instruments/qblox/controller.py index 3bef3175b2..7c7fc5f054 100644 --- a/src/qibolab/instruments/qblox/controller.py +++ b/src/qibolab/instruments/qblox/controller.py @@ -204,7 +204,7 @@ def _execute_pulse_sequence( i_raw = acquisition_results[ro_pulse.serial].raw_i q_raw = acquisition_results[ro_pulse.serial].raw_q _res = i_raw + 1j * q_raw - else: + elif options.acquisition_type is AcquisitionType.INTEGRATION: ires = acquisition_results[ro_pulse.serial].shots_i qres = acquisition_results[ro_pulse.serial].shots_q _res = ires + 1j * qres