164 lines
6.6 KiB
Python
164 lines
6.6 KiB
Python
"""
|
|
Filename: participant.py
|
|
Description: Participant analysis window for FLARES
|
|
|
|
Author: Tyler de Zeeuw
|
|
License: GPL-3.0
|
|
"""
|
|
|
|
import os
|
|
from pathlib import Path
|
|
from datetime import datetime
|
|
|
|
from PySide6.QtWidgets import QGridLayout, QHBoxLayout, QMessageBox, QPushButton, QScrollArea, QWidget, QVBoxLayout, QLabel
|
|
from PySide6.QtCore import Qt, QSize
|
|
from PySide6.QtGui import QPixmap
|
|
|
|
from src.shared.flaresbasewidget import ClickableLabel, FlaresBaseWidget
|
|
from src.shared.shareddata import APP_NAME
|
|
|
|
|
|
class ParticipantImageViewerWidget(FlaresBaseWidget):
|
|
def __init__(self, haemo_dict, fig_bytes_dict):
|
|
super().__init__("ParticipantImage")
|
|
self.setAttribute(Qt.WidgetAttribute.WA_DeleteOnClose)
|
|
self.setWindowTitle(f"Participant Viewer - {APP_NAME.upper()}")
|
|
self.haemo_dict = haemo_dict
|
|
self.fig_bytes_dict = fig_bytes_dict
|
|
|
|
# Create mappings: file_path -> participant label and dropdown display text
|
|
self.participant_map = {} # file_path -> "Participant 1"
|
|
self.participant_dropdown_items = [] # "Participant 1 (filename)"
|
|
|
|
for i, file_path in enumerate(self.haemo_dict.keys(), start=1):
|
|
short_label = f"Participant {i}"
|
|
display_label = f"{short_label} ({os.path.basename(file_path)})"
|
|
self.participant_map[file_path] = short_label
|
|
self.participant_dropdown_items.append(display_label)
|
|
|
|
self.layout = QVBoxLayout(self)
|
|
self.top_bar = QHBoxLayout()
|
|
self.layout.addLayout(self.top_bar)
|
|
|
|
self.participant_dropdown = self._create_multiselect_dropdown(self.participant_dropdown_items)
|
|
self.participant_dropdown.currentIndexChanged.connect(self.update_participant_dropdown_label)
|
|
|
|
first_fig_dict = next(iter(self.fig_bytes_dict.values()))
|
|
image_label_items = list(first_fig_dict.keys())
|
|
|
|
self.image_index_dropdown = self._create_multiselect_dropdown(image_label_items)
|
|
self.image_index_dropdown.currentIndexChanged.connect(self.update_image_index_dropdown_label)
|
|
|
|
self.submit_button = QPushButton("Submit")
|
|
self.submit_button.clicked.connect(self.show_selected_images)
|
|
|
|
self.top_bar.addWidget(QLabel("Participants:"))
|
|
self.top_bar.addWidget(self.participant_dropdown)
|
|
self.top_bar.addWidget(QLabel("Image Indexes:"))
|
|
self.top_bar.addWidget(self.image_index_dropdown)
|
|
self.top_bar.addWidget(self.submit_button)
|
|
|
|
self.scroll = QScrollArea()
|
|
self.scroll.setWidgetResizable(True)
|
|
self.scroll_content = QWidget()
|
|
self.grid_layout = QGridLayout(self.scroll_content)
|
|
self.scroll.setWidget(self.scroll_content)
|
|
self.layout.addWidget(self.scroll)
|
|
|
|
self.thumb_size = QSize(280, 180)
|
|
|
|
self.save_button = QPushButton("Save Displayed Images")
|
|
self.save_button.clicked.connect(self.save_displayed_images)
|
|
self.top_bar.addWidget(self.save_button)
|
|
|
|
self.showMaximized()
|
|
|
|
|
|
|
|
def show_selected_images(self):
|
|
# Clear previous images
|
|
while self.grid_layout.count():
|
|
item = self.grid_layout.takeAt(0)
|
|
widget = item.widget()
|
|
if widget:
|
|
widget.deleteLater()
|
|
|
|
selected_display_names = self._get_checked_items(self.participant_dropdown)
|
|
# Map from display names back to file paths
|
|
selected_file_paths = []
|
|
for display_name in selected_display_names:
|
|
# Find file_path by matching display name
|
|
for fp, short_label in self.participant_map.items():
|
|
expected_display = f"{short_label} ({os.path.basename(fp)})"
|
|
if display_name == expected_display:
|
|
selected_file_paths.append(fp)
|
|
break
|
|
|
|
selected_labels = self._get_checked_items(self.image_index_dropdown)
|
|
|
|
row, col = 0, 0
|
|
for file_path in selected_file_paths:
|
|
fig_list = self.fig_bytes_dict.get(file_path, [])
|
|
participant_label = self.participant_map[file_path]
|
|
for label in selected_labels:
|
|
fig_bytes = fig_list.get(label)
|
|
if not fig_bytes:
|
|
continue
|
|
|
|
full_pixmap = QPixmap()
|
|
full_pixmap.loadFromData(fig_bytes)
|
|
|
|
thumbnail_pixmap = full_pixmap.scaled(
|
|
self.thumb_size,
|
|
Qt.AspectRatioMode.KeepAspectRatio,
|
|
Qt.TransformationMode.SmoothTransformation
|
|
)
|
|
|
|
container = QWidget()
|
|
hlayout = QHBoxLayout(container)
|
|
hlayout.setContentsMargins(0, 0, 0, 0)
|
|
hlayout.setSpacing(0)
|
|
hlayout.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
|
|
|
image_label = ClickableLabel(full_pixmap, thumbnail_pixmap)
|
|
image_label.setToolTip(f"{participant_label}\n{label}")
|
|
hlayout.addWidget(image_label)
|
|
|
|
self.grid_layout.addWidget(container, row, col)
|
|
|
|
col += 1
|
|
if col >= 6:
|
|
col = 0
|
|
row += 1
|
|
|
|
# Update dropdown labels after display
|
|
self.update_participant_dropdown_label()
|
|
self.update_image_index_dropdown_label()
|
|
|
|
|
|
def save_displayed_images(self):
|
|
# Ensure the folder exists
|
|
save_dir = Path("individual_images")
|
|
save_dir.mkdir(exist_ok=True)
|
|
|
|
selected_display_names = self._get_checked_items(self.participant_dropdown)
|
|
selected_image_labels = self._get_checked_items(self.image_index_dropdown)
|
|
|
|
for display_name in selected_display_names:
|
|
# Match display name to file path
|
|
for file_path, short_label in self.participant_map.items():
|
|
expected_display = f"{short_label} ({os.path.basename(file_path)})"
|
|
if display_name == expected_display:
|
|
fig_dict = self.fig_bytes_dict.get(file_path, {})
|
|
for label in selected_image_labels:
|
|
if label not in fig_dict:
|
|
continue
|
|
fig_bytes = fig_dict[label]
|
|
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
|
filename = f"{os.path.basename(file_path)}_{label}_{timestamp}.png"
|
|
output_path = save_dir / filename
|
|
with open(output_path, "wb") as f:
|
|
f.write(fig_bytes)
|
|
break # file_path matched; stop loop
|
|
|
|
QMessageBox.information(self, "Save Complete", f"Images saved to {save_dir.resolve()}") |