mirror of
https://github.com/nqrduck/nqrduck-spectrometer.git
synced 2024-12-22 08:17:49 +00:00
commit
cb5df0a9af
3 changed files with 174 additions and 50 deletions
|
@ -2,6 +2,7 @@ import logging
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
from PyQt6.QtCore import pyqtSlot, pyqtSignal, QObject
|
from PyQt6.QtCore import pyqtSlot, pyqtSignal, QObject
|
||||||
from nqrduck.module.module_model import ModuleModel
|
from nqrduck.module.module_model import ModuleModel
|
||||||
|
from.settings import Setting
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
@ -18,35 +19,7 @@ class BaseSpectrometerModel(ModuleModel):
|
||||||
"""
|
"""
|
||||||
settings : OrderedDict
|
settings : OrderedDict
|
||||||
pulse_parameter_options : OrderedDict
|
pulse_parameter_options : OrderedDict
|
||||||
|
|
||||||
class Setting(QObject):
|
|
||||||
"""A setting for the spectrometer is a value that is the same for all events in a pulse sequence.
|
|
||||||
E.g. the number of averages or the number of points in a spectrum.
|
|
||||||
"""
|
|
||||||
settings_changed = pyqtSignal()
|
|
||||||
|
|
||||||
def __init__(self, name : str, default : str, description : str) -> None:
|
|
||||||
"""Initializes the setting.
|
|
||||||
|
|
||||||
Arguments:
|
|
||||||
name (str) -- The name of the setting
|
|
||||||
default (str) -- The default value of the setting
|
|
||||||
description (str) -- The description of the setting
|
|
||||||
"""
|
|
||||||
super().__init__()
|
|
||||||
self.name = name
|
|
||||||
self.value = default
|
|
||||||
self.description = description
|
|
||||||
|
|
||||||
@pyqtSlot(str)
|
|
||||||
def on_value_changed(self, value):
|
|
||||||
logger.debug("Setting %s changed to %s", self.name, value)
|
|
||||||
self.value = value
|
|
||||||
self.settings_changed.emit()
|
|
||||||
|
|
||||||
def get_setting(self):
|
|
||||||
return float(self.value)
|
|
||||||
|
|
||||||
class PulseParameter:
|
class PulseParameter:
|
||||||
"""A pulse parameter is a value that can be different for each event in a pulse sequence.
|
"""A pulse parameter is a value that can be different for each event in a pulse sequence.
|
||||||
E.g. the transmit pulse power or the phase of the transmit pulse.
|
E.g. the transmit pulse power or the phase of the transmit pulse.
|
||||||
|
@ -115,18 +88,11 @@ class BaseSpectrometerModel(ModuleModel):
|
||||||
self.settings = OrderedDict()
|
self.settings = OrderedDict()
|
||||||
self.pulse_parameter_options = OrderedDict()
|
self.pulse_parameter_options = OrderedDict()
|
||||||
|
|
||||||
def add_setting(self, name : str, value: str, description : str, category : str) -> None:
|
def add_setting(self, setting : Setting, category : str) -> None:
|
||||||
"""Adds a setting to the spectrometer.
|
|
||||||
|
|
||||||
Arguments:
|
|
||||||
name (str) -- The name of the setting
|
|
||||||
value (str) -- The default value of the setting
|
|
||||||
description (str) -- The description of the setting
|
|
||||||
category (str) -- The category of the setting
|
|
||||||
"""
|
|
||||||
if category not in self.settings.keys():
|
if category not in self.settings.keys():
|
||||||
self.settings[category] = []
|
self.settings[category] = []
|
||||||
self.settings[category].append(self.Setting(name, value, description))
|
self.settings[category].append(setting)
|
||||||
|
|
||||||
def get_setting_by_name(self, name : str) -> Setting:
|
def get_setting_by_name(self, name : str) -> Setting:
|
||||||
"""Gets a setting by its name.
|
"""Gets a setting by its name.
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
import logging
|
import logging
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from PyQt6.QtWidgets import QWidget, QLabel, QLineEdit, QHBoxLayout, QSizePolicy, QSpacerItem, QVBoxLayout
|
from PyQt6.QtWidgets import QWidget, QLabel, QLineEdit, QHBoxLayout, QSizePolicy, QSpacerItem, QVBoxLayout, QCheckBox, QComboBox
|
||||||
from PyQt6.QtGui import QIcon
|
from PyQt6.QtGui import QIcon
|
||||||
from PyQt6.QtCore import Qt, pyqtSlot
|
from PyQt6.QtCore import Qt, pyqtSlot
|
||||||
from nqrduck.module.module_view import ModuleView
|
from nqrduck.module.module_view import ModuleView
|
||||||
from nqrduck.assets.icons import Logos
|
from nqrduck.assets.icons import Logos
|
||||||
|
from .settings import FloatSetting, IntSetting, BooleanSetting, SelectionSetting, StringSetting
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
@ -46,18 +47,31 @@ class BaseSpectrometerView(ModuleView):
|
||||||
category_layout.addWidget(category_label)
|
category_layout.addWidget(category_label)
|
||||||
for setting in self.module.model.settings[category]:
|
for setting in self.module.model.settings[category]:
|
||||||
logger.debug("Adding setting to settings view: %s", setting.name)
|
logger.debug("Adding setting to settings view: %s", setting.name)
|
||||||
|
|
||||||
spacer = QSpacerItem(20, 20)
|
spacer = QSpacerItem(20, 20)
|
||||||
# Create a label for the setting
|
# Create a label for the setting
|
||||||
setting_label = QLabel(setting.name)
|
setting_label = QLabel(setting.name)
|
||||||
setting_label.setMinimumWidth(200)
|
setting_label.setMinimumWidth(200)
|
||||||
# Add an QLineEdit for the setting
|
|
||||||
line_edit = QLineEdit(str(setting.value))
|
# Depending on the setting type we add different widgets to the view
|
||||||
line_edit.setMinimumWidth(100)
|
if isinstance(setting, FloatSetting) or isinstance(setting, IntSetting) or isinstance(setting, StringSetting):
|
||||||
# Add a horizontal layout for the setting
|
edit_widget = QLineEdit(str(setting.value))
|
||||||
layout = QHBoxLayout()
|
edit_widget.setMinimumWidth(100)
|
||||||
# Connect the editingFinished signal to the on_value_changed slot of the setting
|
# Connect the editingFinished signal to the on_value_changed slot of the setting
|
||||||
line_edit.editingFinished.connect(lambda x=line_edit, s=setting: s.on_value_changed(x.text()))
|
edit_widget.editingFinished.connect(lambda x=edit_widget, s=setting: s.on_value_changed(x.text()))
|
||||||
|
|
||||||
|
elif isinstance(setting, BooleanSetting):
|
||||||
|
edit_widget = QCheckBox()
|
||||||
|
edit_widget.setChecked(setting.value)
|
||||||
|
edit_widget.stateChanged.connect(lambda x=edit_widget, s=setting: s.on_value_changed(x))
|
||||||
|
|
||||||
|
elif isinstance(setting, SelectionSetting):
|
||||||
|
edit_widget = QComboBox()
|
||||||
|
edit_widget.addItems(setting.options)
|
||||||
|
edit_widget.setCurrentText(setting.value)
|
||||||
|
edit_widget.currentTextChanged.connect(lambda x=edit_widget, s=setting: s.on_value_changed(x))
|
||||||
|
|
||||||
|
|
||||||
# Add a icon that can be used as a tooltip
|
# Add a icon that can be used as a tooltip
|
||||||
if setting.description is not None:
|
if setting.description is not None:
|
||||||
logger.debug("Adding tooltip to setting: %s", setting.name)
|
logger.debug("Adding tooltip to setting: %s", setting.name)
|
||||||
|
@ -68,11 +82,13 @@ class BaseSpectrometerView(ModuleView):
|
||||||
icon_label.setFixedSize(icon.availableSizes()[0])
|
icon_label.setFixedSize(icon.availableSizes()[0])
|
||||||
|
|
||||||
icon_label.setToolTip(setting.description)
|
icon_label.setToolTip(setting.description)
|
||||||
|
|
||||||
|
# Add a horizontal layout for the setting
|
||||||
|
layout = QHBoxLayout()
|
||||||
# Add the label and the line edit to the layout
|
# Add the label and the line edit to the layout
|
||||||
layout.addItem(spacer)
|
layout.addItem(spacer)
|
||||||
layout.addWidget(setting_label)
|
layout.addWidget(setting_label)
|
||||||
layout.addWidget(line_edit)
|
layout.addWidget(edit_widget)
|
||||||
layout.addWidget(icon_label)
|
layout.addWidget(icon_label)
|
||||||
layout.addStretch(1)
|
layout.addStretch(1)
|
||||||
# Add the layout to the vertical layout of the widget
|
# Add the layout to the vertical layout of the widget
|
||||||
|
@ -84,4 +100,5 @@ class BaseSpectrometerView(ModuleView):
|
||||||
|
|
||||||
# Push all the settings to the top of the widget
|
# Push all the settings to the top of the widget
|
||||||
self._ui_form.verticalLayout.addStretch(1)
|
self._ui_form.verticalLayout.addStretch(1)
|
||||||
|
|
||||||
|
|
141
src/nqrduck_spectrometer/settings.py
Normal file
141
src/nqrduck_spectrometer/settings.py
Normal file
|
@ -0,0 +1,141 @@
|
||||||
|
import logging
|
||||||
|
import ipaddress
|
||||||
|
from PyQt6.QtCore import QObject, pyqtSignal, pyqtSlot
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
class Setting(QObject):
|
||||||
|
"""A setting for the spectrometer is a value that is the same for all events in a pulse sequence.
|
||||||
|
E.g. the number of averages or the number of points in a spectrum."""
|
||||||
|
settings_changed = pyqtSignal()
|
||||||
|
|
||||||
|
def __init__(self, name, description) -> None:
|
||||||
|
super().__init__()
|
||||||
|
self.name = name
|
||||||
|
self.description = description
|
||||||
|
|
||||||
|
@pyqtSlot(str)
|
||||||
|
def on_value_changed(self, value):
|
||||||
|
logger.debug("Setting %s changed to %s", self.name, value)
|
||||||
|
self.value = value
|
||||||
|
self.settings_changed.emit()
|
||||||
|
|
||||||
|
def get_setting(self):
|
||||||
|
return float(self.value)
|
||||||
|
|
||||||
|
class FloatSetting(Setting):
|
||||||
|
""" A setting that is a Float. """
|
||||||
|
def __init__(self, name : str, default : float, description : str) -> None:
|
||||||
|
super().__init__(name, description)
|
||||||
|
self.value = default
|
||||||
|
|
||||||
|
@property
|
||||||
|
def value(self):
|
||||||
|
return self._value
|
||||||
|
|
||||||
|
@value.setter
|
||||||
|
def value(self, value):
|
||||||
|
try:
|
||||||
|
self._value = float(value)
|
||||||
|
except ValueError:
|
||||||
|
raise ValueError("Value must be a float")
|
||||||
|
self.settings_changed.emit()
|
||||||
|
|
||||||
|
|
||||||
|
class IntSetting(Setting):
|
||||||
|
""" A setting that is an Integer."""
|
||||||
|
def __init__(self, name : str, default : int, description : str) -> None:
|
||||||
|
super().__init__(name, description)
|
||||||
|
self.value = default
|
||||||
|
|
||||||
|
@property
|
||||||
|
def value(self):
|
||||||
|
return self._value
|
||||||
|
|
||||||
|
@value.setter
|
||||||
|
def value(self, value):
|
||||||
|
try:
|
||||||
|
self._value = int(value)
|
||||||
|
except ValueError:
|
||||||
|
raise ValueError("Value must be an int")
|
||||||
|
self.settings_changed.emit()
|
||||||
|
|
||||||
|
class BooleanSetting(Setting):
|
||||||
|
""" A setting that is a Boolean."""
|
||||||
|
|
||||||
|
def __init__(self, name : str, default : bool, description : str) -> None:
|
||||||
|
super().__init__(name, description)
|
||||||
|
self.value = default
|
||||||
|
|
||||||
|
@property
|
||||||
|
def value(self):
|
||||||
|
return self._value
|
||||||
|
|
||||||
|
@value.setter
|
||||||
|
def value(self, value):
|
||||||
|
try:
|
||||||
|
self._value = bool(value)
|
||||||
|
except ValueError:
|
||||||
|
raise ValueError("Value must be a bool")
|
||||||
|
self.settings_changed.emit()
|
||||||
|
|
||||||
|
class SelectionSetting(Setting):
|
||||||
|
""" A setting that is a selection from a list of options."""
|
||||||
|
def __init__(self, name : str, options : list, default : str, description : str) -> None:
|
||||||
|
super().__init__(name, description)
|
||||||
|
# Check if default is in options
|
||||||
|
if default not in options:
|
||||||
|
raise ValueError("Default value must be one of the options")
|
||||||
|
|
||||||
|
self.options = options
|
||||||
|
self.value = default
|
||||||
|
|
||||||
|
@property
|
||||||
|
def value(self):
|
||||||
|
return self._value
|
||||||
|
|
||||||
|
@value.setter
|
||||||
|
def value(self, value):
|
||||||
|
if value in self.options:
|
||||||
|
self._value = value
|
||||||
|
else:
|
||||||
|
raise ValueError("Value must be one of the options")
|
||||||
|
self.settings_changed.emit()
|
||||||
|
|
||||||
|
class IPSetting(Setting):
|
||||||
|
""" A setting that is an IP address."""
|
||||||
|
def __init__(self, name : str, default : str, description : str) -> None:
|
||||||
|
super().__init__(name, description)
|
||||||
|
self.value = default
|
||||||
|
|
||||||
|
@property
|
||||||
|
def value(self):
|
||||||
|
return self._value
|
||||||
|
|
||||||
|
@value.setter
|
||||||
|
def value(self, value):
|
||||||
|
try:
|
||||||
|
ipaddress.ip_address(value)
|
||||||
|
self._value = value
|
||||||
|
except ValueError:
|
||||||
|
raise ValueError("Value must be a valid IP address")
|
||||||
|
self.settings_changed.emit()
|
||||||
|
|
||||||
|
class StringSetting(Setting):
|
||||||
|
""" A setting that is a string."""
|
||||||
|
def __init__(self, name : str, default : str, description : str) -> None:
|
||||||
|
super().__init__(name, description)
|
||||||
|
self.value = default
|
||||||
|
|
||||||
|
@property
|
||||||
|
def value(self):
|
||||||
|
return self._value
|
||||||
|
|
||||||
|
@value.setter
|
||||||
|
def value(self, value):
|
||||||
|
try:
|
||||||
|
self._value = str(value)
|
||||||
|
except ValueError:
|
||||||
|
raise ValueError("Value must be a string")
|
||||||
|
|
||||||
|
self.settings_changed.emit()
|
Loading…
Reference in a new issue