Source code for cosedaUI.mainwindow_sections.workflow

import os
import webbrowser

from PyQt6.QtWidgets import QDialog, QMessageBox, QTextEdit, QVBoxLayout

from cosedaUI.export import ExportMtzWindow
from cosedaUI.merging_window import MergingSettingsWindow
from cosedaUI.metadata_window import MetadataWindow
from cosedaUI.strip_file_window import StripFilesWindow
from cosedaUI.unitcell_window import UnitCellHistogramWindow
from cosedaUI.workspace_unitcell_fit_window import WorkspaceUnitCellFitWindow


[docs] class WorkflowMixin:
[docs] def open_strip_files_window(self): if not self.full_ini_file_path or not os.path.exists(self.full_ini_file_path): QMessageBox.warning(self, "No INI File", "Please load an INI file first.") return # Prevent multiple instances if hasattr(self, 'strip_files_window') and self.strip_files_window.isVisible(): self.strip_files_window.raise_() self.strip_files_window.activateWindow() else: self.strip_files_window = StripFilesWindow( parent=self, ini_directory=self.ini_directory, ini_file_path=self.full_ini_file_path ) self.strip_files_window.show()
[docs] def open_index_window(self): QMessageBox.information(self, "Not Implemented", "The Index function is not implemented yet.")
[docs] def open_index_integrate_window(self): from cosedaUI.indexintegrate_window import IndexingControlWindow # Pass the ini_directory and the HDF5 file path instead of the INI file path self.index_integrate_window = IndexingControlWindow(self, self.ini_directory, self.hdf5_path) # Two-way synchronization of file selection w = self.index_integrate_window # Main -> Index window (try common handler names) for slot_name in ("on_mainwindow_ini_changed", "_sync_from_mainwindow_selection", "handle_mainwindow_ini_changed"): if hasattr(w, slot_name): try: self.ini_selection_changed.connect(getattr(w, slot_name)) break except Exception: pass # Index window -> Main (try common signal names) for sig_name in ("ini_selection_changed", "ini_selected", "request_select_ini", "file_selection_changed", "file_selected"): if hasattr(w, sig_name): try: getattr(w, sig_name).connect(self.on_indexintegrate_requested_select_ini) break except Exception: pass # Immediately sync current selection to the Index window if self.full_ini_file_path: self.ini_selection_changed.emit(self.full_ini_file_path) self.index_integrate_window.show()
[docs] def open_merge_window(self): if not self.full_ini_file_path or not os.path.exists(self.full_ini_file_path): QMessageBox.warning(self, "No INI File", "Please load an INI file first.") return # Prevent multiple instances if hasattr(self, 'merging_window') and self.merging_window.isVisible(): self.merging_window.raise_() self.merging_window.activateWindow() else: # Pass the workspace file path (fallback to current INI if not available) workspace_path = self.workspace_file_path or self.full_ini_file_path self.merging_window = MergingSettingsWindow( parent=self, ini_directory=self.ini_directory, ini_file_path=self.full_ini_file_path, workspace_path=workspace_path, ) self.merging_window.show()
[docs] def open_export_window(self): """ Open the Export window which lists available CrystFEL HKL files and converts them to SHELX HKLF4, and can also write RES/P4P from CrystFEL cell files. """ # Determine a sensible workspace root to scan for *_merge_* folders. workspace_path = self.workspace_file_path or self.full_ini_file_path if not workspace_path or not os.path.exists(workspace_path): QMessageBox.warning(self, "No Workspace", "Please open or create a workspace first.") return # Prevent multiple instances if hasattr(self, 'export_mtz_window') and self.export_mtz_window.isVisible(): self.export_mtz_window.raise_() self.export_mtz_window.activateWindow() else: try: self.export_mtz_window = ExportMtzWindow(workspace_path=workspace_path, parent=self) self.export_mtz_window.show() except Exception as e: QMessageBox.critical(self, "Export HKLF4", f"Failed to open Export HKLF4 window:\n{e}")
[docs] def open_check_metadata_window(self): """ Opens the metadata dialog showing acquisition details. """ if not self.full_ini_file_path or not os.path.exists(self.full_ini_file_path): QMessageBox.warning(self, "No INI File", "Please load an INI file first.") return # Prevent multiple instances if hasattr(self, 'check_metadata_window') and self.check_metadata_window.isVisible(): self.check_metadata_window.raise_() self.check_metadata_window.activateWindow() else: self.check_metadata_window = MetadataWindow(self.full_ini_file_path, parent=self) self.check_metadata_window.exec() # Reload the file while preserving the current frame self.reload_file_preserve_frame() # Re-evaluate workflow buttons after metadata dialog closes self.update_workflow_buttons()
[docs] def open_unit_cell_hist_window(self, auto_refresh: bool = False): """ Open the unit cell histogram viewer for the current stream. """ # Prefer current stream from the indexing manager but allow manual selection in the dialog. stream_path = None try: stream_path = getattr(self, "indexing_manager", None).stream_path except Exception: stream_path = None # Reuse existing window if open if hasattr(self, "unit_cell_hist_window") and self.unit_cell_hist_window.isVisible(): self.unit_cell_hist_window.raise_() self.unit_cell_hist_window.activateWindow() if auto_refresh: try: self.unit_cell_hist_window.start_auto_refresh() except Exception: pass return self.unit_cell_hist_window = UnitCellHistogramWindow( parent=self, stream_path=stream_path, indexing_manager=getattr(self, "indexing_manager", None), ) # Show dialog unless it immediately closed itself (e.g., missing parser) if self.unit_cell_hist_window is not None: if auto_refresh: try: self.unit_cell_hist_window.start_auto_refresh() except Exception: pass self.unit_cell_hist_window.show()
[docs] def open_workspace_unit_cell_fit_window(self): """Open the workspace-wide unit-cell Gaussian fit tool.""" workspace_ini_paths = list(getattr(self, "workspace_ini_paths", {}).values()) workspace_path = getattr(self, "workspace_file_path", None) or getattr(self, "full_ini_file_path", None) if hasattr(self, "workspace_unit_cell_fit_window") and self.workspace_unit_cell_fit_window.isVisible(): self.workspace_unit_cell_fit_window.set_workspace_context(workspace_ini_paths, workspace_path) self.workspace_unit_cell_fit_window.raise_() self.workspace_unit_cell_fit_window.activateWindow() return self.workspace_unit_cell_fit_window = WorkspaceUnitCellFitWindow( parent=self, workspace_ini_paths=workspace_ini_paths, workspace_path=workspace_path, ) self.workspace_unit_cell_fit_window.show()
[docs] def report_issue(self): recipient_email = "contact-project+kristallorakel-coseda-reportissue@incoming.gitlab.com" subject = "Issue Report for " + self.window_title body = "Please describe your issue or feedback." mailto_link = f"mailto:{recipient_email}?subject={subject}&body={body}" webbrowser.open(mailto_link)
[docs] def display_log_file(self): if not self.log_file_path or not os.path.exists(self.log_file_path): QMessageBox.information(self, "Log File", "Log file not found.") return with open(self.log_file_path, 'r') as file: log_contents = file.read() # Create a popup window dialog = QDialog(self) dialog.setWindowTitle("Log File") dialog.resize(600, 400) layout = QVBoxLayout(dialog) text_edit = QTextEdit() text_edit.setPlainText(log_contents) text_edit.setReadOnly(True) # Make it read-only layout.addWidget(text_edit) dialog.exec()