|
1 | | -# Classification Event Editor |
| 1 | +# 🏷️ Classification Event Editor |
2 | 2 |
|
3 | | -**Path:** `ui/classification/widgets/event_editor/` |
| 3 | +**Path:** `ui/classification/event_editor/` |
4 | 4 |
|
5 | 5 | ## Overview |
6 | 6 |
|
7 | | -The **Event Editor** package is responsible for the **Right Panel** of the Classification Mode. It serves as the primary interface for manual data annotation. unlike the Localization mode which deals with timestamps, this editor focuses on assigning global attributes (labels) to entire video clips or actions. |
| 7 | +The **Event Editor** package is responsible for the **Right Panel** of the Classification Mode. Originally serving as the interface for manual data annotation, it has been massively expanded into a **Tabbed Command Center**. |
8 | 8 |
|
9 | | -It features a **schema-driven UI**, meaning the widgets (Radio Buttons or Checkboxes) are dynamically rendered based on the loaded project JSON configuration. |
| 9 | +It now handles three distinct workflows: **Hand Annotation** (dynamic schema-driven UI), **Smart Annotation** (AI-powered single/batch inference with native visualizations), and **Model Training** (hyperparameter configuration and live console monitoring). |
10 | 10 |
|
11 | | -## Key Features |
| 11 | +## ✨ Key Features |
12 | 12 |
|
13 | | -* **Dynamic Rendering:** Automatically generates UI groups based on the label definition (Schema). |
14 | | -* **Schema Management:** Allows users to add new Categories (Heads) and Labels dynamically during runtime. |
15 | | -* **Annotation Input:** |
16 | | - * **Single-choice:** Uses Radio Button groups. |
17 | | - * **Multi-choice:** Uses Checkbox groups. |
18 | | -* **Task Information:** Displays the current task name. |
19 | | -* **History Control:** Hosts the Undo/Redo buttons for the classification workflow. |
| 13 | +* **Tabbed Interface:** Seamlessly separates the workflows into `Hand Annotation`, `Smart Annotation`, and `Train` tabs. |
| 14 | +* **Smart Contextual Controls:** The bottom "Confirm" and "Clear" buttons are tab-aware, executing different logic depending on whether the user is working with manual labels or AI predictions. |
| 15 | +* **Native Data Visualization:** Includes a custom `NativeDonutChart` built from scratch using `QPainter` to elegantly display AI confidence scores and probabilities with interactive hover tooltips. |
| 16 | +* **Batch Inference Control:** Provides dynamic start/end comboboxes that validate sequence logic, allowing users to run AI predictions over a specific subset of videos. |
| 17 | +* **In-App Training Monitor:** Hosts a complete UI for fine-tuning models, featuring hyperparameter inputs (Epochs, LR, Batch, Device), a live progress bar, and a real-time terminal console. |
| 18 | +* **Dynamic Rendering:** Automatically generates UI groups (Radio/Checkboxes) based on the label definition (Schema) for manual annotation. |
20 | 19 |
|
21 | | -## File Structure |
| 20 | +--- |
| 21 | + |
| 22 | +## 📂 File Structure |
22 | 23 |
|
23 | 24 | ```text |
24 | 25 | event_editor/ |
25 | 26 | ├── __init__.py # Package entry point; exports the main classes. |
26 | | -├── editor.py # Defines the main container widget (ClassificationEventEditor). |
| 27 | +├── editor.py # Defines the main container widget & Native Donut Chart. |
27 | 28 | └── dynamic_widgets.py # Defines the atomic UI components (Label Groups). |
28 | | -
|
29 | 29 | ``` |
30 | 30 |
|
31 | | -## Module Descriptions |
32 | | - |
33 | | -### 1. `editor.py` |
34 | | - |
35 | | -Contains the `ClassificationEventEditor` class (formerly `ClassRightPanel`). |
| 31 | +--- |
36 | 32 |
|
37 | | -**Responsibilities:** |
| 33 | +## 📝 Module Descriptions |
38 | 34 |
|
39 | | -* Layout management (Vertical layout). |
40 | | -* **Top Section:** Undo/Redo controls. |
41 | | -* **Info Section:** Task name display. |
42 | | -* **Schema Editor:** Input field and button to add new Label Heads. |
43 | | -* **Scroll Area:** Holds the dynamic list of label groups. |
44 | | -* **Bottom Section:** "Save Annotation" and "Clear Selection" buttons. |
| 35 | +### 1. `editor.py` |
| 36 | +Contains the core interface components for the right panel. |
45 | 37 |
|
46 | | -**Key Signals:** |
| 38 | +**`NativeDonutChart` (New):** |
| 39 | +* A highly optimized, custom PyQT component that draws interactive pie/donut charts. |
| 40 | +* Calculates angles and colors dynamically based on the AI's confidence dictionary (`conf_dict`). |
| 41 | +* Features math-driven collision detection to show specific probabilities when the user hovers over a slice. |
47 | 42 |
|
48 | | -* `add_head_clicked(str)`: Emitted when the user wants to add a new category. |
49 | | -* `remove_head_clicked(str)`: Emitted when a category is deleted. |
| 43 | +**`ClassificationEventEditor` (formerly `ClassRightPanel`):** |
| 44 | +* **Top Section**: Undo/Redo history controls and Task name display. |
| 45 | +* **Category Editor**: Global input field to add new Schema Heads. |
| 46 | +* **Tab 1 - Hand Annotation**: Holds the `QScrollArea` populated by dynamic Radio/Checkbox widgets for traditional manual labeling. |
| 47 | +* **Tab 2 - Smart Annotation**: Hosts the Single and Batch inference buttons, progress bars, the Donut Chart, and a text output area for batch prediction summaries. |
| 48 | +* **Tab 3 - Train**: Collects parameters (Device, Workers, Epochs) and provides "Start/Stop" controls tied to a live-updating `QTextEdit` console. |
| 49 | +* **Bottom Section**: Houses the global `Confirm` and `Clear Selection` buttons, which intelligently emit different signals (`hand_clear_requested` vs. `smart_clear_requested`) based on the active tab. |
50 | 50 |
|
51 | 51 | ### 2. `dynamic_widgets.py` |
52 | | - |
53 | | -Contains the reusable widgets that represent a single Label Head (Category). |
| 52 | +Contains the reusable widgets that represent a single Label Head (Category) inside the Hand Annotation tab. |
54 | 53 |
|
55 | 54 | * **`DynamicSingleLabelGroup`**: |
56 | | -* Used when the schema type is `single_label`. |
57 | | -* Renders a `QButtonGroup` with `QRadioButton`s. |
58 | | -* Allows adding/removing individual labels within the group. |
59 | | - |
| 55 | + * Used when the schema type is `single_label`. |
| 56 | + * Renders a tightly controlled `QButtonGroup` with `QRadioButton`s. |
| 57 | + * Allows adding/removing individual labels or the entire category dynamically. |
60 | 58 |
|
61 | 59 | * **`DynamicMultiLabelGroup`**: |
62 | | -* Used when the schema type is `multi_label`. |
63 | | -* Renders a list of `QCheckBox`es. |
64 | | -* Allows multiple selections simultaneously. |
65 | | - |
66 | | - |
| 60 | + * Used when the schema type is `multi_label`. |
| 61 | + * Renders a list of independent `QCheckBox`es. |
| 62 | + * Allows multiple selections simultaneously. |
67 | 63 |
|
68 | 64 | ### 3. `__init__.py` |
69 | | - |
70 | | -Exposes the classes to the rest of the application. |
| 65 | +Exposes the classes to the rest of the application and handles legacy aliasing. |
71 | 66 |
|
72 | 67 | ```python |
73 | 68 | from .editor import ClassificationEventEditor |
74 | 69 | from .dynamic_widgets import DynamicSingleLabelGroup, DynamicMultiLabelGroup |
75 | 70 |
|
| 71 | +ClassRightPanel = ClassificationEventEditor # Legacy support alias |
76 | 72 | ``` |
77 | 73 |
|
78 | | -## Usage Example |
| 74 | +--- |
79 | 75 |
|
80 | | -This module is typically instantiated by the `UnifiedTaskPanel` in the Main Window. |
| 76 | +## 🚀 Usage Example |
| 77 | + |
| 78 | +This module is typically instantiated by the main workspace layout. |
81 | 79 |
|
82 | 80 | ```python |
83 | | -# In ui/common/main_window.py |
84 | | -from ui.classification.widgets.event_editor import ClassificationEventEditor |
| 81 | +# In ui/classification/widgets/workspace.py |
| 82 | +from ui.classification.event_editor import ClassificationEventEditor |
85 | 83 |
|
86 | 84 | self.right_panel = ClassificationEventEditor() |
87 | 85 |
|
88 | | -# To populate the UI based on JSON schema: |
| 86 | +# To populate the Hand Annotation Tab based on JSON schema: |
89 | 87 | self.right_panel.setup_dynamic_labels(label_definitions_dict) |
90 | 88 |
|
91 | | -# To get the user's current selection: |
92 | | -user_data = self.right_panel.get_annotation() |
93 | | - |
94 | | -``` |
95 | | - |
96 | | -## Dependencies |
97 | | - |
98 | | -* **PyQt6**: Core UI framework. |
99 | | -* **utils**: Uses `get_square_remove_btn_style` for the delete buttons. |
100 | | - |
| 89 | +# Connect tab-aware signals to the Controller Logic: |
| 90 | +self.right_panel.annotation_saved.connect(self.manager.save_manual_annotation) |
| 91 | +self.right_panel.smart_confirm_requested.connect(self.manager.confirm_smart_prediction) |
0 commit comments