diff --git a/cluster4npu_ui/Screenshot 2025-07-10 at 1.22.11 PM.png b/cluster4npu_ui/Screenshot 2025-07-10 at 1.22.11 PM.png new file mode 100644 index 0000000..2bc851c Binary files /dev/null and b/cluster4npu_ui/Screenshot 2025-07-10 at 1.22.11 PM.png differ diff --git a/cluster4npu_ui/Screenshot 2025-07-10 at 11.28.30 AM.png b/cluster4npu_ui/Screenshot 2025-07-10 at 11.28.30 AM.png deleted file mode 100644 index 3b76c5d..0000000 Binary files a/cluster4npu_ui/Screenshot 2025-07-10 at 11.28.30 AM.png and /dev/null differ diff --git a/cluster4npu_ui/test.mflow b/cluster4npu_ui/test.mflow index 8d13aaf..83042cb 100644 --- a/cluster4npu_ui/test.mflow +++ b/cluster4npu_ui/test.mflow @@ -3,7 +3,7 @@ "description": "", "nodes": [ { - "id": "0x111398750", + "id": "0x1131773d0", "name": "Input Node", "type": "ExactInputNode", "pos": [ @@ -19,7 +19,7 @@ } }, { - "id": "0x1113b5a50", + "id": "0x12b4ae9d0", "name": "Model Node", "type": "ExactModelNode", "pos": [ @@ -30,11 +30,13 @@ "dongle_series": "520", "num_dongles": 1, "model_path": "", + "scpu_fw_path": "", + "ncpu_fw_path": "", "port_id": "" } }, { - "id": "0x1113b6e90", + "id": "0x12b4aff50", "name": "Output Node", "type": "ExactOutputNode", "pos": [ @@ -47,19 +49,33 @@ "destination": "", "save_interval": 1.0 } + }, + { + "id": "0x12b4c8990", + "name": "Preprocess Node", + "type": "ExactPreprocessNode", + "pos": [ + 230.0, + 190.0 + ], + "properties": { + "resize_width": 112, + "resize_height": 112, + "operations": "resize,normalize" + } } ], "connections": [ { - "input_node": "0x1113b5a50", + "input_node": "0x12b4ae9d0", "input_port": "input", - "output_node": "0x111398750", + "output_node": "0x1131773d0", "output_port": "output" }, { - "input_node": "0x1113b6e90", + "input_node": "0x12b4aff50", "input_port": "input", - "output_node": "0x1113b5a50", + "output_node": "0x12b4ae9d0", "output_port": "output" } ], diff --git a/cluster4npu_ui/ui/windows/pipeline_editor.py b/cluster4npu_ui/ui/windows/pipeline_editor.py index 8c2e635..92a5599 100644 --- a/cluster4npu_ui/ui/windows/pipeline_editor.py +++ b/cluster4npu_ui/ui/windows/pipeline_editor.py @@ -1,667 +1,667 @@ -""" -Pipeline Editor window with stage counting functionality. +# """ +# Pipeline Editor window with stage counting functionality. -This module provides the main pipeline editor interface with visual node-based -pipeline design and automatic stage counting display. +# This module provides the main pipeline editor interface with visual node-based +# pipeline design and automatic stage counting display. -Main Components: - - PipelineEditor: Main pipeline editor window - - Stage counting display in canvas - - Node graph integration - - Pipeline validation and analysis +# Main Components: +# - PipelineEditor: Main pipeline editor window +# - Stage counting display in canvas +# - Node graph integration +# - Pipeline validation and analysis -Usage: - from cluster4npu_ui.ui.windows.pipeline_editor import PipelineEditor +# Usage: +# from cluster4npu_ui.ui.windows.pipeline_editor import PipelineEditor - editor = PipelineEditor() - editor.show() -""" +# editor = PipelineEditor() +# editor.show() +# """ -import sys -from PyQt5.QtWidgets import (QMainWindow, QWidget, QVBoxLayout, QHBoxLayout, - QLabel, QStatusBar, QFrame, QPushButton, QAction, - QMenuBar, QToolBar, QSplitter, QTextEdit, QMessageBox, - QScrollArea) -from PyQt5.QtCore import Qt, QTimer, pyqtSignal -from PyQt5.QtGui import QFont, QPixmap, QIcon, QTextCursor +# import sys +# from PyQt5.QtWidgets import (QMainWindow, QWidget, QVBoxLayout, QHBoxLayout, +# QLabel, QStatusBar, QFrame, QPushButton, QAction, +# QMenuBar, QToolBar, QSplitter, QTextEdit, QMessageBox, +# QScrollArea) +# from PyQt5.QtCore import Qt, QTimer, pyqtSignal +# from PyQt5.QtGui import QFont, QPixmap, QIcon, QTextCursor -try: - from NodeGraphQt import NodeGraph - from NodeGraphQt.constants import IN_PORT, OUT_PORT - NODEGRAPH_AVAILABLE = True -except ImportError: - NODEGRAPH_AVAILABLE = False - print("NodeGraphQt not available. Install with: pip install NodeGraphQt") +# try: +# from NodeGraphQt import NodeGraph +# from NodeGraphQt.constants import IN_PORT, OUT_PORT +# NODEGRAPH_AVAILABLE = True +# except ImportError: +# NODEGRAPH_AVAILABLE = False +# print("NodeGraphQt not available. Install with: pip install NodeGraphQt") -from ...core.pipeline import get_stage_count, analyze_pipeline_stages, get_pipeline_summary -from ...core.nodes.exact_nodes import ( - ExactInputNode, ExactModelNode, ExactPreprocessNode, - ExactPostprocessNode, ExactOutputNode -) -# Keep the original imports as fallback -try: - from ...core.nodes.model_node import ModelNode - from ...core.nodes.preprocess_node import PreprocessNode - from ...core.nodes.postprocess_node import PostprocessNode - from ...core.nodes.input_node import InputNode - from ...core.nodes.output_node import OutputNode -except ImportError: - # Use ExactNodes as fallback - ModelNode = ExactModelNode - PreprocessNode = ExactPreprocessNode - PostprocessNode = ExactPostprocessNode - InputNode = ExactInputNode - OutputNode = ExactOutputNode +# from ...core.pipeline import get_stage_count, analyze_pipeline_stages, get_pipeline_summary +# from ...core.nodes.exact_nodes import ( +# ExactInputNode, ExactModelNode, ExactPreprocessNode, +# ExactPostprocessNode, ExactOutputNode +# ) +# # Keep the original imports as fallback +# try: +# from ...core.nodes.model_node import ModelNode +# from ...core.nodes.preprocess_node import PreprocessNode +# from ...core.nodes.postprocess_node import PostprocessNode +# from ...core.nodes.input_node import InputNode +# from ...core.nodes.output_node import OutputNode +# except ImportError: +# # Use ExactNodes as fallback +# ModelNode = ExactModelNode +# PreprocessNode = ExactPreprocessNode +# PostprocessNode = ExactPostprocessNode +# InputNode = ExactInputNode +# OutputNode = ExactOutputNode -class StageCountWidget(QWidget): - """Widget to display stage count information in the pipeline editor.""" +# class StageCountWidget(QWidget): +# """Widget to display stage count information in the pipeline editor.""" - def __init__(self, parent=None): - super().__init__(parent) - self.stage_count = 0 - self.pipeline_valid = True - self.pipeline_error = "" +# def __init__(self, parent=None): +# super().__init__(parent) +# self.stage_count = 0 +# self.pipeline_valid = True +# self.pipeline_error = "" - self.setup_ui() - self.setFixedSize(200, 80) +# self.setup_ui() +# self.setFixedSize(200, 80) - def setup_ui(self): - """Setup the stage count widget UI.""" - layout = QVBoxLayout() - layout.setContentsMargins(10, 5, 10, 5) +# def setup_ui(self): +# """Setup the stage count widget UI.""" +# layout = QVBoxLayout() +# layout.setContentsMargins(10, 5, 10, 5) - # Stage count label - self.stage_label = QLabel("Stages: 0") - self.stage_label.setFont(QFont("Arial", 11, QFont.Bold)) - self.stage_label.setStyleSheet("color: #2E7D32; font-weight: bold;") +# # Stage count label +# self.stage_label = QLabel("Stages: 0") +# self.stage_label.setFont(QFont("Arial", 11, QFont.Bold)) +# self.stage_label.setStyleSheet("color: #2E7D32; font-weight: bold;") - # Status label - self.status_label = QLabel("Ready") - self.status_label.setFont(QFont("Arial", 9)) - self.status_label.setStyleSheet("color: #666666;") +# # Status label +# self.status_label = QLabel("Ready") +# self.status_label.setFont(QFont("Arial", 9)) +# self.status_label.setStyleSheet("color: #666666;") - # Error label (initially hidden) - self.error_label = QLabel("") - self.error_label.setFont(QFont("Arial", 8)) - self.error_label.setStyleSheet("color: #D32F2F;") - self.error_label.setWordWrap(True) - self.error_label.setMaximumHeight(30) - self.error_label.hide() +# # Error label (initially hidden) +# self.error_label = QLabel("") +# self.error_label.setFont(QFont("Arial", 8)) +# self.error_label.setStyleSheet("color: #D32F2F;") +# self.error_label.setWordWrap(True) +# self.error_label.setMaximumHeight(30) +# self.error_label.hide() - layout.addWidget(self.stage_label) - layout.addWidget(self.status_label) - layout.addWidget(self.error_label) +# layout.addWidget(self.stage_label) +# layout.addWidget(self.status_label) +# layout.addWidget(self.error_label) - self.setLayout(layout) +# self.setLayout(layout) - # Style the widget - self.setStyleSheet(""" - StageCountWidget { - background-color: #F5F5F5; - border: 1px solid #E0E0E0; - border-radius: 5px; - } - """) +# # Style the widget +# self.setStyleSheet(""" +# StageCountWidget { +# background-color: #F5F5F5; +# border: 1px solid #E0E0E0; +# border-radius: 5px; +# } +# """) - def update_stage_count(self, count: int, valid: bool = True, error: str = ""): - """Update the stage count display.""" - self.stage_count = count - self.pipeline_valid = valid - self.pipeline_error = error +# def update_stage_count(self, count: int, valid: bool = True, error: str = ""): +# """Update the stage count display.""" +# self.stage_count = count +# self.pipeline_valid = valid +# self.pipeline_error = error - # Update stage count - self.stage_label.setText(f"Stages: {count}") +# # Update stage count +# self.stage_label.setText(f"Stages: {count}") - # Update status and styling - if not valid: - self.stage_label.setStyleSheet("color: #D32F2F; font-weight: bold;") - self.status_label.setText("Invalid Pipeline") - self.status_label.setStyleSheet("color: #D32F2F;") - self.error_label.setText(error) - self.error_label.show() - else: - self.stage_label.setStyleSheet("color: #2E7D32; font-weight: bold;") - if count == 0: - self.status_label.setText("No stages defined") - self.status_label.setStyleSheet("color: #FF8F00;") - else: - self.status_label.setText(f"Pipeline ready ({count} stage{'s' if count != 1 else ''})") - self.status_label.setStyleSheet("color: #2E7D32;") - self.error_label.hide() +# # Update status and styling +# if not valid: +# self.stage_label.setStyleSheet("color: #D32F2F; font-weight: bold;") +# self.status_label.setText("Invalid Pipeline") +# self.status_label.setStyleSheet("color: #D32F2F;") +# self.error_label.setText(error) +# self.error_label.show() +# else: +# self.stage_label.setStyleSheet("color: #2E7D32; font-weight: bold;") +# if count == 0: +# self.status_label.setText("No stages defined") +# self.status_label.setStyleSheet("color: #FF8F00;") +# else: +# self.status_label.setText(f"Pipeline ready ({count} stage{'s' if count != 1 else ''})") +# self.status_label.setStyleSheet("color: #2E7D32;") +# self.error_label.hide() -class PipelineEditor(QMainWindow): - """ - Main pipeline editor window with stage counting functionality. +# class PipelineEditor(QMainWindow): +# """ +# Main pipeline editor window with stage counting functionality. - This window provides a visual node-based pipeline editor with automatic - stage detection and counting displayed in the canvas. - """ +# This window provides a visual node-based pipeline editor with automatic +# stage detection and counting displayed in the canvas. +# """ - # Signals - pipeline_changed = pyqtSignal() - stage_count_changed = pyqtSignal(int) +# # Signals +# pipeline_changed = pyqtSignal() +# stage_count_changed = pyqtSignal(int) - def __init__(self, parent=None): - super().__init__(parent) +# def __init__(self, parent=None): +# super().__init__(parent) - self.node_graph = None - self.stage_count_widget = None - self.analysis_timer = None - self.previous_stage_count = 0 # Track previous stage count for comparison +# self.node_graph = None +# self.stage_count_widget = None +# self.analysis_timer = None +# self.previous_stage_count = 0 # Track previous stage count for comparison - self.setup_ui() - self.setup_node_graph() - self.setup_analysis_timer() +# self.setup_ui() +# self.setup_node_graph() +# self.setup_analysis_timer() - # Connect signals - self.pipeline_changed.connect(self.analyze_pipeline) +# # Connect signals +# self.pipeline_changed.connect(self.analyze_pipeline) - # Initial analysis - print("Pipeline Editor initialized") - self.analyze_pipeline() +# # Initial analysis +# print("Pipeline Editor initialized") +# self.analyze_pipeline() - def setup_ui(self): - """Setup the main UI components.""" - self.setWindowTitle("Pipeline Editor - Cluster4NPU") - self.setGeometry(100, 100, 1200, 800) +# def setup_ui(self): +# """Setup the main UI components.""" +# self.setWindowTitle("Pipeline Editor - Cluster4NPU") +# self.setGeometry(100, 100, 1200, 800) - # Create central widget - central_widget = QWidget() - self.setCentralWidget(central_widget) +# # Create central widget +# central_widget = QWidget() +# self.setCentralWidget(central_widget) - # Create main layout - main_layout = QVBoxLayout() - central_widget.setLayout(main_layout) +# # Create main layout +# main_layout = QVBoxLayout() +# central_widget.setLayout(main_layout) - # Create splitter for main content - splitter = QSplitter(Qt.Horizontal) - main_layout.addWidget(splitter) +# # Create splitter for main content +# splitter = QSplitter(Qt.Horizontal) +# main_layout.addWidget(splitter) - # Left panel for node graph - self.graph_widget = QWidget() - self.graph_layout = QVBoxLayout() - self.graph_widget.setLayout(self.graph_layout) - splitter.addWidget(self.graph_widget) +# # Left panel for node graph +# self.graph_widget = QWidget() +# self.graph_layout = QVBoxLayout() +# self.graph_widget.setLayout(self.graph_layout) +# splitter.addWidget(self.graph_widget) - # Right panel for properties and tools - right_panel = QWidget() - right_panel.setMaximumWidth(300) - right_layout = QVBoxLayout() - right_panel.setLayout(right_layout) +# # Right panel for properties and tools +# right_panel = QWidget() +# right_panel.setMaximumWidth(300) +# right_layout = QVBoxLayout() +# right_panel.setLayout(right_layout) - # Stage count widget (positioned at bottom right) - self.stage_count_widget = StageCountWidget() - right_layout.addWidget(self.stage_count_widget) +# # Stage count widget (positioned at bottom right) +# self.stage_count_widget = StageCountWidget() +# right_layout.addWidget(self.stage_count_widget) - # Properties panel - properties_label = QLabel("Properties") - properties_label.setFont(QFont("Arial", 10, QFont.Bold)) - right_layout.addWidget(properties_label) +# # Properties panel +# properties_label = QLabel("Properties") +# properties_label.setFont(QFont("Arial", 10, QFont.Bold)) +# right_layout.addWidget(properties_label) - self.properties_text = QTextEdit() - self.properties_text.setMaximumHeight(200) - self.properties_text.setReadOnly(True) - right_layout.addWidget(self.properties_text) +# self.properties_text = QTextEdit() +# self.properties_text.setMaximumHeight(200) +# self.properties_text.setReadOnly(True) +# right_layout.addWidget(self.properties_text) - # Pipeline info panel - info_label = QLabel("Pipeline Info") - info_label.setFont(QFont("Arial", 10, QFont.Bold)) - right_layout.addWidget(info_label) +# # Pipeline info panel +# info_label = QLabel("Pipeline Info") +# info_label.setFont(QFont("Arial", 10, QFont.Bold)) +# right_layout.addWidget(info_label) - self.info_text = QTextEdit() - self.info_text.setReadOnly(True) - right_layout.addWidget(self.info_text) +# self.info_text = QTextEdit() +# self.info_text.setReadOnly(True) +# right_layout.addWidget(self.info_text) - splitter.addWidget(right_panel) +# splitter.addWidget(right_panel) - # Set splitter proportions - splitter.setSizes([800, 300]) +# # Set splitter proportions +# splitter.setSizes([800, 300]) - # Create toolbar - self.create_toolbar() +# # Create toolbar +# self.create_toolbar() - # Create status bar - self.create_status_bar() +# # Create status bar +# self.create_status_bar() - # Apply styling - self.apply_styling() +# # Apply styling +# self.apply_styling() - def create_toolbar(self): - """Create the toolbar with pipeline operations.""" - toolbar = self.addToolBar("Pipeline Operations") +# def create_toolbar(self): +# """Create the toolbar with pipeline operations.""" +# toolbar = self.addToolBar("Pipeline Operations") - # Add nodes actions - add_input_action = QAction("Add Input", self) - add_input_action.triggered.connect(self.add_input_node) - toolbar.addAction(add_input_action) +# # Add nodes actions +# add_input_action = QAction("Add Input", self) +# add_input_action.triggered.connect(self.add_input_node) +# toolbar.addAction(add_input_action) - add_model_action = QAction("Add Model", self) - add_model_action.triggered.connect(self.add_model_node) - toolbar.addAction(add_model_action) +# add_model_action = QAction("Add Model", self) +# add_model_action.triggered.connect(self.add_model_node) +# toolbar.addAction(add_model_action) - add_preprocess_action = QAction("Add Preprocess", self) - add_preprocess_action.triggered.connect(self.add_preprocess_node) - toolbar.addAction(add_preprocess_action) +# add_preprocess_action = QAction("Add Preprocess", self) +# add_preprocess_action.triggered.connect(self.add_preprocess_node) +# toolbar.addAction(add_preprocess_action) - add_postprocess_action = QAction("Add Postprocess", self) - add_postprocess_action.triggered.connect(self.add_postprocess_node) - toolbar.addAction(add_postprocess_action) +# add_postprocess_action = QAction("Add Postprocess", self) +# add_postprocess_action.triggered.connect(self.add_postprocess_node) +# toolbar.addAction(add_postprocess_action) - add_output_action = QAction("Add Output", self) - add_output_action.triggered.connect(self.add_output_node) - toolbar.addAction(add_output_action) +# add_output_action = QAction("Add Output", self) +# add_output_action.triggered.connect(self.add_output_node) +# toolbar.addAction(add_output_action) - toolbar.addSeparator() +# toolbar.addSeparator() - # Pipeline actions - validate_action = QAction("Validate Pipeline", self) - validate_action.triggered.connect(self.validate_pipeline) - toolbar.addAction(validate_action) +# # Pipeline actions +# validate_action = QAction("Validate Pipeline", self) +# validate_action.triggered.connect(self.validate_pipeline) +# toolbar.addAction(validate_action) - clear_action = QAction("Clear Pipeline", self) - clear_action.triggered.connect(self.clear_pipeline) - toolbar.addAction(clear_action) +# clear_action = QAction("Clear Pipeline", self) +# clear_action.triggered.connect(self.clear_pipeline) +# toolbar.addAction(clear_action) - def create_status_bar(self): - """Create the status bar.""" - self.status_bar = QStatusBar() - self.setStatusBar(self.status_bar) - self.status_bar.showMessage("Ready") +# def create_status_bar(self): +# """Create the status bar.""" +# self.status_bar = QStatusBar() +# self.setStatusBar(self.status_bar) +# self.status_bar.showMessage("Ready") - def setup_node_graph(self): - """Setup the node graph widget.""" - if not NODEGRAPH_AVAILABLE: - # Show error message - error_label = QLabel("NodeGraphQt not available. Please install it to use the pipeline editor.") - error_label.setAlignment(Qt.AlignCenter) - error_label.setStyleSheet("color: red; font-size: 14px;") - self.graph_layout.addWidget(error_label) - return +# def setup_node_graph(self): +# """Setup the node graph widget.""" +# if not NODEGRAPH_AVAILABLE: +# # Show error message +# error_label = QLabel("NodeGraphQt not available. Please install it to use the pipeline editor.") +# error_label.setAlignment(Qt.AlignCenter) +# error_label.setStyleSheet("color: red; font-size: 14px;") +# self.graph_layout.addWidget(error_label) +# return - # Create node graph - self.node_graph = NodeGraph() +# # Create node graph +# self.node_graph = NodeGraph() - # Register node types - use ExactNode classes - print("Registering nodes with NodeGraphQt...") +# # Register node types - use ExactNode classes +# print("Registering nodes with NodeGraphQt...") - # Try to register ExactNode classes first - try: - self.node_graph.register_node(ExactInputNode) - print(f"✓ Registered ExactInputNode with identifier {ExactInputNode.__identifier__}") - except Exception as e: - print(f"✗ Failed to register ExactInputNode: {e}") +# # Try to register ExactNode classes first +# try: +# self.node_graph.register_node(ExactInputNode) +# print(f"✓ Registered ExactInputNode with identifier {ExactInputNode.__identifier__}") +# except Exception as e: +# print(f"✗ Failed to register ExactInputNode: {e}") - try: - self.node_graph.register_node(ExactModelNode) - print(f"✓ Registered ExactModelNode with identifier {ExactModelNode.__identifier__}") - except Exception as e: - print(f"✗ Failed to register ExactModelNode: {e}") +# try: +# self.node_graph.register_node(ExactModelNode) +# print(f"✓ Registered ExactModelNode with identifier {ExactModelNode.__identifier__}") +# except Exception as e: +# print(f"✗ Failed to register ExactModelNode: {e}") - try: - self.node_graph.register_node(ExactPreprocessNode) - print(f"✓ Registered ExactPreprocessNode with identifier {ExactPreprocessNode.__identifier__}") - except Exception as e: - print(f"✗ Failed to register ExactPreprocessNode: {e}") +# try: +# self.node_graph.register_node(ExactPreprocessNode) +# print(f"✓ Registered ExactPreprocessNode with identifier {ExactPreprocessNode.__identifier__}") +# except Exception as e: +# print(f"✗ Failed to register ExactPreprocessNode: {e}") - try: - self.node_graph.register_node(ExactPostprocessNode) - print(f"✓ Registered ExactPostprocessNode with identifier {ExactPostprocessNode.__identifier__}") - except Exception as e: - print(f"✗ Failed to register ExactPostprocessNode: {e}") +# try: +# self.node_graph.register_node(ExactPostprocessNode) +# print(f"✓ Registered ExactPostprocessNode with identifier {ExactPostprocessNode.__identifier__}") +# except Exception as e: +# print(f"✗ Failed to register ExactPostprocessNode: {e}") - try: - self.node_graph.register_node(ExactOutputNode) - print(f"✓ Registered ExactOutputNode with identifier {ExactOutputNode.__identifier__}") - except Exception as e: - print(f"✗ Failed to register ExactOutputNode: {e}") +# try: +# self.node_graph.register_node(ExactOutputNode) +# print(f"✓ Registered ExactOutputNode with identifier {ExactOutputNode.__identifier__}") +# except Exception as e: +# print(f"✗ Failed to register ExactOutputNode: {e}") - print("Node graph setup completed successfully") +# print("Node graph setup completed successfully") - # Connect node graph signals - self.node_graph.node_created.connect(self.on_node_created) - self.node_graph.node_deleted.connect(self.on_node_deleted) - self.node_graph.connection_changed.connect(self.on_connection_changed) +# # Connect node graph signals +# self.node_graph.node_created.connect(self.on_node_created) +# self.node_graph.node_deleted.connect(self.on_node_deleted) +# self.node_graph.connection_changed.connect(self.on_connection_changed) - # Connect additional signals for more comprehensive updates - if hasattr(self.node_graph, 'nodes_deleted'): - self.node_graph.nodes_deleted.connect(self.on_nodes_deleted) - if hasattr(self.node_graph, 'connection_sliced'): - self.node_graph.connection_sliced.connect(self.on_connection_changed) +# # Connect additional signals for more comprehensive updates +# if hasattr(self.node_graph, 'nodes_deleted'): +# self.node_graph.nodes_deleted.connect(self.on_nodes_deleted) +# if hasattr(self.node_graph, 'connection_sliced'): +# self.node_graph.connection_sliced.connect(self.on_connection_changed) - # Add node graph widget to layout - self.graph_layout.addWidget(self.node_graph.widget) +# # Add node graph widget to layout +# self.graph_layout.addWidget(self.node_graph.widget) - def setup_analysis_timer(self): - """Setup timer for pipeline analysis.""" - self.analysis_timer = QTimer() - self.analysis_timer.setSingleShot(True) - self.analysis_timer.timeout.connect(self.analyze_pipeline) - self.analysis_timer.setInterval(500) # 500ms delay +# def setup_analysis_timer(self): +# """Setup timer for pipeline analysis.""" +# self.analysis_timer = QTimer() +# self.analysis_timer.setSingleShot(True) +# self.analysis_timer.timeout.connect(self.analyze_pipeline) +# self.analysis_timer.setInterval(500) # 500ms delay - def apply_styling(self): - """Apply custom styling to the editor.""" - self.setStyleSheet(""" - QMainWindow { - background-color: #FAFAFA; - } - QToolBar { - background-color: #FFFFFF; - border: 1px solid #E0E0E0; - spacing: 5px; - padding: 5px; - } - QToolBar QAction { - padding: 5px 10px; - margin: 2px; - border: 1px solid #E0E0E0; - border-radius: 3px; - background-color: #FFFFFF; - } - QToolBar QAction:hover { - background-color: #F5F5F5; - } - QTextEdit { - border: 1px solid #E0E0E0; - border-radius: 3px; - padding: 5px; - background-color: #FFFFFF; - } - QLabel { - color: #333333; - } - """) +# def apply_styling(self): +# """Apply custom styling to the editor.""" +# self.setStyleSheet(""" +# QMainWindow { +# background-color: #FAFAFA; +# } +# QToolBar { +# background-color: #FFFFFF; +# border: 1px solid #E0E0E0; +# spacing: 5px; +# padding: 5px; +# } +# QToolBar QAction { +# padding: 5px 10px; +# margin: 2px; +# border: 1px solid #E0E0E0; +# border-radius: 3px; +# background-color: #FFFFFF; +# } +# QToolBar QAction:hover { +# background-color: #F5F5F5; +# } +# QTextEdit { +# border: 1px solid #E0E0E0; +# border-radius: 3px; +# padding: 5px; +# background-color: #FFFFFF; +# } +# QLabel { +# color: #333333; +# } +# """) - def add_input_node(self): - """Add an input node to the pipeline.""" - if self.node_graph: - print("Adding Input Node via toolbar...") - # Try multiple identifier formats - identifiers = [ - 'com.cluster.input_node', - 'com.cluster.input_node.ExactInputNode', - 'com.cluster.input_node.ExactInputNode.ExactInputNode' - ] - node = self.create_node_with_fallback(identifiers, "Input Node") - self.schedule_analysis() +# def add_input_node(self): +# """Add an input node to the pipeline.""" +# if self.node_graph: +# print("Adding Input Node via toolbar...") +# # Try multiple identifier formats +# identifiers = [ +# 'com.cluster.input_node', +# 'com.cluster.input_node.ExactInputNode', +# 'com.cluster.input_node.ExactInputNode.ExactInputNode' +# ] +# node = self.create_node_with_fallback(identifiers, "Input Node") +# self.schedule_analysis() - def add_model_node(self): - """Add a model node to the pipeline.""" - if self.node_graph: - print("Adding Model Node via toolbar...") - # Try multiple identifier formats - identifiers = [ - 'com.cluster.model_node', - 'com.cluster.model_node.ExactModelNode', - 'com.cluster.model_node.ExactModelNode.ExactModelNode' - ] - node = self.create_node_with_fallback(identifiers, "Model Node") - self.schedule_analysis() +# def add_model_node(self): +# """Add a model node to the pipeline.""" +# if self.node_graph: +# print("Adding Model Node via toolbar...") +# # Try multiple identifier formats +# identifiers = [ +# 'com.cluster.model_node', +# 'com.cluster.model_node.ExactModelNode', +# 'com.cluster.model_node.ExactModelNode.ExactModelNode' +# ] +# node = self.create_node_with_fallback(identifiers, "Model Node") +# self.schedule_analysis() - def add_preprocess_node(self): - """Add a preprocess node to the pipeline.""" - if self.node_graph: - print("Adding Preprocess Node via toolbar...") - # Try multiple identifier formats - identifiers = [ - 'com.cluster.preprocess_node', - 'com.cluster.preprocess_node.ExactPreprocessNode', - 'com.cluster.preprocess_node.ExactPreprocessNode.ExactPreprocessNode' - ] - node = self.create_node_with_fallback(identifiers, "Preprocess Node") - self.schedule_analysis() +# def add_preprocess_node(self): +# """Add a preprocess node to the pipeline.""" +# if self.node_graph: +# print("Adding Preprocess Node via toolbar...") +# # Try multiple identifier formats +# identifiers = [ +# 'com.cluster.preprocess_node', +# 'com.cluster.preprocess_node.ExactPreprocessNode', +# 'com.cluster.preprocess_node.ExactPreprocessNode.ExactPreprocessNode' +# ] +# node = self.create_node_with_fallback(identifiers, "Preprocess Node") +# self.schedule_analysis() - def add_postprocess_node(self): - """Add a postprocess node to the pipeline.""" - if self.node_graph: - print("Adding Postprocess Node via toolbar...") - # Try multiple identifier formats - identifiers = [ - 'com.cluster.postprocess_node', - 'com.cluster.postprocess_node.ExactPostprocessNode', - 'com.cluster.postprocess_node.ExactPostprocessNode.ExactPostprocessNode' - ] - node = self.create_node_with_fallback(identifiers, "Postprocess Node") - self.schedule_analysis() +# def add_postprocess_node(self): +# """Add a postprocess node to the pipeline.""" +# if self.node_graph: +# print("Adding Postprocess Node via toolbar...") +# # Try multiple identifier formats +# identifiers = [ +# 'com.cluster.postprocess_node', +# 'com.cluster.postprocess_node.ExactPostprocessNode', +# 'com.cluster.postprocess_node.ExactPostprocessNode.ExactPostprocessNode' +# ] +# node = self.create_node_with_fallback(identifiers, "Postprocess Node") +# self.schedule_analysis() - def add_output_node(self): - """Add an output node to the pipeline.""" - if self.node_graph: - print("Adding Output Node via toolbar...") - # Try multiple identifier formats - identifiers = [ - 'com.cluster.output_node', - 'com.cluster.output_node.ExactOutputNode', - 'com.cluster.output_node.ExactOutputNode.ExactOutputNode' - ] - node = self.create_node_with_fallback(identifiers, "Output Node") - self.schedule_analysis() +# def add_output_node(self): +# """Add an output node to the pipeline.""" +# if self.node_graph: +# print("Adding Output Node via toolbar...") +# # Try multiple identifier formats +# identifiers = [ +# 'com.cluster.output_node', +# 'com.cluster.output_node.ExactOutputNode', +# 'com.cluster.output_node.ExactOutputNode.ExactOutputNode' +# ] +# node = self.create_node_with_fallback(identifiers, "Output Node") +# self.schedule_analysis() - def create_node_with_fallback(self, identifiers, node_type): - """Try to create a node with multiple identifier fallbacks.""" - for identifier in identifiers: - try: - node = self.node_graph.create_node(identifier) - print(f"✓ Successfully created {node_type} with identifier: {identifier}") - return node - except Exception as e: - continue +# def create_node_with_fallback(self, identifiers, node_type): +# """Try to create a node with multiple identifier fallbacks.""" +# for identifier in identifiers: +# try: +# node = self.node_graph.create_node(identifier) +# print(f"✓ Successfully created {node_type} with identifier: {identifier}") +# return node +# except Exception as e: +# continue - print(f"Failed to create {node_type} with any identifier: {identifiers}") - return None +# print(f"Failed to create {node_type} with any identifier: {identifiers}") +# return None - def validate_pipeline(self): - """Validate the current pipeline configuration.""" - if not self.node_graph: - return +# def validate_pipeline(self): +# """Validate the current pipeline configuration.""" +# if not self.node_graph: +# return - print("🔍 Validating pipeline...") - summary = get_pipeline_summary(self.node_graph) +# print("🔍 Validating pipeline...") +# summary = get_pipeline_summary(self.node_graph) - if summary['valid']: - print(f"Pipeline validation passed - {summary['stage_count']} stages, {summary['total_nodes']} nodes") - QMessageBox.information(self, "Pipeline Validation", - f"Pipeline is valid!\n\n" - f"Stages: {summary['stage_count']}\n" - f"Total nodes: {summary['total_nodes']}") - else: - print(f"Pipeline validation failed: {summary['error']}") - QMessageBox.warning(self, "Pipeline Validation", - f"Pipeline validation failed:\n\n{summary['error']}") +# if summary['valid']: +# print(f"Pipeline validation passed - {summary['stage_count']} stages, {summary['total_nodes']} nodes") +# QMessageBox.information(self, "Pipeline Validation", +# f"Pipeline is valid!\n\n" +# f"Stages: {summary['stage_count']}\n" +# f"Total nodes: {summary['total_nodes']}") +# else: +# print(f"Pipeline validation failed: {summary['error']}") +# QMessageBox.warning(self, "Pipeline Validation", +# f"Pipeline validation failed:\n\n{summary['error']}") - def clear_pipeline(self): - """Clear the entire pipeline.""" - if self.node_graph: - print("🗑️ Clearing entire pipeline...") - self.node_graph.clear_session() - self.schedule_analysis() +# def clear_pipeline(self): +# """Clear the entire pipeline.""" +# if self.node_graph: +# print("🗑️ Clearing entire pipeline...") +# self.node_graph.clear_session() +# self.schedule_analysis() - def schedule_analysis(self): - """Schedule pipeline analysis after a delay.""" - if self.analysis_timer: - self.analysis_timer.start() +# def schedule_analysis(self): +# """Schedule pipeline analysis after a delay.""" +# if self.analysis_timer: +# self.analysis_timer.start() - def analyze_pipeline(self): - """Analyze the current pipeline and update stage count.""" - if not self.node_graph: - return +# def analyze_pipeline(self): +# """Analyze the current pipeline and update stage count.""" +# if not self.node_graph: +# return - try: - # Get pipeline summary - summary = get_pipeline_summary(self.node_graph) - current_stage_count = summary['stage_count'] +# try: +# # Get pipeline summary +# summary = get_pipeline_summary(self.node_graph) +# current_stage_count = summary['stage_count'] - # Print detailed pipeline analysis - self.print_pipeline_analysis(summary, current_stage_count) +# # Print detailed pipeline analysis +# self.print_pipeline_analysis(summary, current_stage_count) - # Update stage count widget - self.stage_count_widget.update_stage_count( - current_stage_count, - summary['valid'], - summary.get('error', '') - ) +# # Update stage count widget +# self.stage_count_widget.update_stage_count( +# current_stage_count, +# summary['valid'], +# summary.get('error', '') +# ) - # Update info panel - self.update_info_panel(summary) +# # Update info panel +# self.update_info_panel(summary) - # Update status bar - if summary['valid']: - self.status_bar.showMessage(f"Pipeline ready - {current_stage_count} stages") - else: - self.status_bar.showMessage(f"Pipeline invalid - {summary.get('error', 'Unknown error')}") +# # Update status bar +# if summary['valid']: +# self.status_bar.showMessage(f"Pipeline ready - {current_stage_count} stages") +# else: +# self.status_bar.showMessage(f"Pipeline invalid - {summary.get('error', 'Unknown error')}") - # Update previous count for next comparison - self.previous_stage_count = current_stage_count +# # Update previous count for next comparison +# self.previous_stage_count = current_stage_count - # Emit signal - self.stage_count_changed.emit(current_stage_count) +# # Emit signal +# self.stage_count_changed.emit(current_stage_count) - except Exception as e: - print(f"X Pipeline analysis error: {str(e)}") - self.stage_count_widget.update_stage_count(0, False, f"Analysis error: {str(e)}") - self.status_bar.showMessage(f"Analysis error: {str(e)}") +# except Exception as e: +# print(f"X Pipeline analysis error: {str(e)}") +# self.stage_count_widget.update_stage_count(0, False, f"Analysis error: {str(e)}") +# self.status_bar.showMessage(f"Analysis error: {str(e)}") - def print_pipeline_analysis(self, summary, current_stage_count): - """Print detailed pipeline analysis to terminal.""" - # Check if stage count changed - if current_stage_count != self.previous_stage_count: - if self.previous_stage_count == 0 and current_stage_count > 0: - print(f"Initial stage count: {current_stage_count}") - elif current_stage_count != self.previous_stage_count: - change = current_stage_count - self.previous_stage_count - if change > 0: - print(f"Stage count increased: {self.previous_stage_count} → {current_stage_count} (+{change})") - else: - print(f"Stage count decreased: {self.previous_stage_count} → {current_stage_count} ({change})") +# def print_pipeline_analysis(self, summary, current_stage_count): +# """Print detailed pipeline analysis to terminal.""" +# # Check if stage count changed +# if current_stage_count != self.previous_stage_count: +# if self.previous_stage_count == 0 and current_stage_count > 0: +# print(f"Initial stage count: {current_stage_count}") +# elif current_stage_count != self.previous_stage_count: +# change = current_stage_count - self.previous_stage_count +# if change > 0: +# print(f"Stage count increased: {self.previous_stage_count} → {current_stage_count} (+{change})") +# else: +# print(f"Stage count decreased: {self.previous_stage_count} → {current_stage_count} ({change})") - # Always print current pipeline status for clarity - print(f"Current Pipeline Status:") - print(f" • Stages: {current_stage_count}") - print(f" • Total Nodes: {summary['total_nodes']}") - print(f" • Model Nodes: {summary['model_nodes']}") - print(f" • Input Nodes: {summary['input_nodes']}") - print(f" • Output Nodes: {summary['output_nodes']}") - print(f" • Preprocess Nodes: {summary['preprocess_nodes']}") - print(f" • Postprocess Nodes: {summary['postprocess_nodes']}") - print(f" • Valid: {'V' if summary['valid'] else 'X'}") +# # Always print current pipeline status for clarity +# print(f"Current Pipeline Status:") +# print(f" • Stages: {current_stage_count}") +# print(f" • Total Nodes: {summary['total_nodes']}") +# print(f" • Model Nodes: {summary['model_nodes']}") +# print(f" • Input Nodes: {summary['input_nodes']}") +# print(f" • Output Nodes: {summary['output_nodes']}") +# print(f" • Preprocess Nodes: {summary['preprocess_nodes']}") +# print(f" • Postprocess Nodes: {summary['postprocess_nodes']}") +# print(f" • Valid: {'V' if summary['valid'] else 'X'}") - if not summary['valid'] and summary.get('error'): - print(f" • Error: {summary['error']}") +# if not summary['valid'] and summary.get('error'): +# print(f" • Error: {summary['error']}") - # Print stage details if available - if summary.get('stages') and len(summary['stages']) > 0: - print(f"Stage Details:") - for i, stage in enumerate(summary['stages'], 1): - model_name = stage['model_config'].get('node_name', 'Unknown Model') - preprocess_count = len(stage['preprocess_configs']) - postprocess_count = len(stage['postprocess_configs']) +# # Print stage details if available +# if summary.get('stages') and len(summary['stages']) > 0: +# print(f"Stage Details:") +# for i, stage in enumerate(summary['stages'], 1): +# model_name = stage['model_config'].get('node_name', 'Unknown Model') +# preprocess_count = len(stage['preprocess_configs']) +# postprocess_count = len(stage['postprocess_configs']) - stage_info = f" Stage {i}: {model_name}" - if preprocess_count > 0: - stage_info += f" (with {preprocess_count} preprocess)" - if postprocess_count > 0: - stage_info += f" (with {postprocess_count} postprocess)" +# stage_info = f" Stage {i}: {model_name}" +# if preprocess_count > 0: +# stage_info += f" (with {preprocess_count} preprocess)" +# if postprocess_count > 0: +# stage_info += f" (with {postprocess_count} postprocess)" - print(stage_info) - elif current_stage_count > 0: - print(f"{current_stage_count} stage(s) detected but details not available") +# print(stage_info) +# elif current_stage_count > 0: +# print(f"{current_stage_count} stage(s) detected but details not available") - print("─" * 50) # Separator line +# print("─" * 50) # Separator line - def update_info_panel(self, summary): - """Update the pipeline info panel with analysis results.""" - info_text = f"""Pipeline Analysis: +# def update_info_panel(self, summary): +# """Update the pipeline info panel with analysis results.""" +# info_text = f"""Pipeline Analysis: -Stage Count: {summary['stage_count']} -Valid: {'Yes' if summary['valid'] else 'No'} -{f"Error: {summary['error']}" if summary.get('error') else ""} +# Stage Count: {summary['stage_count']} +# Valid: {'Yes' if summary['valid'] else 'No'} +# {f"Error: {summary['error']}" if summary.get('error') else ""} -Node Statistics: -- Total Nodes: {summary['total_nodes']} -- Input Nodes: {summary['input_nodes']} -- Model Nodes: {summary['model_nodes']} -- Preprocess Nodes: {summary['preprocess_nodes']} -- Postprocess Nodes: {summary['postprocess_nodes']} -- Output Nodes: {summary['output_nodes']} +# Node Statistics: +# - Total Nodes: {summary['total_nodes']} +# - Input Nodes: {summary['input_nodes']} +# - Model Nodes: {summary['model_nodes']} +# - Preprocess Nodes: {summary['preprocess_nodes']} +# - Postprocess Nodes: {summary['postprocess_nodes']} +# - Output Nodes: {summary['output_nodes']} -Stages:""" +# Stages:""" - for i, stage in enumerate(summary.get('stages', []), 1): - info_text += f"\n Stage {i}: {stage['model_config']['node_name']}" - if stage['preprocess_configs']: - info_text += f" (with {len(stage['preprocess_configs'])} preprocess)" - if stage['postprocess_configs']: - info_text += f" (with {len(stage['postprocess_configs'])} postprocess)" +# for i, stage in enumerate(summary.get('stages', []), 1): +# info_text += f"\n Stage {i}: {stage['model_config']['node_name']}" +# if stage['preprocess_configs']: +# info_text += f" (with {len(stage['preprocess_configs'])} preprocess)" +# if stage['postprocess_configs']: +# info_text += f" (with {len(stage['postprocess_configs'])} postprocess)" - self.info_text.setPlainText(info_text) +# self.info_text.setPlainText(info_text) - def on_node_created(self, node): - """Handle node creation.""" - node_type = self.get_node_type_name(node) - print(f"+ Node added: {node_type}") - self.schedule_analysis() +# def on_node_created(self, node): +# """Handle node creation.""" +# node_type = self.get_node_type_name(node) +# print(f"+ Node added: {node_type}") +# self.schedule_analysis() - def on_node_deleted(self, node): - """Handle node deletion.""" - node_type = self.get_node_type_name(node) - print(f"- Node removed: {node_type}") - self.schedule_analysis() +# def on_node_deleted(self, node): +# """Handle node deletion.""" +# node_type = self.get_node_type_name(node) +# print(f"- Node removed: {node_type}") +# self.schedule_analysis() - def on_nodes_deleted(self, nodes): - """Handle multiple node deletion.""" - node_types = [self.get_node_type_name(node) for node in nodes] - print(f"- Multiple nodes removed: {', '.join(node_types)}") - self.schedule_analysis() +# def on_nodes_deleted(self, nodes): +# """Handle multiple node deletion.""" +# node_types = [self.get_node_type_name(node) for node in nodes] +# print(f"- Multiple nodes removed: {', '.join(node_types)}") +# self.schedule_analysis() - def on_connection_changed(self, input_port, output_port): - """Handle connection changes.""" - print(f"🔗 Connection changed: {input_port} <-> {output_port}") - self.schedule_analysis() +# def on_connection_changed(self, input_port, output_port): +# """Handle connection changes.""" +# print(f"🔗 Connection changed: {input_port} <-> {output_port}") +# self.schedule_analysis() - def get_node_type_name(self, node): - """Get a readable name for the node type.""" - if hasattr(node, 'NODE_NAME'): - return node.NODE_NAME - elif hasattr(node, '__identifier__'): - # Convert identifier to readable name - identifier = node.__identifier__ - if 'model' in identifier: - return "Model Node" - elif 'input' in identifier: - return "Input Node" - elif 'output' in identifier: - return "Output Node" - elif 'preprocess' in identifier: - return "Preprocess Node" - elif 'postprocess' in identifier: - return "Postprocess Node" +# def get_node_type_name(self, node): +# """Get a readable name for the node type.""" +# if hasattr(node, 'NODE_NAME'): +# return node.NODE_NAME +# elif hasattr(node, '__identifier__'): +# # Convert identifier to readable name +# identifier = node.__identifier__ +# if 'model' in identifier: +# return "Model Node" +# elif 'input' in identifier: +# return "Input Node" +# elif 'output' in identifier: +# return "Output Node" +# elif 'preprocess' in identifier: +# return "Preprocess Node" +# elif 'postprocess' in identifier: +# return "Postprocess Node" - # Fallback to class name - return type(node).__name__ +# # Fallback to class name +# return type(node).__name__ - def get_current_stage_count(self): - """Get the current stage count.""" - return self.stage_count_widget.stage_count if self.stage_count_widget else 0 +# def get_current_stage_count(self): +# """Get the current stage count.""" +# return self.stage_count_widget.stage_count if self.stage_count_widget else 0 - def get_pipeline_summary(self): - """Get the current pipeline summary.""" - if self.node_graph: - return get_pipeline_summary(self.node_graph) - return {'stage_count': 0, 'valid': False, 'error': 'No pipeline graph'} +# def get_pipeline_summary(self): +# """Get the current pipeline summary.""" +# if self.node_graph: +# return get_pipeline_summary(self.node_graph) +# return {'stage_count': 0, 'valid': False, 'error': 'No pipeline graph'} -def main(): - """Main function for testing the pipeline editor.""" - from PyQt5.QtWidgets import QApplication +# def main(): +# """Main function for testing the pipeline editor.""" +# from PyQt5.QtWidgets import QApplication - app = QApplication(sys.argv) +# app = QApplication(sys.argv) - editor = PipelineEditor() - editor.show() +# editor = PipelineEditor() +# editor.show() - sys.exit(app.exec_()) +# sys.exit(app.exec_()) -if __name__ == '__main__': - main() \ No newline at end of file +# if __name__ == '__main__': +# main() \ No newline at end of file