mirror of
https://github.com/nqrduck/nqrduck-autotm.git
synced 2024-09-18 18:30:35 +00:00
Linting.
This commit is contained in:
parent
3a23b126fe
commit
bfbc20c2e9
5 changed files with 556 additions and 212 deletions
|
@ -1 +1,3 @@
|
||||||
from .autotm import AutoTM as Module
|
"""The NQRduck AutoTM module. It is used to automatically tune and match magnetic resonance probe coils."""
|
||||||
|
|
||||||
|
from .autotm import AutoTM as Module
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
|
"""The Module creation snippet for the NQRduck AutoTM module."""
|
||||||
|
|
||||||
from nqrduck.module.module import Module
|
from nqrduck.module.module import Module
|
||||||
from .model import AutoTMModel
|
from .model import AutoTMModel
|
||||||
from .view import AutoTMView
|
from .view import AutoTMView
|
||||||
from .controller import AutoTMController
|
from .controller import AutoTMController
|
||||||
|
|
||||||
AutoTM = Module(AutoTMModel, AutoTMView, AutoTMController)
|
AutoTM = Module(AutoTMModel, AutoTMView, AutoTMController)
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,3 +1,10 @@
|
||||||
|
"""The module model for the NQRduck AutoTM module. It is used to store the data and state of the AutoTM module.
|
||||||
|
|
||||||
|
Additionally it includes the LookupTable class which is used to store tuning and matching voltages for different frequencies.
|
||||||
|
|
||||||
|
The S11Data class is used to store the S11 data that is read in via the serial connection.
|
||||||
|
"""
|
||||||
|
|
||||||
import cmath
|
import cmath
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import logging
|
import logging
|
||||||
|
@ -10,6 +17,7 @@ logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class S11Data:
|
class S11Data:
|
||||||
|
"""This class is used to store the S11 data that is read in via the serial connection."""
|
||||||
FILE_EXTENSION = "s11"
|
FILE_EXTENSION = "s11"
|
||||||
# Conversion factors - the data is generally sent and received in mV
|
# Conversion factors - the data is generally sent and received in mV
|
||||||
# These values are used to convert the data to dB and degrees
|
# These values are used to convert the data to dB and degrees
|
||||||
|
@ -19,26 +27,32 @@ class S11Data:
|
||||||
PHASE_SLOPE = 10 # deg/mV
|
PHASE_SLOPE = 10 # deg/mV
|
||||||
|
|
||||||
def __init__(self, data_points: list) -> None:
|
def __init__(self, data_points: list) -> None:
|
||||||
|
"""Initialize the S11 data."""
|
||||||
self.frequency = np.array([data_point[0] for data_point in data_points])
|
self.frequency = np.array([data_point[0] for data_point in data_points])
|
||||||
self.return_loss_mv = np.array([data_point[1] for data_point in data_points])
|
self.return_loss_mv = np.array([data_point[1] for data_point in data_points])
|
||||||
self.phase_mv = np.array([data_point[2] for data_point in data_points])
|
self.phase_mv = np.array([data_point[2] for data_point in data_points])
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def millivolts(self):
|
def millivolts(self):
|
||||||
|
"""The reflection data in millivolts. This is the raw data that is read in via the serial connection."""
|
||||||
return self.frequency, self.return_loss_mv, self.phase_mv
|
return self.frequency, self.return_loss_mv, self.phase_mv
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def return_loss_db(self):
|
def return_loss_db(self):
|
||||||
|
"""Returns the return loss in dB calculated from the return loss in mV."""
|
||||||
return (
|
return (
|
||||||
self.return_loss_mv - self.CENTER_POINT_MAGNITUDE
|
self.return_loss_mv - self.CENTER_POINT_MAGNITUDE
|
||||||
) / self.MAGNITUDE_SLOPE
|
) / self.MAGNITUDE_SLOPE
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def phase_deg(self, phase_correction=True):
|
def phase_deg(self, phase_correction=True) -> np.array:
|
||||||
"""Returns the absolute value of the phase in degrees
|
"""Returns the absolute value of the phase in degrees.
|
||||||
|
|
||||||
Keyword Arguments:
|
Args:
|
||||||
phase_correction {bool} -- If True, the phase correction is applied. (default: {False})
|
phase_correction (bool, optional): If True, the phase correction is applied. Defaults to True.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
np.array: The absolute value of the phase in degrees.
|
||||||
"""
|
"""
|
||||||
phase_deg = (self.phase_mv - self.CENTER_POINT_PHASE) / self.PHASE_SLOPE
|
phase_deg = (self.phase_mv - self.CENTER_POINT_PHASE) / self.PHASE_SLOPE
|
||||||
if phase_correction:
|
if phase_correction:
|
||||||
|
@ -48,11 +62,12 @@ class S11Data:
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def phase_rad(self):
|
def phase_rad(self):
|
||||||
|
"""Returns the phase in radians."""
|
||||||
return self.phase_deg * cmath.pi / 180
|
return self.phase_deg * cmath.pi / 180
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def gamma(self):
|
def gamma(self):
|
||||||
"""Complex reflection coefficient"""
|
"""Complex reflection coefficient."""
|
||||||
if len(self.return_loss_db) != len(self.phase_rad):
|
if len(self.return_loss_db) != len(self.phase_rad):
|
||||||
raise ValueError("return_loss_db and phase_rad must be the same length")
|
raise ValueError("return_loss_db and phase_rad must be the same length")
|
||||||
|
|
||||||
|
@ -65,6 +80,7 @@ class S11Data:
|
||||||
self, frequency_data: np.array, phase_data: np.array
|
self, frequency_data: np.array, phase_data: np.array
|
||||||
) -> np.array:
|
) -> np.array:
|
||||||
"""This method fixes the phase sign of the phase data.
|
"""This method fixes the phase sign of the phase data.
|
||||||
|
|
||||||
The AD8302 can only measure the absolute value of the phase.
|
The AD8302 can only measure the absolute value of the phase.
|
||||||
Therefore we need to correct the phase sign. This can be done via the slope of the phase.
|
Therefore we need to correct the phase sign. This can be done via the slope of the phase.
|
||||||
If the slope is negative, the phase is positive and vice versa.
|
If the slope is negative, the phase is positive and vice versa.
|
||||||
|
@ -145,6 +161,7 @@ class S11Data:
|
||||||
return phase_data_corrected
|
return phase_data_corrected
|
||||||
|
|
||||||
def to_json(self):
|
def to_json(self):
|
||||||
|
"""Convert the S11 data to a JSON serializable format."""
|
||||||
return {
|
return {
|
||||||
"frequency": self.frequency.tolist(),
|
"frequency": self.frequency.tolist(),
|
||||||
"return_loss_mv": self.return_loss_mv.tolist(),
|
"return_loss_mv": self.return_loss_mv.tolist(),
|
||||||
|
@ -153,6 +170,7 @@ class S11Data:
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_json(cls, json):
|
def from_json(cls, json):
|
||||||
|
"""Create an S11Data object from a JSON serializable format."""
|
||||||
f = json["frequency"]
|
f = json["frequency"]
|
||||||
rl = json["return_loss_mv"]
|
rl = json["return_loss_mv"]
|
||||||
p = json["phase_mv"]
|
p = json["phase_mv"]
|
||||||
|
@ -171,13 +189,14 @@ class LookupTable:
|
||||||
stop_frequency: float,
|
stop_frequency: float,
|
||||||
frequency_step: float,
|
frequency_step: float,
|
||||||
) -> None:
|
) -> None:
|
||||||
|
"""Initialize the lookup table."""
|
||||||
self.start_frequency = start_frequency
|
self.start_frequency = start_frequency
|
||||||
self.stop_frequency = stop_frequency
|
self.stop_frequency = stop_frequency
|
||||||
self.frequency_step = frequency_step
|
self.frequency_step = frequency_step
|
||||||
|
|
||||||
# This is the frequency at which the tuning and matching process was started
|
# This is the frequency at which the tuning and matching process was started
|
||||||
self.started_frequency = None
|
self.started_frequency = None
|
||||||
|
|
||||||
def get_entry_number(self, frequency: float) -> int:
|
def get_entry_number(self, frequency: float) -> int:
|
||||||
"""This method returns the entry number of the given frequency.
|
"""This method returns the entry number of the given frequency.
|
||||||
|
|
||||||
|
@ -190,57 +209,78 @@ class LookupTable:
|
||||||
# Round to closest integer
|
# Round to closest integer
|
||||||
return int(round((frequency - self.start_frequency) / self.frequency_step))
|
return int(round((frequency - self.start_frequency) / self.frequency_step))
|
||||||
|
|
||||||
class Stepper:
|
|
||||||
|
|
||||||
|
class Stepper:
|
||||||
|
"""This class is used to store the state of a stepper motor."""
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
|
"""Initialize the stepper motor."""
|
||||||
self.homed = False
|
self.homed = False
|
||||||
self.position = 0
|
self.position = 0
|
||||||
|
|
||||||
|
|
||||||
class SavedPosition:
|
class SavedPosition:
|
||||||
"""This class is used to store a saved position for tuning and matching of electrical probeheads."""
|
"""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:
|
|
||||||
|
def __init__(
|
||||||
|
self, frequency: float, tuning_position: int, matching_position: int
|
||||||
|
) -> None:
|
||||||
|
"""Initialize the saved position."""
|
||||||
self.frequency = frequency
|
self.frequency = frequency
|
||||||
self.tuning_position = tuning_position
|
self.tuning_position = tuning_position
|
||||||
self.matching_position = matching_position
|
self.matching_position = matching_position
|
||||||
|
|
||||||
def to_json(self):
|
def to_json(self):
|
||||||
|
"""Convert the saved position to a JSON serializable format."""
|
||||||
return {
|
return {
|
||||||
"frequency": self.frequency,
|
"frequency": self.frequency,
|
||||||
"tuning_position": self.tuning_position,
|
"tuning_position": self.tuning_position,
|
||||||
"matching_position": self.matching_position,
|
"matching_position": self.matching_position,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class TuningStepper(Stepper):
|
class TuningStepper(Stepper):
|
||||||
|
"""This class is used to store the state of the tuning stepper motor."""
|
||||||
TYPE = "Tuning"
|
TYPE = "Tuning"
|
||||||
MAX_STEPS = 1e6
|
MAX_STEPS = 1e6
|
||||||
BACKLASH_STEPS = 60
|
BACKLASH_STEPS = 60
|
||||||
|
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
|
"""Initialize the tuning stepper motor."""
|
||||||
super().__init__()
|
super().__init__()
|
||||||
# Backlash stepper
|
# Backlash stepper
|
||||||
self.last_direction = None
|
self.last_direction = None
|
||||||
|
|
||||||
|
|
||||||
class MatchingStepper(Stepper):
|
class MatchingStepper(Stepper):
|
||||||
|
"""This class is used to store the state of the matching stepper motor."""
|
||||||
TYPE = "Matching"
|
TYPE = "Matching"
|
||||||
MAX_STEPS = 1e6
|
MAX_STEPS = 1e6
|
||||||
|
|
||||||
BACKLASH_STEPS = 0
|
BACKLASH_STEPS = 0
|
||||||
|
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
|
"""Initialize the matching stepper motor."""
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.last_direction = None
|
self.last_direction = None
|
||||||
|
|
||||||
|
|
||||||
class ElectricalLookupTable(LookupTable):
|
class ElectricalLookupTable(LookupTable):
|
||||||
|
"""This class is used to store a lookup table for tuning and matching of electrical probeheads."""
|
||||||
TYPE = "Electrical"
|
TYPE = "Electrical"
|
||||||
|
|
||||||
def __init__(self, start_frequency: float, stop_frequency: float, frequency_step: float) -> None:
|
def __init__(
|
||||||
|
self, start_frequency: float, stop_frequency: float, frequency_step: float
|
||||||
|
) -> None:
|
||||||
|
"""Initialize the lookup table."""
|
||||||
super().__init__(start_frequency, stop_frequency, frequency_step)
|
super().__init__(start_frequency, stop_frequency, frequency_step)
|
||||||
self.init_voltages()
|
self.init_voltages()
|
||||||
|
|
||||||
def init_voltages(self) -> None:
|
def init_voltages(self) -> None:
|
||||||
"""Initialize the lookup table with default values."""
|
"""Initialize the lookup table with default values."""
|
||||||
for frequency in np.arange(
|
for frequency in np.arange(
|
||||||
self.start_frequency, self.stop_frequency + self.frequency_step, self.frequency_step
|
self.start_frequency,
|
||||||
|
self.stop_frequency + self.frequency_step,
|
||||||
|
self.frequency_step,
|
||||||
):
|
):
|
||||||
self.started_frequency = frequency
|
self.started_frequency = frequency
|
||||||
self.add_voltages(None, None)
|
self.add_voltages(None, None)
|
||||||
|
@ -250,7 +290,7 @@ class ElectricalLookupTable(LookupTable):
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
tuning_voltage (float): The tuning voltage for the given frequency.
|
tuning_voltage (float): The tuning voltage for the given frequency.
|
||||||
matching_voltage (float): The matching voltage for the given frequency.
|
matching_voltage (float): The matching voltage for the given frequency.
|
||||||
"""
|
"""
|
||||||
self.data[self.started_frequency] = (tuning_voltage, matching_voltage)
|
self.data[self.started_frequency] = (tuning_voltage, matching_voltage)
|
||||||
|
|
||||||
|
@ -266,10 +306,11 @@ class ElectricalLookupTable(LookupTable):
|
||||||
entry_number = self.get_entry_number(frequency)
|
entry_number = self.get_entry_number(frequency)
|
||||||
key = list(self.data.keys())[entry_number]
|
key = list(self.data.keys())[entry_number]
|
||||||
return self.data[key]
|
return self.data[key]
|
||||||
|
|
||||||
def is_incomplete(self) -> bool:
|
def is_incomplete(self) -> bool:
|
||||||
"""This method returns True if the lookup table is incomplete,
|
"""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.
|
|
||||||
|
I.e. if there are frequencies for which no the tuning or matching voltage is none.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
bool: True if the lookup table is incomplete, False otherwise.
|
bool: True if the lookup table is incomplete, False otherwise.
|
||||||
|
@ -293,19 +334,25 @@ class ElectricalLookupTable(LookupTable):
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
class MechanicalLookupTable(LookupTable):
|
class MechanicalLookupTable(LookupTable):
|
||||||
|
"""This class is used to store a lookup table for tuning and matching of mechanical probeheads."""
|
||||||
# Hmm duplicate code
|
# Hmm duplicate code
|
||||||
TYPE = "Mechanical"
|
TYPE = "Mechanical"
|
||||||
|
|
||||||
|
|
||||||
def __init__(self, start_frequency: float, stop_frequency: float, frequency_step: float) -> None:
|
def __init__(
|
||||||
|
self, start_frequency: float, stop_frequency: float, frequency_step: float
|
||||||
|
) -> None:
|
||||||
|
"""Initialize the lookup table."""
|
||||||
super().__init__(start_frequency, stop_frequency, frequency_step)
|
super().__init__(start_frequency, stop_frequency, frequency_step)
|
||||||
self.init_positions()
|
self.init_positions()
|
||||||
|
|
||||||
def init_positions(self) -> None:
|
def init_positions(self) -> None:
|
||||||
"""Initialize the lookup table with default values."""
|
"""Initialize the lookup table with default values."""
|
||||||
for frequency in np.arange(
|
for frequency in np.arange(
|
||||||
self.start_frequency, self.stop_frequency + self.frequency_step, self.frequency_step
|
self.start_frequency,
|
||||||
|
self.stop_frequency + self.frequency_step,
|
||||||
|
self.frequency_step,
|
||||||
):
|
):
|
||||||
self.started_frequency = frequency
|
self.started_frequency = frequency
|
||||||
self.add_positions(None, None)
|
self.add_positions(None, None)
|
||||||
|
@ -315,7 +362,7 @@ class MechanicalLookupTable(LookupTable):
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
tuning_position (int): The tuning position for the given frequency.
|
tuning_position (int): The tuning position for the given frequency.
|
||||||
matching_position (int): The matching position for the given frequency.
|
matching_position (int): The matching position for the given frequency.
|
||||||
"""
|
"""
|
||||||
self.data[self.started_frequency] = (tuning_position, matching_position)
|
self.data[self.started_frequency] = (tuning_position, matching_position)
|
||||||
|
|
||||||
|
@ -331,10 +378,11 @@ class MechanicalLookupTable(LookupTable):
|
||||||
entry_number = self.get_entry_number(frequency)
|
entry_number = self.get_entry_number(frequency)
|
||||||
key = list(self.data.keys())[entry_number]
|
key = list(self.data.keys())[entry_number]
|
||||||
return self.data[key]
|
return self.data[key]
|
||||||
|
|
||||||
def is_incomplete(self) -> bool:
|
def is_incomplete(self) -> bool:
|
||||||
"""This method returns True if the lookup table is incomplete,
|
"""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.
|
|
||||||
|
I.e. if there are frequencies for which no the tuning or matching position is none.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
bool: True if the lookup table is incomplete, False otherwise.
|
bool: True if the lookup table is incomplete, False otherwise.
|
||||||
|
@ -345,7 +393,7 @@ class MechanicalLookupTable(LookupTable):
|
||||||
for tuning_position, matching_position in self.data.values()
|
for tuning_position, matching_position in self.data.values()
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
def get_next_frequency(self) -> float:
|
def get_next_frequency(self) -> float:
|
||||||
"""This method returns the next frequency for which the tuning and matching position is not yet set.
|
"""This method returns the next frequency for which the tuning and matching position is not yet set.
|
||||||
|
|
||||||
|
@ -357,8 +405,10 @@ class MechanicalLookupTable(LookupTable):
|
||||||
return frequency
|
return frequency
|
||||||
|
|
||||||
return None
|
return None
|
||||||
class AutoTMModel(ModuleModel):
|
|
||||||
|
|
||||||
|
|
||||||
|
class AutoTMModel(ModuleModel):
|
||||||
|
"""The module model for the NQRduck AutoTM module. It is used to store the data and state of the AutoTM module."""
|
||||||
available_devices_changed = pyqtSignal(list)
|
available_devices_changed = pyqtSignal(list)
|
||||||
serial_changed = pyqtSignal(QSerialPort)
|
serial_changed = pyqtSignal(QSerialPort)
|
||||||
data_points_changed = pyqtSignal(list)
|
data_points_changed = pyqtSignal(list)
|
||||||
|
@ -372,6 +422,7 @@ class AutoTMModel(ModuleModel):
|
||||||
measurement_finished = pyqtSignal(S11Data)
|
measurement_finished = pyqtSignal(S11Data)
|
||||||
|
|
||||||
def __init__(self, module) -> None:
|
def __init__(self, module) -> None:
|
||||||
|
"""Initialize the AutoTM model."""
|
||||||
super().__init__(module)
|
super().__init__(module)
|
||||||
self.data_points = []
|
self.data_points = []
|
||||||
self.active_calibration = None
|
self.active_calibration = None
|
||||||
|
@ -398,6 +449,7 @@ class AutoTMModel(ModuleModel):
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def available_devices(self):
|
def available_devices(self):
|
||||||
|
"""The available_devices property is used to store the available serial devices."""
|
||||||
return self._available_devices
|
return self._available_devices
|
||||||
|
|
||||||
@available_devices.setter
|
@available_devices.setter
|
||||||
|
@ -419,6 +471,7 @@ class AutoTMModel(ModuleModel):
|
||||||
self, frequency: float, return_loss: float, phase: float
|
self, frequency: float, return_loss: float, phase: float
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Add a data point to the model. These data points are our intermediate data points read in via the serial connection.
|
"""Add a data point to the model. These data points are our intermediate data points read in via the serial connection.
|
||||||
|
|
||||||
They will be saved in the according properties later on.
|
They will be saved in the according properties later on.
|
||||||
"""
|
"""
|
||||||
self.data_points.append((frequency, return_loss, phase))
|
self.data_points.append((frequency, return_loss, phase))
|
||||||
|
@ -431,16 +484,21 @@ class AutoTMModel(ModuleModel):
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def saved_positions(self):
|
def saved_positions(self):
|
||||||
|
"""The saved_positions property is used to store the saved positions for tuning and matching of the probeheads."""
|
||||||
return self._saved_positions
|
return self._saved_positions
|
||||||
|
|
||||||
@saved_positions.setter
|
@saved_positions.setter
|
||||||
def saved_positions(self, value):
|
def saved_positions(self, value):
|
||||||
self._saved_positions = value
|
self._saved_positions = value
|
||||||
self.saved_positions_changed.emit(value)
|
self.saved_positions_changed.emit(value)
|
||||||
|
|
||||||
def add_saved_position(self, frequency: float, tuning_position: int, matching_position: int) -> None:
|
def add_saved_position(
|
||||||
|
self, frequency: float, tuning_position: int, matching_position: int
|
||||||
|
) -> None:
|
||||||
"""Add a saved position to the model."""
|
"""Add a saved position to the model."""
|
||||||
self.saved_positions.append(SavedPosition(frequency, tuning_position, matching_position))
|
self.saved_positions.append(
|
||||||
|
SavedPosition(frequency, tuning_position, matching_position)
|
||||||
|
)
|
||||||
self.saved_positions_changed.emit(self.saved_positions)
|
self.saved_positions_changed.emit(self.saved_positions)
|
||||||
|
|
||||||
def delete_saved_position(self, position: SavedPosition) -> None:
|
def delete_saved_position(self, position: SavedPosition) -> None:
|
||||||
|
@ -451,6 +509,7 @@ class AutoTMModel(ModuleModel):
|
||||||
@property
|
@property
|
||||||
def measurement(self):
|
def measurement(self):
|
||||||
"""The measurement property is used to store the current measurement.
|
"""The measurement property is used to store the current measurement.
|
||||||
|
|
||||||
This is the measurement that is shown in the main S11 plot
|
This is the measurement that is shown in the main S11 plot
|
||||||
"""
|
"""
|
||||||
return self._measurement
|
return self._measurement
|
||||||
|
@ -463,8 +522,9 @@ class AutoTMModel(ModuleModel):
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def active_stepper(self):
|
def active_stepper(self):
|
||||||
|
"""The active_stepper property is used to store the active stepper motor."""
|
||||||
return self._active_stepper
|
return self._active_stepper
|
||||||
|
|
||||||
@active_stepper.setter
|
@active_stepper.setter
|
||||||
def active_stepper(self, value):
|
def active_stepper(self, value):
|
||||||
self._active_stepper = value
|
self._active_stepper = value
|
||||||
|
@ -474,6 +534,7 @@ class AutoTMModel(ModuleModel):
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def active_calibration(self):
|
def active_calibration(self):
|
||||||
|
"""The active_calibration property is used to store the active calibration type."""
|
||||||
return self._active_calibration
|
return self._active_calibration
|
||||||
|
|
||||||
@active_calibration.setter
|
@active_calibration.setter
|
||||||
|
@ -482,6 +543,7 @@ class AutoTMModel(ModuleModel):
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def short_calibration(self):
|
def short_calibration(self):
|
||||||
|
"""The short_calibration property is used to store the short calibration data."""
|
||||||
return self._short_calibration
|
return self._short_calibration
|
||||||
|
|
||||||
@short_calibration.setter
|
@short_calibration.setter
|
||||||
|
@ -497,6 +559,7 @@ class AutoTMModel(ModuleModel):
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def open_calibration(self):
|
def open_calibration(self):
|
||||||
|
"""The open calibration data."""
|
||||||
return self._open_calibration
|
return self._open_calibration
|
||||||
|
|
||||||
@open_calibration.setter
|
@open_calibration.setter
|
||||||
|
@ -512,6 +575,7 @@ class AutoTMModel(ModuleModel):
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def load_calibration(self):
|
def load_calibration(self):
|
||||||
|
"""The load calibration data."""
|
||||||
return self._load_calibration
|
return self._load_calibration
|
||||||
|
|
||||||
@load_calibration.setter
|
@load_calibration.setter
|
||||||
|
@ -527,6 +591,7 @@ class AutoTMModel(ModuleModel):
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def calibration(self):
|
def calibration(self):
|
||||||
|
"""The calibration data."""
|
||||||
return self._calibration
|
return self._calibration
|
||||||
|
|
||||||
@calibration.setter
|
@calibration.setter
|
||||||
|
@ -536,6 +601,7 @@ class AutoTMModel(ModuleModel):
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def LUT(self):
|
def LUT(self):
|
||||||
|
"""The lookup table for tuning and matching of the probeheads."""
|
||||||
return self._LUT
|
return self._LUT
|
||||||
|
|
||||||
@LUT.setter
|
@LUT.setter
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
"""This module contains the view class for the AutoTM module."""
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
import cmath
|
import cmath
|
||||||
|
@ -27,7 +29,9 @@ logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class AutoTMView(ModuleView):
|
class AutoTMView(ModuleView):
|
||||||
|
"""The view class for the AutoTM module."""
|
||||||
def __init__(self, module):
|
def __init__(self, module):
|
||||||
|
"""Initializes the AutoTM view."""
|
||||||
super().__init__(module)
|
super().__init__(module)
|
||||||
|
|
||||||
widget = QWidget()
|
widget = QWidget()
|
||||||
|
@ -127,11 +131,27 @@ class AutoTMView(ModuleView):
|
||||||
self._ui_form.startButton.setIconSize(self._ui_form.startButton.size())
|
self._ui_form.startButton.setIconSize(self._ui_form.startButton.size())
|
||||||
|
|
||||||
# Stepper selection
|
# Stepper selection
|
||||||
self._ui_form.stepperselectBox.currentIndexChanged.connect(lambda: self.module.controller.on_stepper_changed(self._ui_form.stepperselectBox.currentText()))
|
self._ui_form.stepperselectBox.currentIndexChanged.connect(
|
||||||
self._ui_form.increaseButton.clicked.connect(lambda: self.module.controller.on_relative_move(self._ui_form.stepsizeBox.text()))
|
lambda: self.module.controller.on_stepper_changed(
|
||||||
self._ui_form.decreaseButton.clicked.connect(lambda: self.module.controller.on_relative_move("-" + self._ui_form.stepsizeBox.text()))
|
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()))
|
self._ui_form.absoluteGoButton.clicked.connect(
|
||||||
|
lambda: self.module.controller.on_absolute_move(
|
||||||
|
self._ui_form.absoluteposBox.text()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
# Active stepper changed
|
# Active stepper changed
|
||||||
self.module.model.active_stepper_changed.connect(self.on_active_stepper_changed)
|
self.module.model.active_stepper_changed.connect(self.on_active_stepper_changed)
|
||||||
|
@ -175,6 +195,7 @@ class AutoTMView(ModuleView):
|
||||||
|
|
||||||
def on_calibration_button_clicked(self) -> None:
|
def on_calibration_button_clicked(self) -> None:
|
||||||
"""This method is called when the calibration button is clicked.
|
"""This method is called when the calibration button is clicked.
|
||||||
|
|
||||||
It opens the calibration window.
|
It opens the calibration window.
|
||||||
"""
|
"""
|
||||||
logger.debug("Calibration button clicked")
|
logger.debug("Calibration button clicked")
|
||||||
|
@ -183,7 +204,11 @@ class AutoTMView(ModuleView):
|
||||||
|
|
||||||
@pyqtSlot(list)
|
@pyqtSlot(list)
|
||||||
def on_available_devices_changed(self, available_devices: list) -> None:
|
def on_available_devices_changed(self, available_devices: list) -> None:
|
||||||
"""Update the available devices list in the view."""
|
"""Update the available devices list in the view.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
available_devices (list): List of available devices.
|
||||||
|
"""
|
||||||
logger.debug("Updating available devices list")
|
logger.debug("Updating available devices list")
|
||||||
self._ui_form.portBox.clear()
|
self._ui_form.portBox.clear()
|
||||||
self._ui_form.portBox.addItems(available_devices)
|
self._ui_form.portBox.addItems(available_devices)
|
||||||
|
@ -201,6 +226,7 @@ class AutoTMView(ModuleView):
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
def on_connect_button_clicked(self) -> None:
|
def on_connect_button_clicked(self) -> None:
|
||||||
"""This method is called when the connect button is clicked.
|
"""This method is called when the connect button is clicked.
|
||||||
|
|
||||||
It calls the connect method of the controller with the currently selected device.
|
It calls the connect method of the controller with the currently selected device.
|
||||||
"""
|
"""
|
||||||
logger.debug("Connect button clicked")
|
logger.debug("Connect button clicked")
|
||||||
|
@ -217,7 +243,7 @@ class AutoTMView(ModuleView):
|
||||||
logger.debug("Updating serial connection label")
|
logger.debug("Updating serial connection label")
|
||||||
if serial.isOpen():
|
if serial.isOpen():
|
||||||
self._ui_form.connectionLabel.setText(serial.portName())
|
self._ui_form.connectionLabel.setText(serial.portName())
|
||||||
self.add_info_text("Connected to device %s" % serial.portName())
|
self.add_info_text(f"Connected to device {serial.portName()}")
|
||||||
# Change the connectButton to a disconnectButton
|
# Change the connectButton to a disconnectButton
|
||||||
self._ui_form.connectButton.setText("Disconnect")
|
self._ui_form.connectButton.setText("Disconnect")
|
||||||
else:
|
else:
|
||||||
|
@ -231,7 +257,9 @@ class AutoTMView(ModuleView):
|
||||||
def on_active_stepper_changed(self) -> None:
|
def on_active_stepper_changed(self) -> None:
|
||||||
"""Update the stepper position label according to the current stepper position."""
|
"""Update the stepper position label according to the current stepper position."""
|
||||||
logger.debug("Updating stepper position label")
|
logger.debug("Updating stepper position label")
|
||||||
self._ui_form.stepperposLabel.setText(str(self.module.model.active_stepper.position))
|
self._ui_form.stepperposLabel.setText(
|
||||||
|
str(self.module.model.active_stepper.position)
|
||||||
|
)
|
||||||
logger.debug("Updated stepper position label")
|
logger.debug("Updated stepper position label")
|
||||||
|
|
||||||
# Only allow position change when stepper is homed
|
# Only allow position change when stepper is homed
|
||||||
|
@ -253,6 +281,7 @@ class AutoTMView(ModuleView):
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
def on_position_button_clicked(self) -> None:
|
def on_position_button_clicked(self) -> None:
|
||||||
"""This method is called when the position button is clicked.
|
"""This method is called when the position button is clicked.
|
||||||
|
|
||||||
It opens the position window.
|
It opens the position window.
|
||||||
"""
|
"""
|
||||||
logger.debug("Position button clicked")
|
logger.debug("Position button clicked")
|
||||||
|
@ -263,7 +292,7 @@ class AutoTMView(ModuleView):
|
||||||
"""Update the S11 plot with the current data points.
|
"""Update the S11 plot with the current data points.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
data_points (list): List of data points to plot.
|
data (S11Data): The current S11 data points.
|
||||||
|
|
||||||
@TODO: implement proper calibration. See the controller class for more information.
|
@TODO: implement proper calibration. See the controller class for more information.
|
||||||
"""
|
"""
|
||||||
|
@ -328,7 +357,7 @@ class AutoTMView(ModuleView):
|
||||||
"""
|
"""
|
||||||
# Add a timestamp to the text
|
# Add a timestamp to the text
|
||||||
timestamp = datetime.now().strftime("%H:%M:%S")
|
timestamp = datetime.now().strftime("%H:%M:%S")
|
||||||
text = "[%s] %s" % (timestamp, text)
|
text = f"[{timestamp}] {text}"
|
||||||
text_label = QLabel(text)
|
text_label = QLabel(text)
|
||||||
text_label.setStyleSheet("font-size: 25px;")
|
text_label.setStyleSheet("font-size: 25px;")
|
||||||
self._ui_form.scrollAreaWidgetContents.layout().addWidget(text_label)
|
self._ui_form.scrollAreaWidgetContents.layout().addWidget(text_label)
|
||||||
|
@ -351,7 +380,7 @@ class AutoTMView(ModuleView):
|
||||||
)
|
)
|
||||||
# Add a timestamp to the text
|
# Add a timestamp to the text
|
||||||
timestamp = datetime.now().strftime("%H:%M:%S")
|
timestamp = datetime.now().strftime("%H:%M:%S")
|
||||||
text = "[%s] %s" % (timestamp, text)
|
text = f"[{timestamp}] {text}"
|
||||||
text_label = QLabel(text)
|
text_label = QLabel(text)
|
||||||
text_label.setStyleSheet("font-size: 25px; color: red;")
|
text_label.setStyleSheet("font-size: 25px; color: red;")
|
||||||
|
|
||||||
|
@ -365,7 +394,9 @@ class AutoTMView(ModuleView):
|
||||||
|
|
||||||
def create_frequency_sweep_spinner_dialog(self) -> None:
|
def create_frequency_sweep_spinner_dialog(self) -> None:
|
||||||
"""Creates a frequency sweep spinner dialog."""
|
"""Creates a frequency sweep spinner dialog."""
|
||||||
self.frequency_sweep_spinner = self.LoadingSpinner("Performing frequency sweep ...", self)
|
self.frequency_sweep_spinner = self.LoadingSpinner(
|
||||||
|
"Performing frequency sweep ...", self
|
||||||
|
)
|
||||||
self.frequency_sweep_spinner.show()
|
self.frequency_sweep_spinner.show()
|
||||||
|
|
||||||
def create_el_LUT_spinner_dialog(self) -> None:
|
def create_el_LUT_spinner_dialog(self) -> None:
|
||||||
|
@ -375,7 +406,9 @@ class AutoTMView(ModuleView):
|
||||||
|
|
||||||
def create_mech_LUT_spinner_dialog(self) -> None:
|
def create_mech_LUT_spinner_dialog(self) -> None:
|
||||||
"""Creates a mechanical LUT spinner dialog."""
|
"""Creates a mechanical LUT spinner dialog."""
|
||||||
self.mech_LUT_spinner = self.LoadingSpinner("Generating mechanical LUT ...", self)
|
self.mech_LUT_spinner = self.LoadingSpinner(
|
||||||
|
"Generating mechanical LUT ...", self
|
||||||
|
)
|
||||||
self.mech_LUT_spinner.show()
|
self.mech_LUT_spinner.show()
|
||||||
|
|
||||||
def view_el_lut(self) -> None:
|
def view_el_lut(self) -> None:
|
||||||
|
@ -417,7 +450,9 @@ class AutoTMView(ModuleView):
|
||||||
self.module.controller.load_measurement(file_name)
|
self.module.controller.load_measurement(file_name)
|
||||||
|
|
||||||
class StepperSavedPositionsWindow(QDialog):
|
class StepperSavedPositionsWindow(QDialog):
|
||||||
|
"""This class implements a window that shows the saved positions of the stepper."""
|
||||||
def __init__(self, module, parent=None):
|
def __init__(self, module, parent=None):
|
||||||
|
"""Initializes the StepperSavedPositionsWindow."""
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
self.setParent(parent)
|
self.setParent(parent)
|
||||||
self.module = module
|
self.module = module
|
||||||
|
@ -432,7 +467,13 @@ class AutoTMView(ModuleView):
|
||||||
self.table_widget = QTableWidget()
|
self.table_widget = QTableWidget()
|
||||||
self.table_widget.setColumnCount(5)
|
self.table_widget.setColumnCount(5)
|
||||||
self.table_widget.setHorizontalHeaderLabels(
|
self.table_widget.setHorizontalHeaderLabels(
|
||||||
["Frequency (MHz)", "Tuning Position", "Matching Position", "Button", "Delete"]
|
[
|
||||||
|
"Frequency (MHz)",
|
||||||
|
"Tuning Position",
|
||||||
|
"Matching Position",
|
||||||
|
"Button",
|
||||||
|
"Delete",
|
||||||
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
self.table_widget.setColumnWidth(0, 150)
|
self.table_widget.setColumnWidth(0, 150)
|
||||||
|
@ -461,8 +502,9 @@ class AutoTMView(ModuleView):
|
||||||
main_layout.addWidget(self.table_widget)
|
main_layout.addWidget(self.table_widget)
|
||||||
|
|
||||||
# On saved positions changed
|
# On saved positions changed
|
||||||
self.module.model.saved_positions_changed.connect(self.on_saved_positions_changed)
|
self.module.model.saved_positions_changed.connect(
|
||||||
|
self.on_saved_positions_changed
|
||||||
|
)
|
||||||
|
|
||||||
self.setLayout(main_layout)
|
self.setLayout(main_layout)
|
||||||
|
|
||||||
|
@ -482,13 +524,13 @@ class AutoTMView(ModuleView):
|
||||||
def on_load_position_button_clicked(self) -> None:
|
def on_load_position_button_clicked(self) -> None:
|
||||||
"""File picker for loading a position from a file."""
|
"""File picker for loading a position from a file."""
|
||||||
filename = self.file_selector("load")
|
filename = self.file_selector("load")
|
||||||
logger.debug("Loading position from %s" % filename)
|
logger.debug(f"Loading position from {filename}")
|
||||||
self.module.controller.load_positions(filename)
|
self.module.controller.load_positions(filename)
|
||||||
|
|
||||||
def on_save_position_button_clicked(self) -> None:
|
def on_save_position_button_clicked(self) -> None:
|
||||||
"""File picker for saving a position to a file."""
|
"""File picker for saving a position to a file."""
|
||||||
filename = self.file_selector("save")
|
filename = self.file_selector("save")
|
||||||
logger.debug("Saving position to %s" % filename)
|
logger.debug(f"Saving position to {filename}")
|
||||||
self.module.controller.save_positions(filename)
|
self.module.controller.save_positions(filename)
|
||||||
|
|
||||||
def on_new_position_button_clicked(self) -> None:
|
def on_new_position_button_clicked(self) -> None:
|
||||||
|
@ -497,9 +539,9 @@ class AutoTMView(ModuleView):
|
||||||
self.new_position_window = self.NewPositionWindow(self.module, self)
|
self.new_position_window = self.NewPositionWindow(self.module, self)
|
||||||
self.new_position_window.show()
|
self.new_position_window.show()
|
||||||
|
|
||||||
|
|
||||||
def on_saved_positions_changed(self) -> None:
|
def on_saved_positions_changed(self) -> None:
|
||||||
"""This method is called when the saved positions changed.
|
"""This method is called when the saved positions changed.
|
||||||
|
|
||||||
It updates the table widget.
|
It updates the table widget.
|
||||||
"""
|
"""
|
||||||
logger.debug("Updating saved positions table")
|
logger.debug("Updating saved positions table")
|
||||||
|
@ -508,7 +550,9 @@ class AutoTMView(ModuleView):
|
||||||
|
|
||||||
for row, position in enumerate(self.module.model.saved_positions):
|
for row, position in enumerate(self.module.model.saved_positions):
|
||||||
self.table_widget.insertRow(row)
|
self.table_widget.insertRow(row)
|
||||||
self.table_widget.setItem(row, 0, QTableWidgetItem(str(position.frequency)))
|
self.table_widget.setItem(
|
||||||
|
row, 0, QTableWidgetItem(str(position.frequency))
|
||||||
|
)
|
||||||
self.table_widget.setItem(
|
self.table_widget.setItem(
|
||||||
row, 1, QTableWidgetItem(position.tuning_position)
|
row, 1, QTableWidgetItem(position.tuning_position)
|
||||||
)
|
)
|
||||||
|
@ -517,7 +561,8 @@ class AutoTMView(ModuleView):
|
||||||
)
|
)
|
||||||
go_button = QPushButton("Go")
|
go_button = QPushButton("Go")
|
||||||
go_button.clicked.connect(
|
go_button.clicked.connect(
|
||||||
lambda _, position=position: self.module.controller.on_go_to_position(
|
lambda _,
|
||||||
|
position=position: self.module.controller.on_go_to_position(
|
||||||
position
|
position
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
@ -525,16 +570,19 @@ class AutoTMView(ModuleView):
|
||||||
|
|
||||||
delete_button = QPushButton("Delete")
|
delete_button = QPushButton("Delete")
|
||||||
delete_button.clicked.connect(
|
delete_button.clicked.connect(
|
||||||
lambda _, position=position: self.module.controller.on_delete_position(
|
lambda _,
|
||||||
|
position=position: self.module.controller.on_delete_position(
|
||||||
position
|
position
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
self.table_widget.setCellWidget(row, 4, delete_button)
|
self.table_widget.setCellWidget(row, 4, delete_button)
|
||||||
|
|
||||||
logger.debug("Updated saved positions table")
|
logger.debug("Updated saved positions table")
|
||||||
|
|
||||||
class NewPositionWindow(QDialog):
|
class NewPositionWindow(QDialog):
|
||||||
|
"""This class implements a window for adding a new position."""
|
||||||
def __init__(self, module, parent=None):
|
def __init__(self, module, parent=None):
|
||||||
|
"""Initializes the NewPositionWindow."""
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
self.setParent(parent)
|
self.setParent(parent)
|
||||||
self.module = module
|
self.module = module
|
||||||
|
@ -578,22 +626,32 @@ class AutoTMView(ModuleView):
|
||||||
data_layout = QVBoxLayout()
|
data_layout = QVBoxLayout()
|
||||||
# Apply button
|
# Apply button
|
||||||
apply_button = QPushButton("Apply")
|
apply_button = QPushButton("Apply")
|
||||||
apply_button.clicked.connect(lambda: self.on_apply_button_clicked(frequency_edit.text(), tuning_edit.text(), matching_edit.text()))
|
apply_button.clicked.connect(
|
||||||
|
lambda: self.on_apply_button_clicked(
|
||||||
|
frequency_edit.text(), tuning_edit.text(), matching_edit.text()
|
||||||
|
)
|
||||||
|
)
|
||||||
data_layout.addWidget(apply_button)
|
data_layout.addWidget(apply_button)
|
||||||
|
|
||||||
main_layout.addLayout(data_layout)
|
main_layout.addLayout(data_layout)
|
||||||
|
|
||||||
self.setLayout(main_layout)
|
self.setLayout(main_layout)
|
||||||
|
|
||||||
def on_apply_button_clicked(self, frequency: str, tuning_position: str, matching_position: str) -> None:
|
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."""
|
"""This method is called when the apply button is clicked."""
|
||||||
self.module.controller.add_position(frequency, tuning_position, matching_position)
|
self.module.controller.add_position(
|
||||||
|
frequency, tuning_position, matching_position
|
||||||
|
)
|
||||||
# Close the calibration window
|
# Close the calibration window
|
||||||
self.close()
|
self.close()
|
||||||
|
|
||||||
class LoadingSpinner(QDialog):
|
class LoadingSpinner(QDialog):
|
||||||
"""This class implements a spinner dialog that is shown during a frequency sweep."""
|
"""This class implements a spinner dialog that is shown during a frequency sweep."""
|
||||||
|
|
||||||
def __init__(self, text : str, parent=None):
|
def __init__(self, text: str, parent=None):
|
||||||
|
"""Initializes the LoadingSpinner."""
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
self.setWindowTitle("Loading")
|
self.setWindowTitle("Loading")
|
||||||
self.setModal(True)
|
self.setModal(True)
|
||||||
|
@ -611,7 +669,9 @@ class AutoTMView(ModuleView):
|
||||||
self.spinner_movie.start()
|
self.spinner_movie.start()
|
||||||
|
|
||||||
class LutWindow(QDialog):
|
class LutWindow(QDialog):
|
||||||
|
"""This class implements a window that shows the LUT."""
|
||||||
def __init__(self, module, parent=None):
|
def __init__(self, module, parent=None):
|
||||||
|
"""Initializes the LutWindow."""
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.module = module
|
self.module = module
|
||||||
self.setParent(parent)
|
self.setParent(parent)
|
||||||
|
@ -641,7 +701,7 @@ class AutoTMView(ModuleView):
|
||||||
self.table_widget.setHorizontalHeaderLabels(
|
self.table_widget.setHorizontalHeaderLabels(
|
||||||
["Frequency (MHz)", "Tuning Voltage", "Matching Voltage"]
|
["Frequency (MHz)", "Tuning Voltage", "Matching Voltage"]
|
||||||
)
|
)
|
||||||
|
|
||||||
for row, frequency in enumerate(LUT.data.keys()):
|
for row, frequency in enumerate(LUT.data.keys()):
|
||||||
self.table_widget.insertRow(row)
|
self.table_widget.insertRow(row)
|
||||||
self.table_widget.setItem(row, 0, QTableWidgetItem(str(frequency)))
|
self.table_widget.setItem(row, 0, QTableWidgetItem(str(frequency)))
|
||||||
|
@ -659,7 +719,9 @@ class AutoTMView(ModuleView):
|
||||||
tuning_voltage = str(LUT.data[frequency][0])
|
tuning_voltage = str(LUT.data[frequency][0])
|
||||||
matching_voltage = str(LUT.data[frequency][1])
|
matching_voltage = str(LUT.data[frequency][1])
|
||||||
test_button.clicked.connect(
|
test_button.clicked.connect(
|
||||||
lambda _, tuning_voltage=tuning_voltage, matching_voltage=matching_voltage: self.module.controller.set_voltages(
|
lambda _,
|
||||||
|
tuning_voltage=tuning_voltage,
|
||||||
|
matching_voltage=matching_voltage: self.module.controller.set_voltages(
|
||||||
tuning_voltage, matching_voltage
|
tuning_voltage, matching_voltage
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
@ -668,11 +730,13 @@ class AutoTMView(ModuleView):
|
||||||
tuning_position = str(LUT.data[frequency][0])
|
tuning_position = str(LUT.data[frequency][0])
|
||||||
matching_position = str(LUT.data[frequency][1])
|
matching_position = str(LUT.data[frequency][1])
|
||||||
test_button.clicked.connect(
|
test_button.clicked.connect(
|
||||||
lambda _, tuning_position=tuning_position, matching_position=matching_position: self.module.controller.go_to_position(
|
lambda _,
|
||||||
|
tuning_position=tuning_position,
|
||||||
|
matching_position=matching_position: self.module.controller.go_to_position(
|
||||||
tuning_position, matching_position
|
tuning_position, matching_position
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
self.table_widget.setCellWidget(row, 3, test_button)
|
self.table_widget.setCellWidget(row, 3, test_button)
|
||||||
|
|
||||||
# Add table widget to main layout
|
# Add table widget to main layout
|
||||||
|
@ -681,6 +745,7 @@ class AutoTMView(ModuleView):
|
||||||
|
|
||||||
def test_lut(self):
|
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.
|
"""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.
|
One can then view the matching on a seperate VNA.
|
||||||
"""
|
"""
|
||||||
# This should be in the controller
|
# This should be in the controller
|
||||||
|
@ -690,7 +755,9 @@ class AutoTMView(ModuleView):
|
||||||
self.module.controller.set_voltages(tuning_voltage, matching_voltage)
|
self.module.controller.set_voltages(tuning_voltage, matching_voltage)
|
||||||
|
|
||||||
class CalibrationWindow(QDialog):
|
class CalibrationWindow(QDialog):
|
||||||
|
"""The calibration Dialog."""
|
||||||
def __init__(self, module, parent=None):
|
def __init__(self, module, parent=None):
|
||||||
|
"""Initializes the CalibrationWindow."""
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
self.setParent(parent)
|
self.setParent(parent)
|
||||||
self.module = module
|
self.module = module
|
||||||
|
@ -791,18 +858,22 @@ class AutoTMView(ModuleView):
|
||||||
)
|
)
|
||||||
|
|
||||||
def on_short_calibration_finished(self, short_calibration: "S11Data") -> None:
|
def on_short_calibration_finished(self, short_calibration: "S11Data") -> None:
|
||||||
|
"""This method is called when the short calibration has finished. It plots the calibration data on the short_plot widget."""
|
||||||
self.on_calibration_finished("short", self.short_plot, short_calibration)
|
self.on_calibration_finished("short", self.short_plot, short_calibration)
|
||||||
|
|
||||||
def on_open_calibration_finished(self, open_calibration: "S11Data") -> None:
|
def on_open_calibration_finished(self, open_calibration: "S11Data") -> None:
|
||||||
|
"""This method is called when the open calibration has finished. It plots the calibration data on the open_plot widget."""
|
||||||
self.on_calibration_finished("open", self.open_plot, open_calibration)
|
self.on_calibration_finished("open", self.open_plot, open_calibration)
|
||||||
|
|
||||||
def on_load_calibration_finished(self, load_calibration: "S11Data") -> None:
|
def on_load_calibration_finished(self, load_calibration: "S11Data") -> None:
|
||||||
|
"""This method is called when the load calibration has finished. It plots the calibration data on the load_plot widget."""
|
||||||
self.on_calibration_finished("load", self.load_plot, load_calibration)
|
self.on_calibration_finished("load", self.load_plot, load_calibration)
|
||||||
|
|
||||||
def on_calibration_finished(
|
def on_calibration_finished(
|
||||||
self, type: str, widget: MplWidget, data: "S11Data"
|
self, type: str, widget: MplWidget, data: "S11Data"
|
||||||
) -> None:
|
) -> None:
|
||||||
"""This method is called when a calibration has finished.
|
"""This method is called when a calibration has finished.
|
||||||
|
|
||||||
It plots the calibration data on the given widget.
|
It plots the calibration data on the given widget.
|
||||||
"""
|
"""
|
||||||
frequency = data.frequency
|
frequency = data.frequency
|
||||||
|
@ -829,13 +900,14 @@ class AutoTMView(ModuleView):
|
||||||
widget.canvas.flush_events()
|
widget.canvas.flush_events()
|
||||||
|
|
||||||
def on_export_button_clicked(self) -> None:
|
def on_export_button_clicked(self) -> None:
|
||||||
|
"""Called when the export button was clicked."""
|
||||||
filedialog = QFileDialog()
|
filedialog = QFileDialog()
|
||||||
filedialog.setAcceptMode(QFileDialog.AcceptMode.AcceptSave)
|
filedialog.setAcceptMode(QFileDialog.AcceptMode.AcceptSave)
|
||||||
filedialog.setNameFilter("calibration files (*.cal)")
|
filedialog.setNameFilter("calibration files (*.cal)")
|
||||||
filedialog.setDefaultSuffix("cal")
|
filedialog.setDefaultSuffix("cal")
|
||||||
filedialog.exec()
|
filedialog.exec()
|
||||||
filename = filedialog.selectedFiles()[0]
|
filename = filedialog.selectedFiles()[0]
|
||||||
logger.debug("Exporting calibration to %s" % filename)
|
logger.debug(f"Exporting calibration to {filename}")
|
||||||
self.module.controller.export_calibration(filename)
|
self.module.controller.export_calibration(filename)
|
||||||
|
|
||||||
def on_import_button_clicked(self) -> None:
|
def on_import_button_clicked(self) -> None:
|
||||||
|
@ -846,7 +918,7 @@ class AutoTMView(ModuleView):
|
||||||
filedialog.setDefaultSuffix("cal")
|
filedialog.setDefaultSuffix("cal")
|
||||||
filedialog.exec()
|
filedialog.exec()
|
||||||
filename = filedialog.selectedFiles()[0]
|
filename = filedialog.selectedFiles()[0]
|
||||||
logger.debug("Importing calibration from %s" % filename)
|
logger.debug(f"Importing calibration from {filename}")
|
||||||
self.module.controller.import_calibration(filename)
|
self.module.controller.import_calibration(filename)
|
||||||
|
|
||||||
def on_apply_button_clicked(self) -> None:
|
def on_apply_button_clicked(self) -> None:
|
||||||
|
|
Loading…
Reference in a new issue