From cfa9461f269e616d6d54658d583b37d215f35a7b Mon Sep 17 00:00:00 2001 From: "Matthias P. Braendli" Date: Wed, 28 Nov 2018 11:11:22 +0100 Subject: GUI: Add part of calibration routine --- gui/dpd/Capture.py | 51 +++++++++++++++++++++++++++++---------------------- gui/dpd/__init__.py | 14 ++++++++++++++ 2 files changed, 43 insertions(+), 22 deletions(-) (limited to 'gui/dpd') diff --git a/gui/dpd/Capture.py b/gui/dpd/Capture.py index e2ac63d..4c0e99c 100644 --- a/gui/dpd/Capture.py +++ b/gui/dpd/Capture.py @@ -36,6 +36,9 @@ import io from . import Align as sa +def correlation_coefficient(sig_tx, sig_rx): + return np.corrcoef(sig_tx, sig_rx)[0, 1] + def align_samples(sig_tx, sig_rx): """ Returns an aligned version of sig_tx and sig_rx by cropping, subsample alignment and @@ -61,7 +64,7 @@ def align_samples(sig_tx, sig_rx): # Fine subsample alignment and phase offset sig_rx = sa.subsample_align(sig_rx, sig_tx) sig_rx = sa.phase_align(sig_rx, sig_tx) - return sig_tx, sig_rx + return sig_tx, sig_rx, abs(off_meas) class Capture: """Capture samples from ODR-DabMod""" @@ -76,14 +79,16 @@ class Capture: # samples to avoid that the polynomial gets overfitted in the low-amplitude # part, which is less interesting than the high-amplitude part, where # non-linearities become apparent. - self.binning_start = 0.0 - self.binning_end = 1.0 self.binning_n_bins = 64 # Number of bins between binning_start and binning_end self.binning_n_per_bin = 128 # Number of measurements pre bin - self.target_median = 0.05 - self.median_max = self.target_median * 1.4 - self.median_min = self.target_median / 1.4 + self.rx_normalisation = 1.0 + + self.clear_accumulated() + + def clear_accumulated(self): + self.binning_start = 0.0 + self.binning_end = 1.0 # axis 0: bins # axis 1: 0=tx, 1=rx @@ -156,30 +161,32 @@ class Capture: return txframe, tx_ts, rxframe, rx_ts - def get_samples(self): - """Connect to ODR-DabMod, retrieve TX and RX samples, load - into numpy arrays, and return a tuple - (txframe_aligned, tx_ts, tx_median, rxframe_aligned, rx_ts, rx_median) - """ - + def calibrate(self): txframe, tx_ts, rxframe, rx_ts = self.receive_tcp() # Normalize received signal with sent signal tx_median = np.median(np.abs(txframe)) + rx_median = np.median(np.abs(rxframe)) + self.rx_normalisation = tx_median / rx_median - if self.median_max < tx_median: - raise ValueError("TX median {} too high, decrease digital_gain!".format(tx_median)) - elif tx_median < self.median_min: - raise ValueError("TX median {} too low, increase digital_gain!".format(tx_median)) - else: - rx_median = np.median(np.abs(rxframe)) - rxframe = rxframe / rx_median * tx_median + rxframe = rxframe * self.rx_normalisation + txframe_aligned, rxframe_aligned, coarse_offset = align_samples(txframe, rxframe) - txframe_aligned, rxframe_aligned = align_samples(txframe, rxframe) + return tx_ts, tx_median, rx_ts, rx_median, coarse_offset, correlation_coefficient(txframe_aligned, rxframe_aligned) + + def get_samples(self): + """Connect to ODR-DabMod, retrieve TX and RX samples, load + into numpy arrays, and return a tuple + (txframe_aligned, tx_ts, tx_median, rxframe_aligned, rx_ts, rx_median) + """ - self._bin_and_accumulate(txframe_aligned, rxframe_aligned) + txframe, tx_ts, rxframe, rx_ts = self.receive_tcp() - return txframe_aligned, tx_ts, tx_median, rxframe_aligned, rx_ts, rx_median + # Normalize received signal with calibrated normalisation + rxframe = rxframe * self.rx_normalisation + txframe_aligned, rxframe_aligned, coarse_offset = align_samples(txframe, rxframe) + self._bin_and_accumulate(txframe_aligned, rxframe_aligned) + return txframe_aligned, tx_ts, tx_median, rxframe_aligned, rx_ts, rx_median def bin_histogram(self): return [b.shape[0] for b in self.accumulated_bins] diff --git a/gui/dpd/__init__.py b/gui/dpd/__init__.py index 06d180d..716b8c2 100644 --- a/gui/dpd/__init__.py +++ b/gui/dpd/__init__.py @@ -23,6 +23,7 @@ # along with ODR-DabMod. If not, see . from . import Capture +import numpy as np class DPD: def __init__(self, samplerate=8192000): @@ -50,6 +51,19 @@ class DPD: def pointcloud_png(self): return self.capture.pointcloud_png() + def clear_accumulated(self): + return self.capture.clear_accumulated() + + def capture_calibration(self): + tx_ts, tx_median, rx_ts, rx_median, coarse_offset, correlation_coefficient = self.capture.calibrate() + result = {'status': "ok"} + result['length'] = len(txframe_aligned) + result['tx_median'] = "{:.2}dB".format(20*np.log10(tx_median)) + result['rx_median'] = "{:.2}dB".format(20*np.log10(rx_median)) + result['tx_ts'] = tx_ts + result['rx_ts'] = rx_ts + result['correlation'] = correlation_coefficient + def capture_samples(self): """Captures samples and store them in the accumulated samples, returns a dict with some info""" -- cgit v1.2.3