Skip to content
Snippets Groups Projects
Commit a8b79691 authored by Olle Hansson's avatar Olle Hansson Committed by Oscar Gustafsson
Browse files

Add FromFile signal generator.

parent ec553c1b
No related branches found
No related tags found
1 merge request!232Guifilesignal
Pipeline #90360 passed
# -*- coding: utf-8 -*-
from qtpy.QtWidgets import QGridLayout, QLabel, QLineEdit, QSpinBox
from qtpy.QtWidgets import (
QFileDialog,
QGridLayout,
QLabel,
QLineEdit,
QPushButton,
QSpinBox,
)
from b_asic.signal_generator import (
Constant,
FromFile,
Gaussian,
Impulse,
SignalGenerator,
......@@ -94,6 +102,31 @@ class ZeroPadInput(SignalGeneratorInput):
return ZeroPad(input_values)
class FromFileInput(SignalGeneratorInput):
"""
Class for graphically configuring and generating a
:class:`~b_asic.signal_generators.FromFile` signal generator.
"""
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.file_label = QLabel("Browse")
self.addWidget(self.file_label, 0, 0)
self.file_browser = QPushButton("No file selected")
self.file_browser.clicked.connect(
lambda i: self.get_input_file(i, self.file_browser)
)
self.addWidget(self.file_browser, 0, 1)
def get_generator(self) -> SignalGenerator:
return FromFile(self.file_browser.text())
def get_input_file(self, i, file_browser):
module, accepted = QFileDialog().getOpenFileName()
file_browser.setText(module)
return
class SinusoidInput(SignalGeneratorInput):
"""
Class for graphically configuring and generating a
......@@ -272,4 +305,5 @@ _GENERATOR_MAPPING = {
"Step": StepInput,
"Uniform": UniformInput,
"ZeroPad": ZeroPadInput,
"FromFile": FromFileInput,
}
......@@ -16,6 +16,7 @@ from qtpy.QtWidgets import (
QGridLayout,
QHBoxLayout,
QLabel,
QLayout,
QLineEdit,
QPushButton,
QShortcut,
......@@ -25,6 +26,7 @@ from qtpy.QtWidgets import (
)
from b_asic.GUI.signal_generator_input import _GENERATOR_MAPPING
from b_asic.signal_generator import FromFile
class SimulateSFGWindow(QDialog):
......@@ -40,6 +42,7 @@ class SimulateSFGWindow(QDialog):
self.setWindowTitle("Simulate SFG")
self.dialog_layout = QVBoxLayout()
self.dialog_layout.setSizeConstraint(QLayout.SetFixedSize)
self.simulate_btn = QPushButton("Simulate")
self.simulate_btn.clicked.connect(self.save_properties)
self.dialog_layout.addWidget(self.simulate_btn)
......@@ -89,15 +92,13 @@ class SimulateSFGWindow(QDialog):
self.input_grid.addWidget(input_label, i, 0)
input_dropdown = QComboBox()
input_dropdown.insertItems(
0, list(_GENERATOR_MAPPING.keys()) + ["File"]
)
input_dropdown.insertItems(0, list(_GENERATOR_MAPPING.keys()))
input_dropdown.currentTextChanged.connect(
lambda text, i=i: self.change_input_format(i, text)
)
self.input_grid.addWidget(input_dropdown, i, 1, alignment=Qt.AlignLeft)
self.change_input_format(i, "Impulse")
self.change_input_format(i, "Constant")
y += 1
......@@ -125,14 +126,6 @@ class SimulateSFGWindow(QDialog):
if text in _GENERATOR_MAPPING:
param_grid = _GENERATOR_MAPPING[text](self._window.logger)
elif text == "File":
file_label = QLabel("Browse")
param_grid.addWidget(file_label, 0, 0)
file_browser = QPushButton("No file selected")
file_browser.clicked.connect(
lambda i=i: self.get_input_file(i, file_browser)
)
param_grid.addWidget(file_browser, 0, 1)
else:
raise Exception("Input selection is not implemented")
......@@ -140,30 +133,6 @@ class SimulateSFGWindow(QDialog):
return
def get_input_file(self, i, file_browser):
module, accepted = QFileDialog().getOpenFileName()
file_browser.setText(module)
return
def parse_input_values(self, input_values):
_input_values = []
for _list in input_values:
_list_values = []
for val in _list:
val = val.strip()
try:
if not val:
val = 0
_list_values.append(complex(val))
except ValueError:
self._window.logger.warning(f"Skipping value: {val}, not a digit.")
continue
_input_values.append(_list_values)
return _input_values
def save_properties(self):
for sfg, _properties in self.input_fields.items():
ic_value = self.input_fields[sfg]["iteration_count"].value()
......@@ -178,16 +147,6 @@ class SimulateSFGWindow(QDialog):
if in_format in _GENERATOR_MAPPING:
tmp2 = in_param.get_generator()
elif in_format == "File":
widget = in_param.itemAtPosition(0, 1).widget()
path = widget.text()
try:
tmp2 = self.parse_input_values(
np.loadtxt(path, dtype=str).tolist()
)
except FileNotFoundError:
self._window.logger.error(f"Selected input file not found.")
continue
else:
raise Exception("Input selection is not implemented")
......
......@@ -13,6 +13,7 @@ if you want more information.
from math import pi, sin
from numbers import Number
from pathlib import Path
from typing import Optional, Sequence
import numpy as np
......@@ -161,6 +162,31 @@ class ZeroPad(SignalGenerator):
return f"ZeroPad({self._data})"
class FromFile(SignalGenerator):
"""
Signal generator that reads from file and pads a sequence with zeros.
File should be of type .txt or .csv and contain a single column vector
Parameters
----------
path : string
Path to input file.
"""
def __init__(self, path) -> None:
self._path = path
data = np.loadtxt(path, dtype=complex).tolist()
self._data = data
self._len = len(data)
def __call__(self, time: int) -> complex:
if 0 <= time < self._len:
return self._data[time]
return 0.0
def __repr__(self) -> str:
return f"FromFile({self._path!r})"
class Sinusoid(SignalGenerator):
"""
Signal generator that generates a sinusoid.
......
......@@ -148,6 +148,22 @@ def test_help_dialogs(qtbot):
widget.exit_app()
def test_simulate(qtbot, datadir):
# Smoke test to open up the "Simulate SFG" and run default simulation
# Should really test all different tests
widget = GUI.MainWindow()
qtbot.addWidget(widget)
widget._load_from_file(datadir.join('twotapfir.py'))
assert 'twotapfir' in widget.sfg_dict
widget.simulate_sfg()
qtbot.wait(100)
# widget.dialog.save_properties()
# qtbot.wait(100)
widget.dialog.close()
widget.exit_app()
def test_properties_window_smoke_test(qtbot, datadir):
# Smoke test to open up the properties window
# Should really check that the contents are correct and changes works etc
......@@ -159,9 +175,7 @@ def test_properties_window_smoke_test(qtbot, datadir):
dragbutton = widget.operationDragDict[op]
dragbutton.show_properties_window()
assert dragbutton._properties_window.operation == dragbutton
qtbot.mouseClick(
dragbutton._properties_window.ok, QtCore.Qt.MouseButton.LeftButton
)
qtbot.mouseClick(dragbutton._properties_window.ok, QtCore.Qt.MouseButton.LeftButton)
widget.exit_app()
......@@ -179,9 +193,7 @@ def test_properties_window_change_name(qtbot, datadir):
dragbutton.show_properties_window()
assert dragbutton._properties_window.edit_name.text() == "cmul2"
dragbutton._properties_window.edit_name.setText("cmul73")
qtbot.mouseClick(
dragbutton._properties_window.ok, QtCore.Qt.MouseButton.LeftButton
)
qtbot.mouseClick(dragbutton._properties_window.ok, QtCore.Qt.MouseButton.LeftButton)
dragbutton._properties_window.save_properties()
assert dragbutton.name == "cmul73"
assert dragbutton.operation.name == "cmul73"
......
import os
from math import sqrt
import pytest
......@@ -5,6 +6,7 @@ import pytest
from b_asic.signal_generator import (
Constant,
Delay,
FromFile,
Gaussian,
Impulse,
Sinusoid,
......@@ -269,3 +271,17 @@ def test_division():
assert str(g) == "Sinusoid(0.5, 0.25) / (0.5 * Step())"
assert isinstance(g, _DivGenerator)
def test_fromfile(datadir):
g = FromFile(datadir.join('input.csv'))
assert g(-1) == 0.0
assert g(0) == 0
assert g(1) == 1
assert g(2) == 0
with pytest.raises(FileNotFoundError, match="tset.py not found"):
g = FromFile(datadir.join('tset.py'))
with pytest.raises(ValueError, match="could not convert string"):
g = FromFile(datadir.join('bad.csv'))
0
a
0
1
0
0
0
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment