diff --git a/b_asic/GUI/arrow.py b/b_asic/GUI/arrow.py index eb4e279d0da3de0f85ed27f63379242c17cfd868..badb1f0b80e11d86b73a26757d9554d3c01c4b54 100644 --- a/b_asic/GUI/arrow.py +++ b/b_asic/GUI/arrow.py @@ -9,12 +9,10 @@ from b_asic import Signal class Arrow(QGraphicsLineItem): - def __init__(self, source, destination, window, create_signal=True, parent=None): + def __init__(self, source, destination, window, signal=None, parent=None): super(Arrow, self).__init__(parent) self.source = source - # if an signal does not exist create one - if create_signal: - self.signal = Signal(source.port, destination.port) + self.signal = Signal(source.port, destination.port) if signal is None else signal self.destination = destination self._window = window self.moveLine() @@ -41,6 +39,8 @@ class Arrow(QGraphicsLineItem): del self._window.sfg_dict[self._window.opToSFG[operation].name] self._window.opToSFG = {op: self._window.opToSFG[op] for op in self._window.opToSFG if self._window.opToSFG[op] is not self._window.opToSFG[operation]} + del self._window.signalPortDict[self] + def moveLine(self): self.setPen(QPen(Qt.black, 3)) self.setLine(QLineF(self.source.operation.x()+self.source.x()+14,\ diff --git a/b_asic/GUI/drag_button.py b/b_asic/GUI/drag_button.py index a67027d8e0877541c3932f89a4a8d885f26bdce6..6d5c47c39adb5c06147abf505bea17e04808b4a9 100644 --- a/b_asic/GUI/drag_button.py +++ b/b_asic/GUI/drag_button.py @@ -123,18 +123,16 @@ class DragButton(QPushButton): for signal, ports in self._window.signalPortDict.items(): if any(map(lambda port: set(port).intersection(set(self._window.portDict[self])), ports)): self._window.logger.info(f"Removed signal with name: {signal.signal.name} to/from operation: {self.operation.name}.") - signal.remove() _signals.append(signal) + for signal in _signals: + signal.remove() + if self in self._window.opToSFG: self._window.logger.info(f"Operation detected in existing sfg, removing sfg with name: {self._window.opToSFG[self].name}.") del self._window.sfg_dict[self._window.opToSFG[self].name] self._window.opToSFG = {op: self._window.opToSFG[op] for op in self._window.opToSFG if self._window.opToSFG[op] is not self._window.opToSFG[self]} - for signal in _signals: - del self._window.signalPortDict[signal] - signal.remove() - for port in self._window.portDict[self]: if port in self._window.pressed_ports: self._window.pressed_ports.remove(port) diff --git a/b_asic/GUI/main_window.py b/b_asic/GUI/main_window.py index 7a387efb363e9f3863e36e82a24aa0f903a3a654..d8067bcbea1b6e4399bd9d486473cb394377812d 100644 --- a/b_asic/GUI/main_window.py +++ b/b_asic/GUI/main_window.py @@ -214,6 +214,7 @@ class MainWindow(QMainWindow): for op in sfg.split(): self.operationDragDict[op].setToolTip(sfg.name) + self.opToSFG[self.operationDragDict[op]] = sfg self.sfg_dict[sfg.name] = sfg self.logger.info(f"Loaded sfg from path: {module}.") @@ -260,10 +261,6 @@ class MainWindow(QMainWindow): self.logger.info(f"Created SFG with name: {name} from selected operations.") def check_equality(signal, signal_2): - # check operation types - if not (signal.source is not None or signal_2.source is not None): - return False - if not (signal.source.operation.type_name() == signal_2.source.operation.type_name() \ and signal.destination.operation.type_name() == signal_2.destination.operation.type_name()): return False @@ -378,7 +375,6 @@ class MainWindow(QMainWindow): self.add_operations_from_namespace(namespace, self.ui.custom_operations_list) def create_operation(self, op, position=None): - self.logger.info(f"Creating operation of type: {op.type_name()}.") try: attr_button = DragButton(op.graph_id, op, op.type_name().lower(), True, window = self) if position is None: @@ -465,9 +461,13 @@ class MainWindow(QMainWindow): port.select_port() def connect_button(self, source, destination): - signal_exists = any([signal.destination is destination.port for signal in source.port.signals]) + signal_exists = (signal for signal in source.port.signals if signal.destination is destination.port) self.logger.info(f"Connecting: {source.operation.operation.type_name()} -> {destination.operation.operation.type_name()}.") - line = Arrow(source, destination, self, create_signal=not signal_exists) + try: + line = Arrow(source, destination, self, signal=next(signal_exists)) + except StopIteration: + line = Arrow(source, destination, self) + if line not in self.signalPortDict: self.signalPortDict[line] = [] diff --git a/b_asic/GUI/simulate_sfg_window.py b/b_asic/GUI/simulate_sfg_window.py index a4cfd24a699bda5c6f569ad2b246d7754ea5d878..f787e1ce25c0881ffdc5fa0c238ead0a971c3d61 100644 --- a/b_asic/GUI/simulate_sfg_window.py +++ b/b_asic/GUI/simulate_sfg_window.py @@ -69,9 +69,8 @@ class SimulateSFGWindow(QDialog): input_label = QLabel("in" + str(i)) input_layout.addWidget(input_label) input_value = QLineEdit() - input_value.setPlaceholderText("0") - input_value.setValidator(QDoubleValidator()) - input_value.setFixedWidth(50) + input_value.setPlaceholderText("e.g 0, 0, 0") + input_value.setFixedWidth(100) input_layout.addWidget(input_value) input_layout.addStretch() input_layout.setSpacing(10) @@ -90,19 +89,47 @@ class SimulateSFGWindow(QDialog): self.sfg_to_layout[sfg] = sfg_layout self.dialog_layout.addLayout(sfg_layout) - def save_properties(self): - for sfg, properties in self.input_fields.items(): + def parse_input_values(self, input_values): + _input_values = [] + for _list in list(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 - self.properties[sfg] = { - "iteration_count": self.input_fields[sfg]["iteration_count"].value(), - "show_plot": self.input_fields[sfg]["show_plot"].isChecked(), - "all_results": self.input_fields[sfg]["all_results"].isChecked(), - "input_values": [float(widget.text().replace(",", ".")) if widget.text() else 0 for widget in self.input_fields[sfg]["input_values"]] - } + _input_values.append(_list_values) - # If we plot we should also print the entire data, since you can't really interact with the graph. - if self.properties[sfg]["show_plot"]: - self.properties[sfg]["all_results"] = True + return _input_values + + def save_properties(self): + for sfg, properties in self.input_fields.items(): + input_values = self.parse_input_values(widget.text().split(",") if widget.text() else [0] for widget in self.input_fields[sfg]["input_values"]) + if max(len(list_) for list_ in input_values) != min(len(list_) for list_ in input_values): + self._window.logger.error(f"Minimum length of input lists are not equal to maximum length of input lists: {max(len(list_) for list_ in input_values)} != {min(len(list_) for list_ in input_values)}.") + elif self.input_fields[sfg]["iteration_count"].value() > min(len(list_) for list_ in input_values): + self._window.logger.error(f"Minimum length of input lists are less than the iteration count: {self.input_fields[sfg]['iteration_count'].value()} > {min(len(list_) for list_ in input_values)}.") + else: + self.properties[sfg] = { + "iteration_count": self.input_fields[sfg]["iteration_count"].value(), + "show_plot": self.input_fields[sfg]["show_plot"].isChecked(), + "all_results": self.input_fields[sfg]["all_results"].isChecked(), + "input_values": input_values + } + + # If we plot we should also print the entire data, since you can't really interact with the graph. + if self.properties[sfg]["show_plot"]: + self.properties[sfg]["all_results"] = True + + continue + + self._window.logger.info(f"Skipping simulation of sfg with name: {sfg.name}, due to previous errors.") self.accept() self.simulate.emit()