mirror of
https://github.com/nqrduck/nqrduck-autotm.git
synced 2025-01-02 20:58:08 +00:00
Fixed calibration and bug with phase plotting.
This commit is contained in:
parent
9ee2f54a97
commit
e2a7bc997f
3 changed files with 76 additions and 146 deletions
|
@ -32,9 +32,7 @@ class AutoTMController(ModuleController):
|
||||||
self.module.model.serial = QtSerialPort.QSerialPort(
|
self.module.model.serial = QtSerialPort.QSerialPort(
|
||||||
device, baudRate=self.BAUDRATE, readyRead=self.on_ready_read
|
device, baudRate=self.BAUDRATE, readyRead=self.on_ready_read
|
||||||
)
|
)
|
||||||
self.module.model.serial.open(
|
self.module.model.serial.open(QtSerialPort.QSerialPort.OpenModeFlag.ReadWrite)
|
||||||
QtSerialPort.QSerialPort.OpenModeFlag.ReadWrite
|
|
||||||
)
|
|
||||||
|
|
||||||
logger.debug("Connected to device %s", device)
|
logger.debug("Connected to device %s", device)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
@ -77,9 +75,9 @@ class AutoTMController(ModuleController):
|
||||||
return
|
return
|
||||||
|
|
||||||
if start_frequency < MIN_FREQUENCY or stop_frequency > MAX_FREQUENCY:
|
if start_frequency < MIN_FREQUENCY or stop_frequency > MAX_FREQUENCY:
|
||||||
error = (
|
error = "Could not start frequency sweep. Start and stop frequency must be between %s and %s MHz" % (
|
||||||
"Could not start frequency sweep. Start and stop frequency must be between %s and %s MHz"
|
MIN_FREQUENCY / 1e6,
|
||||||
% (MIN_FREQUENCY / 1e6, MAX_FREQUENCY / 1e6)
|
MAX_FREQUENCY / 1e6,
|
||||||
)
|
)
|
||||||
logger.error(error)
|
logger.error(error)
|
||||||
self.module.view.add_info_text(error)
|
self.module.view.add_info_text(error)
|
||||||
|
@ -111,10 +109,7 @@ class AutoTMController(ModuleController):
|
||||||
# logger.debug("Received data: %s", text)
|
# logger.debug("Received data: %s", text)
|
||||||
# If the text starts with 'f' and the frequency sweep spinner is visible we know that the data is a data point
|
# If the text starts with 'f' and the frequency sweep spinner is visible we know that the data is a data point
|
||||||
# then we have the data for the return loss and the phase at a certain frequency
|
# then we have the data for the return loss and the phase at a certain frequency
|
||||||
if (
|
if text.startswith("f") and self.module.view.frequency_sweep_spinner.isVisible():
|
||||||
text.startswith("f")
|
|
||||||
and self.module.view.frequency_sweep_spinner.isVisible()
|
|
||||||
):
|
|
||||||
text = text[1:].split("r")
|
text = text[1:].split("r")
|
||||||
frequency = float(text[0])
|
frequency = float(text[0])
|
||||||
return_loss, phase = map(float, text[1].split("p"))
|
return_loss, phase = map(float, text[1].split("p"))
|
||||||
|
@ -122,38 +117,24 @@ class AutoTMController(ModuleController):
|
||||||
# If the text starts with 'r' and no calibration is active we know that the data is a measurement
|
# If the text starts with 'r' and no calibration is active we know that the data is a measurement
|
||||||
elif text.startswith("r") and self.module.model.active_calibration == None:
|
elif text.startswith("r") and self.module.model.active_calibration == None:
|
||||||
logger.debug("Measurement finished")
|
logger.debug("Measurement finished")
|
||||||
self.module.model.measurement = S11Data(
|
self.module.model.measurement = S11Data(self.module.model.data_points.copy())
|
||||||
self.module.model.data_points.copy()
|
|
||||||
)
|
|
||||||
self.module.view.frequency_sweep_spinner.hide()
|
self.module.view.frequency_sweep_spinner.hide()
|
||||||
# If the text starts with 'r' and a short calibration is active we know that the data is a short calibration
|
# If the text starts with 'r' and a short calibration is active we know that the data is a short calibration
|
||||||
elif (
|
elif text.startswith("r") and self.module.model.active_calibration == "short":
|
||||||
text.startswith("r") and self.module.model.active_calibration == "short"
|
|
||||||
):
|
|
||||||
logger.debug("Short calibration finished")
|
logger.debug("Short calibration finished")
|
||||||
self.module.model.short_calibration = S11Data(
|
self.module.model.short_calibration = S11Data(self.module.model.data_points.copy())
|
||||||
self.module.model.data_points.copy()
|
|
||||||
)
|
|
||||||
self.module.model.active_calibration = None
|
self.module.model.active_calibration = None
|
||||||
self.module.view.frequency_sweep_spinner.hide()
|
self.module.view.frequency_sweep_spinner.hide()
|
||||||
# If the text starts with 'r' and an open calibration is active we know that the data is an open calibration
|
# If the text starts with 'r' and an open calibration is active we know that the data is an open calibration
|
||||||
elif (
|
elif text.startswith("r") and self.module.model.active_calibration == "open":
|
||||||
text.startswith("r") and self.module.model.active_calibration == "open"
|
|
||||||
):
|
|
||||||
logger.debug("Open calibration finished")
|
logger.debug("Open calibration finished")
|
||||||
self.module.model.open_calibration = S11Data(
|
self.module.model.open_calibration = S11Data(self.module.model.data_points.copy())
|
||||||
self.module.model.data_points.copy()
|
|
||||||
)
|
|
||||||
self.module.model.active_calibration = None
|
self.module.model.active_calibration = None
|
||||||
self.module.view.frequency_sweep_spinner.hide()
|
self.module.view.frequency_sweep_spinner.hide()
|
||||||
# If the text starts with 'r' and a load calibration is active we know that the data is a load calibration
|
# If the text starts with 'r' and a load calibration is active we know that the data is a load calibration
|
||||||
elif (
|
elif text.startswith("r") and self.module.model.active_calibration == "load":
|
||||||
text.startswith("r") and self.module.model.active_calibration == "load"
|
|
||||||
):
|
|
||||||
logger.debug("Load calibration finished")
|
logger.debug("Load calibration finished")
|
||||||
self.module.model.load_calibration = S11Data(
|
self.module.model.load_calibration = S11Data(self.module.model.data_points.copy())
|
||||||
self.module.model.data_points.copy()
|
|
||||||
)
|
|
||||||
self.module.model.active_calibration = None
|
self.module.model.active_calibration = None
|
||||||
self.module.view.frequency_sweep_spinner.hide()
|
self.module.view.frequency_sweep_spinner.hide()
|
||||||
# If the text starts with 'i' we know that the data is an info message
|
# If the text starts with 'i' we know that the data is an info message
|
||||||
|
@ -187,9 +168,7 @@ class AutoTMController(ModuleController):
|
||||||
logger.debug("Starting next voltage sweep: %s", command)
|
logger.debug("Starting next voltage sweep: %s", command)
|
||||||
serial.write(command.encode("utf-8"))
|
serial.write(command.encode("utf-8"))
|
||||||
|
|
||||||
def on_short_calibration(
|
def on_short_calibration(self, start_frequency: float, stop_frequency: float) -> None:
|
||||||
self, start_frequency: float, stop_frequency: float
|
|
||||||
) -> None:
|
|
||||||
"""This method is called when the short calibration button is pressed.
|
"""This method is called when the short calibration button is pressed.
|
||||||
It starts a frequency sweep in the specified range and then starts a short calibration.
|
It starts a frequency sweep in the specified range and then starts a short calibration.
|
||||||
"""
|
"""
|
||||||
|
@ -197,9 +176,7 @@ class AutoTMController(ModuleController):
|
||||||
self.module.model.init_short_calibration()
|
self.module.model.init_short_calibration()
|
||||||
self.start_frequency_sweep(start_frequency, stop_frequency)
|
self.start_frequency_sweep(start_frequency, stop_frequency)
|
||||||
|
|
||||||
def on_open_calibration(
|
def on_open_calibration(self, start_frequency: float, stop_frequency: float) -> None:
|
||||||
self, start_frequency: float, stop_frequency: float
|
|
||||||
) -> None:
|
|
||||||
"""This method is called when the open calibration button is pressed.
|
"""This method is called when the open calibration button is pressed.
|
||||||
It starts a frequency sweep in the specified range and then starts an open calibration.
|
It starts a frequency sweep in the specified range and then starts an open calibration.
|
||||||
"""
|
"""
|
||||||
|
@ -207,9 +184,7 @@ class AutoTMController(ModuleController):
|
||||||
self.module.model.init_open_calibration()
|
self.module.model.init_open_calibration()
|
||||||
self.start_frequency_sweep(start_frequency, stop_frequency)
|
self.start_frequency_sweep(start_frequency, stop_frequency)
|
||||||
|
|
||||||
def on_load_calibration(
|
def on_load_calibration(self, start_frequency: float, stop_frequency: float) -> None:
|
||||||
self, start_frequency: float, stop_frequency: float
|
|
||||||
) -> None:
|
|
||||||
"""This method is called when the load calibration button is pressed.
|
"""This method is called when the load calibration button is pressed.
|
||||||
It starts a frequency sweep in the specified range and then loads a calibration.
|
It starts a frequency sweep in the specified range and then loads a calibration.
|
||||||
"""
|
"""
|
||||||
|
@ -221,9 +196,8 @@ class AutoTMController(ModuleController):
|
||||||
"""This method is called when the calculate calibration button is pressed.
|
"""This method is called when the calculate calibration button is pressed.
|
||||||
It calculates the calibration from the short, open and calibration data points.
|
It calculates the calibration from the short, open and calibration data points.
|
||||||
|
|
||||||
@TODO: Make calibration useful. Right now the calibration does not work for the probe coils. It completly messes up the S11 data.
|
@TODO: Improvements to the calibrations can be made the following ways:
|
||||||
For 50 Ohm reference loads the calibration makes the S11 data usable - one then gets a flat line at -50 dB.
|
|
||||||
The problem is probably two things:
|
|
||||||
1. The ideal values for open, short and load should be measured with a VNA and then be loaded for the calibration.
|
1. The ideal values for open, short and load should be measured with a VNA and then be loaded for the calibration.
|
||||||
The ideal values are probably not -1, 1 and 0 but will also show frequency dependent behaviour.
|
The ideal values are probably not -1, 1 and 0 but will also show frequency dependent behaviour.
|
||||||
2 The AD8302 chip only returns the absolute value of the phase. One would probably need to calculate the phase with various algorithms found in the literature.
|
2 The AD8302 chip only returns the absolute value of the phase. One would probably need to calculate the phase with various algorithms found in the literature.
|
||||||
|
@ -232,19 +206,13 @@ class AutoTMController(ModuleController):
|
||||||
logger.debug("Calculating calibration")
|
logger.debug("Calculating calibration")
|
||||||
# First we check if the short and open calibration data points are available
|
# First we check if the short and open calibration data points are available
|
||||||
if self.module.model.short_calibration == None:
|
if self.module.model.short_calibration == None:
|
||||||
logger.error(
|
logger.error("Could not calculate calibration. No short calibration data points available.")
|
||||||
"Could not calculate calibration. No short calibration data points available."
|
|
||||||
)
|
|
||||||
return
|
return
|
||||||
if self.module.model.open_calibration == None:
|
if self.module.model.open_calibration == None:
|
||||||
logger.error(
|
logger.error("Could not calculate calibration. No open calibration data points available.")
|
||||||
"Could not calculate calibration. No open calibration data points available."
|
|
||||||
)
|
|
||||||
return
|
return
|
||||||
if self.module.model.load_calibration == None:
|
if self.module.model.load_calibration == None:
|
||||||
logger.error(
|
logger.error("Could not calculate calibration. No load calibration data points available.")
|
||||||
"Could not calculate calibration. No load calibration data points available."
|
|
||||||
)
|
|
||||||
return
|
return
|
||||||
|
|
||||||
# Then we calculate the calibration
|
# Then we calculate the calibration
|
||||||
|
@ -256,42 +224,29 @@ class AutoTMController(ModuleController):
|
||||||
measured_gamma_open = self.module.model.open_calibration.gamma
|
measured_gamma_open = self.module.model.open_calibration.gamma
|
||||||
measured_gamma_load = self.module.model.load_calibration.gamma
|
measured_gamma_load = self.module.model.load_calibration.gamma
|
||||||
|
|
||||||
E_Ds = []
|
e_00s = []
|
||||||
E_Ss = []
|
e_11s = []
|
||||||
E_ts = []
|
delta_es = []
|
||||||
for gamma_s, gamma_o, gamma_l in zip(
|
for gamma_s, gamma_o, gamma_l in zip(measured_gamma_short, measured_gamma_open, measured_gamma_load):
|
||||||
measured_gamma_short, measured_gamma_open, measured_gamma_load
|
|
||||||
):
|
|
||||||
# This is the solution from
|
# This is the solution from
|
||||||
# A = np.array([
|
A = np.array(
|
||||||
# [1, ideal_gamma_short * gamma_s, -ideal_gamma_short],
|
[
|
||||||
# [1, ideal_gamma_open * gamma_o, -ideal_gamma_open],
|
[1, ideal_gamma_short * gamma_s, -ideal_gamma_short],
|
||||||
# [1, ideal_gamma_load * gamma_l, -ideal_gamma_load]
|
[1, ideal_gamma_open * gamma_o, -ideal_gamma_open],
|
||||||
# ])
|
[1, ideal_gamma_load * gamma_l, -ideal_gamma_load],
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
# B = np.array([gamma_s, gamma_o, gamma_l])
|
B = np.array([gamma_s, gamma_o, gamma_l])
|
||||||
|
|
||||||
# Solve the system
|
# Solve the system
|
||||||
# e_00, e11, delta_e = np.linalg.lstsq(A, B, rcond=None)[0]
|
e_00, e11, delta_e = np.linalg.lstsq(A, B, rcond=None)[0]
|
||||||
|
|
||||||
E_D = gamma_l
|
e_00s.append(e_00)
|
||||||
E_ = (2 * gamma_l - (gamma_s + gamma_o)) / (gamma_s - gamma_o)
|
e_11s.append(e11)
|
||||||
E_S = (2 * (gamma_o + gamma_l) * (gamma_s + gamma_l)) / (gamma_s - gamma_o)
|
delta_es.append(delta_e)
|
||||||
|
|
||||||
E_Ds.append(E_D)
|
self.module.model.calibration = (e_00s, e_11s, delta_es)
|
||||||
E_Ss.append(E_S)
|
|
||||||
E_ts.append(E_)
|
|
||||||
# e_00 = gamma_l # Because here the reflection coefficient should be 0
|
|
||||||
|
|
||||||
# e11 = (gamma_o + gamma_o - 2 * e_00) / (gamma_o - gamma_s)
|
|
||||||
|
|
||||||
# delta_e = -gamma_o + gamma_o* e11 + e_00
|
|
||||||
|
|
||||||
# e_00s.append(e_00)
|
|
||||||
# e11s.append(e11)
|
|
||||||
# delta_es.append(delta_e)
|
|
||||||
|
|
||||||
self.module.model.calibration = (E_Ds, E_Ss, E_ts)
|
|
||||||
|
|
||||||
def export_calibration(self, filename: str) -> None:
|
def export_calibration(self, filename: str) -> None:
|
||||||
"""This method is called when the export calibration button is pressed.
|
"""This method is called when the export calibration button is pressed.
|
||||||
|
@ -303,21 +258,15 @@ class AutoTMController(ModuleController):
|
||||||
logger.debug("Exporting calibration")
|
logger.debug("Exporting calibration")
|
||||||
# First we check if the short and open calibration data points are available
|
# First we check if the short and open calibration data points are available
|
||||||
if self.module.model.short_calibration == None:
|
if self.module.model.short_calibration == None:
|
||||||
logger.error(
|
logger.error("Could not export calibration. No short calibration data points available.")
|
||||||
"Could not export calibration. No short calibration data points available."
|
|
||||||
)
|
|
||||||
return
|
return
|
||||||
|
|
||||||
if self.module.model.open_calibration == None:
|
if self.module.model.open_calibration == None:
|
||||||
logger.error(
|
logger.error("Could not export calibration. No open calibration data points available.")
|
||||||
"Could not export calibration. No open calibration data points available."
|
|
||||||
)
|
|
||||||
return
|
return
|
||||||
|
|
||||||
if self.module.model.load_calibration == None:
|
if self.module.model.load_calibration == None:
|
||||||
logger.error(
|
logger.error("Could not export calibration. No load calibration data points available.")
|
||||||
"Could not export calibration. No load calibration data points available."
|
|
||||||
)
|
|
||||||
return
|
return
|
||||||
|
|
||||||
# Then we export the different calibrations as a json file
|
# Then we export the different calibrations as a json file
|
||||||
|
@ -368,9 +317,7 @@ class AutoTMController(ModuleController):
|
||||||
return
|
return
|
||||||
|
|
||||||
if tuning_voltage < 0 or matching_voltage < 0:
|
if tuning_voltage < 0 or matching_voltage < 0:
|
||||||
error = (
|
error = "Could not set voltages. Tuning and matching voltage must be positive"
|
||||||
"Could not set voltages. Tuning and matching voltage must be positive"
|
|
||||||
)
|
|
||||||
logger.error(error)
|
logger.error(error)
|
||||||
self.module.view.add_info_text(error)
|
self.module.view.add_info_text(error)
|
||||||
return
|
return
|
||||||
|
@ -424,12 +371,7 @@ class AutoTMController(ModuleController):
|
||||||
self.module.view.add_info_text(error)
|
self.module.view.add_info_text(error)
|
||||||
return
|
return
|
||||||
|
|
||||||
if (
|
if start_frequency < 0 or stop_frequency < 0 or frequency_step < 0 or voltage_resolution < 0:
|
||||||
start_frequency < 0
|
|
||||||
or stop_frequency < 0
|
|
||||||
or frequency_step < 0
|
|
||||||
or voltage_resolution < 0
|
|
||||||
):
|
|
||||||
error = "Could not generate LUT. Start frequency, stop frequency, frequency step and voltage resolution must be positive"
|
error = "Could not generate LUT. Start frequency, stop frequency, frequency step and voltage resolution must be positive"
|
||||||
logger.error(error)
|
logger.error(error)
|
||||||
self.module.view.add_info_text(error)
|
self.module.view.add_info_text(error)
|
||||||
|
@ -456,9 +398,7 @@ class AutoTMController(ModuleController):
|
||||||
)
|
)
|
||||||
|
|
||||||
# We create the lookup table
|
# We create the lookup table
|
||||||
LUT = LookupTable(
|
LUT = LookupTable(start_frequency, stop_frequency, frequency_step, voltage_resolution)
|
||||||
start_frequency, stop_frequency, frequency_step, voltage_resolution
|
|
||||||
)
|
|
||||||
|
|
||||||
LUT.started_frequency = start_frequency
|
LUT.started_frequency = start_frequency
|
||||||
self.module.model.LUT = LUT
|
self.module.model.LUT = LUT
|
||||||
|
|
|
@ -12,7 +12,7 @@ class S11Data:
|
||||||
# Conversion factors - the data is generally sent and received in mV
|
# Conversion factors - the data is generally sent and received in mV
|
||||||
# These values are used to convert the data to dB and degrees
|
# These values are used to convert the data to dB and degrees
|
||||||
CENTER_POINT_MAGNITUDE = 900 # mV
|
CENTER_POINT_MAGNITUDE = 900 # mV
|
||||||
CENTER_POINT_PHASE = 1800 # mV
|
CENTER_POINT_PHASE = 900 # mV
|
||||||
MAGNITUDE_SLOPE = 30 # dB/mV
|
MAGNITUDE_SLOPE = 30 # dB/mV
|
||||||
PHASE_SLOPE = 10 # deg/mV
|
PHASE_SLOPE = 10 # deg/mV
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import logging
|
import logging
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
import time
|
import time
|
||||||
|
import cmath
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from PyQt6.QtGui import QMovie
|
from PyQt6.QtGui import QMovie
|
||||||
from PyQt6.QtSerialPort import QSerialPort
|
from PyQt6.QtSerialPort import QSerialPort
|
||||||
|
@ -18,6 +19,7 @@ from PyQt6.QtWidgets import (
|
||||||
QTableWidgetItem,
|
QTableWidgetItem,
|
||||||
)
|
)
|
||||||
from PyQt6.QtCore import pyqtSlot, Qt
|
from PyQt6.QtCore import pyqtSlot, Qt
|
||||||
|
from PyQt6.QtTest import QTest
|
||||||
from nqrduck.module.module_view import ModuleView
|
from nqrduck.module.module_view import ModuleView
|
||||||
from nqrduck.contrib.mplwidget import MplWidget
|
from nqrduck.contrib.mplwidget import MplWidget
|
||||||
from .widget import Ui_Form
|
from .widget import Ui_Form
|
||||||
|
@ -107,6 +109,8 @@ class AutoTMView(ModuleView):
|
||||||
ax.set_ylim(-100, 0)
|
ax.set_ylim(-100, 0)
|
||||||
self._ui_form.S11Plot.canvas.draw()
|
self._ui_form.S11Plot.canvas.draw()
|
||||||
|
|
||||||
|
self.phase_ax = self._ui_form.S11Plot.canvas.ax.twinx()
|
||||||
|
|
||||||
def on_calibration_button_clicked(self) -> None:
|
def on_calibration_button_clicked(self) -> None:
|
||||||
"""This method is called when the calibration button is clicked.
|
"""This method is called when the calibration button is clicked.
|
||||||
It opens the calibration window.
|
It opens the calibration window.
|
||||||
|
@ -164,59 +168,43 @@ class AutoTMView(ModuleView):
|
||||||
phase = data.phase_deg
|
phase = data.phase_deg
|
||||||
|
|
||||||
gamma = data.gamma
|
gamma = data.gamma
|
||||||
# Plot complex reflection coefficient
|
|
||||||
""" import matplotlib.pyplot as plt
|
|
||||||
fig, ax = plt.subplots()
|
|
||||||
ax.plot([g.real for g in gamma], [g.imag for g in gamma])
|
|
||||||
ax.set_aspect('equal')
|
|
||||||
ax.grid(True)
|
|
||||||
ax.set_title("Complex reflection coefficient")
|
|
||||||
ax.set_xlabel("Real")
|
|
||||||
ax.set_ylabel("Imaginary")
|
|
||||||
plt.show()
|
|
||||||
"""
|
|
||||||
|
|
||||||
self._ui_form.S11Plot.canvas.ax.clear()
|
self._ui_form.S11Plot.canvas.ax.clear()
|
||||||
|
|
||||||
magnitude_ax = self._ui_form.S11Plot.canvas.ax
|
magnitude_ax = self._ui_form.S11Plot.canvas.ax
|
||||||
magnitude_ax.clear()
|
magnitude_ax.clear()
|
||||||
phase_ax = self._ui_form.S11Plot.canvas.ax.twinx()
|
|
||||||
phase_ax.clear()
|
|
||||||
|
|
||||||
# @ TODO: implement proper calibration
|
self.phase_ax.clear()
|
||||||
|
logger.debug("Shape of phase: %s", phase.shape)
|
||||||
|
|
||||||
|
# Calibration for visualization happens here.
|
||||||
if self.module.model.calibration is not None:
|
if self.module.model.calibration is not None:
|
||||||
# Calibration test:
|
|
||||||
import cmath
|
|
||||||
|
|
||||||
calibration = self.module.model.calibration
|
calibration = self.module.model.calibration
|
||||||
E_D = calibration[0]
|
e_00 = calibration[0]
|
||||||
E_S = calibration[1]
|
e11 = calibration[1]
|
||||||
E_t = calibration[2]
|
delta_e = calibration[2]
|
||||||
|
|
||||||
# gamma_corr = [(data_point - e_00[i]) / (data_point * e11[i] - delta_e[i]) for i, data_point in enumerate(gamma)]
|
|
||||||
gamma_corr = [
|
gamma_corr = [
|
||||||
(data_point - E_D[i]) / (E_S[i] * (data_point - E_D[i]) + E_t[i]) for i, data_point in enumerate(gamma)
|
(data_point - e_00[i]) / (data_point * e11[i] - delta_e[i]) for i, data_point in enumerate(gamma)
|
||||||
]
|
]
|
||||||
""" fig, ax = plt.subplots()
|
|
||||||
ax.plot([g.real for g in gamma_corr], [g.imag for g in gamma_corr])
|
|
||||||
ax.set_aspect('equal')
|
|
||||||
ax.grid(True)
|
|
||||||
ax.set_title("Complex reflection coefficient")
|
|
||||||
ax.set_xlabel("Real")
|
|
||||||
ax.set_ylabel("Imaginary")
|
|
||||||
plt.show() """
|
|
||||||
return_loss_db_corr = [-20 * cmath.log10(abs(g + 1e-12)) for g in gamma_corr]
|
return_loss_db_corr = [-20 * cmath.log10(abs(g + 1e-12)) for g in gamma_corr]
|
||||||
magnitude_ax.plot(frequency, return_loss_db_corr, color="red")
|
magnitude_ax.plot(frequency, return_loss_db_corr, color="red")
|
||||||
|
|
||||||
phase_ax.set_ylabel("|Phase (deg)|")
|
else:
|
||||||
phase_ax.plot(frequency, phase, color="orange", linestyle="--")
|
magnitude_ax.plot(frequency, return_loss_db, color="blue")
|
||||||
phase_ax.set_ylim(-180, 180)
|
|
||||||
phase_ax.invert_yaxis()
|
self.phase_ax.set_ylabel("|Phase (deg)|")
|
||||||
|
self.phase_ax.plot(frequency, phase, color="orange", linestyle="--")
|
||||||
|
self.phase_ax.set_ylim(-180, 180)
|
||||||
|
self.phase_ax.invert_yaxis()
|
||||||
|
|
||||||
magnitude_ax.set_xlabel("Frequency (MHz)")
|
magnitude_ax.set_xlabel("Frequency (MHz)")
|
||||||
magnitude_ax.set_ylabel("S11 (dB)")
|
magnitude_ax.set_ylabel("S11 (dB)")
|
||||||
magnitude_ax.set_title("S11")
|
magnitude_ax.set_title("S11")
|
||||||
magnitude_ax.grid(True)
|
magnitude_ax.grid(True)
|
||||||
magnitude_ax.plot(frequency, return_loss_db, color="blue")
|
|
||||||
# make the y axis go down instead of up
|
# make the y axis go down instead of up
|
||||||
magnitude_ax.invert_yaxis()
|
magnitude_ax.invert_yaxis()
|
||||||
|
|
||||||
|
@ -297,7 +285,7 @@ class AutoTMView(ModuleView):
|
||||||
# Create table widget
|
# Create table widget
|
||||||
self.table_widget = QTableWidget()
|
self.table_widget = QTableWidget()
|
||||||
self.table_widget.setColumnCount(3)
|
self.table_widget.setColumnCount(3)
|
||||||
self.table_widget.setHorizontalHeaderLabels(["Frequency (MHz)", "Tuning Voltage", "Matching Voltage"])
|
self.table_widget.setHorizontalHeaderLabels(["Frequency (MHz)", "Matching Voltage", "Tuning Voltage"])
|
||||||
LUT = self.module.model.LUT
|
LUT = self.module.model.LUT
|
||||||
for row, frequency in enumerate(LUT.data.keys()):
|
for row, frequency in enumerate(LUT.data.keys()):
|
||||||
self.table_widget.insertRow(row)
|
self.table_widget.insertRow(row)
|
||||||
|
@ -320,11 +308,13 @@ class AutoTMView(ModuleView):
|
||||||
One can then view the matching on a seperate VNA.
|
One can then view the matching on a seperate VNA.
|
||||||
"""
|
"""
|
||||||
for frequency in self.module.model.LUT.data.keys():
|
for frequency in self.module.model.LUT.data.keys():
|
||||||
tuning_voltage = str(self.module.model.LUT.data[frequency][0])
|
tuning_voltage = str(self.module.model.LUT.data[frequency][1])
|
||||||
matching_voltage = str(self.module.model.LUT.data[frequency][1])
|
matching_voltage = str(self.module.model.LUT.data[frequency][0])
|
||||||
self.module.controller.set_voltages(tuning_voltage, matching_voltage)
|
self.module.controller.set_voltages(tuning_voltage, matching_voltage)
|
||||||
# Evil
|
|
||||||
time.sleep(0.5)
|
# Wait for 0.5 seconds
|
||||||
|
QTest.qWait(500)
|
||||||
|
QApplication.processEvents()
|
||||||
|
|
||||||
class CalibrationWindow(QWidget):
|
class CalibrationWindow(QWidget):
|
||||||
def __init__(self, module, parent=None):
|
def __init__(self, module, parent=None):
|
||||||
|
@ -358,7 +348,7 @@ class AutoTMView(ModuleView):
|
||||||
short_layout = QVBoxLayout()
|
short_layout = QVBoxLayout()
|
||||||
short_button = QPushButton("Short")
|
short_button = QPushButton("Short")
|
||||||
short_button.clicked.connect(
|
short_button.clicked.connect(
|
||||||
lambda: self.module.controller.on_short_calibration(float(start_edit.text()), float(stop_edit.text()))
|
lambda: self.module.controller.on_short_calibration(start_edit.text(), stop_edit.text())
|
||||||
)
|
)
|
||||||
# Short plot widget
|
# Short plot widget
|
||||||
self.short_plot = MplWidget()
|
self.short_plot = MplWidget()
|
||||||
|
@ -370,7 +360,7 @@ class AutoTMView(ModuleView):
|
||||||
open_layout = QVBoxLayout()
|
open_layout = QVBoxLayout()
|
||||||
open_button = QPushButton("Open")
|
open_button = QPushButton("Open")
|
||||||
open_button.clicked.connect(
|
open_button.clicked.connect(
|
||||||
lambda: self.module.controller.on_open_calibration(float(start_edit.text()), float(stop_edit.text()))
|
lambda: self.module.controller.on_open_calibration(start_edit.text(), stop_edit.text())
|
||||||
)
|
)
|
||||||
# Open plot widget
|
# Open plot widget
|
||||||
self.open_plot = MplWidget()
|
self.open_plot = MplWidget()
|
||||||
|
@ -382,7 +372,7 @@ class AutoTMView(ModuleView):
|
||||||
load_layout = QVBoxLayout()
|
load_layout = QVBoxLayout()
|
||||||
load_button = QPushButton("Load")
|
load_button = QPushButton("Load")
|
||||||
load_button.clicked.connect(
|
load_button.clicked.connect(
|
||||||
lambda: self.module.controller.on_load_calibration(float(start_edit.text()), float(stop_edit.text()))
|
lambda: self.module.controller.on_load_calibration(start_edit.text(), stop_edit.text())
|
||||||
)
|
)
|
||||||
# Load plot widget
|
# Load plot widget
|
||||||
self.load_plot = MplWidget()
|
self.load_plot = MplWidget()
|
||||||
|
|
Loading…
Reference in a new issue