From 2deb8dd9d7b9706f30f5ddaac25f4c19e2f95c45 Mon Sep 17 00:00:00 2001
From: Olle Hansson <olle.hansson@liu.se>
Date: Fri, 24 Feb 2023 10:36:32 +0100
Subject: [PATCH] FromFileInput added

---
 b_asic/GUI/signal_generator_input.py | 31 ++++++++++++++++-
 b_asic/GUI/simulate_sfg_window.py    | 50 +++-------------------------
 b_asic/signal_generator.py           | 27 +++++++++++++++
 3 files changed, 61 insertions(+), 47 deletions(-)

diff --git a/b_asic/GUI/signal_generator_input.py b/b_asic/GUI/signal_generator_input.py
index 8fba385a..a2db9aa0 100644
--- a/b_asic/GUI/signal_generator_input.py
+++ b/b_asic/GUI/signal_generator_input.py
@@ -1,8 +1,16 @@
 # -*- 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,26 @@ class ZeroPadInput(SignalGeneratorInput):
         return ZeroPad(input_values)
 
 
+class FromFileInput(SignalGeneratorInput):
+    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 +300,5 @@ _GENERATOR_MAPPING = {
     "Step": StepInput,
     "Uniform": UniformInput,
     "ZeroPad": ZeroPadInput,
+    "FromFile": FromFileInput,
 }
diff --git a/b_asic/GUI/simulate_sfg_window.py b/b_asic/GUI/simulate_sfg_window.py
index 13fbf3c8..f389beb6 100644
--- a/b_asic/GUI/simulate_sfg_window.py
+++ b/b_asic/GUI/simulate_sfg_window.py
@@ -25,6 +25,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 +41,7 @@ class SimulateSFGWindow(QDialog):
         self.setWindowTitle("Simulate SFG")
 
         self.dialog_layout = QVBoxLayout()
+
         self.simulate_btn = QPushButton("Simulate")
         self.simulate_btn.clicked.connect(self.save_properties)
         self.dialog_layout.addWidget(self.simulate_btn)
@@ -89,15 +91,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 +125,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 +132,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 +146,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")
 
diff --git a/b_asic/signal_generator.py b/b_asic/signal_generator.py
index 27b12518..45840415 100644
--- a/b_asic/signal_generator.py
+++ b/b_asic/signal_generator.py
@@ -161,6 +161,33 @@ class ZeroPad(SignalGenerator):
         return f"ZeroPad({self._data})"
 
 
+class FromFile(SignalGenerator):
+    """
+    Signal generator that reads from file and pads a sequence with zeros.
+
+    Parameters
+    ----------
+    path : string
+        Path to input file.
+    """
+
+    def __init__(self, path) -> None:
+        try:
+            data = np.loadtxt(path, dtype=complex).tolist()
+            self._data = data
+            self._len = len(data)
+        except FileNotFoundError:
+            self._window.logger.error(f"Selected input file not found.")
+
+    def __call__(self, time: int) -> complex:
+        if 0 <= time < self._len:
+            return self._data[time]
+        return 0.0
+
+    def __repr__(self) -> str:
+        return f"ZeroPad({self._data})"
+
+
 class Sinusoid(SignalGenerator):
     """
     Signal generator that generates a sinusoid.
-- 
GitLab