From f619fd21fe39cbb0abee9d40e39242e657249ba2 Mon Sep 17 00:00:00 2001
From: Oscar Gustafsson <oscar.gustafsson@gmail.com>
Date: Fri, 17 Feb 2023 09:35:06 +0100
Subject: [PATCH] Refactor signal generation GUI

---
 b_asic/GUI/signal_generator_input.py | 63 ++++++++++++++++++++++++++
 b_asic/GUI/simulate_sfg_window.py    | 66 ++++++++--------------------
 docs_sphinx/GUI.rst                  | 12 +++++
 3 files changed, 93 insertions(+), 48 deletions(-)
 create mode 100644 b_asic/GUI/signal_generator_input.py

diff --git a/b_asic/GUI/signal_generator_input.py b/b_asic/GUI/signal_generator_input.py
new file mode 100644
index 00000000..5779f53f
--- /dev/null
+++ b/b_asic/GUI/signal_generator_input.py
@@ -0,0 +1,63 @@
+# -*- coding: utf-8 -*-
+from qtpy.QtWidgets import (
+    QCheckBox,
+    QComboBox,
+    QDialog,
+    QFileDialog,
+    QFormLayout,
+    QFrame,
+    QGridLayout,
+    QHBoxLayout,
+    QLabel,
+    QLineEdit,
+    QPushButton,
+    QShortcut,
+    QSizePolicy,
+    QSpinBox,
+    QVBoxLayout,
+)
+
+from b_asic.signal_generator import Impulse, Step
+
+
+class SignalGeneratorInput(QGridLayout):
+    """Abstract class for graphically configuring and generating signal generators.
+    """
+
+    def get_generator(self):
+        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)
+
+
+class ImpulseInput(DelayInput):
+    """
+    Class for graphically configuring and generating a
+    :class:`~b_asic.signal_generators.Impulse` signal generator.
+    """
+
+    def get_generator(self):
+        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):
+        return Step(self.delay_spin_box.value())
diff --git a/b_asic/GUI/simulate_sfg_window.py b/b_asic/GUI/simulate_sfg_window.py
index 9a7429de..6961733a 100644
--- a/b_asic/GUI/simulate_sfg_window.py
+++ b/b_asic/GUI/simulate_sfg_window.py
@@ -26,8 +26,11 @@ from qtpy.QtWidgets import (
     QVBoxLayout,
 )
 
+from b_asic.GUI.signal_generator_input import ImpulseInput, StepInput
 from b_asic.signal_generator import Impulse, Step, ZeroPad
 
+_GENERATOR_MAPPING = {"Impulse": ImpulseInput, "Step": StepInput}
+
 
 class SimulateSFGWindow(QDialog):
     simulate = Signal()
@@ -58,12 +61,15 @@ class SimulateSFGWindow(QDialog):
 
         spin_box = QSpinBox()
         spin_box.setRange(0, 2147483647)
+        spin_box.setValue(100)
         options_layout.addRow("Iteration count: ", spin_box)
 
         check_box_plot = QCheckBox()
+        check_box_plot.setCheckState(Qt.CheckState.Checked)
         options_layout.addRow("Plot results: ", check_box_plot)
 
         check_box_all = QCheckBox()
+        check_box_all.setCheckState(Qt.CheckState.Checked)
         options_layout.addRow("Get all results: ", check_box_all)
 
         sfg_layout.addLayout(options_layout)
@@ -124,18 +130,8 @@ class SimulateSFGWindow(QDialog):
 
         param_grid = QGridLayout()
 
-        if text == "Impulse":
-            delay_label = QLabel("Delay")
-            param_grid.addWidget(delay_label, 0, 0)
-            delay_spin_box = QSpinBox()
-            delay_spin_box.setRange(0, 2147483647)
-            param_grid.addWidget(delay_spin_box, 0, 1)
-        elif text == "Step":
-            delay_label = QLabel("Delay")
-            param_grid.addWidget(delay_label, 0, 0)
-            delay_spin_box = QSpinBox()
-            delay_spin_box.setRange(0, 2147483647)
-            param_grid.addWidget(delay_spin_box, 0, 1)
+        if text in ("Impulse", "Step"):
+            param_grid = _GENERATOR_MAPPING[text]()
         elif text == "Input":
             input_label = QLabel("Input")
             param_grid.addWidget(input_label, 0, 0)
