Skip to content
Snippets Groups Projects

Refactor signal generation GUI

Merged Oscar Gustafsson requested to merge guisignalgenerator into master
Files
3
+ 275
0
 
# -*- coding: utf-8 -*-
 
from qtpy.QtWidgets import QGridLayout, QLabel, QLineEdit, QSpinBox
 
 
from b_asic.signal_generator import (
 
Constant,
 
Gaussian,
 
Impulse,
 
SignalGenerator,
 
Sinusoid,
 
Step,
 
Uniform,
 
ZeroPad,
 
)
 
 
 
class SignalGeneratorInput(QGridLayout):
 
"""Abstract class for graphically configuring and generating signal generators."""
 
 
def __init__(self, logger, *args, **kwargs):
 
super().__init__(*args, **kwargs)
 
self._logger = logger
 
 
def get_generator(self) -> SignalGenerator:
 
"""Return the SignalGenerator based on the graphical input."""
 
raise NotImplementedError
 
 
 
class DelayInput(SignalGeneratorInput):
 
"""
 
Abstract class for graphically configuring and generating signal generators that
 
have a single delay parameter.
 
"""
 
 
def __init__(self, *args, **kwargs):
 
super().__init__(*args, **kwargs)
 
self.delay_label = QLabel("Delay")
 
self.addWidget(self.delay_label, 0, 0)
 
self.delay_spin_box = QSpinBox()
 
self.delay_spin_box.setRange(0, 2147483647)
 
self.addWidget(self.delay_spin_box, 0, 1)
 
 
def get_generator(self) -> SignalGenerator:
 
raise NotImplementedError
 
 
 
class ImpulseInput(DelayInput):
 
"""
 
Class for graphically configuring and generating a
 
:class:`~b_asic.signal_generators.Impulse` signal generator.
 
"""
 
 
def get_generator(self) -> SignalGenerator:
 
return Impulse(self.delay_spin_box.value())
 
 
 
class StepInput(DelayInput):
 
"""
 
Class for graphically configuring and generating a
 
:class:`~b_asic.signal_generators.Step` signal generator.
 
"""
 
 
def get_generator(self) -> SignalGenerator:
 
return Step(self.delay_spin_box.value())
 
 
 
class ZeroPadInput(SignalGeneratorInput):
 
"""
 
Class for graphically configuring and generating a
 
:class:`~b_asic.signal_generators.ZeroPad` signal generator.
 
"""
 
 
def __init__(self, *args, **kwargs):
 
super().__init__(*args, **kwargs)
 
self.input_label = QLabel("Input")
 
self.addWidget(self.input_label, 0, 0)
 
self.input_sequence = QLineEdit()
 
self.addWidget(self.input_sequence, 0, 1)
 
 
def get_generator(self) -> SignalGenerator:
 
input_values = []
 
for val in self.input_sequence.text().split(","):
 
val = val.strip()
 
try:
 
if not val:
 
val = 0
 
 
val = complex(val)
 
except ValueError:
 
self._logger.warning(f"Skipping value: {val}, not a digit.")
 
continue
 
 
input_values.append(val)
 
 
return ZeroPad(input_values)
 
 
 
class SinusoidInput(SignalGeneratorInput):
 
"""
 
Class for graphically configuring and generating a
 
:class:`~b_asic.signal_generators.Sinusoid` signal generator.
 
"""
 
 
def __init__(self, *args, **kwargs):
 
super().__init__(*args, **kwargs)
 
self.frequency_label = QLabel("Frequency")
 
self.addWidget(self.frequency_label, 0, 0)
 
self.frequency_input = QLineEdit()
 
self.addWidget(self.frequency_input, 0, 1)
 
 
self.phase_label = QLabel("Phase")
 
self.addWidget(self.phase_label, 1, 0)
 
self.phase_input = QLineEdit()
 
self.addWidget(self.phase_input, 1, 1)
 
 
def get_generator(self) -> SignalGenerator:
 
frequency = self.frequency_input.text().strip()
 
try:
 
if not frequency:
 
frequency = 0.1
 
 
frequency = float(frequency)
 
except ValueError:
 
self._logger.warning(f"Cannot parse frequency: {frequency} not a number.")
 
frequency = 0.1
 
 
phase = self.phase_input.text().strip()
 
try:
 
if not phase:
 
phase = 0
 
 
phase = float(phase)
 
except ValueError:
 
self._logger.warning(f"Cannot parse phase: {phase} not a number.")
 
phase = 0
 
 
return Sinusoid(frequency, phase)
 
 
 
class GaussianInput(SignalGeneratorInput):
 
