diff --git a/NanoVNASaver/Calibration.py b/NanoVNASaver/Calibration.py index f89e369..02f29b6 100644 --- a/NanoVNASaver/Calibration.py +++ b/NanoVNASaver/Calibration.py @@ -84,6 +84,13 @@ class CalibrationWindow(QtWidgets.QWidget): # btn_cal_isolation.setDisabled(True) self.cal_isolation_label = QtWidgets.QLabel("Uncalibrated") + self.input_offset_delay = QtWidgets.QDoubleSpinBox() + self.input_offset_delay.setValue(0) + self.input_offset_delay.setSuffix(" ps") + self.input_offset_delay.setAlignment(QtCore.Qt.AlignRight) + self.input_offset_delay.valueChanged.connect(self.setOffsetDelay) + self.input_offset_delay.setRange(-10e6, 10e6) + calibration_control_layout.addRow(btn_cal_short, self.cal_short_label) calibration_control_layout.addRow(btn_cal_open, self.cal_open_label) calibration_control_layout.addRow(btn_cal_load, self.cal_load_label) @@ -91,6 +98,7 @@ class CalibrationWindow(QtWidgets.QWidget): calibration_control_layout.addRow(btn_cal_through, self.cal_through_label) calibration_control_layout.addRow(QtWidgets.QLabel("")) + calibration_control_layout.addRow("Offset delay", self.input_offset_delay) self.btn_automatic = QtWidgets.QPushButton("Calibration assistant") calibration_control_layout.addRow(self.btn_automatic) @@ -433,6 +441,10 @@ class CalibrationWindow(QtWidgets.QWidget): self.app.saveData(self.app.worker.rawData11, self.app.worker.rawData21, self.app.sweepSource) self.app.worker.signals.updated.emit() + def setOffsetDelay(self, value: float): + logger.debug("New offset delay value: %f ps", value) + self.app.worker.offsetDelay = value / 10e12 + def calculate(self): if self.app.btnStopSweep.isEnabled(): # Currently sweeping @@ -922,6 +934,18 @@ class Calibration: s21 = (s21m - self.e30[index]) / self.e10e32[index] return s21.real, s21.imag + @staticmethod + def correctDelay11(d: Datapoint, delay): + input_val = np.complex(d.re, d.im) + output = input_val * np.exp(np.complex(0, 1) * 2 * 2 * math.pi * d.freq * delay * -1) + return Datapoint(d.freq, output.real, output.imag) + + @staticmethod + def correctDelay21(d: Datapoint, delay): + input_val = np.complex(d.re, d.im) + output = input_val * np.exp(np.complex(0, 1) * 2 * math.pi * d.freq * delay * -1) + return Datapoint(d.freq, output.real, output.imag) + def saveCalibration(self, filename): # Save the calibration data to file if filename == "" or not self.isValid1Port(): diff --git a/NanoVNASaver/Chart.py b/NanoVNASaver/Chart.py index ef60126..f92e4dc 100644 --- a/NanoVNASaver/Chart.py +++ b/NanoVNASaver/Chart.py @@ -3785,7 +3785,7 @@ class CapacitanceChart(FrequencyChart): minValue = 1 maxValue = -1 for d in self.data: - val = d.to_capacitive_equivalent() + val = d.capacitive_equivalent() if val > maxValue: maxValue = val if val < minValue: @@ -3793,7 +3793,7 @@ class CapacitanceChart(FrequencyChart): for d in self.reference: # Also check min/max for the reference sweep if d.freq < self.fstart or d.freq > self.fstop: continue - val = d.to_capacitive_equivalent() + val = d.capacitive_equivalent() if val > maxValue: maxValue = val if val < minValue: @@ -3832,7 +3832,7 @@ class CapacitanceChart(FrequencyChart): self.drawMarkers(qp) def getYPosition(self, d: Datapoint) -> int: - return self.topMargin + round((self.maxValue - d.to_capacitive_equivalent()) / self.span * self.chartHeight) + return self.topMargin + round((self.maxValue - d.capacitive_equivalent()) / self.span * self.chartHeight) def valueAtPosition(self, y) -> List[float]: absy = y - self.topMargin @@ -3908,7 +3908,7 @@ class InductanceChart(FrequencyChart): minValue = 1 maxValue = -1 for d in self.data: - val = d.to_inductive_equivalent() + val = d.inductive_equivalent() if val > maxValue: maxValue = val if val < minValue: @@ -3916,7 +3916,7 @@ class InductanceChart(FrequencyChart): for d in self.reference: # Also check min/max for the reference sweep if d.freq < self.fstart or d.freq > self.fstop: continue - val = d.to_inductive_equivalent() + val = d.inductive_equivalent() if val > maxValue: maxValue = val if val < minValue: @@ -3955,7 +3955,7 @@ class InductanceChart(FrequencyChart): self.drawMarkers(qp) def getYPosition(self, d: Datapoint) -> int: - return self.topMargin + round((self.maxValue - d.to_inductive_equivalent()) / self.span * self.chartHeight) + return self.topMargin + round((self.maxValue - d.inductive_equivalent()) / self.span * self.chartHeight) def valueAtPosition(self, y) -> List[float]: absy = y - self.topMargin diff --git a/NanoVNASaver/SweepWorker.py b/NanoVNASaver/SweepWorker.py index 48f55c1..a39abe0 100644 --- a/NanoVNASaver/SweepWorker.py +++ b/NanoVNASaver/SweepWorker.py @@ -24,6 +24,7 @@ from PyQt5.QtCore import pyqtSlot, pyqtSignal import NanoVNASaver import logging +from NanoVNASaver.Calibration import Calibration from NanoVNASaver.Hardware import VNA, InvalidVNA from NanoVNASaver.RFTools import RFTools, Datapoint @@ -57,6 +58,7 @@ class SweepWorker(QtCore.QRunnable): self.averages = 3 self.truncates = 0 self.error_message = "" + self.offsetDelay = 0 @pyqtSlot() def run(self): @@ -183,6 +185,7 @@ class SweepWorker(QtCore.QRunnable): re, im = self.app.calibration.correct11(re, im, freq) if self.app.calibration.isValid2Port(): re21, im21 = self.app.calibration.correct21(re21, im21, freq) + self.data11[offset*101 + i] = Datapoint(freq, re, im) self.data21[offset * 101 + i] = Datapoint(freq, re21, im21) self.rawData11[offset * 101 + i] = rawData11 @@ -212,6 +215,17 @@ class SweepWorker(QtCore.QRunnable): def applyCalibration(self, raw_data11: List[Datapoint], raw_data21: List[Datapoint]) ->\ (List[Datapoint], List[Datapoint]): + if self.offsetDelay != 0: + logger.debug("Applying offset delay of %f ps.", self.offsetDelay) + tmp = [] + for d in raw_data11: + tmp.append(Calibration.correctDelay11(d, self.offsetDelay)) + raw_data11 = tmp + tmp = [] + for d in raw_data21: + tmp.append(Calibration.correctDelay21(d, self.offsetDelay)) + raw_data21 = tmp + if not self.app.calibration.isCalculated: return raw_data11, raw_data21