@@ -192,7 +188,7 @@ class SimulateSFGWindow(QDialog):
             if ic_value == 0:
                 self._window.logger.error("Iteration count is set to zero.")
 
-            tmp = []
+            input_values = []
 
             for i in range(self.input_grid.rowCount()):
                 in_format = (
@@ -200,33 +196,22 @@ class SimulateSFGWindow(QDialog):
                 )
                 in_param = self.input_grid.itemAtPosition(i, 2)
 
-                tmp2 = []
-
-                if in_format == "Impulse":
-                    g = Impulse(in_param.itemAtPosition(0, 1).widget().value())
-                    for j in range(ic_value):
-                        tmp2.append(str(g(j)))
-
-                elif in_format == "Step":
-                    g = Step(in_param.itemAtPosition(0, 1).widget().value())
-                    for j in range(ic_value):
-                        tmp2.append(str(g(j)))
-
+                if in_format in ("Impulse", "Step"):
+                    tmp2 = in_param.get_generator()
                 elif in_format == "Input":
                     widget = in_param.itemAtPosition(0, 1).widget()
                     tmp3 = widget.text().split(",")
                     if in_param.itemAtPosition(1, 1).widget().isChecked():
-                        g = ZeroPad(tmp3)
-                        for j in range(ic_value):
-                            tmp2.append(str(g(j)))
+                        tmp2 = ZeroPad(tmp3)
                     else:
-                        tmp2 = tmp3
-
+                        tmp2 = self.parse_input_values(tmp3)
                 elif in_format == "File":
                     widget = in_param.itemAtPosition(0, 1).widget()
                     path = widget.text()
                     try:
-                        tmp2 = np.loadtxt(path, dtype=str).tolist()
+                        tmp2 = self.parse_input_values(
+                            np.loadtxt(path, dtype=str).tolist()
+                        )
                     except FileNotFoundError:
                         self._window.logger.error(
                             f"Selected input file not found."
@@ -235,24 +220,9 @@ class SimulateSFGWindow(QDialog):
                 else:
                     raise Exception("Input selection is not implemented")
 
-                tmp.append(tmp2)
-
-            input_values = self.parse_input_values(tmp)
-
-            max_len = max(len(list_) for list_ in input_values)
-            min_len = min(len(list_) for list_ in input_values)
+                input_values.append(tmp2)
 
-            if max_len != min_len:
-                self._window.logger.error(
-                    "Minimum length of input lists are not equal to maximum "
-                    f"length of input lists: {max_len} != {min_len}."
-                )
-            elif ic_value > min_len:
-                self._window.logger.error(
-                    "Minimum length of input lists are less than the "
-                    f"iteration count: {ic_value} > {min_len}."
-                )
-            else:
+            if True:
                 self.properties[sfg] = {
                     "iteration_count": ic_value,
                     "show_plot": self.input_fields[sfg][
diff --git a/docs_sphinx/GUI.rst b/docs_sphinx/GUI.rst
index bbe6459b..83b24cd9 100644
--- a/docs_sphinx/GUI.rst
+++ b/docs_sphinx/GUI.rst
@@ -76,6 +76,18 @@ GUI.show\_pc\_window module
    :undoc-members:
    :show-inheritance:
 
+GUI.signal\_generator\_input module
+-----------------------------------
+
+.. inheritance-diagram:: b_asic.GUI.signal_generator_input
+   :parts: 1
+   :top-classes: b_asic.GUI.signal_generator_input.SignalGeneratorInput
+
+.. automodule:: b_asic.GUI.signal_generator_input
+   :members:
+   :undoc-members:
+   :show-inheritance:
+
 GUI.simulate\_sfg\_window module
 --------------------------------
 
-- 
GitLab