"""
 
Class for graphically configuring and generating a
 
:class:`~b_asic.signal_generators.Gaussian` signal generator.
 
"""
 
 
def __init__(self, *args, **kwargs):
 
super().__init__(*args, **kwargs)
 
self.scale_label = QLabel("Standard deviation")
 
self.addWidget(self.scale_label, 0, 0)
 
self.scale_input = QLineEdit()
 
self.scale_input.setText("1.0")
 
self.addWidget(self.scale_input, 0, 1)
 
 
self.loc_label = QLabel("Average value")
 
self.addWidget(self.loc_label, 1, 0)
 
self.loc_input = QLineEdit()
 
self.loc_input.setText("0.0")
 
self.addWidget(self.loc_input, 1, 1)
 
 
self.seed_label = QLabel("Seed")
 
self.addWidget(self.seed_label, 2, 0)
 
self.seed_spin_box = QSpinBox()
 
self.seed_spin_box.setRange(0, 2147483647)
 
self.addWidget(self.seed_spin_box, 2, 1)
 
 
def get_generator(self) -> SignalGenerator:
 
scale = self.scale_input.text().strip()
 
try:
 
if not scale:
 
scale = 1
 
 
scale = float(scale)
 
except ValueError:
 
self._logger.warning(f"Cannot parse scale: {scale} not a number.")
 
scale = 1
 
 
loc = self.loc_input.text().strip()
 
try:
 
if not loc:
 
loc = 0
 
 
loc = float(loc)
 
except ValueError:
 
self._logger.warning(f"Cannot parse loc: {loc} not a number.")
 
loc = 0
 
 
return Gaussian(self.seed_spin_box.value(), loc, scale)
 
 
 
class UniformInput(SignalGeneratorInput):
 
"""
 
Class for graphically configuring and generating a
 
:class:`~b_asic.signal_generators.Uniform` signal generator.
 
"""
 
 
def __init__(self, *args, **kwargs):
 
super().__init__(*args, **kwargs)
 
self.low_label = QLabel("Lower bound")
 
self.addWidget(self.low_label, 0, 0)
 
self.low_input = QLineEdit()
 
self.low_input.setText("-1.0")
 
self.addWidget(self.low_input, 0, 1)
 
 
self.high_label = QLabel("Upper bound")
 
self.addWidget(self.high_label, 1, 0)
 
self.high_input = QLineEdit()
 
self.high_input.setText("1.0")
 
self.addWidget(self.high_input, 1, 1)
 
 
self.seed_label = QLabel("Seed")
 
self.addWidget(self.seed_label, 2, 0)
 
self.seed_spin_box = QSpinBox()
 
self.seed_spin_box.setRange(0, 2147483647)
 
self.addWidget(self.seed_spin_box, 2, 1)
 
 
def get_generator(self) -> SignalGenerator:
 
low = self.low_input.text().strip()
 
try:
 
if not low:
 
low = -1.0
 
 
low = float(low)
 
except ValueError:
 
self._logger.warning(f"Cannot parse low: {low} not a number.")
 
low = -1.0
 
 
high = self.high_input.text().strip()
 
try:
 
if not high:
 
high = 1.0
 
 
high = float(high)
 
except ValueError:
 
self._logger.warning(f"Cannot parse high: {high} not a number.")
 
high = 1.0
 
 
return Uniform(self.seed_spin_box.value(), low, high)
 
 
 
class ConstantInput(SignalGeneratorInput):
 
"""
 
Class for graphically configuring and generating a
 
:class:`~b_asic.signal_generators.Constant` signal generator.
 
"""
 
 
def __init__(self, *args, **kwargs):
 
super().__init__(*args, **kwargs)
 
self.constant_label = QLabel("Constant")
 
self.addWidget(self.constant_label, 0, 0)
 
self.constant_input = QLineEdit()
 
self.constant_input.setText("1.0")
 
self.addWidget(self.constant_input, 0, 1)
 
 
def get_generator(self) -> SignalGenerator:
 
constant = self.constant_input.text().strip()
 
try:
 
if not constant:
 
constant = 1.0
 
 
constant = complex(constant)
 
except ValueError:
 
self._logger.warning(f"Cannot parse constant: {constant} not a number.")
 
constant = 0.0
 
 
return Constant(constant)
 
 
 
_GENERATOR_MAPPING = {
 
"Constant": ConstantInput,
 
"Gaussian": GaussianInput,
 
"Impulse": ImpulseInput,
 
"Sinusoid": SinusoidInput,
 
"Step": StepInput,
 
"Uniform": UniformInput,
 
"ZeroPad": ZeroPadInput,
 
}
Loading