mirror of
https://github.com/nqrduck/nqrduck-autotm.git
synced 2024-11-05 01:40:01 +00:00
Merge branch 'main' of github.com:nqrduck/nqrduck-autotm
This commit is contained in:
commit
236b373b96
6 changed files with 1759 additions and 456 deletions
|
@ -1,4 +1,5 @@
|
|||
import logging
|
||||
import time
|
||||
import numpy as np
|
||||
import json
|
||||
import time
|
||||
|
@ -6,9 +7,10 @@ from serial.tools.list_ports import comports
|
|||
from PyQt6.QtTest import QTest
|
||||
from PyQt6 import QtSerialPort
|
||||
from PyQt6.QtCore import QThread, pyqtSignal, pyqtSlot, Qt
|
||||
from PyQt6.QtCore import QTimer
|
||||
from PyQt6.QtWidgets import QApplication
|
||||
from nqrduck.module.module_controller import ModuleController
|
||||
from .model import S11Data, LookupTable
|
||||
from .model import S11Data, ElectricalLookupTable, MechanicalLookupTable, SavedPosition, Stepper
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
@ -16,6 +18,60 @@ logger = logging.getLogger(__name__)
|
|||
class AutoTMController(ModuleController):
|
||||
BAUDRATE = 115200
|
||||
|
||||
def on_loading(self):
|
||||
"""This method is called when the module is loaded.
|
||||
It sets up the serial connection and connects the signals and slots.
|
||||
"""
|
||||
logger.debug("Setting up serial connection")
|
||||
self.find_devices()
|
||||
|
||||
# Connect signals
|
||||
self.module.model.serial_data_received.connect(self.process_frequency_sweep_data)
|
||||
self.module.model.serial_data_received.connect(self.process_measurement_data)
|
||||
self.module.model.serial_data_received.connect(self.process_calibration_data)
|
||||
self.module.model.serial_data_received.connect(self.process_voltage_sweep_result)
|
||||
self.module.model.serial_data_received.connect(self.print_info)
|
||||
self.module.model.serial_data_received.connect(self.read_position_data)
|
||||
self.module.model.serial_data_received.connect(self.process_reflection_data)
|
||||
self.module.model.serial_data_received.connect(self.process_position_sweep_result)
|
||||
self.module.model.serial_data_received.connect(self.process_signalpath_data)
|
||||
|
||||
@pyqtSlot(str, object)
|
||||
def process_signals(self, key: str, value: object) -> None:
|
||||
logger.debug("Received signal: %s", key)
|
||||
if key == "set_tune_and_match":
|
||||
self.tune_and_match(value)
|
||||
|
||||
def tune_and_match(self, frequency: float) -> None:
|
||||
""" This method is called when this module already has a LUT table. It should then tune and match the probe coil to the specified frequency.
|
||||
"""
|
||||
if self.module.model.LUT is None:
|
||||
logger.error("Could not tune and match. No LUT available.")
|
||||
return
|
||||
elif self.module.model.LUT.TYPE == "Electrical":
|
||||
tuning_voltage, matching_voltage = self.module.model.LUT.get_voltages(frequency)
|
||||
confirmation = self.set_voltages(str(tuning_voltage), str(matching_voltage))
|
||||
# We need to change the signal pathway to preamp to measure the reflection
|
||||
self.switch_to_atm()
|
||||
reflection = self.read_reflection(frequency)
|
||||
# We need to change the signal pathway back to atm to perform a measurement
|
||||
self.switch_to_preamp()
|
||||
self.module.nqrduck_signal.emit("confirm_tune_and_match", reflection)
|
||||
|
||||
elif self.module.model.LUT.TYPE == "Mechanical":
|
||||
tuning_position, matching_position = self.module.model.LUT.get_positions(frequency)
|
||||
self.go_to_position(tuning_position, matching_position)
|
||||
self.switch_to_atm()
|
||||
# Switch to atm to measure the reflection
|
||||
reflection = self.read_reflection(frequency)
|
||||
# Switch back to preamp to perform a measurement
|
||||
self.switch_to_preamp()
|
||||
|
||||
# The Lime doesn"t like it if we send the command to switch to atm and then immediately send the command to measure the reflection.
|
||||
# So we wait a bit before starting the measurement
|
||||
|
||||
QTimer.singleShot(100, lambda: self.module.nqrduck_signal.emit("confirm_tune_and_match", reflection))
|
||||
|
||||
def find_devices(self) -> None:
|
||||
"""Scan for available serial devices and add them to the model as available devices."""
|
||||
logger.debug("Scanning for available serial devices")
|
||||
|
@ -62,6 +118,12 @@ class AutoTMController(ModuleController):
|
|||
self.module.model.serial = serial
|
||||
|
||||
logger.debug("Connected to device %s", device)
|
||||
|
||||
# On opening of the command we set the switch position to atm
|
||||
self.switch_to_atm()
|
||||
|
||||
self.set_voltages("0", "0")
|
||||
|
||||
except Exception as e:
|
||||
logger.error("Could not connect to device %s: %s", device, e)
|
||||
|
||||
|
@ -79,7 +141,7 @@ class AutoTMController(ModuleController):
|
|||
MAX_FREQUENCY = 200e6 # Hz
|
||||
|
||||
try:
|
||||
start_frequence = start_frequency.replace(",", ".")
|
||||
start_frequency = start_frequency.replace(",", ".")
|
||||
stop_frequency = stop_frequency.replace(",", ".")
|
||||
start_frequency = float(start_frequency) * 1e6
|
||||
stop_frequency = float(stop_frequency) * 1e6
|
||||
|
@ -130,98 +192,177 @@ class AutoTMController(ModuleController):
|
|||
self.module.model.clear_data_points()
|
||||
self.module.view.create_frequency_sweep_spinner_dialog()
|
||||
|
||||
@pyqtSlot(str)
|
||||
def process_frequency_sweep_data(self, text : str) -> None:
|
||||
"""This method is called when data is received from the serial connection during a frequency sweep.
|
||||
It processes the data and adds it to the model.
|
||||
"""
|
||||
if text.startswith("f") and self.module.view.frequency_sweep_spinner.isVisible():
|
||||
text = text[1:].split("r")
|
||||
frequency = float(text[0])
|
||||
return_loss, phase = map(float, text[1].split("p"))
|
||||
self.module.model.add_data_point(frequency, return_loss, phase)
|
||||
|
||||
@pyqtSlot(str)
|
||||
def process_measurement_data(self, text : str) -> None:
|
||||
"""This method is called when data is received from the serial connection during a measurement.
|
||||
It processes the data and adds it to the model.
|
||||
"""
|
||||
if self.module.model.active_calibration is None and text.startswith("r"):
|
||||
logger.debug("Measurement finished")
|
||||
self.module.model.measurement = S11Data(
|
||||
self.module.model.data_points.copy()
|
||||
)
|
||||
self.finish_frequency_sweep()
|
||||
|
||||
@pyqtSlot(str)
|
||||
def process_calibration_data(self, text : str) -> None:
|
||||
"""This method is called when data is received from the serial connection during a calibration.
|
||||
It processes the data and adds it to the model.
|
||||
|
||||
Args:
|
||||
calibration_type (str): The type of calibration that is being performed.
|
||||
"""
|
||||
if text.startswith("r") and self.module.model.active_calibration in ["short", "open", "load"]:
|
||||
calibration_type = self.module.model.active_calibration
|
||||
logger.debug(f"{calibration_type.capitalize()} calibration finished")
|
||||
setattr(self.module.model, f"{calibration_type}_calibration",
|
||||
S11Data(self.module.model.data_points.copy()))
|
||||
self.module.model.active_calibration = None
|
||||
self.module.view.frequency_sweep_spinner.hide()
|
||||
|
||||
@pyqtSlot(str)
|
||||
def process_voltage_sweep_result(self, text : str) -> None:
|
||||
"""This method is called when data is received from the serial connection during a voltage sweep.
|
||||
It processes the data and adds it to the model.
|
||||
|
||||
Args:
|
||||
text (str): The data received from the serial connection.
|
||||
"""
|
||||
if text.startswith("v"):
|
||||
text = text[1:].split("t")
|
||||
tuning_voltage, matching_voltage = map(float, text)
|
||||
LUT = self.module.model.el_lut
|
||||
if LUT is not None:
|
||||
if LUT.is_incomplete():
|
||||
logger.debug("Received voltage sweep result: Tuning %s Matching %s", tuning_voltage, matching_voltage)
|
||||
LUT.add_voltages(tuning_voltage, matching_voltage)
|
||||
self.continue_or_finish_voltage_sweep(LUT)
|
||||
|
||||
self.module.model.tuning_voltage = tuning_voltage
|
||||
self.module.model.matching_voltage = matching_voltage
|
||||
logger.debug("Updated voltages: Tuning %s Matching %s", self.module.model.tuning_voltage, self.module.model.matching_voltage)
|
||||
|
||||
def finish_frequency_sweep(self):
|
||||
"""This method is called when a frequency sweep is finished.
|
||||
It hides the frequency sweep spinner dialog and adds the data to the model.
|
||||
"""
|
||||
self.module.view.frequency_sweep_spinner.hide()
|
||||
self.module.model.frequency_sweep_stop = time.time()
|
||||
duration = self.module.model.frequency_sweep_stop - self.module.model.frequency_sweep_start
|
||||
self.module.view.add_info_text(f"Frequency sweep finished in {duration:.2f} seconds")
|
||||
|
||||
def continue_or_finish_voltage_sweep(self, LUT):
|
||||
"""This method is called when a voltage sweep is finished.
|
||||
It checks if the voltage sweep is finished or if the next voltage sweep should be started.
|
||||
|
||||
Args:
|
||||
LUT (LookupTable): The lookup table that is being generated.
|
||||
"""
|
||||
if LUT.is_incomplete():
|
||||
# Start the next voltage sweep
|
||||
self.start_next_voltage_sweep(LUT)
|
||||
else:
|
||||
# Finish voltage sweep
|
||||
self.finish_voltage_sweep(LUT)
|
||||
|
||||
def start_next_voltage_sweep(self, LUT):
|
||||
"""This method is called when a voltage sweep is finished.
|
||||
It starts the next voltage sweep.
|
||||
|
||||
Args:
|
||||
LUT (LookupTable): The lookup table that is being generated.
|
||||
"""
|
||||
next_frequency = LUT.get_next_frequency()
|
||||
# We write the first command to the serial connection
|
||||
if self.module.view._ui_form.prevVoltagecheckBox.isChecked():
|
||||
# Command format is s<frequency in MHz>o<optional tuning voltage>o<optional matching voltage>
|
||||
# We use the currently set voltages
|
||||
command = "s%so%so%s" % (next_frequency, self.module.model.tuning_voltage, self.module.model.matching_voltage)
|
||||
else:
|
||||
command = "s%s" % (next_frequency)
|
||||
|
||||
LUT.started_frequency = next_frequency
|
||||
logger.debug("Starting next voltage sweep: %s", command)
|
||||
self.send_command(command)
|
||||
|
||||
def finish_voltage_sweep(self, LUT):
|
||||
"""This method is called when a voltage sweep is finished.
|
||||
It hides the voltage sweep spinner dialog and adds the data to the model.
|
||||
|
||||
Args:
|
||||
LUT (LookupTable): The lookup table that is being generated."""
|
||||
logger.debug("Voltage sweep finished")
|
||||
self.module.view.el_LUT_spinner.hide()
|
||||
self.module.model.LUT = LUT
|
||||
self.module.model.voltage_sweep_stop = time.time()
|
||||
duration = self.module.model.voltage_sweep_stop - self.module.model.voltage_sweep_start
|
||||
self.module.view.add_info_text(f"Voltage sweep finished in {duration:.2f} seconds")
|
||||
self.module.nqrduck_signal.emit("LUT_finished", LUT)
|
||||
|
||||
@pyqtSlot(str)
|
||||
def print_info(self, text : str) -> None:
|
||||
"""This method is called when data is received from the serial connection.
|
||||
It prints the data to the info text box.
|
||||
|
||||
Args:
|
||||
text (str): The data received from the serial connection.
|
||||
"""
|
||||
if text.startswith("i"):
|
||||
text = text[1:]
|
||||
self.module.view.add_info_text(text)
|
||||
elif text.startswith("e"):
|
||||
text = text[1:]
|
||||
self.module.view.add_error_text(text)
|
||||
|
||||
@pyqtSlot(str)
|
||||
def read_position_data(self, text : str) -> None:
|
||||
"""This method is called when data is received from the serial connection."""
|
||||
if text.startswith("p"):
|
||||
# Format is p<tuning_position>m<matching_position>
|
||||
text = text[1:].split("m")
|
||||
tuning_position, matching_position = map(int, text)
|
||||
self.module.model.tuning_stepper.position = tuning_position
|
||||
self.module.model.matching_stepper.position = matching_position
|
||||
self.module.model.tuning_stepper.homed = True
|
||||
self.module.model.matching_stepper.homed = True
|
||||
logger.debug("Tuning position: %s, Matching position: %s", tuning_position, matching_position)
|
||||
self.module.view.on_active_stepper_changed()
|
||||
|
||||
def on_ready_read(self) -> None:
|
||||
"""This method is called when data is received from the serial connection."""
|
||||
serial = self.module.model.serial
|
||||
|
||||
while serial.canReadLine():
|
||||
text = serial.readLine().data().decode()
|
||||
text = text.rstrip("\r\n")
|
||||
# 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
|
||||
# then we have the data for the return loss and the phase at a certain frequency
|
||||
if (
|
||||
text.startswith("f")
|
||||
and self.module.view.frequency_sweep_spinner.isVisible()
|
||||
):
|
||||
text = text[1:].split("r")
|
||||
frequency = float(text[0])
|
||||
return_loss, phase = map(float, text[1].split("p"))
|
||||
self.module.model.add_data_point(frequency, return_loss, phase)
|
||||
# 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:
|
||||
logger.debug("Measurement finished")
|
||||
self.module.model.measurement = S11Data(
|
||||
self.module.model.data_points.copy()
|
||||
)
|
||||
self.module.view.frequency_sweep_spinner.hide()
|
||||
self.module.model.frequency_sweep_stop = time.time()
|
||||
self.module.view.add_info_text(
|
||||
"Frequency sweep finished in %.2f seconds"
|
||||
% (
|
||||
self.module.model.frequency_sweep_stop
|
||||
- self.module.model.frequency_sweep_start
|
||||
)
|
||||
)
|
||||
# If the text starts with 'r' and a short calibration is active we know that the data is a short calibration
|
||||
elif (
|
||||
text.startswith("r") and self.module.model.active_calibration == "short"
|
||||
):
|
||||
logger.debug("Short calibration finished")
|
||||
self.module.model.short_calibration = S11Data(
|
||||
self.module.model.data_points.copy()
|
||||
)
|
||||
self.module.model.active_calibration = None
|
||||
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
|
||||
elif (
|
||||
text.startswith("r") and self.module.model.active_calibration == "open"
|
||||
):
|
||||
logger.debug("Open calibration finished")
|
||||
self.module.model.open_calibration = S11Data(
|
||||
self.module.model.data_points.copy()
|
||||
)
|
||||
self.module.model.active_calibration = None
|
||||
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
|
||||
elif (
|
||||
text.startswith("r") and self.module.model.active_calibration == "load"
|
||||
):
|
||||
logger.debug("Load calibration finished")
|
||||
self.module.model.load_calibration = S11Data(
|
||||
self.module.model.data_points.copy()
|
||||
)
|
||||
self.module.model.active_calibration = None
|
||||
self.module.view.frequency_sweep_spinner.hide()
|
||||
# If the text starts with 'i' we know that the data is an info message
|
||||
elif text.startswith("i"):
|
||||
text = "ATM Info: " + text[1:]
|
||||
self.module.view.add_info_text(text)
|
||||
# If the text starts with 'e' we know that the data is an error message
|
||||
elif text.startswith("e"):
|
||||
text = "ATM Error: " + text[1:]
|
||||
self.module.view.add_info_text(text)
|
||||
# If the text starts with 'v' we know that the data is a voltage sweep result
|
||||
elif text.startswith("v"):
|
||||
text = text[1:]
|
||||
text = text.split("t")
|
||||
matching_voltage = float(text[0])
|
||||
tuning_voltage = float(text[1])
|
||||
# Now we add the datapoint to the current LUT
|
||||
LUT = self.module.model.LUT
|
||||
logger.debug(
|
||||
"Received voltage sweep result: %s %s",
|
||||
matching_voltage,
|
||||
tuning_voltage,
|
||||
)
|
||||
LUT.add_voltages(matching_voltage, tuning_voltage)
|
||||
text = serial.readLine().data().decode().rstrip("\r\n")
|
||||
logger.debug("Received data: %s", text)
|
||||
|
||||
# Start the next voltage sweep if there are more voltages to sweep
|
||||
if LUT.is_incomplete():
|
||||
next_frequency = LUT.get_next_frequency()
|
||||
command = "s%s" % next_frequency
|
||||
LUT.started_frequency = next_frequency
|
||||
logger.debug("Starting next voltage sweep: %s", command)
|
||||
self.send_command(command)
|
||||
self.module.model.serial_data_received.emit(text)
|
||||
|
||||
@pyqtSlot(str)
|
||||
def process_reflection_data(self, text):
|
||||
"""This method is called when data is received from the serial connection.
|
||||
It processes the data and adds it to the model.
|
||||
|
||||
Args:
|
||||
text (str): The data received from the serial connection.
|
||||
"""
|
||||
if text.startswith("m"):
|
||||
text = text[1:]
|
||||
return_loss, phase = map(float, text.split("p"))
|
||||
self.module.model.last_reflection = (return_loss, phase)
|
||||
|
||||
### Calibration Stuff ###
|
||||
|
||||
def on_short_calibration(
|
||||
self, start_frequency: float, stop_frequency: float
|
||||
|
@ -370,6 +511,37 @@ class AutoTMController(ModuleController):
|
|||
self.module.model.open_calibration = S11Data.from_json(data["open"])
|
||||
self.module.model.load_calibration = S11Data.from_json(data["load"])
|
||||
|
||||
def save_measurement(self, filename: str) -> None:
|
||||
"""Save measurement to file.
|
||||
|
||||
Args:
|
||||
filename (str): Path to file.
|
||||
"""
|
||||
logger.debug("Saving measurement.")
|
||||
if not self.module.model.measurement:
|
||||
logger.debug("No measurement to save.")
|
||||
return
|
||||
|
||||
measurement = self.module.model.measurement.to_json()
|
||||
|
||||
with open(filename, "w") as f:
|
||||
json.dump(measurement, f)
|
||||
|
||||
def load_measurement(self, filename: str) -> None:
|
||||
"""Load measurement from file.
|
||||
|
||||
Args:
|
||||
filename (str): Path to file.
|
||||
"""
|
||||
|
||||
logger.debug("Loading measurement.")
|
||||
|
||||
with open(filename, "r") as f:
|
||||
measurement = json.load(f)
|
||||
self.module.model.measurement = S11Data.from_json(measurement)
|
||||
|
||||
### Voltage Control ###
|
||||
|
||||
def set_voltages(self, tuning_voltage: str, matching_voltage: str) -> None:
|
||||
"""This method is called when the set voltages button is pressed.
|
||||
It writes the specified tuning and matching voltage to the serial connection.
|
||||
|
@ -380,6 +552,8 @@ class AutoTMController(ModuleController):
|
|||
"""
|
||||
logger.debug("Setting voltages")
|
||||
MAX_VOLTAGE = 5 # V
|
||||
timeout_duration = 15 # timeout in seconds
|
||||
|
||||
try:
|
||||
tuning_voltage = tuning_voltage.replace(",", ".")
|
||||
matching_voltage = matching_voltage.replace(",", ".")
|
||||
|
@ -411,15 +585,35 @@ class AutoTMController(ModuleController):
|
|||
matching_voltage,
|
||||
)
|
||||
|
||||
command = "v%sv%s" % (matching_voltage, tuning_voltage)
|
||||
self.send_command(command)
|
||||
if tuning_voltage == self.module.model.tuning_voltage and matching_voltage == self.module.model.matching_voltage:
|
||||
logger.debug("Voltages already set")
|
||||
return
|
||||
|
||||
command = "v%sv%s" % (tuning_voltage, matching_voltage)
|
||||
|
||||
start_time = time.time()
|
||||
|
||||
def generate_lut(
|
||||
confirmation = self.send_command(command)
|
||||
while matching_voltage != self.module.model.matching_voltage and tuning_voltage != self.module.model.tuning_voltage:
|
||||
QApplication.processEvents()
|
||||
# Check for timeout
|
||||
if time.time() - start_time > timeout_duration:
|
||||
logger.error("Voltage setting timed out")
|
||||
break
|
||||
|
||||
logger.debug("Voltages set successfully")
|
||||
return confirmation
|
||||
else:
|
||||
logger.error("Could not set voltages")
|
||||
return confirmation
|
||||
|
||||
### Electrical Lookup Table ###
|
||||
|
||||
def generate_electrical_lut(
|
||||
self,
|
||||
start_frequency: str,
|
||||
stop_frequency: str,
|
||||
frequency_step: str,
|
||||
voltage_resolution: str,
|
||||
) -> None:
|
||||
"""This method is called when the generate LUT button is pressed.
|
||||
It generates a lookup table for the specified frequency range and voltage resolution.
|
||||
|
@ -428,20 +622,17 @@ class AutoTMController(ModuleController):
|
|||
start_frequency (str): The start frequency in Hz.
|
||||
stop_frequency (str): The stop frequency in Hz.
|
||||
frequency_step (str): The frequency step in Hz.
|
||||
voltage_resolution (str): The voltage resolution in V.
|
||||
"""
|
||||
logger.debug("Generating LUT")
|
||||
try:
|
||||
start_frequency = start_frequency.replace(",", ".")
|
||||
stop_frequency = stop_frequency.replace(",", ".")
|
||||
frequency_step = frequency_step.replace(",", ".")
|
||||
voltage_resolution = voltage_resolution.replace(",", ".")
|
||||
start_frequency = float(start_frequency)
|
||||
stop_frequency = float(stop_frequency)
|
||||
frequency_step = float(frequency_step)
|
||||
voltage_resolution = float(voltage_resolution)
|
||||
except ValueError:
|
||||
error = "Could not generate LUT. Start frequency, stop frequency, frequency step and voltage resolution must be floats"
|
||||
error = "Could not generate LUT. Start frequency, stop frequency, frequency step must be floats"
|
||||
logger.error(error)
|
||||
self.module.view.add_info_text(error)
|
||||
return
|
||||
|
@ -450,9 +641,8 @@ class AutoTMController(ModuleController):
|
|||
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 must be positive"
|
||||
logger.error(error)
|
||||
self.module.view.add_info_text(error)
|
||||
return
|
||||
|
@ -463,48 +653,101 @@ class AutoTMController(ModuleController):
|
|||
self.module.view.add_info_text(error)
|
||||
return
|
||||
|
||||
if frequency_step > (stop_frequency - start_frequency):
|
||||
# - 0.1 is to prevent float errors
|
||||
if frequency_step - 0.1 > (stop_frequency - start_frequency):
|
||||
error = "Could not generate LUT. Frequency step must be smaller than the frequency range"
|
||||
logger.error(error)
|
||||
self.module.view.add_info_text(error)
|
||||
return
|
||||
|
||||
logger.debug(
|
||||
"Generating LUT from %s MHz to %s MHz with a frequency step of %s MHz and a voltage resolution of %s V",
|
||||
"Generating LUT from %s MHz to %s MHz with a frequency step of %s MHz",
|
||||
start_frequency,
|
||||
stop_frequency,
|
||||
frequency_step,
|
||||
voltage_resolution,
|
||||
)
|
||||
|
||||
self.switch_to_atm()
|
||||
# self.set_voltages("0", "0")
|
||||
|
||||
# We create the lookup table
|
||||
LUT = LookupTable(
|
||||
start_frequency, stop_frequency, frequency_step, voltage_resolution
|
||||
LUT = ElectricalLookupTable(
|
||||
start_frequency, stop_frequency, frequency_step
|
||||
)
|
||||
|
||||
LUT.started_frequency = start_frequency
|
||||
self.module.model.LUT = LUT
|
||||
|
||||
# We write the first command to the serial connection
|
||||
command = "s%s" % (start_frequency)
|
||||
if self.module.view._ui_form.prevVoltagecheckBox.isChecked():
|
||||
# Command format is s<frequency in MHz>o<optional tuning voltage>o<optional matching voltage>
|
||||
# We use the currently set voltages
|
||||
logger.debug("Starting preset Voltage sweep with voltage Tuning: %s V and Matching: %s V", self.module.model.tuning_voltage, self.module.model.matching_voltage)
|
||||
command = "s%so%so%s" % (start_frequency, self.module.model.tuning_voltage, self.module.model.matching_voltage)
|
||||
else:
|
||||
command = "s%s" % (start_frequency)
|
||||
|
||||
# For timing of the voltage sweep
|
||||
self.module.model.voltage_sweep_start = time.time()
|
||||
confirmation = self.send_command(command)
|
||||
if not confirmation:
|
||||
return
|
||||
# If the command was send successfully, we set the LUT
|
||||
if confirmation:
|
||||
self.module.model.el_lut = LUT
|
||||
self.module.view.create_el_LUT_spinner_dialog()
|
||||
|
||||
def switch_to_preamp(self) -> None:
|
||||
"""This method is used to send the command 'cp' to the atm system. This switches the signal pathway of the atm system to 'RX' to 'Preamp'.
|
||||
This is the mode for either NQR or NMR measurements or if on wants to check the tuning of the probe coil on a network analyzer.
|
||||
"""
|
||||
if self.module.model.signal_path == "preamp":
|
||||
logger.debug("Already in preamp")
|
||||
return
|
||||
|
||||
TIMEOUT = 1 # s
|
||||
logger.debug("Switching to preamp")
|
||||
self.send_command("cp")
|
||||
|
||||
start_time = time.time()
|
||||
while self.module.model.signal_path != "preamp":
|
||||
QApplication.processEvents()
|
||||
# Check for timeout
|
||||
if time.time() - start_time > TIMEOUT:
|
||||
logger.error("Switching to preamp timed out")
|
||||
break
|
||||
|
||||
def switch_to_atm(self) -> None:
|
||||
"""This method is used to send the command 'ca' to the atm system. This switches the signal pathway of the atm system to 'RX' to 'ATM.
|
||||
In this state the atm system can be used to measure the reflection coefficient of the probecoils.
|
||||
"""
|
||||
if self.module.model.signal_path == "atm":
|
||||
logger.debug("Already in atm mode")
|
||||
return
|
||||
|
||||
TIMEOUT = 1 # s
|
||||
logger.debug("Switching to atm")
|
||||
self.send_command("ca")
|
||||
|
||||
start_time = time.time()
|
||||
while self.module.model.signal_path != "atm":
|
||||
QApplication.processEvents()
|
||||
# Check for timeout
|
||||
if time.time() - start_time > TIMEOUT:
|
||||
logger.error("Switching to atm timed out")
|
||||
break
|
||||
|
||||
def process_signalpath_data(self, text : str) -> None:
|
||||
"""This method is called when data is received from the serial connection.
|
||||
It processes the data and adds it to the model.
|
||||
|
||||
Args:
|
||||
text (str): The data received from the serial connection.
|
||||
"""
|
||||
if text.startswith("c"):
|
||||
text = text[1:]
|
||||
if text == "p":
|
||||
self.module.model.signal_path = "preamp"
|
||||
elif text == "a":
|
||||
self.module.model.signal_path = "atm"
|
||||
|
||||
def send_command(self, command: str) -> bool:
|
||||
"""This method is used to send a command to the active serial connection.
|
||||
|
||||
|
@ -544,7 +787,7 @@ class AutoTMController(ModuleController):
|
|||
logger.debug("Confirmation: %s", confirmation)
|
||||
|
||||
if confirmation == "c":
|
||||
logger.debug("Command send successfully")
|
||||
logger.debug("Command sent successfully")
|
||||
return True
|
||||
else:
|
||||
logger.error("Could not send command. No confirmation received")
|
||||
|
@ -557,9 +800,378 @@ class AutoTMController(ModuleController):
|
|||
logger.error("Could not send command. %s", e)
|
||||
self.module.view.add_error_text("Could not send command. %s" % e)
|
||||
|
||||
### Stepper Motor Control ###
|
||||
|
||||
def homing(self) -> None:
|
||||
"""This method is used to send the command 'h' to the atm system.
|
||||
This command is used to home the stepper motors of the atm system.
|
||||
"""
|
||||
logger.debug("Homing")
|
||||
self.send_command("h")
|
||||
self.module.model.tuning_stepper.last_direction = 1
|
||||
self.module.model.matching_stepper.last_direction = 1
|
||||
|
||||
@pyqtSlot(str)
|
||||
def on_stepper_changed(self, stepper: str) -> None:
|
||||
"""This method is called when the stepper position is changed.
|
||||
It sends the command to the atm system to change the stepper position.
|
||||
|
||||
Args:
|
||||
stepper (str): The stepper that is being changed. Either 'tuning' or 'matching'.
|
||||
"""
|
||||
logger.debug("Stepper %s changed", stepper)
|
||||
stepper = stepper.lower()
|
||||
if stepper == "tuning":
|
||||
self.module.model.active_stepper = self.module.model.tuning_stepper
|
||||
elif stepper == "matching":
|
||||
self.module.model.active_stepper = self.module.model.matching_stepper
|
||||
|
||||
def validate_position(self, future_position: int, stepper : Stepper) -> bool:
|
||||
"""Validate the stepper's future position."""
|
||||
if future_position < 0:
|
||||
self.module.view.add_error_text("Could not move stepper. Stepper position cannot be negative")
|
||||
return False
|
||||
|
||||
if future_position > stepper.MAX_STEPS:
|
||||
self.module.view.add_error_text(f"Could not move stepper. Stepper position cannot be larger than {stepper.MAX_STEPS}")
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def calculate_steps_for_absolute_move(self, target_position: int, stepper : Stepper) -> int:
|
||||
"""Calculate the number of steps for an absolute move."""
|
||||
current_position = stepper.position
|
||||
return target_position - current_position
|
||||
|
||||
def send_stepper_command(self, steps: int, stepper : Stepper) -> None:
|
||||
"""Send a command to the stepper motor based on the number of steps."""
|
||||
# Here we handle backlash of the tuner
|
||||
# Determine the direction of the current steps
|
||||
backlash = 0
|
||||
current_direction = np.sign(steps) # This will be -1,or 1
|
||||
if stepper.TYPE == "Tuning":
|
||||
logger.debug("Stepper last direction: %s", stepper.last_direction)
|
||||
logger.debug("Current direction: %s", current_direction)
|
||||
if stepper.last_direction != current_direction:
|
||||
backlash = stepper.BACKLASH_STEPS * current_direction
|
||||
|
||||
stepper.last_direction = current_direction
|
||||
logger.debug("Stepper last direction: %s", stepper.last_direction)
|
||||
|
||||
motor_identifier = stepper.TYPE.lower()[0]
|
||||
command = f"m{motor_identifier}{steps},{backlash}"
|
||||
confirmation = self.send_command(command)
|
||||
return confirmation
|
||||
|
||||
def on_relative_move(self, steps: str, stepper: Stepper = None) -> None:
|
||||
"""This method is called when the relative move button is pressed."""
|
||||
timeout_duration = 15 # timeout in seconds
|
||||
start_time = time.time()
|
||||
|
||||
if stepper is None:
|
||||
stepper = self.module.model.active_stepper
|
||||
|
||||
stepper_position = stepper.position
|
||||
future_position = stepper.position + int(steps)
|
||||
if future_position == stepper_position:
|
||||
logger.debug("Stepper already at position")
|
||||
return
|
||||
|
||||
if self.validate_position(future_position, stepper):
|
||||
confirmation = self.send_stepper_command(int(steps), stepper) # Convert the steps string to an integer
|
||||
|
||||
while stepper_position == stepper.position:
|
||||
QApplication.processEvents()
|
||||
# Check for timeout
|
||||
if time.time() - start_time > timeout_duration:
|
||||
logger.error("Relative move timed out")
|
||||
break # or handle timeout differently
|
||||
|
||||
return confirmation
|
||||
|
||||
def on_absolute_move(self, steps: str, stepper: Stepper = None) -> None:
|
||||
"""This method is called when the absolute move button is pressed."""
|
||||
timeout_duration = 15 # timeout in seconds
|
||||
start_time = time.time()
|
||||
|
||||
if stepper is None:
|
||||
stepper = self.module.model.active_stepper
|
||||
|
||||
stepper_position = stepper.position
|
||||
future_position = int(steps)
|
||||
|
||||
if future_position == stepper_position:
|
||||
logger.debug("Stepper already at position")
|
||||
return
|
||||
|
||||
if self.validate_position(future_position, stepper):
|
||||
actual_steps = self.calculate_steps_for_absolute_move(future_position, stepper)
|
||||
confirmation = self.send_stepper_command(actual_steps, stepper)
|
||||
|
||||
while stepper_position == stepper.position:
|
||||
QApplication.processEvents()
|
||||
# Check for timeout
|
||||
if time.time() - start_time > timeout_duration:
|
||||
logger.error("Absolute move timed out")
|
||||
break # or handle timeout differently
|
||||
|
||||
return confirmation
|
||||
|
||||
### Position Saving and Loading ###
|
||||
|
||||
def load_positions(self, path : str) -> None:
|
||||
"""Load the saved positions from a json file.
|
||||
|
||||
Args:
|
||||
path (str): The path to the json file.
|
||||
"""
|
||||
# First clear the old positions
|
||||
self.module.model.saved_positions = []
|
||||
|
||||
with open(path, "r") as f:
|
||||
positions = json.load(f)
|
||||
for position in positions:
|
||||
logger.debug("Loading position: %s", position)
|
||||
self.add_position(position["frequency"], position["tuning_position"], position["matching_position"])
|
||||
|
||||
|
||||
def save_positions(self, path: str) -> None:
|
||||
"""Save the current positions to a json file.
|
||||
|
||||
Args:
|
||||
path (str): The path to the json file.
|
||||
"""
|
||||
positions = self.module.model.saved_positions
|
||||
with open(path, "w") as f:
|
||||
json_position = [position.to_json() for position in positions]
|
||||
json.dump(json_position, f)
|
||||
|
||||
def add_position(self, frequency: str, tuning_position: str, matching_position: str) -> None:
|
||||
"""Add a position to the lookup table.
|
||||
|
||||
Args:
|
||||
frequency (str): The frequency of the position.
|
||||
tuning_position (str): The tuning position.
|
||||
matching_position (str): The matching position.
|
||||
"""
|
||||
logger.debug("Adding new position at %s MHz", frequency)
|
||||
self.module.model.add_saved_position(frequency, tuning_position, matching_position)
|
||||
|
||||
def on_go_to_position(self, position: SavedPosition) -> None:
|
||||
"""Go to the specified position.
|
||||
|
||||
Args:
|
||||
position (SavedPosition): The position to go to.
|
||||
"""
|
||||
logger.debug("Going to position: %s", position)
|
||||
confirmation = self.on_absolute_move(position.tuning_position, self.module.model.tuning_stepper)
|
||||
if confirmation:
|
||||
self.on_absolute_move(position.matching_position, self.module.model.matching_stepper)
|
||||
|
||||
def on_delete_position(self, position: SavedPosition) -> None:
|
||||
"""Delete the specified position.
|
||||
|
||||
Args:
|
||||
position (SavedPosition): The position to delete.
|
||||
"""
|
||||
logger.debug("Deleting position: %s", position)
|
||||
self.module.model.delete_saved_position(position)
|
||||
|
||||
|
||||
#### Mechanical tuning and matching ####
|
||||
|
||||
def generate_mechanical_lut(self, start_frequency: str, stop_frequency: str, frequency_step: str) -> None:
|
||||
"""Generate a lookup table for the specified frequency range and voltage resolution.
|
||||
|
||||
Args:
|
||||
start_frequency (str): The start frequency in Hz.
|
||||
stop_frequency (str): The stop frequency in Hz.
|
||||
frequency_step (str): The frequency step in Hz.
|
||||
"""
|
||||
try:
|
||||
start_frequency = start_frequency.replace(",", ".")
|
||||
stop_frequency = stop_frequency.replace(",", ".")
|
||||
frequency_step = frequency_step.replace(",", ".")
|
||||
start_frequency = float(start_frequency)
|
||||
stop_frequency = float(stop_frequency)
|
||||
frequency_step = float(frequency_step)
|
||||
except ValueError:
|
||||
error = "Could not generate LUT. Start frequency, stop frequency, frequency step must be floats"
|
||||
logger.error(error)
|
||||
self.module.view.add_info_text(error)
|
||||
return
|
||||
|
||||
if (
|
||||
start_frequency < 0
|
||||
or stop_frequency < 0
|
||||
or frequency_step < 0
|
||||
):
|
||||
error = "Could not generate LUT. Start frequency, stop frequency, frequency step must be positive"
|
||||
logger.error(error)
|
||||
self.module.view.add_info_text(error)
|
||||
return
|
||||
|
||||
if start_frequency > stop_frequency:
|
||||
error = "Could not generate LUT. Start frequency must be smaller than stop frequency"
|
||||
logger.error(error)
|
||||
self.module.view.add_info_text(error)
|
||||
return
|
||||
|
||||
# - 0.1 is to prevent float errors
|
||||
if frequency_step - 0.1 > (stop_frequency - start_frequency):
|
||||
error = "Could not generate LUT. Frequency step must be smaller than the frequency range"
|
||||
logger.error(error)
|
||||
self.module.view.add_info_text(error)
|
||||
return
|
||||
|
||||
logger.debug(
|
||||
"Generating LUT from %s MHz to %s MHz with a frequency step of %s MHz",
|
||||
start_frequency,
|
||||
stop_frequency,
|
||||
frequency_step,
|
||||
)
|
||||
|
||||
self.switch_to_atm()
|
||||
|
||||
# We create the lookup table
|
||||
LUT = MechanicalLookupTable(
|
||||
start_frequency, stop_frequency, frequency_step
|
||||
)
|
||||
|
||||
# Lock GUI
|
||||
self.module.view.create_mech_LUT_spinner_dialog()
|
||||
|
||||
self.module.model.mech_lut = LUT
|
||||
|
||||
self.start_next_mechTM(LUT)
|
||||
|
||||
|
||||
def start_next_mechTM(self, LUT):
|
||||
"""Start the next mechanical tuning and matching sweep."""
|
||||
|
||||
next_frequency = LUT.get_next_frequency()
|
||||
LUT.started_frequency = next_frequency
|
||||
logger.debug("Starting next mechanical tuning and matching:")
|
||||
|
||||
# Now we vary the tuning capacitor position and matching capacitor position
|
||||
# Step size tuner:
|
||||
TUNER_STEP_SIZE = 10
|
||||
# Step size matcher:
|
||||
MATCHER_STEP_SIZE = 50
|
||||
|
||||
TUNING_RANGE = 40
|
||||
MATCHING_RANGE = 500
|
||||
|
||||
tuning_backlash = self.module.model.tuning_stepper.BACKLASH_STEPS
|
||||
# I'm not sure about this value ...
|
||||
matching_backlash = 0
|
||||
|
||||
# Command for the position sweep: p<frequency in MHz>t<range>,<step size>,<backlash>,<last_direction>m<range>,<step size>,<backlash>,<last_direction>"
|
||||
tuning_last_direction = self.module.model.tuning_stepper.last_direction
|
||||
matching_last_direction = self.module.model.matching_stepper.last_direction
|
||||
command = f"p{next_frequency}t{TUNING_RANGE},{TUNER_STEP_SIZE},{tuning_backlash},{tuning_last_direction}m{MATCHING_RANGE},{MATCHER_STEP_SIZE},{matching_backlash},{matching_last_direction}"
|
||||
|
||||
confirmation = self.send_command(command)
|
||||
|
||||
@pyqtSlot(str)
|
||||
def process_position_sweep_result(self, text):
|
||||
if text.startswith("z"):
|
||||
text = text[1:]
|
||||
# Format is z<tuning_position>,<tuning_last_direction>m<matching_position>,<matching_last_direction>
|
||||
text = text.split("m")
|
||||
tuning_position, tuning_last_direction = map(int, text[0].split(","))
|
||||
matching_position, matching_last_direction = map(int, text[1].split(","))
|
||||
|
||||
# Keep backlash compensation consistent
|
||||
self.module.model.tuning_stepper.last_direction = tuning_last_direction
|
||||
self.module.model.matching_stepper.last_direction = matching_last_direction
|
||||
|
||||
# Update the positions
|
||||
self.module.model.tuning_stepper.position = tuning_position
|
||||
self.module.model.matching_stepper.position = matching_position
|
||||
self.module.view.on_active_stepper_changed()
|
||||
|
||||
logger.debug("Tuning position: %s, Matching position: %s", tuning_position, matching_position)
|
||||
|
||||
LUT = self.module.model.mech_lut
|
||||
logger.debug("Received position sweep result: %s %s", matching_position, tuning_position)
|
||||
LUT.add_positions(tuning_position, matching_position)
|
||||
self.continue_or_finish_position_sweep(LUT)
|
||||
|
||||
def continue_or_finish_position_sweep(self, LUT):
|
||||
"""Continue or finish the position sweep."""
|
||||
if LUT.is_incomplete():
|
||||
self.start_next_mechTM(LUT)
|
||||
else:
|
||||
self.finish_position_sweep(LUT)
|
||||
|
||||
def finish_position_sweep(self, LUT):
|
||||
"""Finish the position sweep."""
|
||||
logger.debug("Finished position sweep")
|
||||
self.module.model.mech_lut = LUT
|
||||
self.module.model.LUT = LUT
|
||||
self.module.view.mech_LUT_spinner.hide()
|
||||
self.module.nqrduck_signal.emit("LUT_finished", LUT)
|
||||
|
||||
def go_to_position(self, tuning_position : int, matching_position : int) -> None:
|
||||
"""Go to the specified position.
|
||||
|
||||
Args:
|
||||
position (SavedPosition): The position to go to.
|
||||
"""
|
||||
confirmation = self.on_absolute_move(tuning_position, self.module.model.tuning_stepper)
|
||||
if confirmation:
|
||||
confirmation = self.on_absolute_move(matching_position, self.module.model.matching_stepper)
|
||||
if confirmation:
|
||||
return True
|
||||
|
||||
|
||||
# This method isn't used anymore but it might be useful in the future so I'll keep it here
|
||||
def read_reflection(self, frequency) -> float:
|
||||
"""Starts a reflection measurement and reads the reflection at the specified frequency."""
|
||||
# We send the command to the atm system
|
||||
command = f"r{frequency}"
|
||||
try:
|
||||
confirmation = self.send_command(command)
|
||||
QApplication.processEvents()
|
||||
if confirmation:
|
||||
reflection = self.module.model.last_reflection
|
||||
|
||||
# Set the timeout duration (e.g., 5 seconds)
|
||||
timeout_duration = 5
|
||||
# Record the start time
|
||||
start_time = time.time()
|
||||
|
||||
# Wait for reflection data until the timeout is reached
|
||||
while reflection is None:
|
||||
# Check if the timeout has been reached
|
||||
if time.time() - start_time > timeout_duration:
|
||||
logger.error("Reading reflection timed out after %d seconds", timeout_duration)
|
||||
self.module.view.add_error_text(f"Could not read reflection. Timed out after {timeout_duration} seconds")
|
||||
return None
|
||||
|
||||
# Refresh the reflection data
|
||||
reflection = self.module.model.last_reflection
|
||||
QApplication.processEvents()
|
||||
|
||||
# Reset the reflection cache
|
||||
self.module.model.last_reflection = None
|
||||
|
||||
magnitude = reflection[0]
|
||||
CENTER_POINT_MAGNITUDE = 900 # mV
|
||||
MAGNITUDE_SLOPE = 30 # dB/mV
|
||||
magnitude = (magnitude - CENTER_POINT_MAGNITUDE) / MAGNITUDE_SLOPE
|
||||
|
||||
return -magnitude
|
||||
|
||||
else:
|
||||
logger.error("Could not read reflection. No confirmation received")
|
||||
self.module.view.add_error_text("Could not read reflection. No confirmation received")
|
||||
return None
|
||||
|
||||
except Exception as e:
|
||||
logger.error("Could not read reflection. %s", e)
|
||||
self.module.view.add_error_text(f"Could not read reflection. {e}")
|
||||
return None
|
||||
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@ logger = logging.getLogger(__name__)
|
|||
|
||||
|
||||
class S11Data:
|
||||
FILE_EXTENSION = "s11"
|
||||
# Conversion factors - the data is generally sent and received in mV
|
||||
# These values are used to convert the data to dB and degrees
|
||||
CENTER_POINT_MAGNITUDE = 900 # mV
|
||||
|
@ -139,6 +140,9 @@ class S11Data:
|
|||
* phase_sign[i]
|
||||
)
|
||||
|
||||
# Murks: The last point is always wrong so just set it to the previous value
|
||||
phase_data_corrected[-1] = phase_data_corrected[-2]
|
||||
|
||||
return phase_data_corrected
|
||||
|
||||
def to_json(self):
|
||||
|
@ -167,26 +171,102 @@ class LookupTable:
|
|||
start_frequency: float,
|
||||
stop_frequency: float,
|
||||
frequency_step: float,
|
||||
voltage_resolution: float,
|
||||
) -> None:
|
||||
self.start_frequency = start_frequency
|
||||
self.stop_frequency = stop_frequency
|
||||
self.frequency_step = frequency_step
|
||||
self.voltage_resolution = voltage_resolution
|
||||
|
||||
# This is the frequency at which the tuning and matching process was started
|
||||
self.started_frequency = None
|
||||
|
||||
def get_entry_number(self, frequency: float) -> int:
|
||||
"""This method returns the entry number of the given frequency.
|
||||
|
||||
Args:
|
||||
frequency (float): The frequency for which the entry number should be returned.
|
||||
|
||||
Returns:
|
||||
int: The entry number of the given frequency.
|
||||
"""
|
||||
# Round to closest integer
|
||||
return int(round((frequency - self.start_frequency) / self.frequency_step))
|
||||
|
||||
class Stepper:
|
||||
|
||||
def __init__(self) -> None:
|
||||
self.homed = False
|
||||
self.position = 0
|
||||
|
||||
class SavedPosition():
|
||||
"""This class is used to store a saved position for tuning and matching of electrical probeheads."""
|
||||
def __init__(self, frequency: float, tuning_position : int, matching_position : int) -> None:
|
||||
self.frequency = frequency
|
||||
self.tuning_position = tuning_position
|
||||
self.matching_position = matching_position
|
||||
|
||||
def to_json(self):
|
||||
return {
|
||||
"frequency": self.frequency,
|
||||
"tuning_position": self.tuning_position,
|
||||
"matching_position": self.matching_position,
|
||||
}
|
||||
|
||||
class TuningStepper(Stepper):
|
||||
TYPE = "Tuning"
|
||||
MAX_STEPS = 1e6
|
||||
BACKLASH_STEPS = 60
|
||||
|
||||
def __init__(self) -> None:
|
||||
super().__init__()
|
||||
# Backlash stepper
|
||||
self.last_direction = None
|
||||
|
||||
class MatchingStepper(Stepper):
|
||||
TYPE = "Matching"
|
||||
MAX_STEPS = 1e6
|
||||
|
||||
BACKLASH_STEPS = 0
|
||||
|
||||
def __init__(self) -> None:
|
||||
super().__init__()
|
||||
self.last_direction = None
|
||||
|
||||
class ElectricalLookupTable(LookupTable):
|
||||
TYPE = "Electrical"
|
||||
|
||||
def __init__(self, start_frequency: float, stop_frequency: float, frequency_step: float) -> None:
|
||||
super().__init__(start_frequency, stop_frequency, frequency_step)
|
||||
self.init_voltages()
|
||||
|
||||
def init_voltages(self) -> None:
|
||||
"""Initialize the lookup table with default values."""
|
||||
for frequency in np.arange(
|
||||
self.start_frequency, self.stop_frequency, self.frequency_step
|
||||
self.start_frequency, self.stop_frequency + self.frequency_step, self.frequency_step
|
||||
):
|
||||
self.started_frequency = frequency
|
||||
self.add_voltages(None, None)
|
||||
|
||||
def add_voltages(self, tuning_voltage: float, matching_voltage: float) -> None:
|
||||
"""Add a tuning and matching voltage for the last started frequency to the lookup table.
|
||||
|
||||
Args:
|
||||
tuning_voltage (float): The tuning voltage for the given frequency.
|
||||
matching_voltage (float): The matching voltage for the given frequency."""
|
||||
self.data[self.started_frequency] = (tuning_voltage, matching_voltage)
|
||||
|
||||
def get_voltages(self, frequency: float) -> tuple:
|
||||
"""Get the tuning and matching voltage for the given frequency.
|
||||
|
||||
Args:
|
||||
frequency (float): The frequency for which the tuning and matching voltage should be returned.
|
||||
|
||||
Returns:
|
||||
tuple: The tuning and matching voltage for the given frequency.
|
||||
"""
|
||||
entry_number = self.get_entry_number(frequency)
|
||||
key = list(self.data.keys())[entry_number]
|
||||
return self.data[key]
|
||||
|
||||
def is_incomplete(self) -> bool:
|
||||
"""This method returns True if the lookup table is incomplete,
|
||||
i.e. if there are frequencies for which no the tuning or matching voltage is none.
|
||||
|
@ -214,19 +294,78 @@ class LookupTable:
|
|||
|
||||
return None
|
||||
|
||||
def add_voltages(self, tuning_voltage: float, matching_voltage: float) -> None:
|
||||
"""Add a tuning and matching voltage for the last started frequency to the lookup table.
|
||||
class MechanicalLookupTable(LookupTable):
|
||||
# Hmm duplicate code
|
||||
TYPE = "Mechanical"
|
||||
|
||||
|
||||
def __init__(self, start_frequency: float, stop_frequency: float, frequency_step: float) -> None:
|
||||
super().__init__(start_frequency, stop_frequency, frequency_step)
|
||||
self.init_positions()
|
||||
|
||||
def init_positions(self) -> None:
|
||||
"""Initialize the lookup table with default values."""
|
||||
for frequency in np.arange(
|
||||
self.start_frequency, self.stop_frequency + self.frequency_step, self.frequency_step
|
||||
):
|
||||
self.started_frequency = frequency
|
||||
self.add_positions(None, None)
|
||||
|
||||
def add_positions(self, tuning_position: int, matching_position: int) -> None:
|
||||
"""Add a tuning and matching position for the last started frequency to the lookup table.
|
||||
|
||||
Args:
|
||||
tuning_voltage (float): The tuning voltage for the given frequency.
|
||||
matching_voltage (float): The matching voltage for the given frequency."""
|
||||
self.data[self.started_frequency] = (tuning_voltage, matching_voltage)
|
||||
tuning_position (int): The tuning position for the given frequency.
|
||||
matching_position (int): The matching position for the given frequency."""
|
||||
self.data[self.started_frequency] = (tuning_position, matching_position)
|
||||
|
||||
def get_positions(self, frequency: float) -> tuple:
|
||||
"""Get the tuning and matching position for the given frequency.
|
||||
|
||||
Args:
|
||||
frequency (float): The frequency for which the tuning and matching position should be returned.
|
||||
|
||||
Returns:
|
||||
tuple: The tuning and matching position for the given frequency.
|
||||
"""
|
||||
entry_number = self.get_entry_number(frequency)
|
||||
key = list(self.data.keys())[entry_number]
|
||||
return self.data[key]
|
||||
|
||||
def is_incomplete(self) -> bool:
|
||||
"""This method returns True if the lookup table is incomplete,
|
||||
i.e. if there are frequencies for which no the tuning or matching position is none.
|
||||
|
||||
Returns:
|
||||
bool: True if the lookup table is incomplete, False otherwise.
|
||||
"""
|
||||
return any(
|
||||
[
|
||||
tuning_position is None or matching_position is None
|
||||
for tuning_position, matching_position in self.data.values()
|
||||
]
|
||||
)
|
||||
|
||||
def get_next_frequency(self) -> float:
|
||||
"""This method returns the next frequency for which the tuning and matching position is not yet set.
|
||||
|
||||
Returns:
|
||||
float: The next frequency for which the tuning and matching position is not yet set.
|
||||
"""
|
||||
|
||||
for frequency, (tuning_position, matching_position) in self.data.items():
|
||||
if tuning_position is None or matching_position is None:
|
||||
return frequency
|
||||
|
||||
return None
|
||||
class AutoTMModel(ModuleModel):
|
||||
|
||||
available_devices_changed = pyqtSignal(list)
|
||||
serial_changed = pyqtSignal(QSerialPort)
|
||||
data_points_changed = pyqtSignal(list)
|
||||
active_stepper_changed = pyqtSignal(Stepper)
|
||||
saved_positions_changed = pyqtSignal(list)
|
||||
serial_data_received = pyqtSignal(str)
|
||||
|
||||
short_calibration_finished = pyqtSignal(S11Data)
|
||||
open_calibration_finished = pyqtSignal(S11Data)
|
||||
|
@ -240,6 +379,24 @@ class AutoTMModel(ModuleModel):
|
|||
self.calibration = None
|
||||
self.serial = None
|
||||
|
||||
self.tuning_stepper = TuningStepper()
|
||||
self.matching_stepper = MatchingStepper()
|
||||
self.active_stepper = self.tuning_stepper
|
||||
|
||||
self.saved_positions = []
|
||||
|
||||
self.el_lut = None
|
||||
self.mech_lut = None
|
||||
self.LUT = None
|
||||
|
||||
self.last_reflection = None
|
||||
|
||||
self.tuning_voltage = None
|
||||
self.matching_voltage = None
|
||||
|
||||
# AutoTM system or preamp
|
||||
self.signal_path = None
|
||||
|
||||
@property
|
||||
def available_devices(self):
|
||||
return self._available_devices
|
||||
|
@ -273,6 +430,25 @@ class AutoTMModel(ModuleModel):
|
|||
self.data_points.clear()
|
||||
self.data_points_changed.emit(self.data_points)
|
||||
|
||||
@property
|
||||
def saved_positions(self):
|
||||
return self._saved_positions
|
||||
|
||||
@saved_positions.setter
|
||||
def saved_positions(self, value):
|
||||
self._saved_positions = value
|
||||
self.saved_positions_changed.emit(value)
|
||||
|
||||
def add_saved_position(self, frequency: float, tuning_position: int, matching_position: int) -> None:
|
||||
"""Add a saved position to the model."""
|
||||
self.saved_positions.append(SavedPosition(frequency, tuning_position, matching_position))
|
||||
self.saved_positions_changed.emit(self.saved_positions)
|
||||
|
||||
def delete_saved_position(self, position: SavedPosition) -> None:
|
||||
"""Delete a saved position from the model."""
|
||||
self.saved_positions.remove(position)
|
||||
self.saved_positions_changed.emit(self.saved_positions)
|
||||
|
||||
@property
|
||||
def measurement(self):
|
||||
"""The measurement property is used to store the current measurement.
|
||||
|
@ -285,6 +461,15 @@ class AutoTMModel(ModuleModel):
|
|||
self._measurement = value
|
||||
self.measurement_finished.emit(value)
|
||||
|
||||
@property
|
||||
def active_stepper(self):
|
||||
return self._active_stepper
|
||||
|
||||
@active_stepper.setter
|
||||
def active_stepper(self, value):
|
||||
self._active_stepper = value
|
||||
self.active_stepper_changed.emit(value)
|
||||
|
||||
# Calibration properties
|
||||
|
||||
@property
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1280</width>
|
||||
<height>862</height>
|
||||
<height>1089</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
|
@ -26,6 +26,7 @@
|
|||
<widget class="QLabel" name="titleconnectionLabel">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
|
@ -76,10 +77,70 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="tmsettingsLabel">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>T&M Settings:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout_8">
|
||||
<item row="1" column="1">
|
||||
<widget class="QDoubleSpinBox" name="stopfrequencyBox">
|
||||
<property name="value">
|
||||
<double>80.099999999999994</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_13">
|
||||
<property name="text">
|
||||
<string>Stop Frequency (MHz)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QDoubleSpinBox" name="startfrequencyBox">
|
||||
<property name="value">
|
||||
<double>80.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_12">
|
||||
<property name="text">
|
||||
<string>Start Frequency (MHz)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_14">
|
||||
<property name="text">
|
||||
<string>Frequency Step (MHz)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QDoubleSpinBox" name="frequencystepBox">
|
||||
<property name="value">
|
||||
<double>0.100000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="titletypeLabel">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
|
@ -91,86 +152,17 @@
|
|||
<item>
|
||||
<widget class="QTabWidget" name="typeTab">
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
<number>1</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="mechTab">
|
||||
<attribute name="title">
|
||||
<string>Mechanical</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout" stretch="0,1,0">
|
||||
<layout class="QVBoxLayout" name="verticalLayout" stretch="0,1,0,0,0">
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout_4" rowstretch="0,0,0,0,0,0">
|
||||
<layout class="QGridLayout" name="gridLayout_4" rowstretch="0,0,0,0,0,0,0">
|
||||
<item row="5" column="1">
|
||||
<widget class="QPushButton" name="homematcherButton">
|
||||
<property name="text">
|
||||
<string>Home</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_17">
|
||||
<property name="text">
|
||||
<string>Step Size:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QSpinBox" name="stepsizeBox">
|
||||
<property name="minimum">
|
||||
<number>-1000</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>1000</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>500</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0" colspan="3">
|
||||
<widget class="QLabel" name="label_18">
|
||||
<property name="text">
|
||||
<string>Tuning Stepper:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QPushButton" name="decreasetunerButton">
|
||||
<property name="text">
|
||||
<string>-</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="2">
|
||||
<widget class="QPushButton" name="increasetunerButton">
|
||||
<property name="text">
|
||||
<string>+</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0" colspan="3">
|
||||
<widget class="QLabel" name="label_19">
|
||||
<property name="text">
|
||||
<string>Matching Stepper:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QPushButton" name="decreasematcherButton">
|
||||
<property name="text">
|
||||
<string>-</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="2">
|
||||
<widget class="QPushButton" name="increasematcherButton">
|
||||
<property name="text">
|
||||
<string>+</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QPushButton" name="hometunerButton">
|
||||
<widget class="QPushButton" name="homeButton">
|
||||
<property name="text">
|
||||
<string>Home</string>
|
||||
</property>
|
||||
|
@ -178,17 +170,127 @@
|
|||
</item>
|
||||
<item row="0" column="0" colspan="3">
|
||||
<widget class="QLabel" name="label_16">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Stepper Control:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<widget class="QSpinBox" name="absoluteposBox">
|
||||
<property name="maximum">
|
||||
<number>1000000</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QComboBox" name="stepperselectBox">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Tuning</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Matching</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QPushButton" name="decreaseButton">
|
||||
<property name="text">
|
||||
<string>-</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="2">
|
||||
<widget class="QPushButton" name="increaseButton">
|
||||
<property name="text">
|
||||
<string>+</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_18">
|
||||
<property name="text">
|
||||
<string>Stepper:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<widget class="QLabel" name="label_20">
|
||||
<property name="text">
|
||||
<string>Absolute:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QSpinBox" name="stepsizeBox">
|
||||
<property name="minimum">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>1000000</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>500</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_17">
|
||||
<property name="text">
|
||||
<string>Step Size:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="2">
|
||||
<widget class="QPushButton" name="absoluteGoButton">
|
||||
<property name="text">
|
||||
<string>Go</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>Position:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLabel" name="stepperposLabel">
|
||||
<property name="text">
|
||||
<string>0</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="starpositionButton">
|
||||
<widget class="QPushButton" name="positionButton">
|
||||
<property name="text">
|
||||
<string>Start Position</string>
|
||||
<string>Saved Positions</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="mechLUTButton">
|
||||
<property name="text">
|
||||
<string>Generate LUT</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="viewmechLUTButton">
|
||||
<property name="text">
|
||||
<string>View LUT</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
@ -211,66 +313,12 @@
|
|||
<attribute name="title">
|
||||
<string>Electrical</string>
|
||||
</attribute>
|
||||
<layout class="QGridLayout" name="gridLayout_3" rowstretch="0,0,0,0,0,0,0,0,0,0,0,0,0">
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>Voltage Resolution</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="1">
|
||||
<widget class="QDoubleSpinBox" name="stopfrequencyBox"/>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Voltage Tuning</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QDoubleSpinBox" name="tuningBox"/>
|
||||
</item>
|
||||
<item row="8" column="1">
|
||||
<widget class="QDoubleSpinBox" name="frequencystepBox"/>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_11">
|
||||
<property name="font">
|
||||
<font>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Generate LUT:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<widget class="QDoubleSpinBox" name="startfrequencyBox"/>
|
||||
</item>
|
||||
<item row="9" column="0" colspan="2">
|
||||
<widget class="QPushButton" name="generateLUTButton">
|
||||
<property name="text">
|
||||
<string>Start Voltage Sweep</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="0">
|
||||
<widget class="QLabel" name="label_13">
|
||||
<property name="text">
|
||||
<string>Stop Frequency (MHz)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QDoubleSpinBox" name="resolutionBox"/>
|
||||
</item>
|
||||
<layout class="QGridLayout" name="gridLayout_3" rowstretch="0,0,0,0,0,0,0,0,0,0,0">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_9">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
|
@ -279,15 +327,41 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="11" column="0">
|
||||
<widget class="QLabel" name="label_15">
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>RF Switch:</string>
|
||||
<string>Voltage Tuning</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QDoubleSpinBox" name="matchingBox"/>
|
||||
</item>
|
||||
<item row="8" column="0" colspan="2">
|
||||
<widget class="QPushButton" name="generateLUTButton">
|
||||
<property name="text">
|
||||
<string>Generate LUT</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QDoubleSpinBox" name="tuningBox"/>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_11">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Generate LUT:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="10" column="0" colspan="2">
|
||||
<widget class="QPushButton" name="viewLUTButton">
|
||||
<widget class="QPushButton" name="viewelLUTButton">
|
||||
<property name="text">
|
||||
<string>View LUT</string>
|
||||
</property>
|
||||
|
@ -307,34 +381,10 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<widget class="QLabel" name="label_12">
|
||||
<item row="9" column="0">
|
||||
<widget class="QCheckBox" name="prevVoltagecheckBox">
|
||||
<property name="text">
|
||||
<string>Start Frequency (MHz)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QDoubleSpinBox" name="matchingBox"/>
|
||||
</item>
|
||||
<item row="8" column="0">
|
||||
<widget class="QLabel" name="label_14">
|
||||
<property name="text">
|
||||
<string>Frequency Step (MHz)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="12" column="0">
|
||||
<widget class="QPushButton" name="switchpreampButton">
|
||||
<property name="text">
|
||||
<string>Preamplifier</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="12" column="1">
|
||||
<widget class="QPushButton" name="switchATMButton">
|
||||
<property name="text">
|
||||
<string>ATM</string>
|
||||
<string>Start from previous Voltage</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
@ -342,10 +392,42 @@
|
|||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="rfswitchLabel">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>RF Switch:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout_7">
|
||||
<item row="0" column="0">
|
||||
<widget class="QPushButton" name="switchATMButton">
|
||||
<property name="text">
|
||||
<string>ATM</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QPushButton" name="switchpreampButton">
|
||||
<property name="text">
|
||||
<string>Preamplifier</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="titlefrequencyLabel">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
|
@ -363,17 +445,10 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QLabel" name="label_8">
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="text">
|
||||
<string>MHz</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLineEdit" name="stopEdit">
|
||||
<property name="text">
|
||||
<string>100</string>
|
||||
<string>Stop Frequency:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
@ -384,13 +459,6 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="text">
|
||||
<string>Stop Frequency:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
|
@ -398,6 +466,20 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLineEdit" name="stopEdit">
|
||||
<property name="text">
|
||||
<string>100</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QLabel" name="label_8">
|
||||
<property name="text">
|
||||
<string>MHz</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
|
@ -425,6 +507,7 @@
|
|||
<widget class="QLabel" name="titleinfoLabel">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
|
@ -443,8 +526,8 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>297</width>
|
||||
<height>68</height>
|
||||
<width>291</width>
|
||||
<height>83</height>
|
||||
</rect>
|
||||
</property>
|
||||
</widget>
|
||||
|
@ -464,6 +547,41 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout" stretch="0,0">
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||
<item>
|
||||
<widget class="QPushButton" name="importButton">
|
||||
<property name="text">
|
||||
<string>Import Measurement</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="exportButton">
|
||||
<property name="text">
|
||||
<string>Export Measurement</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 27 KiB |
|
@ -21,6 +21,7 @@ from nqrduck.contrib.mplwidget import MplWidget
|
|||
from nqrduck.assets.icons import Logos
|
||||
from nqrduck.assets.animations import DuckAnimations
|
||||
from .widget import Ui_Form
|
||||
from .model import S11Data
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
@ -34,11 +35,14 @@ class AutoTMView(ModuleView):
|
|||
self._ui_form.setupUi(self)
|
||||
self.widget = widget
|
||||
|
||||
self.frequency_sweep_spinner = self.FrequencySweepSpinner(self)
|
||||
self.frequency_sweep_spinner = self.LoadingSpinner(self)
|
||||
self.frequency_sweep_spinner.hide()
|
||||
|
||||
# Disable the connectButton while no devices are selected
|
||||
self._ui_form.connectButton.setDisabled(True)
|
||||
self._ui_form.decreaseButton.setEnabled(False)
|
||||
self._ui_form.increaseButton.setEnabled(False)
|
||||
self._ui_form.absoluteGoButton.setEnabled(False)
|
||||
|
||||
# On clicking of the refresh button scan for available usb devices
|
||||
self._ui_form.refreshButton.clicked.connect(self.module.controller.find_devices)
|
||||
|
@ -61,18 +65,28 @@ class AutoTMView(ModuleView):
|
|||
)
|
||||
)
|
||||
|
||||
# On clicking of the generateLUTButton call the generate_lut method
|
||||
# On clicking of the generateLUTButton call the generate_mechanical_lut method
|
||||
self._ui_form.generateLUTButton.clicked.connect(
|
||||
lambda: self.module.controller.generate_lut(
|
||||
lambda: self.module.controller.generate_electrical_lut(
|
||||
self._ui_form.startfrequencyBox.text(),
|
||||
self._ui_form.stopfrequencyBox.text(),
|
||||
self._ui_form.frequencystepBox.text(),
|
||||
)
|
||||
)
|
||||
|
||||
# On clicking of the generateLUTButton call the generate_electrical_lut method
|
||||
self._ui_form.mechLUTButton.clicked.connect(
|
||||
lambda: self.module.controller.generate_mechanical_lut(
|
||||
self._ui_form.startfrequencyBox.text(),
|
||||
self._ui_form.stopfrequencyBox.text(),
|
||||
self._ui_form.frequencystepBox.text(),
|
||||
self._ui_form.resolutionBox.text(),
|
||||
)
|
||||
)
|
||||
|
||||
# On clicking of the viewLUTButton call the view_lut method
|
||||
self._ui_form.viewLUTButton.clicked.connect(self.view_lut)
|
||||
self._ui_form.viewelLUTButton.clicked.connect(self.view_el_lut)
|
||||
|
||||
self._ui_form.viewmechLUTButton.clicked.connect(self.view_mech_lut)
|
||||
|
||||
# On clicking of the setvoltagesButton call the set_voltages method
|
||||
self._ui_form.setvoltagesButton.clicked.connect(
|
||||
|
@ -97,7 +111,7 @@ class AutoTMView(ModuleView):
|
|||
)
|
||||
|
||||
# On clicking of the homingButton call the homing method
|
||||
self._ui_form.starpositionButton.clicked.connect(self.module.controller.homing)
|
||||
self._ui_form.homeButton.clicked.connect(self.module.controller.homing)
|
||||
|
||||
# Connect the measurement finished signal to the plot_measurement slot
|
||||
self.module.model.measurement_finished.connect(self.plot_measurement)
|
||||
|
@ -112,11 +126,35 @@ class AutoTMView(ModuleView):
|
|||
self._ui_form.startButton.setIcon(Logos.Play_16x16())
|
||||
self._ui_form.startButton.setIconSize(self._ui_form.startButton.size())
|
||||
|
||||
# Stepper selection
|
||||
self._ui_form.stepperselectBox.currentIndexChanged.connect(lambda: self.module.controller.on_stepper_changed(self._ui_form.stepperselectBox.currentText()))
|
||||
self._ui_form.increaseButton.clicked.connect(lambda: self.module.controller.on_relative_move(self._ui_form.stepsizeBox.text()))
|
||||
self._ui_form.decreaseButton.clicked.connect(lambda: self.module.controller.on_relative_move("-" + self._ui_form.stepsizeBox.text()))
|
||||
|
||||
self._ui_form.absoluteGoButton.clicked.connect(lambda: self.module.controller.on_absolute_move(self._ui_form.absoluteposBox.text()))
|
||||
|
||||
# Active stepper changed
|
||||
self.module.model.active_stepper_changed.connect(self.on_active_stepper_changed)
|
||||
|
||||
# Position Button
|
||||
self._ui_form.positionButton.clicked.connect(self.on_position_button_clicked)
|
||||
|
||||
# Import and export buttons
|
||||
|
||||
self._ui_form.exportButton.setIcon(Logos.Save16x16())
|
||||
self._ui_form.exportButton.setIconSize(self._ui_form.exportButton.size())
|
||||
self._ui_form.exportButton.clicked.connect(self.on_export_button_clicked)
|
||||
|
||||
self._ui_form.importButton.setIcon(Logos.Load16x16())
|
||||
self._ui_form.importButton.setIconSize(self._ui_form.importButton.size())
|
||||
self._ui_form.importButton.clicked.connect(self.on_import_button_clicked)
|
||||
|
||||
self.init_plot()
|
||||
self.init_labels()
|
||||
|
||||
def init_labels(self) -> None:
|
||||
"""Makes some of the labels bold for better readability."""
|
||||
self._ui_form.tmsettingsLabel.setStyleSheet("font-weight: bold;")
|
||||
self._ui_form.titleconnectionLabel.setStyleSheet("font-weight: bold;")
|
||||
self._ui_form.titlefrequencyLabel.setStyleSheet("font-weight: bold;")
|
||||
self._ui_form.titletypeLabel.setStyleSheet("font-weight: bold;")
|
||||
|
@ -126,7 +164,7 @@ class AutoTMView(ModuleView):
|
|||
"""Initialize the S11 plot."""
|
||||
ax = self._ui_form.S11Plot.canvas.ax
|
||||
ax.set_xlabel("Frequency (MHz)")
|
||||
ax.set_ylabel("S11 (dB)")
|
||||
ax.set_ylabel("S11 (dB)", loc="center")
|
||||
ax.set_title("S11")
|
||||
ax.grid(True)
|
||||
ax.set_xlim(0, 100)
|
||||
|
@ -156,6 +194,10 @@ class AutoTMView(ModuleView):
|
|||
self._ui_form.connectButton.setEnabled(False)
|
||||
logger.debug("Updated available devices list")
|
||||
|
||||
def on_stepper_changed():
|
||||
"""Update the stepper position label according to the current stepper position."""
|
||||
logger.debug("Updating stepper position label")
|
||||
|
||||
@pyqtSlot()
|
||||
def on_connect_button_clicked(self) -> None:
|
||||
"""This method is called when the connect button is clicked.
|
||||
|
@ -184,6 +226,38 @@ class AutoTMView(ModuleView):
|
|||
|
||||
logger.debug("Updated serial connection label")
|
||||
|
||||
@pyqtSlot()
|
||||
def on_active_stepper_changed(self) -> None:
|
||||
"""Update the stepper position label according to the current stepper position."""
|
||||
logger.debug("Updating stepper position label")
|
||||
self._ui_form.stepperposLabel.setText(str(self.module.model.active_stepper.position))
|
||||
logger.debug("Updated stepper position label")
|
||||
|
||||
# Only allow position change when stepper is homed
|
||||
if self.module.model.active_stepper.homed:
|
||||
self._ui_form.decreaseButton.setEnabled(True)
|
||||
self._ui_form.increaseButton.setEnabled(True)
|
||||
self._ui_form.absoluteGoButton.setEnabled(True)
|
||||
self._ui_form.positionButton.setEnabled(True)
|
||||
self._ui_form.mechLUTButton.setEnabled(True)
|
||||
self._ui_form.viewmechLUTButton.setEnabled(True)
|
||||
else:
|
||||
self._ui_form.decreaseButton.setEnabled(False)
|
||||
self._ui_form.increaseButton.setEnabled(False)
|
||||
self._ui_form.absoluteGoButton.setEnabled(False)
|
||||
self._ui_form.positionButton.setEnabled(False)
|
||||
self._ui_form.mechLUTButton.setEnabled(False)
|
||||
self._ui_form.viewmechLUTButton.setEnabled(False)
|
||||
|
||||
@pyqtSlot()
|
||||
def on_position_button_clicked(self) -> None:
|
||||
"""This method is called when the position button is clicked.
|
||||
It opens the position window.
|
||||
"""
|
||||
logger.debug("Position button clicked")
|
||||
self.position_window = self.StepperSavedPositionsWindow(self.module, self)
|
||||
self.position_window.show()
|
||||
|
||||
def plot_measurement(self, data: "S11Data") -> None:
|
||||
"""Update the S11 plot with the current data points.
|
||||
|
||||
|
@ -226,7 +300,9 @@ class AutoTMView(ModuleView):
|
|||
else:
|
||||
magnitude_ax.plot(frequency, return_loss_db, color="blue")
|
||||
|
||||
self.phase_ax.set_ylabel("|Phase (deg)|")
|
||||
self.phase_ax.yaxis.tick_right()
|
||||
self.phase_ax.yaxis.set_label_position("right")
|
||||
self.phase_ax.set_ylabel("Phase (deg)")
|
||||
self.phase_ax.plot(frequency, phase, color="orange", linestyle="--")
|
||||
# self.phase_ax.invert_yaxis()
|
||||
|
||||
|
@ -288,21 +364,237 @@ class AutoTMView(ModuleView):
|
|||
|
||||
def create_frequency_sweep_spinner_dialog(self) -> None:
|
||||
"""Creates a frequency sweep spinner dialog."""
|
||||
self.frequency_sweep_spinner = self.FrequencySweepSpinner(self)
|
||||
self.frequency_sweep_spinner = self.LoadingSpinner("Performing frequency sweep ...", self)
|
||||
self.frequency_sweep_spinner.show()
|
||||
|
||||
def view_lut(self) -> None:
|
||||
"""Creates a new Dialog that shows the currently active LUT."""
|
||||
def create_el_LUT_spinner_dialog(self) -> None:
|
||||
"""Creates a electrical LUT spinner dialog."""
|
||||
self.el_LUT_spinner = self.LoadingSpinner("Generating electrical LUT ...", self)
|
||||
self.el_LUT_spinner.show()
|
||||
|
||||
def create_mech_LUT_spinner_dialog(self) -> None:
|
||||
"""Creates a mechanical LUT spinner dialog."""
|
||||
self.mech_LUT_spinner = self.LoadingSpinner("Generating mechanical LUT ...", self)
|
||||
self.mech_LUT_spinner.show()
|
||||
|
||||
def view_el_lut(self) -> None:
|
||||
"""Creates a new Dialog that shows the currently active electrical LUT."""
|
||||
logger.debug("View LUT")
|
||||
if self.module.model.el_lut is None:
|
||||
logger.debug("No LUT available")
|
||||
self.add_error_text("No LUT available")
|
||||
return
|
||||
self.lut_window = self.LutWindow(self.module)
|
||||
self.lut_window.show()
|
||||
|
||||
class FrequencySweepSpinner(QDialog):
|
||||
def view_mech_lut(self) -> None:
|
||||
"""Creates a new Dialog that shows the currently active mechanical LUT."""
|
||||
logger.debug("View mechanical LUT")
|
||||
if self.module.model.mech_lut is None:
|
||||
logger.debug("No LUT available")
|
||||
self.add_error_text("No LUT available")
|
||||
return
|
||||
self.lut_window = self.LutWindow(self.module)
|
||||
self.lut_window.show()
|
||||
|
||||
@pyqtSlot()
|
||||
def on_export_button_clicked(self) -> None:
|
||||
"""Slot for when the export button is clicked."""
|
||||
logger.debug("Export button clicked")
|
||||
file_manager = self.QFileManager(S11Data.FILE_EXTENSION, parent=self.widget)
|
||||
file_name = file_manager.saveFileDialog()
|
||||
if file_name:
|
||||
self.module.controller.save_measurement(file_name)
|
||||
|
||||
@pyqtSlot()
|
||||
def on_import_button_clicked(self) -> None:
|
||||
"""Slot for when the import button is clicked."""
|
||||
logger.debug("Import button clicked")
|
||||
file_manager = self.QFileManager(S11Data.FILE_EXTENSION, parent=self.widget)
|
||||
file_name = file_manager.loadFileDialog()
|
||||
if file_name:
|
||||
self.module.controller.load_measurement(file_name)
|
||||
|
||||
class StepperSavedPositionsWindow(QDialog):
|
||||
def __init__(self, module, parent=None):
|
||||
super().__init__(parent)
|
||||
self.setParent(parent)
|
||||
self.module = module
|
||||
self.setWindowTitle("Saved positions")
|
||||
# make window larger
|
||||
self.resize(800, 800)
|
||||
|
||||
# Add vertical main layout
|
||||
main_layout = QVBoxLayout()
|
||||
|
||||
# Create table widget
|
||||
self.table_widget = QTableWidget()
|
||||
self.table_widget.setColumnCount(5)
|
||||
self.table_widget.setHorizontalHeaderLabels(
|
||||
["Frequency (MHz)", "Tuning Position", "Matching Position", "Button", "Delete"]
|
||||
)
|
||||
|
||||
self.table_widget.setColumnWidth(0, 150)
|
||||
self.table_widget.setColumnWidth(1, 200)
|
||||
self.table_widget.setColumnWidth(2, 200)
|
||||
self.table_widget.setColumnWidth(3, 100)
|
||||
self.table_widget.setColumnWidth(4, 100)
|
||||
self.on_saved_positions_changed()
|
||||
|
||||
# Add a 'Load Position' button (File selector)
|
||||
load_position_button = QPushButton("Load Positions File")
|
||||
load_position_button.clicked.connect(self.on_load_position_button_clicked)
|
||||
main_layout.addWidget(load_position_button)
|
||||
|
||||
# Add a 'Save Position' button (File selector)
|
||||
save_position_button = QPushButton("Save Positions File")
|
||||
save_position_button.clicked.connect(self.on_save_position_button_clicked)
|
||||
main_layout.addWidget(save_position_button)
|
||||
|
||||
# Add a 'New Position' button
|
||||
new_position_button = QPushButton("New Position")
|
||||
new_position_button.clicked.connect(self.on_new_position_button_clicked)
|
||||
main_layout.addWidget(new_position_button)
|
||||
|
||||
# Add table widget to main layout
|
||||
main_layout.addWidget(self.table_widget)
|
||||
|
||||
# On saved positions changed
|
||||
self.module.model.saved_positions_changed.connect(self.on_saved_positions_changed)
|
||||
|
||||
|
||||
self.setLayout(main_layout)
|
||||
|
||||
def file_selector(self, mode) -> str:
|
||||
"""Opens a file selector and returns the selected file."""
|
||||
filedialog = QFileDialog()
|
||||
if mode == "load":
|
||||
filedialog.setAcceptMode(QFileDialog.AcceptMode.AcceptOpen)
|
||||
elif mode == "save":
|
||||
filedialog.setAcceptMode(QFileDialog.AcceptMode.AcceptSave)
|
||||
filedialog.setNameFilter("position files (*.pos)")
|
||||
filedialog.setDefaultSuffix("pos")
|
||||
filedialog.exec()
|
||||
filename = filedialog.selectedFiles()[0]
|
||||
return filename
|
||||
|
||||
def on_load_position_button_clicked(self) -> None:
|
||||
"""File picker for loading a position from a file."""
|
||||
filename = self.file_selector("load")
|
||||
logger.debug("Loading position from %s" % filename)
|
||||
self.module.controller.load_positions(filename)
|
||||
|
||||
def on_save_position_button_clicked(self) -> None:
|
||||
"""File picker for saving a position to a file."""
|
||||
filename = self.file_selector("save")
|
||||
logger.debug("Saving position to %s" % filename)
|
||||
self.module.controller.save_positions(filename)
|
||||
|
||||
def on_new_position_button_clicked(self) -> None:
|
||||
"""Opens a new position dialog."""
|
||||
logger.debug("New position button clicked")
|
||||
self.new_position_window = self.NewPositionWindow(self.module, self)
|
||||
self.new_position_window.show()
|
||||
|
||||
|
||||
def on_saved_positions_changed(self) -> None:
|
||||
"""This method is called when the saved positions changed.
|
||||
It updates the table widget.
|
||||
"""
|
||||
logger.debug("Updating saved positions table")
|
||||
self.table_widget.clearContents()
|
||||
self.table_widget.setRowCount(0)
|
||||
|
||||
for row, position in enumerate(self.module.model.saved_positions):
|
||||
self.table_widget.insertRow(row)
|
||||
self.table_widget.setItem(row, 0, QTableWidgetItem(str(position.frequency)))
|
||||
self.table_widget.setItem(
|
||||
row, 1, QTableWidgetItem(position.tuning_position)
|
||||
)
|
||||
self.table_widget.setItem(
|
||||
row, 2, QTableWidgetItem(position.matching_position)
|
||||
)
|
||||
go_button = QPushButton("Go")
|
||||
go_button.clicked.connect(
|
||||
lambda _, position=position: self.module.controller.on_go_to_position(
|
||||
position
|
||||
)
|
||||
)
|
||||
self.table_widget.setCellWidget(row, 3, go_button)
|
||||
|
||||
delete_button = QPushButton("Delete")
|
||||
delete_button.clicked.connect(
|
||||
lambda _, position=position: self.module.controller.on_delete_position(
|
||||
position
|
||||
)
|
||||
)
|
||||
self.table_widget.setCellWidget(row, 4, delete_button)
|
||||
|
||||
logger.debug("Updated saved positions table")
|
||||
|
||||
class NewPositionWindow(QDialog):
|
||||
def __init__(self, module, parent=None):
|
||||
super().__init__(parent)
|
||||
self.setParent(parent)
|
||||
self.module = module
|
||||
self.setWindowTitle("New Position")
|
||||
|
||||
# Add vertical main layout
|
||||
main_layout = QVBoxLayout()
|
||||
|
||||
# Add horizontal layout for the frequency range
|
||||
frequency_layout = QHBoxLayout()
|
||||
main_layout.addLayout(frequency_layout)
|
||||
frequency_label = QLabel("Frequency")
|
||||
frequency_layout.addWidget(frequency_label)
|
||||
frequency_edit = QLineEdit()
|
||||
frequency_layout.addWidget(frequency_edit)
|
||||
unit_label = QLabel("MHz")
|
||||
frequency_layout.addWidget(unit_label)
|
||||
frequency_layout.addStretch()
|
||||
|
||||
# Add horizontal layout for the calibration type
|
||||
type_layout = QHBoxLayout()
|
||||
main_layout.addLayout(type_layout)
|
||||
|
||||
# Add vertical layout for short calibration
|
||||
tuning_layout = QVBoxLayout()
|
||||
tuning_label = QLabel("Tuning Position")
|
||||
tuning_layout.addWidget(tuning_label)
|
||||
tuning_edit = QLineEdit()
|
||||
tuning_layout.addWidget(tuning_edit)
|
||||
type_layout.addLayout(tuning_layout)
|
||||
|
||||
# Add vertical layout for open calibration
|
||||
matching_layout = QVBoxLayout()
|
||||
matching_label = QLabel("Matching Position")
|
||||
matching_layout.addWidget(matching_label)
|
||||
matching_edit = QLineEdit()
|
||||
matching_layout.addWidget(matching_edit)
|
||||
type_layout.addLayout(matching_layout)
|
||||
|
||||
# Add vertical layout for save calibration
|
||||
data_layout = QVBoxLayout()
|
||||
# Apply button
|
||||
apply_button = QPushButton("Apply")
|
||||
apply_button.clicked.connect(lambda: self.on_apply_button_clicked(frequency_edit.text(), tuning_edit.text(), matching_edit.text()))
|
||||
data_layout.addWidget(apply_button)
|
||||
|
||||
main_layout.addLayout(data_layout)
|
||||
|
||||
self.setLayout(main_layout)
|
||||
|
||||
def on_apply_button_clicked(self, frequency: str, tuning_position: str, matching_position: str) -> None:
|
||||
"""This method is called when the apply button is clicked."""
|
||||
self.module.controller.add_position(frequency, tuning_position, matching_position)
|
||||
# Close the calibration window
|
||||
self.close()
|
||||
class LoadingSpinner(QDialog):
|
||||
"""This class implements a spinner dialog that is shown during a frequency sweep."""
|
||||
|
||||
def __init__(self, parent=None):
|
||||
def __init__(self, text : str, parent=None):
|
||||
super().__init__(parent)
|
||||
self.setWindowTitle("Frequency sweep")
|
||||
self.setWindowTitle("Loading")
|
||||
self.setModal(True)
|
||||
self.setWindowFlag(Qt.WindowType.FramelessWindowHint)
|
||||
self.setAttribute(Qt.WidgetAttribute.WA_TranslucentBackground)
|
||||
|
@ -312,7 +604,7 @@ class AutoTMView(ModuleView):
|
|||
self.spinner_label.setMovie(self.spinner_movie)
|
||||
|
||||
self.layout = QVBoxLayout(self)
|
||||
self.layout.addWidget(QLabel("Performing frequency sweep..."))
|
||||
self.layout.addWidget(QLabel(text))
|
||||
self.layout.addWidget(self.spinner_label)
|
||||
|
||||
self.spinner_movie.start()
|
||||
|
@ -324,16 +616,31 @@ class AutoTMView(ModuleView):
|
|||
self.setParent(parent)
|
||||
self.setWindowTitle("LUT")
|
||||
|
||||
# Set size
|
||||
self.resize(800, 800)
|
||||
|
||||
# Add vertical main layout
|
||||
main_layout = QVBoxLayout()
|
||||
|
||||
LUT = self.module.model.LUT
|
||||
|
||||
# Create table widget
|
||||
self.table_widget = QTableWidget()
|
||||
self.table_widget.setColumnCount(3)
|
||||
self.table_widget.setHorizontalHeaderLabels(
|
||||
["Frequency (MHz)", "Matching Voltage", "Tuning Voltage"]
|
||||
)
|
||||
LUT = self.module.model.LUT
|
||||
self.table_widget.setColumnCount(4)
|
||||
self.table_widget.setColumnWidth(0, 150)
|
||||
self.table_widget.setColumnWidth(1, 200)
|
||||
self.table_widget.setColumnWidth(2, 200)
|
||||
self.table_widget.setColumnWidth(3, 100)
|
||||
|
||||
if LUT.TYPE == "Mechanical":
|
||||
self.table_widget.setHorizontalHeaderLabels(
|
||||
["Frequency (MHz)", "Tuning Position", "Matching Position"]
|
||||
)
|
||||
elif LUT.TYPE == "Electrical":
|
||||
self.table_widget.setHorizontalHeaderLabels(
|
||||
["Frequency (MHz)", "Tuning Voltage", "Matching Voltage"]
|
||||
)
|
||||
|
||||
for row, frequency in enumerate(LUT.data.keys()):
|
||||
self.table_widget.insertRow(row)
|
||||
self.table_widget.setItem(row, 0, QTableWidgetItem(str(frequency)))
|
||||
|
@ -344,20 +651,38 @@ class AutoTMView(ModuleView):
|
|||
row, 2, QTableWidgetItem(str(LUT.data[frequency][1]))
|
||||
)
|
||||
|
||||
# Button to test the specific entry in the LUT
|
||||
test_button = QPushButton("Test")
|
||||
# For electrical probe coils the matching voltage is the first entry in the LUT
|
||||
if LUT.TYPE == "Electrical":
|
||||
tuning_voltage = str(LUT.data[frequency][0])
|
||||
matching_voltage = str(LUT.data[frequency][1])
|
||||
test_button.clicked.connect(
|
||||
lambda _, tuning_voltage=tuning_voltage, matching_voltage=matching_voltage: self.module.controller.set_voltages(
|
||||
tuning_voltage, matching_voltage
|
||||
)
|
||||
)
|
||||
# For mechanical probe coils the tuning voltage is the first entry in the LUT
|
||||
elif LUT.TYPE == "Mechanical":
|
||||
tuning_position = str(LUT.data[frequency][0])
|
||||
matching_position = str(LUT.data[frequency][1])
|
||||
test_button.clicked.connect(
|
||||
lambda _, tuning_position=tuning_position, matching_position=matching_position: self.module.controller.go_to_position(
|
||||
tuning_position, matching_position
|
||||
)
|
||||
)
|
||||
|
||||
self.table_widget.setCellWidget(row, 3, test_button)
|
||||
|
||||
# Add table widget to main layout
|
||||
main_layout.addWidget(self.table_widget)
|
||||
|
||||
# Add Test LUT button
|
||||
test_lut_button = QPushButton("Test LUT")
|
||||
test_lut_button.clicked.connect(self.test_lut)
|
||||
main_layout.addWidget(test_lut_button)
|
||||
|
||||
self.setLayout(main_layout)
|
||||
|
||||
def test_lut(self):
|
||||
"""This method is called when the Test LUT button is clicked. It sets all of the voltages from the lut with a small delay.
|
||||
One can then view the matching on a seperate VNA.
|
||||
"""
|
||||
# This should be in the controller
|
||||
for frequency in self.module.model.LUT.data.keys():
|
||||
tuning_voltage = str(self.module.model.LUT.data[frequency][1])
|
||||
matching_voltage = str(self.module.model.LUT.data[frequency][0])
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# Form implementation generated from reading ui file '../Modules/nqrduck-autotm/src/nqrduck_autotm/resources/autotm_widget.ui'
|
||||
# Form implementation generated from reading ui file 'Modules/nqrduck-autotm/src/nqrduck_autotm/resources/autotm_widget.ui'
|
||||
#
|
||||
# Created by: PyQt6 UI code generator 6.4.2
|
||||
# Created by: PyQt6 UI code generator 6.5.1
|
||||
#
|
||||
# WARNING: Any manual changes made to this file will be lost when pyuic6 is
|
||||
# run again. Do not edit this file unless you know what you are doing.
|
||||
|
@ -12,7 +12,7 @@ from PyQt6 import QtCore, QtGui, QtWidgets
|
|||
class Ui_Form(object):
|
||||
def setupUi(self, Form):
|
||||
Form.setObjectName("Form")
|
||||
Form.resize(1280, 862)
|
||||
Form.resize(1280, 1089)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.Preferred, QtWidgets.QSizePolicy.Policy.Preferred)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
|
@ -25,6 +25,7 @@ class Ui_Form(object):
|
|||
self.titleconnectionLabel = QtWidgets.QLabel(parent=Form)
|
||||
font = QtGui.QFont()
|
||||
font.setBold(True)
|
||||
font.setWeight(75)
|
||||
self.titleconnectionLabel.setFont(font)
|
||||
self.titleconnectionLabel.setObjectName("titleconnectionLabel")
|
||||
self.verticalLayout_2.addWidget(self.titleconnectionLabel)
|
||||
|
@ -50,9 +51,41 @@ class Ui_Form(object):
|
|||
self.connectButton = QtWidgets.QPushButton(parent=Form)
|
||||
self.connectButton.setObjectName("connectButton")
|
||||
self.verticalLayout_2.addWidget(self.connectButton)
|
||||
self.tmsettingsLabel = QtWidgets.QLabel(parent=Form)
|
||||
font = QtGui.QFont()
|
||||
font.setBold(True)
|
||||
font.setWeight(75)
|
||||
self.tmsettingsLabel.setFont(font)
|
||||
self.tmsettingsLabel.setObjectName("tmsettingsLabel")
|
||||
self.verticalLayout_2.addWidget(self.tmsettingsLabel)
|
||||
self.gridLayout_8 = QtWidgets.QGridLayout()
|
||||
self.gridLayout_8.setObjectName("gridLayout_8")
|
||||
self.stopfrequencyBox = QtWidgets.QDoubleSpinBox(parent=Form)
|
||||
self.stopfrequencyBox.setProperty("value", 80.1)
|
||||
self.stopfrequencyBox.setObjectName("stopfrequencyBox")
|
||||
self.gridLayout_8.addWidget(self.stopfrequencyBox, 1, 1, 1, 1)
|
||||
self.label_13 = QtWidgets.QLabel(parent=Form)
|
||||
self.label_13.setObjectName("label_13")
|
||||
self.gridLayout_8.addWidget(self.label_13, 1, 0, 1, 1)
|
||||
self.startfrequencyBox = QtWidgets.QDoubleSpinBox(parent=Form)
|
||||
self.startfrequencyBox.setProperty("value", 80.0)
|
||||
self.startfrequencyBox.setObjectName("startfrequencyBox")
|
||||
self.gridLayout_8.addWidget(self.startfrequencyBox, 0, 1, 1, 1)
|
||||
self.label_12 = QtWidgets.QLabel(parent=Form)
|
||||
self.label_12.setObjectName("label_12")
|
||||
self.gridLayout_8.addWidget(self.label_12, 0, 0, 1, 1)
|
||||
self.label_14 = QtWidgets.QLabel(parent=Form)
|
||||
self.label_14.setObjectName("label_14")
|
||||
self.gridLayout_8.addWidget(self.label_14, 2, 0, 1, 1)
|
||||
self.frequencystepBox = QtWidgets.QDoubleSpinBox(parent=Form)
|
||||
self.frequencystepBox.setProperty("value", 0.1)
|
||||
self.frequencystepBox.setObjectName("frequencystepBox")
|
||||
self.gridLayout_8.addWidget(self.frequencystepBox, 2, 1, 1, 1)
|
||||
self.verticalLayout_2.addLayout(self.gridLayout_8)
|
||||
self.titletypeLabel = QtWidgets.QLabel(parent=Form)
|
||||
font = QtGui.QFont()
|
||||
font.setBold(True)
|
||||
font.setWeight(75)
|
||||
self.titletypeLabel.setFont(font)
|
||||
self.titletypeLabel.setObjectName("titletypeLabel")
|
||||
self.verticalLayout_2.addWidget(self.titletypeLabel)
|
||||
|
@ -64,46 +97,65 @@ class Ui_Form(object):
|
|||
self.verticalLayout.setObjectName("verticalLayout")
|
||||
self.gridLayout_4 = QtWidgets.QGridLayout()
|
||||
self.gridLayout_4.setObjectName("gridLayout_4")
|
||||
self.homematcherButton = QtWidgets.QPushButton(parent=self.mechTab)
|
||||
self.homematcherButton.setObjectName("homematcherButton")
|
||||
self.gridLayout_4.addWidget(self.homematcherButton, 5, 1, 1, 1)
|
||||
self.label_17 = QtWidgets.QLabel(parent=self.mechTab)
|
||||
self.label_17.setObjectName("label_17")
|
||||
self.gridLayout_4.addWidget(self.label_17, 1, 0, 1, 1)
|
||||
self.stepsizeBox = QtWidgets.QSpinBox(parent=self.mechTab)
|
||||
self.stepsizeBox.setMinimum(-1000)
|
||||
self.stepsizeBox.setMaximum(1000)
|
||||
self.stepsizeBox.setProperty("value", 500)
|
||||
self.stepsizeBox.setObjectName("stepsizeBox")
|
||||
self.gridLayout_4.addWidget(self.stepsizeBox, 1, 1, 1, 1)
|
||||
self.label_18 = QtWidgets.QLabel(parent=self.mechTab)
|
||||
self.label_18.setObjectName("label_18")
|
||||
self.gridLayout_4.addWidget(self.label_18, 2, 0, 1, 3)
|
||||
self.decreasetunerButton = QtWidgets.QPushButton(parent=self.mechTab)
|
||||
self.decreasetunerButton.setObjectName("decreasetunerButton")
|
||||
self.gridLayout_4.addWidget(self.decreasetunerButton, 3, 0, 1, 1)
|
||||
self.increasetunerButton = QtWidgets.QPushButton(parent=self.mechTab)
|
||||
self.increasetunerButton.setObjectName("increasetunerButton")
|
||||
self.gridLayout_4.addWidget(self.increasetunerButton, 3, 2, 1, 1)
|
||||
self.label_19 = QtWidgets.QLabel(parent=self.mechTab)
|
||||
self.label_19.setObjectName("label_19")
|
||||
self.gridLayout_4.addWidget(self.label_19, 4, 0, 1, 3)
|
||||
self.decreasematcherButton = QtWidgets.QPushButton(parent=self.mechTab)
|
||||
self.decreasematcherButton.setObjectName("decreasematcherButton")
|
||||
self.gridLayout_4.addWidget(self.decreasematcherButton, 5, 0, 1, 1)
|
||||
self.increasematcherButton = QtWidgets.QPushButton(parent=self.mechTab)
|
||||
self.increasematcherButton.setObjectName("increasematcherButton")
|
||||
self.gridLayout_4.addWidget(self.increasematcherButton, 5, 2, 1, 1)
|
||||
self.hometunerButton = QtWidgets.QPushButton(parent=self.mechTab)
|
||||
self.hometunerButton.setObjectName("hometunerButton")
|
||||
self.gridLayout_4.addWidget(self.hometunerButton, 3, 1, 1, 1)
|
||||
self.homeButton = QtWidgets.QPushButton(parent=self.mechTab)
|
||||
self.homeButton.setObjectName("homeButton")
|
||||
self.gridLayout_4.addWidget(self.homeButton, 5, 1, 1, 1)
|
||||
self.label_16 = QtWidgets.QLabel(parent=self.mechTab)
|
||||
font = QtGui.QFont()
|
||||
font.setBold(True)
|
||||
font.setWeight(75)
|
||||
self.label_16.setFont(font)
|
||||
self.label_16.setObjectName("label_16")
|
||||
self.gridLayout_4.addWidget(self.label_16, 0, 0, 1, 3)
|
||||
self.absoluteposBox = QtWidgets.QSpinBox(parent=self.mechTab)
|
||||
self.absoluteposBox.setMaximum(1000000)
|
||||
self.absoluteposBox.setObjectName("absoluteposBox")
|
||||
self.gridLayout_4.addWidget(self.absoluteposBox, 6, 1, 1, 1)
|
||||
self.stepperselectBox = QtWidgets.QComboBox(parent=self.mechTab)
|
||||
self.stepperselectBox.setObjectName("stepperselectBox")
|
||||
self.stepperselectBox.addItem("")
|
||||
self.stepperselectBox.addItem("")
|
||||
self.gridLayout_4.addWidget(self.stepperselectBox, 1, 1, 1, 1)
|
||||
self.decreaseButton = QtWidgets.QPushButton(parent=self.mechTab)
|
||||
self.decreaseButton.setObjectName("decreaseButton")
|
||||
self.gridLayout_4.addWidget(self.decreaseButton, 5, 0, 1, 1)
|
||||
self.increaseButton = QtWidgets.QPushButton(parent=self.mechTab)
|
||||
self.increaseButton.setObjectName("increaseButton")
|
||||
self.gridLayout_4.addWidget(self.increaseButton, 5, 2, 1, 1)
|
||||
self.label_18 = QtWidgets.QLabel(parent=self.mechTab)
|
||||
self.label_18.setObjectName("label_18")
|
||||
self.gridLayout_4.addWidget(self.label_18, 1, 0, 1, 1)
|
||||
self.label_20 = QtWidgets.QLabel(parent=self.mechTab)
|
||||
self.label_20.setObjectName("label_20")
|
||||
self.gridLayout_4.addWidget(self.label_20, 6, 0, 1, 1)
|
||||
self.stepsizeBox = QtWidgets.QSpinBox(parent=self.mechTab)
|
||||
self.stepsizeBox.setMinimum(0)
|
||||
self.stepsizeBox.setMaximum(1000000)
|
||||
self.stepsizeBox.setProperty("value", 500)
|
||||
self.stepsizeBox.setObjectName("stepsizeBox")
|
||||
self.gridLayout_4.addWidget(self.stepsizeBox, 3, 1, 1, 1)
|
||||
self.label_17 = QtWidgets.QLabel(parent=self.mechTab)
|
||||
self.label_17.setObjectName("label_17")
|
||||
self.gridLayout_4.addWidget(self.label_17, 3, 0, 1, 1)
|
||||
self.absoluteGoButton = QtWidgets.QPushButton(parent=self.mechTab)
|
||||
self.absoluteGoButton.setObjectName("absoluteGoButton")
|
||||
self.gridLayout_4.addWidget(self.absoluteGoButton, 6, 2, 1, 1)
|
||||
self.label_4 = QtWidgets.QLabel(parent=self.mechTab)
|
||||
self.label_4.setObjectName("label_4")
|
||||
self.gridLayout_4.addWidget(self.label_4, 2, 0, 1, 1)
|
||||
self.stepperposLabel = QtWidgets.QLabel(parent=self.mechTab)
|
||||
self.stepperposLabel.setObjectName("stepperposLabel")
|
||||
self.gridLayout_4.addWidget(self.stepperposLabel, 2, 1, 1, 1)
|
||||
self.verticalLayout.addLayout(self.gridLayout_4)
|
||||
self.starpositionButton = QtWidgets.QPushButton(parent=self.mechTab)
|
||||
self.starpositionButton.setObjectName("starpositionButton")
|
||||
self.verticalLayout.addWidget(self.starpositionButton)
|
||||
self.positionButton = QtWidgets.QPushButton(parent=self.mechTab)
|
||||
self.positionButton.setObjectName("positionButton")
|
||||
self.verticalLayout.addWidget(self.positionButton)
|
||||
self.mechLUTButton = QtWidgets.QPushButton(parent=self.mechTab)
|
||||
self.mechLUTButton.setObjectName("mechLUTButton")
|
||||
self.verticalLayout.addWidget(self.mechLUTButton)
|
||||
self.viewmechLUTButton = QtWidgets.QPushButton(parent=self.mechTab)
|
||||
self.viewmechLUTButton.setObjectName("viewmechLUTButton")
|
||||
self.verticalLayout.addWidget(self.viewmechLUTButton)
|
||||
spacerItem = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Policy.Minimum, QtWidgets.QSizePolicy.Policy.Expanding)
|
||||
self.verticalLayout.addItem(spacerItem)
|
||||
self.verticalLayout.setStretch(1, 1)
|
||||
|
@ -112,77 +164,66 @@ class Ui_Form(object):
|
|||
self.elecTab.setObjectName("elecTab")
|
||||
self.gridLayout_3 = QtWidgets.QGridLayout(self.elecTab)
|
||||
self.gridLayout_3.setObjectName("gridLayout_3")
|
||||
self.label_4 = QtWidgets.QLabel(parent=self.elecTab)
|
||||
self.label_4.setObjectName("label_4")
|
||||
self.gridLayout_3.addWidget(self.label_4, 5, 0, 1, 1)
|
||||
self.stopfrequencyBox = QtWidgets.QDoubleSpinBox(parent=self.elecTab)
|
||||
self.stopfrequencyBox.setObjectName("stopfrequencyBox")
|
||||
self.gridLayout_3.addWidget(self.stopfrequencyBox, 7, 1, 1, 1)
|
||||
self.label_2 = QtWidgets.QLabel(parent=self.elecTab)
|
||||
self.label_2.setObjectName("label_2")
|
||||
self.gridLayout_3.addWidget(self.label_2, 1, 0, 1, 1)
|
||||
self.tuningBox = QtWidgets.QDoubleSpinBox(parent=self.elecTab)
|
||||
self.tuningBox.setObjectName("tuningBox")
|
||||
self.gridLayout_3.addWidget(self.tuningBox, 1, 1, 1, 1)
|
||||
self.frequencystepBox = QtWidgets.QDoubleSpinBox(parent=self.elecTab)
|
||||
self.frequencystepBox.setObjectName("frequencystepBox")
|
||||
self.gridLayout_3.addWidget(self.frequencystepBox, 8, 1, 1, 1)
|
||||
self.label_11 = QtWidgets.QLabel(parent=self.elecTab)
|
||||
font = QtGui.QFont()
|
||||
font.setBold(True)
|
||||
self.label_11.setFont(font)
|
||||
self.label_11.setObjectName("label_11")
|
||||
self.gridLayout_3.addWidget(self.label_11, 4, 0, 1, 1)
|
||||
self.startfrequencyBox = QtWidgets.QDoubleSpinBox(parent=self.elecTab)
|
||||
self.startfrequencyBox.setObjectName("startfrequencyBox")
|
||||
self.gridLayout_3.addWidget(self.startfrequencyBox, 6, 1, 1, 1)
|
||||
self.generateLUTButton = QtWidgets.QPushButton(parent=self.elecTab)
|
||||
self.generateLUTButton.setObjectName("generateLUTButton")
|
||||
self.gridLayout_3.addWidget(self.generateLUTButton, 9, 0, 1, 2)
|
||||
self.label_13 = QtWidgets.QLabel(parent=self.elecTab)
|
||||
self.label_13.setObjectName("label_13")
|
||||
self.gridLayout_3.addWidget(self.label_13, 7, 0, 1, 1)
|
||||
self.resolutionBox = QtWidgets.QDoubleSpinBox(parent=self.elecTab)
|
||||
self.resolutionBox.setObjectName("resolutionBox")
|
||||
self.gridLayout_3.addWidget(self.resolutionBox, 5, 1, 1, 1)
|
||||
self.label_9 = QtWidgets.QLabel(parent=self.elecTab)
|
||||
font = QtGui.QFont()
|
||||
font.setBold(True)
|
||||
font.setWeight(75)
|
||||
self.label_9.setFont(font)
|
||||
self.label_9.setObjectName("label_9")
|
||||
self.gridLayout_3.addWidget(self.label_9, 0, 0, 1, 1)
|
||||
self.label_15 = QtWidgets.QLabel(parent=self.elecTab)
|
||||
self.label_15.setObjectName("label_15")
|
||||
self.gridLayout_3.addWidget(self.label_15, 11, 0, 1, 1)
|
||||
self.viewLUTButton = QtWidgets.QPushButton(parent=self.elecTab)
|
||||
self.viewLUTButton.setObjectName("viewLUTButton")
|
||||
self.gridLayout_3.addWidget(self.viewLUTButton, 10, 0, 1, 2)
|
||||
self.label_2 = QtWidgets.QLabel(parent=self.elecTab)
|
||||
self.label_2.setObjectName("label_2")
|
||||
self.gridLayout_3.addWidget(self.label_2, 1, 0, 1, 1)
|
||||
self.matchingBox = QtWidgets.QDoubleSpinBox(parent=self.elecTab)
|
||||
self.matchingBox.setObjectName("matchingBox")
|
||||
self.gridLayout_3.addWidget(self.matchingBox, 2, 1, 1, 1)
|
||||
self.generateLUTButton = QtWidgets.QPushButton(parent=self.elecTab)
|
||||
self.generateLUTButton.setObjectName("generateLUTButton")
|
||||
self.gridLayout_3.addWidget(self.generateLUTButton, 8, 0, 1, 2)
|
||||
self.tuningBox = QtWidgets.QDoubleSpinBox(parent=self.elecTab)
|
||||
self.tuningBox.setObjectName("tuningBox")
|
||||
self.gridLayout_3.addWidget(self.tuningBox, 1, 1, 1, 1)
|
||||
self.label_11 = QtWidgets.QLabel(parent=self.elecTab)
|
||||
font = QtGui.QFont()
|
||||
font.setBold(True)
|
||||
font.setWeight(75)
|
||||
self.label_11.setFont(font)
|
||||
self.label_11.setObjectName("label_11")
|
||||
self.gridLayout_3.addWidget(self.label_11, 4, 0, 1, 1)
|
||||
self.viewelLUTButton = QtWidgets.QPushButton(parent=self.elecTab)
|
||||
self.viewelLUTButton.setObjectName("viewelLUTButton")
|
||||
self.gridLayout_3.addWidget(self.viewelLUTButton, 10, 0, 1, 2)
|
||||
self.setvoltagesButton = QtWidgets.QPushButton(parent=self.elecTab)
|
||||
self.setvoltagesButton.setObjectName("setvoltagesButton")
|
||||
self.gridLayout_3.addWidget(self.setvoltagesButton, 3, 0, 1, 2)
|
||||
self.label_3 = QtWidgets.QLabel(parent=self.elecTab)
|
||||
self.label_3.setObjectName("label_3")
|
||||
self.gridLayout_3.addWidget(self.label_3, 2, 0, 1, 1)
|
||||
self.label_12 = QtWidgets.QLabel(parent=self.elecTab)
|
||||
self.label_12.setObjectName("label_12")
|
||||
self.gridLayout_3.addWidget(self.label_12, 6, 0, 1, 1)
|
||||
self.matchingBox = QtWidgets.QDoubleSpinBox(parent=self.elecTab)
|
||||
self.matchingBox.setObjectName("matchingBox")
|
||||
self.gridLayout_3.addWidget(self.matchingBox, 2, 1, 1, 1)
|
||||
self.label_14 = QtWidgets.QLabel(parent=self.elecTab)
|
||||
self.label_14.setObjectName("label_14")
|
||||
self.gridLayout_3.addWidget(self.label_14, 8, 0, 1, 1)
|
||||
self.switchpreampButton = QtWidgets.QPushButton(parent=self.elecTab)
|
||||
self.switchpreampButton.setObjectName("switchpreampButton")
|
||||
self.gridLayout_3.addWidget(self.switchpreampButton, 12, 0, 1, 1)
|
||||
self.switchATMButton = QtWidgets.QPushButton(parent=self.elecTab)
|
||||
self.switchATMButton.setObjectName("switchATMButton")
|
||||
self.gridLayout_3.addWidget(self.switchATMButton, 12, 1, 1, 1)
|
||||
self.prevVoltagecheckBox = QtWidgets.QCheckBox(parent=self.elecTab)
|
||||
self.prevVoltagecheckBox.setObjectName("prevVoltagecheckBox")
|
||||
self.gridLayout_3.addWidget(self.prevVoltagecheckBox, 9, 0, 1, 1)
|
||||
self.typeTab.addTab(self.elecTab, "")
|
||||
self.verticalLayout_2.addWidget(self.typeTab)
|
||||
self.rfswitchLabel = QtWidgets.QLabel(parent=Form)
|
||||
font = QtGui.QFont()
|
||||
font.setBold(True)
|
||||
font.setWeight(75)
|
||||
self.rfswitchLabel.setFont(font)
|
||||
self.rfswitchLabel.setObjectName("rfswitchLabel")
|
||||
self.verticalLayout_2.addWidget(self.rfswitchLabel)
|
||||
self.gridLayout_7 = QtWidgets.QGridLayout()
|
||||
self.gridLayout_7.setObjectName("gridLayout_7")
|
||||
self.switchATMButton = QtWidgets.QPushButton(parent=Form)
|
||||
self.switchATMButton.setObjectName("switchATMButton")
|
||||
self.gridLayout_7.addWidget(self.switchATMButton, 0, 0, 1, 1)
|
||||
self.switchpreampButton = QtWidgets.QPushButton(parent=Form)
|
||||
self.switchpreampButton.setObjectName("switchpreampButton")
|
||||
self.gridLayout_7.addWidget(self.switchpreampButton, 0, 1, 1, 1)
|
||||
self.verticalLayout_2.addLayout(self.gridLayout_7)
|
||||
self.titlefrequencyLabel = QtWidgets.QLabel(parent=Form)
|
||||
font = QtGui.QFont()
|
||||
font.setBold(True)
|
||||
font.setWeight(75)
|
||||
self.titlefrequencyLabel.setFont(font)
|
||||
self.titlefrequencyLabel.setObjectName("titlefrequencyLabel")
|
||||
self.verticalLayout_2.addWidget(self.titlefrequencyLabel)
|
||||
|
@ -191,21 +232,21 @@ class Ui_Form(object):
|
|||
self.startEdit = QtWidgets.QLineEdit(parent=Form)
|
||||
self.startEdit.setObjectName("startEdit")
|
||||
self.gridLayout.addWidget(self.startEdit, 0, 1, 1, 1)
|
||||
self.label_8 = QtWidgets.QLabel(parent=Form)
|
||||
self.label_8.setObjectName("label_8")
|
||||
self.gridLayout.addWidget(self.label_8, 1, 2, 1, 1)
|
||||
self.stopEdit = QtWidgets.QLineEdit(parent=Form)
|
||||
self.stopEdit.setObjectName("stopEdit")
|
||||
self.gridLayout.addWidget(self.stopEdit, 1, 1, 1, 1)
|
||||
self.label_6 = QtWidgets.QLabel(parent=Form)
|
||||
self.label_6.setObjectName("label_6")
|
||||
self.gridLayout.addWidget(self.label_6, 0, 2, 1, 1)
|
||||
self.label_7 = QtWidgets.QLabel(parent=Form)
|
||||
self.label_7.setObjectName("label_7")
|
||||
self.gridLayout.addWidget(self.label_7, 1, 0, 1, 1)
|
||||
self.label_6 = QtWidgets.QLabel(parent=Form)
|
||||
self.label_6.setObjectName("label_6")
|
||||
self.gridLayout.addWidget(self.label_6, 0, 2, 1, 1)
|
||||
self.label_5 = QtWidgets.QLabel(parent=Form)
|
||||
self.label_5.setObjectName("label_5")
|
||||
self.gridLayout.addWidget(self.label_5, 0, 0, 1, 1)
|
||||
self.stopEdit = QtWidgets.QLineEdit(parent=Form)
|
||||
self.stopEdit.setObjectName("stopEdit")
|
||||
self.gridLayout.addWidget(self.stopEdit, 1, 1, 1, 1)
|
||||
self.label_8 = QtWidgets.QLabel(parent=Form)
|
||||
self.label_8.setObjectName("label_8")
|
||||
self.gridLayout.addWidget(self.label_8, 1, 2, 1, 1)
|
||||
self.verticalLayout_2.addLayout(self.gridLayout)
|
||||
self.startButton = QtWidgets.QPushButton(parent=Form)
|
||||
self.startButton.setObjectName("startButton")
|
||||
|
@ -219,6 +260,7 @@ class Ui_Form(object):
|
|||
self.titleinfoLabel = QtWidgets.QLabel(parent=Form)
|
||||
font = QtGui.QFont()
|
||||
font.setBold(True)
|
||||
font.setWeight(75)
|
||||
self.titleinfoLabel.setFont(font)
|
||||
self.titleinfoLabel.setObjectName("titleinfoLabel")
|
||||
self.verticalLayout_2.addWidget(self.titleinfoLabel)
|
||||
|
@ -226,7 +268,7 @@ class Ui_Form(object):
|
|||
self.scrollArea.setWidgetResizable(True)
|
||||
self.scrollArea.setObjectName("scrollArea")
|
||||
self.scrollAreaWidgetContents = QtWidgets.QWidget()
|
||||
self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, 0, 297, 68))
|
||||
self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, 0, 291, 83))
|
||||
self.scrollAreaWidgetContents.setObjectName("scrollAreaWidgetContents")
|
||||
self.scrollArea.setWidget(self.scrollAreaWidgetContents)
|
||||
self.verticalLayout_2.addWidget(self.scrollArea)
|
||||
|
@ -241,11 +283,25 @@ class Ui_Form(object):
|
|||
self.S11Plot.setSizePolicy(sizePolicy)
|
||||
self.S11Plot.setObjectName("S11Plot")
|
||||
self.verticalLayout_5.addWidget(self.S11Plot)
|
||||
self.horizontalLayout = QtWidgets.QHBoxLayout()
|
||||
self.horizontalLayout.setObjectName("horizontalLayout")
|
||||
self.verticalLayout_4 = QtWidgets.QVBoxLayout()
|
||||
self.verticalLayout_4.setObjectName("verticalLayout_4")
|
||||
self.importButton = QtWidgets.QPushButton(parent=Form)
|
||||
self.importButton.setObjectName("importButton")
|
||||
self.verticalLayout_4.addWidget(self.importButton)
|
||||
self.exportButton = QtWidgets.QPushButton(parent=Form)
|
||||
self.exportButton.setObjectName("exportButton")
|
||||
self.verticalLayout_4.addWidget(self.exportButton)
|
||||
self.horizontalLayout.addLayout(self.verticalLayout_4)
|
||||
spacerItem1 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum)
|
||||
self.horizontalLayout.addItem(spacerItem1)
|
||||
self.verticalLayout_5.addLayout(self.horizontalLayout)
|
||||
self.horizontalLayout_2.addLayout(self.verticalLayout_5)
|
||||
self.horizontalLayout_2.setStretch(1, 1)
|
||||
|
||||
self.retranslateUi(Form)
|
||||
self.typeTab.setCurrentIndex(0)
|
||||
self.typeTab.setCurrentIndex(1)
|
||||
QtCore.QMetaObject.connectSlotsByName(Form)
|
||||
|
||||
def retranslateUi(self, Form):
|
||||
|
@ -256,43 +312,50 @@ class Ui_Form(object):
|
|||
self.label.setText(_translate("Form", "Port:"))
|
||||
self.label_10.setText(_translate("Form", "Connected to:"))
|
||||
self.connectButton.setText(_translate("Form", "Connect"))
|
||||
self.titletypeLabel.setText(_translate("Form", "T&M Type:"))
|
||||
self.homematcherButton.setText(_translate("Form", "Home"))
|
||||
self.label_17.setText(_translate("Form", "Step Size:"))
|
||||
self.label_18.setText(_translate("Form", "Tuning Stepper:"))
|
||||
self.decreasetunerButton.setText(_translate("Form", "-"))
|
||||
self.increasetunerButton.setText(_translate("Form", "+"))
|
||||
self.label_19.setText(_translate("Form", "Matching Stepper:"))
|
||||
self.decreasematcherButton.setText(_translate("Form", "-"))
|
||||
self.increasematcherButton.setText(_translate("Form", "+"))
|
||||
self.hometunerButton.setText(_translate("Form", "Home"))
|
||||
self.label_16.setText(_translate("Form", "Stepper Control:"))
|
||||
self.starpositionButton.setText(_translate("Form", "Start Position"))
|
||||
self.typeTab.setTabText(self.typeTab.indexOf(self.mechTab), _translate("Form", "Mechanical"))
|
||||
self.label_4.setText(_translate("Form", "Voltage Resolution"))
|
||||
self.label_2.setText(_translate("Form", "Voltage Tuning"))
|
||||
self.label_11.setText(_translate("Form", "Generate LUT:"))
|
||||
self.generateLUTButton.setText(_translate("Form", "Start Voltage Sweep"))
|
||||
self.tmsettingsLabel.setText(_translate("Form", "T&M Settings:"))
|
||||
self.label_13.setText(_translate("Form", "Stop Frequency (MHz)"))
|
||||
self.label_9.setText(_translate("Form", "Set Voltages:"))
|
||||
self.label_15.setText(_translate("Form", "RF Switch:"))
|
||||
self.viewLUTButton.setText(_translate("Form", "View LUT"))
|
||||
self.setvoltagesButton.setText(_translate("Form", "Set Voltages"))
|
||||
self.label_3.setText(_translate("Form", "Voltage Matching"))
|
||||
self.label_12.setText(_translate("Form", "Start Frequency (MHz)"))
|
||||
self.label_14.setText(_translate("Form", "Frequency Step (MHz)"))
|
||||
self.switchpreampButton.setText(_translate("Form", "Preamplifier"))
|
||||
self.switchATMButton.setText(_translate("Form", "ATM"))
|
||||
self.titletypeLabel.setText(_translate("Form", "T&M Type:"))
|
||||
self.homeButton.setText(_translate("Form", "Home"))
|
||||
self.label_16.setText(_translate("Form", "Stepper Control:"))
|
||||
self.stepperselectBox.setItemText(0, _translate("Form", "Tuning"))
|
||||
self.stepperselectBox.setItemText(1, _translate("Form", "Matching"))
|
||||
self.decreaseButton.setText(_translate("Form", "-"))
|
||||
self.increaseButton.setText(_translate("Form", "+"))
|
||||
self.label_18.setText(_translate("Form", "Stepper:"))
|
||||
self.label_20.setText(_translate("Form", "Absolute:"))
|
||||
self.label_17.setText(_translate("Form", "Step Size:"))
|
||||
self.absoluteGoButton.setText(_translate("Form", "Go"))
|
||||
self.label_4.setText(_translate("Form", "Position:"))
|
||||
self.stepperposLabel.setText(_translate("Form", "0"))
|
||||
self.positionButton.setText(_translate("Form", "Saved Positions"))
|
||||
self.mechLUTButton.setText(_translate("Form", "Generate LUT"))
|
||||
self.viewmechLUTButton.setText(_translate("Form", "View LUT"))
|
||||
self.typeTab.setTabText(self.typeTab.indexOf(self.mechTab), _translate("Form", "Mechanical"))
|
||||
self.label_9.setText(_translate("Form", "Set Voltages:"))
|
||||
self.label_2.setText(_translate("Form", "Voltage Tuning"))
|
||||
self.generateLUTButton.setText(_translate("Form", "Generate LUT"))
|
||||
self.label_11.setText(_translate("Form", "Generate LUT:"))
|
||||
self.viewelLUTButton.setText(_translate("Form", "View LUT"))
|
||||
self.setvoltagesButton.setText(_translate("Form", "Set Voltages"))
|
||||
self.label_3.setText(_translate("Form", "Voltage Matching"))
|
||||
self.prevVoltagecheckBox.setText(_translate("Form", "Start from previous Voltage"))
|
||||
self.typeTab.setTabText(self.typeTab.indexOf(self.elecTab), _translate("Form", "Electrical"))
|
||||
self.rfswitchLabel.setText(_translate("Form", "RF Switch:"))
|
||||
self.switchATMButton.setText(_translate("Form", "ATM"))
|
||||
self.switchpreampButton.setText(_translate("Form", "Preamplifier"))
|
||||
self.titlefrequencyLabel.setText(_translate("Form", "Frequency Sweep:"))
|
||||
self.startEdit.setText(_translate("Form", "80"))
|
||||
self.label_8.setText(_translate("Form", "MHz"))
|
||||
self.stopEdit.setText(_translate("Form", "100"))
|
||||
self.label_6.setText(_translate("Form", "MHz"))
|
||||
self.label_7.setText(_translate("Form", "Stop Frequency:"))
|
||||
self.label_6.setText(_translate("Form", "MHz"))
|
||||
self.label_5.setText(_translate("Form", "Start Frequency:"))
|
||||
self.stopEdit.setText(_translate("Form", "100"))
|
||||
self.label_8.setText(_translate("Form", "MHz"))
|
||||
self.startButton.setText(_translate("Form", "Start Sweep"))
|
||||
self.calibrationButton.setText(_translate("Form", "Calibrate"))
|
||||
self.pushButton_3.setText(_translate("Form", "T&M Settings"))
|
||||
self.titleinfoLabel.setText(_translate("Form", "Info Box:"))
|
||||
self.importButton.setText(_translate("Form", "Import Measurement"))
|
||||
self.exportButton.setText(_translate("Form", "Export Measurement"))
|
||||
from nqrduck.contrib.mplwidget import MplWidget
|
||||
|
|
Loading…
Reference in a new issue