diff --git a/debye_bec/bec_widgets/widgets/data_viewer/data_viewer.py b/debye_bec/bec_widgets/widgets/data_viewer/data_viewer.py index b745ffc..9dc185e 100644 --- a/debye_bec/bec_widgets/widgets/data_viewer/data_viewer.py +++ b/debye_bec/bec_widgets/widgets/data_viewer/data_viewer.py @@ -16,7 +16,7 @@ from bec_widgets.utils.colors import apply_theme, get_accent_colors from bec_widgets.utils.error_popups import SafeSlot # pylint: disable=E0611 -from qtpy.QtWidgets import QApplication, QVBoxLayout, QWidget +from qtpy.QtWidgets import QApplication, QFileDialog, QVBoxLayout, QWidget from .panels.input_panel import InputPanel from .panels.scan_view import ScanViewer @@ -55,8 +55,9 @@ class DataViewer(BECWidget, QWidget): self.current_row = 0 self.input.scan_sel.currentItemChanged_connect(self.scan_sel_changed) - self.input.load_button.clicked_connect(self.load_scan) - self.input.unload_button.clicked_connect(self.unload_all_scans) + self.input.load_button.clicked_connect(self.load_scan_from_history) + self.input.load_from_folder_button.clicked_connect(self.load_scan_from_folder) + self.viewer.unload_button.clicked_connect(self.unload_all_scans) self.input.open_fm_button.clicked_connect(self.open_in_file_manager) def apply_theme(self, theme: Literal["dark", "light"]): @@ -89,7 +90,7 @@ class DataViewer(BECWidget, QWidget): ) @SafeSlot() - def load_scan(self, *_): + def load_scan_from_history(self, *_): """ Loads a scan. Find all files within the scan folder, sort them and then load the files in the scan view @@ -97,23 +98,46 @@ class DataViewer(BECWidget, QWidget): if len(self.history) > 0: scan = self.history[self.current_row] base_filepath = scan["file_components"][0].decode().rsplit("/", 1)[0] - filenames = [ - f - for f in os.listdir(base_filepath) - if os.path.isfile(os.path.join(base_filepath, f)) - ] + self.load_scan(base_filepath) - def sort_priority(name): - if "master" in name: - return 0 - if name.endswith(".h5"): - return 1 - return 2 + @SafeSlot() + def load_scan_from_folder(self, *_): + """ + Loads a scan from a folder. Find all files within the scan folder, sort them and + then load the files in the scan view + """ - sorted_files = [ - f"{base_filepath}/{name}" for name in sorted(filenames, key=sort_priority) - ] - self.viewer.load_files(sorted_files) + hostname = self.client._hostname + start = hostname.find("x") + if start != -1: + beamline = hostname[start : start + 5] + active_account = self.client.active_account + start_folder = f"/sls/{beamline}/data/{active_account}/raw" + else: + start_folder = "/sls" + base_filepath = QFileDialog.getExistingDirectory(self, "Open Scan Folder", start_folder) + + if base_filepath != "": + self.load_scan(base_filepath) + + def load_scan(self, base_filepath): + """ + Loads a scan from a base_filepath. Find all files within the scan folder, sort them and + then load the files in the scan view + """ + filenames = [ + f for f in os.listdir(base_filepath) if os.path.isfile(os.path.join(base_filepath, f)) + ] + + def sort_priority(name): + if "master" in name: + return 0 + if name.endswith(".h5"): + return 1 + return 2 + + sorted_files = [f"{base_filepath}/{name}" for name in sorted(filenames, key=sort_priority)] + self.viewer.load_files(sorted_files) @SafeSlot() def unload_all_scans(self, *_): @@ -176,13 +200,21 @@ class DataViewer(BECWidget, QWidget): start_time = self.client.history[-n].metadata["start_time"] # type: ignore end_time = self.client.history[-n].metadata["end_time"] # type: ignore scan_data = self.client.history[-n].metadata["bec"] # type: ignore + # logger.info(f"scan_data: {scan_data}") scan_number = scan_data["scan_number"] scan_name = scan_data["scan_name"] - if "metadata" in scan_data: - comment = scan_data["metadata"]["user_metadata"]["comment"] - sample_name = scan_data["metadata"]["user_metadata"]["sample_name"] - else: - comment, sample_name = "", "" + + comment, sample_name = "", "" + user_metadata = scan_data.get("user_metadata", {}) + comment = user_metadata.get("comment", comment) + sample_name = user_metadata.get("sample_name", sample_name) + if comment == "": + metadata_user = scan_data.get("metadata", {}).get("user_metadata", {}) + comment = metadata_user.get("comment", comment) + if sample_name == "": + metadata_user = scan_data.get("metadata", {}).get("user_metadata", {}) + sample_name = metadata_user.get("sample_name", sample_name) + status = scan_data["status"] self.history.append( { diff --git a/debye_bec/bec_widgets/widgets/data_viewer/panels/input_panel.py b/debye_bec/bec_widgets/widgets/data_viewer/panels/input_panel.py index f249b94..3d2088e 100644 --- a/debye_bec/bec_widgets/widgets/data_viewer/panels/input_panel.py +++ b/debye_bec/bec_widgets/widgets/data_viewer/panels/input_panel.py @@ -1,5 +1,5 @@ # pylint: disable=E0611 -from qtpy.QtWidgets import QHBoxLayout, QVBoxLayout, QWidget +from qtpy.QtWidgets import QFrame, QHBoxLayout, QVBoxLayout, QWidget # pylint: disable=E0402 from ..widgets.qt_widgets import Button, Group, ListWidget @@ -15,13 +15,21 @@ class InputPanel(QWidget): # Scan selection self.scan_sel = ListWidget("scan_sel") self.load_button = Button(label_button="Load Dataset", enabled=True) - self.unload_button = Button(label_button="Unload all", enabled=True) self.open_fm_button = Button(label_button="Open in File Manager", enabled=True) + line = QFrame() + line.setFrameShape(QFrame.HLine) + line.setFrameShadow(QFrame.Sunken) + + self.load_from_folder_button = Button( + label_button="Load Dataset from File Manager", enabled=True + ) + self._button_layout = QVBoxLayout() self._button_layout.addWidget(self.load_button) - self._button_layout.addWidget(self.unload_button) self._button_layout.addWidget(self.open_fm_button) + self._button_layout.addWidget(line) + self._button_layout.addWidget(self.load_from_folder_button) self._button_layout.addStretch() # Assemble complete scan selection group diff --git a/debye_bec/bec_widgets/widgets/data_viewer/panels/scan_view.py b/debye_bec/bec_widgets/widgets/data_viewer/panels/scan_view.py index aa3ebe7..9c730b1 100644 --- a/debye_bec/bec_widgets/widgets/data_viewer/panels/scan_view.py +++ b/debye_bec/bec_widgets/widgets/data_viewer/panels/scan_view.py @@ -27,7 +27,7 @@ from qtpy.QtWidgets import ( # pylint: disable=E0402 from ..loaders import BaseFileLoader, registry -from ..widgets.qt_widgets import Group +from ..widgets.qt_widgets import Button, Group from .data_view import DataView logger = bec_logger.logger @@ -59,6 +59,7 @@ class ScanViewer(QMainWindow): left_pane = QWidget() left_layout = QVBoxLayout(left_pane) + self.unload_button = Button(label_button="Unload all", enabled=True) self.tree = QTreeWidget() self.tree.setMinimumWidth(250) self.tree.setHeaderLabels(["Name", "Type", "Shape"]) @@ -68,6 +69,7 @@ class ScanViewer(QMainWindow): self.tree.header().setSectionResizeMode(2, QHeaderView.ResizeMode.ResizeToContents) self.tree.itemClicked.connect(self._on_item_clicked) + left_layout.addWidget(self.unload_button) left_layout.addWidget(self.tree, 1) self.data_panel = DataView() diff --git a/debye_bec/bec_widgets/widgets/data_viewer/widgets/qt_widgets.py b/debye_bec/bec_widgets/widgets/data_viewer/widgets/qt_widgets.py index 187157e..7242c1e 100644 --- a/debye_bec/bec_widgets/widgets/data_viewer/widgets/qt_widgets.py +++ b/debye_bec/bec_widgets/widgets/data_viewer/widgets/qt_widgets.py @@ -45,15 +45,13 @@ class Button(QWidget): def __init__(self, label=None, label_button: str = "", enabled=False): super().__init__() layout = QHBoxLayout(self) - layout.setContentsMargins(10, 0, 0, 0) + layout.setContentsMargins(0, 0, 0, 0) layout.setSpacing(0) if label is not None: self.label = QLabel(label) - self.label.setFixedWidth(140) + self.label.setFixedWidth(160) layout.addWidget(self.label) self.button = QPushButton(label_button) - if label is not None: - self.button.setFixedWidth(160) self.enable_button(enabled) layout.addWidget(self.button) diff --git a/tests/tests_devices/test_pilatus.py b/tests/tests_devices/test_pilatus.py index 2f1bb01..fc02311 100644 --- a/tests/tests_devices/test_pilatus.py +++ b/tests/tests_devices/test_pilatus.py @@ -6,23 +6,14 @@ from unittest import mock import ophyd import pytest from bec_lib.messages import ScanStatusMessage -from bec_server.scan_server.scan_worker import ScanWorker -from bec_server.scan_server.scans.scan_base import ScanInfo as ScanServerScanInfo from bec_server.scan_server.tests.scan_fixtures import * from bec_server.scan_server.tests.scan_fixtures import _MockDevice -from ophyd_devices import CompareStatus, DeviceStatus +from ophyd_devices import DeviceStatus from ophyd_devices.interfaces.base_classes.psi_device_base import DeviceStoppedError from ophyd_devices.tests.utils import MockPV, patch_dual_pvs from ophyd_devices.utils.psi_device_base_utils import TaskStatus -from debye_bec.devices.pilatus.pilatus import ( - ACQUIREMODE, - COMPRESSIONALGORITHM, - DETECTORSTATE, - FILEWRITEMODE, - TRIGGERMODE, - Pilatus, -) +from debye_bec.devices.pilatus.pilatus import ACQUIREMODE, DETECTORSTATE, Pilatus from debye_bec.devices.utils.utils import fetch_scan_info if TYPE_CHECKING: # pragma no cover @@ -38,8 +29,8 @@ if TYPE_CHECKING: # pragma no cover @pytest.fixture( scope="function", params=[ - (("samx", 0.1, 1, 5, "samy", 0, 1, 5), {"relative": True}, "_v4_hexagonal_scan"), - ((1, 0.2), {}, "_v4_time_scan"), + (("samx", 0.1, 1, 5, "samy", 0, 1, 5), {"relative": True}, "hexagonal_scan"), + ((1, 0.2), {}, "time_scan"), ((9000, 10000, 1, 20, 0.1, 9500), {}, "xas_advanced_scan"), ], )