mainly whitespace, but also some generic qol improvements
This commit is contained in:
1 parent
2a5e3f5606
commit
3a8ffbdf70
26 files changed
+1871
-1224
No files matched your search
@@ -14,11 +14,12 @@ import pandas as pd
|
||||
from pandas import DataFrame
|
||||
|
||||
from PySide6.QtWidgets import QApplication, QComboBox, QDialog, QGridLayout, QHBoxLayout, QLabel, QLineEdit, QListView, QMessageBox, QPushButton, QScrollArea, QSizePolicy, QVBoxLayout, QWidget, QFrame, QSpinBox, QFileDialog
|
||||
from PySide6.QtGui import QPalette, QStandardItemModel, QStandardItem, QPixmap, QIntValidator, QDoubleValidator
|
||||
from PySide6.QtGui import QStandardItemModel, QStandardItem, QPixmap, QIntValidator, QDoubleValidator
|
||||
from PySide6.QtCore import QEvent, QPoint, QSize, QTimer, Qt, Signal
|
||||
|
||||
from src.shared.shareddata import APP_NAME, PIPELINE_STAGES
|
||||
|
||||
|
||||
class FullClickComboBox(QComboBox):
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent)
|
||||
@@ -28,16 +29,16 @@ class FullClickComboBox(QComboBox):
|
||||
|
||||
def eventFilter(self, obj, event):
|
||||
if obj == self.lineEdit():
|
||||
|
||||
|
||||
if event.type() == QEvent.MouseButtonPress:
|
||||
return True
|
||||
|
||||
if event.type() == QEvent.MouseButtonRelease:
|
||||
self.showPopup()
|
||||
return True
|
||||
|
||||
|
||||
return super().eventFilter(obj, event)
|
||||
|
||||
|
||||
|
||||
class ClickableLabel(QLabel):
|
||||
def __init__(self, full_pixmap: QPixmap, thumbnail_pixmap: QPixmap):
|
||||
@@ -47,7 +48,7 @@ class ClickableLabel(QLabel):
|
||||
self.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
||||
self.setFixedSize(thumbnail_pixmap.size())
|
||||
self.setStyleSheet("border: 1px solid gray; margin: 2px;")
|
||||
|
||||
|
||||
def mousePressEvent(self, event):
|
||||
viewer = QWidget()
|
||||
viewer.setWindowTitle(f"Expanded View - {APP_NAME.upper()}")
|
||||
@@ -100,12 +101,12 @@ class ParameterInputDialog(QDialog):
|
||||
self.scroll.setMaximumHeight(800)
|
||||
self.scroll.setVerticalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAsNeeded)
|
||||
self.scroll.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff)
|
||||
|
||||
|
||||
self.scroll_content = QWidget()
|
||||
self.scroll_layout = QVBoxLayout(self.scroll_content)
|
||||
self.scroll_layout.setContentsMargins(10, 10, 10, 10)
|
||||
self.scroll.setWidget(self.scroll_content)
|
||||
|
||||
|
||||
main_layout.addWidget(self.scroll)
|
||||
|
||||
for idx, param_list in params_dict.items():
|
||||
@@ -123,7 +124,7 @@ class ParameterInputDialog(QDialog):
|
||||
# Convert options to string just in case they aren't
|
||||
options = [str(opt) for opt in param_info.get("options", [])]
|
||||
widget.addItems(options)
|
||||
|
||||
|
||||
# Set default choice if it exists in the options list
|
||||
default_val = str(param_info.get("default", ""))
|
||||
if default_val in options:
|
||||
@@ -231,14 +232,14 @@ class FullClickComboBox(QComboBox):
|
||||
|
||||
def eventFilter(self, obj, event):
|
||||
if obj == self.lineEdit():
|
||||
|
||||
|
||||
if event.type() == QEvent.MouseButtonPress:
|
||||
return True
|
||||
|
||||
if event.type() == QEvent.MouseButtonRelease:
|
||||
self.showPopup()
|
||||
return True
|
||||
|
||||
|
||||
return super().eventFilter(obj, event)
|
||||
|
||||
|
||||
@@ -249,32 +250,32 @@ class FilePickerWidget(QWidget):
|
||||
|
||||
def __init__(self, default_val="", file_filter="JSON Files (*.json);;All Files (*)", parent=None):
|
||||
super().__init__(parent)
|
||||
|
||||
|
||||
# Inline layout to hold line edit and button side-by-side
|
||||
layout = QHBoxLayout(self)
|
||||
layout.setContentsMargins(0, 0, 0, 0)
|
||||
layout.setSpacing(5)
|
||||
|
||||
|
||||
self.line_edit = QLineEdit()
|
||||
self.line_edit.setText(str(default_val))
|
||||
self.line_edit.setPlaceholderText("Select file path...")
|
||||
# Forward internal text updates out through our custom component signal
|
||||
self.line_edit.textChanged.connect(self.textChanged.emit)
|
||||
|
||||
|
||||
self.browse_btn = QPushButton("Browse...")
|
||||
self.browse_btn.clicked.connect(self.open_file_dialog)
|
||||
|
||||
|
||||
layout.addWidget(self.line_edit)
|
||||
layout.addWidget(self.browse_btn)
|
||||
|
||||
|
||||
self.file_filter = file_filter
|
||||
|
||||
def open_file_dialog(self):
|
||||
# Open PySide6 native file browser
|
||||
file_path, _ = QFileDialog.getOpenFileName(
|
||||
self,
|
||||
"Select Configuration File",
|
||||
self.line_edit.text(),
|
||||
self,
|
||||
"Select Configuration File",
|
||||
self.line_edit.text(),
|
||||
self.file_filter
|
||||
)
|
||||
if file_path:
|
||||
@@ -308,7 +309,7 @@ class ParamSection(QWidget):
|
||||
"""
|
||||
|
||||
dirty_state_changed = Signal(bool)
|
||||
|
||||
|
||||
def __init__(self, section_data, global_widgets):
|
||||
super().__init__()
|
||||
layout = QVBoxLayout()
|
||||
@@ -317,7 +318,7 @@ class ParamSection(QWidget):
|
||||
self.dependencies = []
|
||||
self.selected_path = None
|
||||
|
||||
self.param_rows = []
|
||||
self.param_rows = []
|
||||
self.header_widgets = []
|
||||
self.dirty_params = {}
|
||||
self._updating_checkstates = False
|
||||
@@ -344,7 +345,7 @@ class ParamSection(QWidget):
|
||||
# Build label text and tooltips
|
||||
label_text = f"⚠️ {param_name}" if is_advanced else param_name
|
||||
label = QLabel(label_text)
|
||||
|
||||
|
||||
if is_advanced:
|
||||
label.setToolTip(f"ADVANCED: {help_text}")
|
||||
else:
|
||||
@@ -371,19 +372,19 @@ class ParamSection(QWidget):
|
||||
widget.setCurrentText(str(default_val))
|
||||
widget.currentTextChanged.connect(lambda _, p=param_name: self.check_if_changed(p))
|
||||
widget.currentTextChanged.connect(self.notify_global_update)
|
||||
|
||||
|
||||
elif param_type == int or "int" in type_str:
|
||||
widget = QLineEdit()
|
||||
widget.setValidator(QIntValidator())
|
||||
widget.setText(str(default_val))
|
||||
widget.textChanged.connect(lambda _, p=param_name: self.check_if_changed(p))
|
||||
|
||||
|
||||
elif param_type == float or "float" in type_str:
|
||||
widget = QLineEdit()
|
||||
widget.setValidator(QDoubleValidator())
|
||||
widget.setText(str(default_val))
|
||||
widget.textChanged.connect(lambda _, p=param_name: self.check_if_changed(p))
|
||||
|
||||
|
||||
elif param_type == list or "list" in type_str:
|
||||
options = param.get("options", [])
|
||||
if param.get("exclusive", True):
|
||||
@@ -406,12 +407,12 @@ class ParamSection(QWidget):
|
||||
else:
|
||||
widget.setValue(15)
|
||||
widget.valueChanged.connect(lambda _, p=param_name: self.check_if_changed(p))
|
||||
|
||||
|
||||
elif param_type == "json_file":
|
||||
widget = FilePickerWidget(default_val=default_val, file_filter="JSON Files (*.json)")
|
||||
widget.textChanged.connect(lambda _, p=param_name: self.check_if_changed(p))
|
||||
|
||||
else:
|
||||
|
||||
else:
|
||||
widget = QLineEdit()
|
||||
widget.setText(str(default_val))
|
||||
widget.textChanged.connect(lambda _, p=param_name: self.check_if_changed(p))
|
||||
@@ -447,7 +448,7 @@ class ParamSection(QWidget):
|
||||
def update_theme_colors(self):
|
||||
self.title_label.style().unpolish(self.title_label)
|
||||
self.title_label.style().polish(self.title_label)
|
||||
|
||||
|
||||
def is_different(self, val_a, val_b, param_type=None):
|
||||
"""Compares two parameter values to determine if they differ."""
|
||||
type_str = str(param_type).lower()
|
||||
@@ -566,7 +567,7 @@ class ParamSection(QWidget):
|
||||
normal_items.append(item)
|
||||
state = Qt.Checked if item.text() in defaults else Qt.Unchecked
|
||||
item.setCheckState(state)
|
||||
|
||||
|
||||
# Sync toggle select all item
|
||||
toggle_item = model.item(1)
|
||||
if toggle_item and normal_items:
|
||||
@@ -637,7 +638,7 @@ class ParamSection(QWidget):
|
||||
|
||||
for hw in self.header_widgets:
|
||||
hw.setVisible(has_visible_rows)
|
||||
|
||||
|
||||
self.setVisible(has_visible_rows)
|
||||
|
||||
def has_any_changes(self):
|
||||
@@ -663,7 +664,7 @@ class ParamSection(QWidget):
|
||||
for cond in dep["conditions"]:
|
||||
parent_name = cond.get("parent_name") or cond.get("parent")
|
||||
required_val = str(cond.get("depends_value") if "depends_value" in cond else cond.get("value", "True"))
|
||||
|
||||
|
||||
parent_info = self.widgets.get(parent_name)
|
||||
if not parent_info:
|
||||
all_conditions_met = False
|
||||
@@ -745,7 +746,7 @@ class ParamSection(QWidget):
|
||||
toggle_item.setCheckState(Qt.Checked if all_checked else Qt.Unchecked)
|
||||
|
||||
self._updating_checkstates = False
|
||||
|
||||
|
||||
if param_name:
|
||||
self.update_dropdown_label(param_name)
|
||||
self.check_if_changed(param_name)
|
||||
@@ -813,7 +814,7 @@ class ParamSection(QWidget):
|
||||
|
||||
selected = self._get_checked_items(widget)
|
||||
widget.lineEdit().setText(", ".join(selected) if selected else "<None Selected>")
|
||||
|
||||
|
||||
# def update_annotation_dropdown_from_loaded_files(self, bubble_widgets, button1):
|
||||
# file_paths = [bubble.file_path for bubble in bubble_widgets.values()]
|
||||
# if not file_paths:
|
||||
@@ -822,12 +823,12 @@ class ParamSection(QWidget):
|
||||
# # 1. Start the UI immediately
|
||||
# progress = QProgressDialog("Accessing Workers...", "Cancel", 0, len(file_paths), self)
|
||||
# progress.setWindowModality(Qt.WindowModality.WindowModal)
|
||||
# progress.setMinimumDuration(0)
|
||||
# progress.setMinimumDuration(0)
|
||||
# progress.setValue(0)
|
||||
|
||||
|
||||
# # Force the UI to draw the window NOW before we start the loop
|
||||
# progress.show()
|
||||
# QApplication.processEvents()
|
||||
# QApplication.processEvents()
|
||||
|
||||
# annotation_sets = []
|
||||
|
||||
@@ -843,7 +844,7 @@ class ParamSection(QWidget):
|
||||
# # This call is now nearly instant because the process is already warm
|
||||
# future = self.file_executor.submit(_extract_annotations, path)
|
||||
# try:
|
||||
# labels_list = future.result()
|
||||
# labels_list = future.result()
|
||||
# if labels_list:
|
||||
# annotation_sets.append(set(labels_list))
|
||||
# except Exception as e:
|
||||
@@ -870,10 +871,10 @@ class ProgressBubble(QWidget):
|
||||
file_path (str): Associated file path stored with the bubble.
|
||||
|
||||
"""
|
||||
|
||||
|
||||
clicked = Signal(object)
|
||||
rightClicked = Signal(object, QPoint)
|
||||
|
||||
|
||||
def __init__(self, display_name, file_path):
|
||||
super().__init__()
|
||||
|
||||
@@ -964,7 +965,7 @@ class ProgressBubble(QWidget):
|
||||
else:
|
||||
rect.setStyleSheet("background-color: white; border: 1px solid gray;")
|
||||
|
||||
|
||||
|
||||
def mark_cancelled(self):
|
||||
for i, rect in enumerate(self.rects):
|
||||
if i < self.current_step:
|
||||
@@ -1074,7 +1075,7 @@ class FlaresBaseWidget(QWidget):
|
||||
model.itemChanged.connect(on_item_changed)
|
||||
combo.setInsertPolicy(QComboBox.NoInsert)
|
||||
return combo
|
||||
|
||||
|
||||
|
||||
# def _get_checked_items(self, combo):
|
||||
# model = combo.model()
|
||||
@@ -1084,20 +1085,20 @@ class FlaresBaseWidget(QWidget):
|
||||
# if item.checkState() == Qt.Checked:
|
||||
# checked.append(item.text())
|
||||
# return checked
|
||||
|
||||
|
||||
def _get_checked_items(
|
||||
self,
|
||||
combo: QComboBox | None = None
|
||||
) -> list[str]:
|
||||
|
||||
target = combo if combo is not None else getattr(self, 'participant_dropdown', None)
|
||||
|
||||
|
||||
if target is None or target.model() is None:
|
||||
return []
|
||||
|
||||
model = target.model()
|
||||
checked_items = []
|
||||
|
||||
|
||||
# Exclusion list: any item text that should never be treated as data
|
||||
forbidden = {"Toggle All", "Select All", "<None Selected>", "Toggle"}
|
||||
|
||||
@@ -1108,7 +1109,7 @@ class FlaresBaseWidget(QWidget):
|
||||
# Only add if it's not a 'UI control' item
|
||||
if text not in forbidden and not text.startswith("Toggle"):
|
||||
checked_items.append(text)
|
||||
|
||||
|
||||
return checked_items
|
||||
|
||||
|
||||
@@ -1125,7 +1126,7 @@ class FlaresBaseWidget(QWidget):
|
||||
|
||||
# 1. Figure out which dropdown we are talking to
|
||||
target_combo = combo if combo is not None else getattr(self, "participant_dropdown", None)
|
||||
|
||||
|
||||
if target_combo is None:
|
||||
return # Safety check: nothing to update
|
||||
|
||||
@@ -1141,11 +1142,11 @@ class FlaresBaseWidget(QWidget):
|
||||
# 3. Conditional trigger for event updates
|
||||
# We only update events if we aren't in one of the excluded viewers
|
||||
excluded_viewers = {
|
||||
"ParticipantImage",
|
||||
"ParticipantFoldChannels",
|
||||
"ExportToCSV",
|
||||
"ParticipantImage",
|
||||
"ParticipantFoldChannels",
|
||||
"ExportToCSV",
|
||||
}
|
||||
|
||||
|
||||
if getattr(self, "caller", None) not in excluded_viewers:
|
||||
self._update_event_dropdown()
|
||||
|
||||
@@ -1162,7 +1163,7 @@ class FlaresBaseWidget(QWidget):
|
||||
|
||||
def _update_event_dropdown(self):
|
||||
is_split_group = hasattr(self, 'participant_dropdown_a') and hasattr(self, 'participant_dropdown_b')
|
||||
|
||||
|
||||
bypass = False
|
||||
main_win = next((w for w in QApplication.topLevelWidgets()
|
||||
if w.objectName() == "MainApplication" or hasattr(w, "missing_events_bypass")), None)
|
||||
@@ -1199,7 +1200,7 @@ class FlaresBaseWidget(QWidget):
|
||||
|
||||
if not bypass:
|
||||
final_annotations = set.intersection(*(sets_a + sets_b))
|
||||
else:
|
||||
else:
|
||||
all_events_a = {event for s in sets_a for event in s}
|
||||
all_events_b = {event for s in sets_b for event in s}
|
||||
|
||||
@@ -1216,7 +1217,7 @@ class FlaresBaseWidget(QWidget):
|
||||
valid_b.add(event)
|
||||
|
||||
final_annotations = valid_a.intersection(valid_b)
|
||||
|
||||
|
||||
else:
|
||||
names = self._get_checked_items(self.participant_dropdown)
|
||||
if not names:
|
||||
@@ -1288,8 +1289,7 @@ class FlaresBaseWidget(QWidget):
|
||||
self._updating_checkstates = False
|
||||
|
||||
model.itemChanged.connect(on_item_changed)
|
||||
|
||||
|
||||
|
||||
|
||||
def update_participant_list_for_group(self, group_name=None, combo=None):
|
||||
|
||||
@@ -1323,7 +1323,7 @@ class FlaresBaseWidget(QWidget):
|
||||
# 4. Refresh the Model
|
||||
model = target_combo.model()
|
||||
model.clear()
|
||||
|
||||
|
||||
for text in ["<None Selected>", "Toggle Select All"]:
|
||||
item = QStandardItem(str(text))
|
||||
if text == "Toggle Select All":
|
||||
@@ -1343,7 +1343,7 @@ class FlaresBaseWidget(QWidget):
|
||||
target_combo.setEnabled(True)
|
||||
# Get file paths (handles target_group as int or str)
|
||||
group_file_paths = self.group_to_paths.get(target_group, [])
|
||||
|
||||
|
||||
for i, file_path in enumerate(group_file_paths, start=1):
|
||||
short_label = f"Participant {i}"
|
||||
display_label = f"{short_label} ({os.path.basename(file_path)})"
|
||||
@@ -1363,8 +1363,8 @@ class InterGroupUIMixin:
|
||||
participant_map: dict[str, str]
|
||||
|
||||
def setup_inter_group_ui(
|
||||
self,
|
||||
index_texts: Sequence[str],
|
||||
self,
|
||||
index_texts: Sequence[str],
|
||||
placeholder_text: str = ""
|
||||
) -> None:
|
||||
|
||||
@@ -1394,7 +1394,7 @@ class InterGroupUIMixin:
|
||||
self.event_dropdown = QComboBox()
|
||||
self.event_dropdown.addItem("<None Selected>")
|
||||
|
||||
|
||||
|
||||
self.participant_dropdown_a = self._create_multiselect_dropdown([])
|
||||
line_edit = self.participant_dropdown_a.lineEdit()
|
||||
assert line_edit is not None, "Dropdown A must be editable to have a lineEdit"
|
||||
@@ -1453,10 +1453,10 @@ class InterGroupUIMixin:
|
||||
def _update_group_b_options(self):
|
||||
"""Triggered when Group B changes: Update Group A to exclude B's choice"""
|
||||
selected_b = self.group_b_dropdown.currentText()
|
||||
|
||||
|
||||
# Refresh Group A and exclude what was just picked in Group B
|
||||
self._refresh_group_dropdown(self.group_a_dropdown, exclude=selected_b)
|
||||
|
||||
|
||||
# Update the participants for Group B
|
||||
self.update_participant_list_for_group(selected_b, self.participant_dropdown_b)
|
||||
self._update_event_dropdown()
|
||||
@@ -1464,10 +1464,10 @@ class InterGroupUIMixin:
|
||||
def _update_group_a_options(self):
|
||||
"""Triggered when Group A changes: Update Group B to exclude A's choice"""
|
||||
selected_a = self.group_a_dropdown.currentText()
|
||||
|
||||
|
||||
# Refresh Group B and exclude what was just picked in Group A
|
||||
self._refresh_group_dropdown(self.group_b_dropdown, exclude=selected_a)
|
||||
|
||||
|
||||
# Update the participants for Group A
|
||||
self.update_participant_list_for_group(selected_a, self.participant_dropdown_a)
|
||||
self._update_event_dropdown()
|
||||
@@ -1491,8 +1491,6 @@ class InterGroupUIMixin:
|
||||
dropdown.setCurrentIndex(0) # Reset to "<None Selected>"
|
||||
dropdown.blockSignals(False)
|
||||
|
||||
|
||||
|
||||
|
||||
def _get_file_paths_from_labels(self, labels, group_name):
|
||||
file_paths = []
|
||||
@@ -1516,14 +1514,14 @@ class InterGroupUIMixin:
|
||||
file_paths.append(file_path)
|
||||
|
||||
return file_paths
|
||||
|
||||
|
||||
def get_common_request_data(
|
||||
self,
|
||||
parameterized_indexes: dict[int, list[dict[str, Any]]],
|
||||
df_ind_dict: dict[str, DataFrame] | None = None,
|
||||
contrast_dfs: dict[str, dict[str, Any]] | None = None,
|
||||
) -> tuple[str | None, list[str], list[str], list[str], list[int], dict[str, Any]] | None:
|
||||
|
||||
|
||||
selected_event = self.event_dropdown.currentText()
|
||||
if selected_event == "<None Selected>":
|
||||
selected_event = None
|
||||
@@ -1562,7 +1560,7 @@ class InterGroupUIMixin:
|
||||
}
|
||||
|
||||
dynamic_rois = []
|
||||
|
||||
|
||||
if df_ind_dict:
|
||||
roi_set = set()
|
||||
for fp in all_selected_paths:
|
||||
@@ -1572,7 +1570,7 @@ class InterGroupUIMixin:
|
||||
|
||||
if roi_set:
|
||||
dynamic_rois = sorted(list(roi_set))
|
||||
|
||||
|
||||
# Fallback to prevent UI crashes if JSON file doesn't exist or is empty
|
||||
if not dynamic_rois:
|
||||
dynamic_rois = ["Option 1", "Option 2"]
|
||||
@@ -1588,7 +1586,7 @@ class InterGroupUIMixin:
|
||||
# If an event is selected, only keep contrasts containing the event name as a substring.
|
||||
if selected_event is None or selected_event in contrast_name:
|
||||
contrast_set.add(contrast_name)
|
||||
|
||||
|
||||
# Sort them cleanly for the UI
|
||||
dynamic_contrasts = sorted(list(contrast_set))
|
||||
|
||||
@@ -1634,15 +1632,15 @@ class InterGroupUIMixin:
|
||||
selected_indexes,
|
||||
param_values,
|
||||
)
|
||||
|
||||
|
||||
|
||||
class CSVUIMixin:
|
||||
|
||||
def setup_csv_ui(
|
||||
self,
|
||||
self,
|
||||
index_texts: Sequence[str]
|
||||
) -> None:
|
||||
|
||||
|
||||
# Create mappings: file_path -> participant label and dropdown display text
|
||||
self.participant_map: dict[str, str] = {} # file_path -> "Participant 1"
|
||||
self.participant_dropdown_items: list[str] = [] # "Participant 1 (filename)"
|
||||
@@ -1659,7 +1657,7 @@ class CSVUIMixin:
|
||||
|
||||
self.participant_dropdown: FullClickComboBox = self._create_multiselect_dropdown(self.participant_dropdown_items)
|
||||
self.participant_dropdown.currentIndexChanged.connect(self.update_participant_dropdown_label)
|
||||
|
||||
|
||||
self.index_texts = index_texts
|
||||
|
||||
self.image_index_dropdown: FullClickComboBox = self._create_multiselect_dropdown(self.index_texts)
|
||||
@@ -1693,14 +1691,14 @@ class CSVUIMixin:
|
||||
class IntraGroupUIMixin:
|
||||
|
||||
def setup_intra_group_ui(
|
||||
self,
|
||||
index_texts: Sequence[str],
|
||||
self,
|
||||
index_texts: Sequence[str],
|
||||
placeholder_text: str = ""
|
||||
) -> None:
|
||||
|
||||
|
||||
self.show_all_events = True
|
||||
self._updating_checkstates = False
|
||||
|
||||
|
||||
# Create mappings: file_path -> participant label and dropdown display text
|
||||
self.participant_map: dict[str, str] = {} # file_path -> "Participant 1"
|
||||
self.participant_dropdown_items = [] # "Participant 1 (filename)"
|
||||
@@ -1771,7 +1769,7 @@ class IntraGroupUIMixin:
|
||||
df_ind_dict: dict[str, DataFrame] | None = None,
|
||||
contrast_dfs: dict[str, dict[str, Any]] | None = None,
|
||||
) -> tuple[str | None, list[str], list[int], dict[str, Any]] | None:
|
||||
|
||||
|
||||
selected_event = self.event_dropdown.currentText()
|
||||
if selected_event == "<None Selected>":
|
||||
selected_event = None
|
||||
@@ -1793,7 +1791,7 @@ class IntraGroupUIMixin:
|
||||
if raw is not None and hasattr(raw, "annotations"):
|
||||
if selected_event in raw.annotations.description:
|
||||
valid_paths.append(fp)
|
||||
|
||||
|
||||
selected_file_paths = valid_paths
|
||||
|
||||
selected_indexes = [
|
||||
@@ -1803,7 +1801,7 @@ class IntraGroupUIMixin:
|
||||
if not selected_file_paths:
|
||||
print("No participants selected.")
|
||||
return
|
||||
|
||||
|
||||
|
||||
# Inject full_text from index_texts
|
||||
for idx, params_list in parameterized_indexes.items():
|
||||
@@ -1814,7 +1812,7 @@ class IntraGroupUIMixin:
|
||||
indexes_needing_params = {idx: parameterized_indexes[idx] for idx in selected_indexes if idx in parameterized_indexes}
|
||||
|
||||
dynamic_rois = []
|
||||
|
||||
|
||||
if df_ind_dict:
|
||||
roi_set = set()
|
||||
for fp in selected_file_paths:
|
||||
@@ -1840,7 +1838,7 @@ class IntraGroupUIMixin:
|
||||
# If an event is selected, only keep contrasts containing the event name as a substring.
|
||||
if selected_event is None or selected_event in contrast_name:
|
||||
contrast_set.add(contrast_name)
|
||||
|
||||
|
||||
# Sort them cleanly for the UI
|
||||
dynamic_contrasts = sorted(list(contrast_set))
|
||||
|
||||
@@ -1868,7 +1866,6 @@ class IntraGroupUIMixin:
|
||||
param_info["options"] = dynamic_contrasts
|
||||
param_info["default"] = dynamic_contrasts[0] if dynamic_contrasts else ""
|
||||
|
||||
|
||||
param_values = {}
|
||||
if indexes_needing_params:
|
||||
dialog = ParameterInputDialog(indexes_needing_params, parent=self)
|
||||
@@ -1878,21 +1875,22 @@ class IntraGroupUIMixin:
|
||||
return
|
||||
else:
|
||||
return
|
||||
|
||||
|
||||
return (
|
||||
selected_event,
|
||||
selected_file_paths,
|
||||
selected_indexes,
|
||||
param_values,
|
||||
)
|
||||
|
||||
|
||||
|
||||
class ParticipantUIMixin:
|
||||
def setup_participant_ui(
|
||||
self,
|
||||
self,
|
||||
index_texts: Sequence[str],
|
||||
placeholder_text: str = ""
|
||||
) -> None:
|
||||
|
||||
|
||||
# Create mappings: file_path -> participant label and dropdown display text
|
||||
self.participant_map: dict[str, str] = {} # file_path -> "Participant 1"
|
||||
self.participant_dropdown_items = [] # "Participant 1 (filename)"
|
||||
@@ -1913,7 +1911,6 @@ class ParticipantUIMixin:
|
||||
self.event_dropdown = QComboBox()
|
||||
self.event_dropdown.addItem("<None Selected>")
|
||||
|
||||
|
||||
self.index_texts = index_texts
|
||||
|
||||
self.image_index_dropdown = self._create_multiselect_dropdown(self.index_texts)
|
||||
@@ -1968,8 +1965,6 @@ class ParticipantUIMixin:
|
||||
]
|
||||
|
||||
|
||||
|
||||
|
||||
# Inject full_text from index_texts
|
||||
for idx, params_list in parameterized_indexes.items():
|
||||
full_text = self.index_texts[idx] if idx < len(self.index_texts) else f"{idx} (No label found)"
|
||||
@@ -1987,10 +1982,10 @@ class ParticipantUIMixin:
|
||||
return
|
||||
else:
|
||||
return
|
||||
|
||||
|
||||
return (
|
||||
selected_event,
|
||||
selected_file_paths,
|
||||
selected_indexes,
|
||||
param_values,
|
||||
selected_event,
|
||||
selected_file_paths,
|
||||
selected_indexes,
|
||||
param_values,
|
||||
)
|
||||
Reference in new issue
Block a user