Source code for hbat.gui.pdb_fixing_dialog

"""
PDB Fixing configuration dialog for HBAT GUI.

This module provides a dedicated dialog for configuring PDB fixing parameters,
separate from the main geometry parameter settings.
"""

import tkinter as tk
from tkinter import ttk
from typing import Dict, Any, Optional

from ..constants.parameters import ParametersDefault


[docs] class PDBFixingDialog: """Dialog for configuring PDB fixing parameters."""
[docs] def __init__(self, parent: tk.Tk): """Initialize PDB fixing dialog. :param parent: Parent window :type parent: tk.Tk """ self.parent = parent self.result = None # Create dialog window self.dialog = tk.Toplevel(parent) self.dialog.title("PDB Fixing Settings") self.dialog.geometry("800x600") self.dialog.resizable(False, False) # Make dialog modal self.dialog.transient(parent) self.dialog.grab_set() # Initialize variables self._init_variables() # Create widgets self._create_widgets() # Center the dialog self.dialog.update_idletasks() x = (self.dialog.winfo_screenwidth() // 2) - (self.dialog.winfo_width() // 2) y = (self.dialog.winfo_screenheight() // 2) - (self.dialog.winfo_height() // 2) self.dialog.geometry(f"+{x}+{y}") # Handle window closing self.dialog.protocol("WM_DELETE_WINDOW", self._cancel)
def _init_variables(self): """Initialize tkinter variables with default values.""" self.fix_pdb_enabled = tk.BooleanVar(value=ParametersDefault.FIX_PDB_ENABLED) self.fix_pdb_method = tk.StringVar(value=ParametersDefault.FIX_PDB_METHOD) self.fix_pdb_add_hydrogens = tk.BooleanVar(value=ParametersDefault.FIX_PDB_ADD_HYDROGENS) self.fix_pdb_add_heavy_atoms = tk.BooleanVar(value=ParametersDefault.FIX_PDB_ADD_HEAVY_ATOMS) self.fix_pdb_replace_nonstandard = tk.BooleanVar(value=ParametersDefault.FIX_PDB_REPLACE_NONSTANDARD) self.fix_pdb_remove_heterogens = tk.BooleanVar(value=ParametersDefault.FIX_PDB_REMOVE_HETEROGENS) self.fix_pdb_keep_water = tk.BooleanVar(value=ParametersDefault.FIX_PDB_KEEP_WATER) def _create_widgets(self): """Create dialog widgets.""" # Main frame with padding main_frame = ttk.Frame(self.dialog, padding="20") main_frame.pack(fill=tk.BOTH, expand=True) # Title title_label = ttk.Label( main_frame, text="PDB Structure Fixing Settings", font=("TkDefaultFont", 12, "bold") ) title_label.pack(pady=(0, 20)) # Enable PDB fixing checkbox self.enable_check = ttk.Checkbutton( main_frame, text="Enable PDB structure fixing", variable=self.fix_pdb_enabled, command=self._on_enable_changed ) self.enable_check.pack(anchor=tk.W, pady=(0, 15)) # Method selection frame method_frame = ttk.LabelFrame(main_frame, text="Fixing Method", padding="10") method_frame.pack(fill=tk.X, pady=(0, 15)) ttk.Radiobutton( method_frame, text="PDBFixer (recommended for proteins)", variable=self.fix_pdb_method, value="pdbfixer", command=self._on_method_changed, ).pack(anchor=tk.W) ttk.Radiobutton( method_frame, text="OpenBabel", variable=self.fix_pdb_method, value="openbabel", command=self._on_method_changed, ).pack(anchor=tk.W) # Operations frame operations_frame = ttk.LabelFrame(main_frame, text="Operations", padding="10") operations_frame.pack(fill=tk.BOTH, expand=True, pady=(0, 15)) # Add hydrogens (both methods) self.add_hydrogens_check = ttk.Checkbutton( operations_frame, text="Add missing hydrogen atoms", variable=self.fix_pdb_add_hydrogens ) self.add_hydrogens_check.pack(anchor=tk.W, pady=2) # PDBFixer-only operations self.add_heavy_atoms_check = ttk.Checkbutton( operations_frame, text="Add missing heavy atoms (PDBFixer only)", variable=self.fix_pdb_add_heavy_atoms ) self.add_heavy_atoms_check.pack(anchor=tk.W, pady=2) self.replace_nonstandard_check = ttk.Checkbutton( operations_frame, text="Replace nonstandard residues (PDBFixer only)", variable=self.fix_pdb_replace_nonstandard ) self.replace_nonstandard_check.pack(anchor=tk.W, pady=2) self.remove_heterogens_check = ttk.Checkbutton( operations_frame, text="Remove heterogens (PDBFixer only)", variable=self.fix_pdb_remove_heterogens, command=self._on_remove_heterogens_changed ) self.remove_heterogens_check.pack(anchor=tk.W, pady=2) # Keep water sub-option self.keep_water_check = ttk.Checkbutton( operations_frame, text=" Keep water molecules", variable=self.fix_pdb_keep_water ) self.keep_water_check.pack(anchor=tk.W, pady=2) # Store PDBFixer-only widgets self.pdbfixer_only_widgets = [ self.add_heavy_atoms_check, self.replace_nonstandard_check, self.remove_heterogens_check, self.keep_water_check ] # Button frame button_frame = ttk.Frame(main_frame) button_frame.pack(fill=tk.X, pady=(20, 0)) ttk.Button( button_frame, text="OK", command=self._ok ).pack(side=tk.RIGHT, padx=(5, 0)) ttk.Button( button_frame, text="Cancel", command=self._cancel ).pack(side=tk.RIGHT) ttk.Button( button_frame, text="Reset to Defaults", command=self._reset_defaults ).pack(side=tk.LEFT, padx=(0, 5)) ttk.Button( button_frame, text="Manage Presets...", command=self._open_preset_manager ).pack(side=tk.LEFT, padx=5) # Initialize widget states self._update_widget_states() def _on_enable_changed(self): """Handle enable checkbox change.""" self._update_widget_states() def _on_method_changed(self): """Handle method selection change.""" self._update_widget_states() def _on_remove_heterogens_changed(self): """Handle remove heterogens checkbox change.""" self._update_widget_states() def _update_widget_states(self): """Update widget enable/disable states based on selections.""" enabled = self.fix_pdb_enabled.get() method = self.fix_pdb_method.get() # Enable/disable based on main checkbox for widget in [self.add_hydrogens_check] + self.pdbfixer_only_widgets: widget.configure(state="normal" if enabled else "disabled") # Further disable PDBFixer-only options if OpenBabel selected if enabled and method == "openbabel": for widget in self.pdbfixer_only_widgets: widget.configure(state="disabled") # Enable keep water only if remove heterogens is checked if enabled and method == "pdbfixer" and self.fix_pdb_remove_heterogens.get(): self.keep_water_check.configure(state="normal") else: self.keep_water_check.configure(state="disabled") def _reset_defaults(self): """Reset all values to defaults.""" self.fix_pdb_enabled.set(ParametersDefault.FIX_PDB_ENABLED) self.fix_pdb_method.set(ParametersDefault.FIX_PDB_METHOD) self.fix_pdb_add_hydrogens.set(ParametersDefault.FIX_PDB_ADD_HYDROGENS) self.fix_pdb_add_heavy_atoms.set(ParametersDefault.FIX_PDB_ADD_HEAVY_ATOMS) self.fix_pdb_replace_nonstandard.set(ParametersDefault.FIX_PDB_REPLACE_NONSTANDARD) self.fix_pdb_remove_heterogens.set(ParametersDefault.FIX_PDB_REMOVE_HETEROGENS) self.fix_pdb_keep_water.set(ParametersDefault.FIX_PDB_KEEP_WATER) self._update_widget_states() def _ok(self): """Handle OK button - save settings and close.""" self.result = { "enabled": self.fix_pdb_enabled.get(), "method": self.fix_pdb_method.get(), "add_hydrogens": self.fix_pdb_add_hydrogens.get(), "add_heavy_atoms": self.fix_pdb_add_heavy_atoms.get(), "replace_nonstandard": self.fix_pdb_replace_nonstandard.get(), "remove_heterogens": self.fix_pdb_remove_heterogens.get(), "keep_water": self.fix_pdb_keep_water.get() } self.dialog.destroy() def _cancel(self): """Handle Cancel button - close without saving.""" self.result = None self.dialog.destroy()
[docs] def get_parameters(self) -> Optional[Dict[str, Any]]: """Get the configured parameters. :returns: Dictionary of PDB fixing parameters or None if cancelled :rtype: Optional[Dict[str, Any]] """ self.dialog.wait_window() return self.result
[docs] def set_parameters(self, params: Dict[str, Any]): """Set parameters from a dictionary. :param params: Dictionary of PDB fixing parameters :type params: Dict[str, Any] """ if "enabled" in params: self.fix_pdb_enabled.set(params["enabled"]) if "method" in params: self.fix_pdb_method.set(params["method"]) if "add_hydrogens" in params: self.fix_pdb_add_hydrogens.set(params["add_hydrogens"]) if "add_heavy_atoms" in params: self.fix_pdb_add_heavy_atoms.set(params["add_heavy_atoms"]) if "replace_nonstandard" in params: self.fix_pdb_replace_nonstandard.set(params["replace_nonstandard"]) if "remove_heterogens" in params: self.fix_pdb_remove_heterogens.set(params["remove_heterogens"]) if "keep_water" in params: self.fix_pdb_keep_water.set(params["keep_water"]) self._update_widget_states()
def _open_preset_manager(self): """Open the preset manager dialog.""" from .preset_manager_dialog import PresetManagerDialog from ..core.analysis import AnalysisParameters from tkinter import messagebox # Create a dummy AnalysisParameters object with current PDB fixing settings # The preset manager expects AnalysisParameters, so we'll use default geometry params # and the user can focus on PDB fixing presets current_params = AnalysisParameters() # Open preset manager dialog = PresetManagerDialog(self.dialog, current_params) result = dialog.get_result() if result and "parameters" in result and "pdb_fixing" in result["parameters"]: # Apply only the PDB fixing part of the loaded preset pdb_params = result["parameters"]["pdb_fixing"] self.set_parameters(pdb_params) messagebox.showinfo("Success", "PDB fixing preset loaded successfully") elif result: messagebox.showwarning("Warning", "Selected preset does not contain PDB fixing parameters")