From 5544af5e445655f37f8e438632dec7499ba450a6 Mon Sep 17 00:00:00 2001
From: Sander de Snoo <59472150+sldesnoo-Delft@users.noreply.github.com>
Date: Mon, 2 Oct 2023 16:46:26 +0200
Subject: [PATCH] Fixed Qblox hardware thresholded data check

---
 pulse_lib/acquisition/measurement_converter.py | 11 ++++++++---
 pulse_lib/qblox/pulsar_uploader.py             | 16 +++++++++++-----
 2 files changed, 19 insertions(+), 8 deletions(-)

diff --git a/pulse_lib/acquisition/measurement_converter.py b/pulse_lib/acquisition/measurement_converter.py
index d056d44a..d821ee84 100644
--- a/pulse_lib/acquisition/measurement_converter.py
+++ b/pulse_lib/acquisition/measurement_converter.py
@@ -322,6 +322,7 @@ class MeasurementConverter:
 
     def _set_data_raw(self, index):
         self._raw = []
+        self._hw_thresholded = {}
         for m in self._description.measurements:
             if isinstance(m, measurement_acquisition):
                 channel_name = m.acquisition_channel
@@ -331,6 +332,9 @@ class MeasurementConverter:
                     data_offset = data_offset[tuple(index)]
                 if m.interval is None:
                     channel_raw = channel_data[...,data_offset]
+                    thresholded = self._channel_raw.get(m.acquisition_channel+'.thresholded', None)
+                    if thresholded is not None:
+                        self._hw_thresholded[len(self._raw)] = thresholded[..., data_offset]
                 else:
                     n_samples = m.n_samples
                     if not isinstance(n_samples, Number):
@@ -364,9 +368,10 @@ class MeasurementConverter:
                 if m.zero_on_high:
                     result = result ^ 1
                 result = result.astype(int)
-                data = self._channel_raw.get(m.acquisition_channel+'.thresholded', None)
-                if data is not None and np.any(result != data):
-                    logger.warning(f'{np.sum(result != data)} differences between hardware and software threshold')
+                hw_thresholded = self._hw_thresholded.get(i, None)
+                if hw_thresholded is not None and np.any(result != hw_thresholded):
+                    logger.warning(f'{np.sum(result != hw_thresholded)} differences between hardware and software threshold. '
+                                   f'({np.where(result != hw_thresholded)})')
             elif isinstance(m, measurement_expression):
                 result = m.expression.evaluate(last_result)
             else:
diff --git a/pulse_lib/qblox/pulsar_uploader.py b/pulse_lib/qblox/pulsar_uploader.py
index ff2b0780..5c32562f 100644
--- a/pulse_lib/qblox/pulsar_uploader.py
+++ b/pulse_lib/qblox/pulsar_uploader.py
@@ -252,10 +252,12 @@ class PulsarUploader:
         channels = job.acquisition_conf.channels
         if channels is None:
             channels = self.digitizer_channels.keys()
+        triggers = {ch_name: getattr(job.program[ch_name], 'trigger', None) for ch_name in channels}
         self.acq_description = AcqDescription(seq_id, index, channels,
                                               job.acq_data_scaling,
                                               job.n_rep,
-                                              job.acquisition_conf.average_repetitions)
+                                              job.acquisition_conf.average_repetitions,
+                                              triggers)
 
         logger.info(f'Play {index}')
 
@@ -315,10 +317,13 @@ class PulsarUploader:
                         raw.append(self._scale_acq_data(path_data, in_ranges[i]/2*scaling*1000))
                     duration_ms = (time.perf_counter()-start)*1000
                     logger.debug(f'Retrieved data {channel_name} in {duration_ms:5.1f} ms')
-                    seq_def = self.q1instrument.readouts[channel_name]
-                    sequencer = self.q1instrument.modules[seq_def.module_name].pulsar.sequencers[seq_def.seq_nr]
-                    if sequencer.thresholded_acq_trigger_en():
-                        result[channel_name+'.thresholded'] = np.array(bin_data['threshold'])
+                    trigger = acq_desc.triggers[channel_name]
+                    if trigger is not None:
+                        result[channel_name+'.thresholded'] = np.array(bin_data['threshold'], dtype=int)
+                        if trigger.invert:
+                            # invert thresholded result as has been done on trigger.
+                            result[channel_name+'.thresholded'] ^= 1
+
                 except KeyError:
                     raw = [np.zeros(0)]*2
 
@@ -385,6 +390,7 @@ class AcqDescription:
     acq_data_scaling: Dict[str, Union[float, np.ndarray]]
     n_rep: int
     average_repetitions: bool = False
+    triggers: Optional[List[object]] = None
 
 
 class Job(object):
-- 
GitLab