Source code for hbat.config.parameter_controller

"""Parameter controller for HBAT analysis parameters.

This module provides a framework-agnostic controller for managing
analysis parameters, independent of any UI framework.
"""

from dataclasses import asdict, fields
from typing import Any, Dict, List, Optional

from ..constants.parameters import AnalysisParameters
from .ui_config import PARAMETER_CONFIGS, PARAMETER_LOOKUP, ParameterConfig


[docs] class ParameterController: """Manage analysis parameters independent of UI framework. Provides get/set operations, validation, persistence, and parameter grouping by category. """
[docs] def __init__(self, params: Optional[AnalysisParameters] = None): """Initialize parameter controller. Args: params: Initial AnalysisParameters instance. If None, creates default. """ self.params = params or AnalysisParameters()
[docs] def get_parameter(self, name: str) -> Any: """Get a parameter value by name. Args: name: Parameter name (e.g., 'hb_distance_cutoff') Returns: Parameter value Raises: AttributeError: If parameter doesn't exist """ return getattr(self.params, name)
[docs] def set_parameter(self, name: str, value: Any) -> None: """Set a parameter value by name. Args: name: Parameter name value: New parameter value Raises: AttributeError: If parameter doesn't exist ValueError: If value fails validation """ if not self.validate_parameter(name, value): config = PARAMETER_LOOKUP.get(name) if config: raise ValueError( f"{name} must be between {config.min_val} and {config.max_val}" ) raise ValueError(f"Invalid value for {name}") setattr(self.params, name, value)
[docs] def validate_parameter(self, name: str, value: Any) -> bool: """Validate a parameter value. Args: name: Parameter name value: Value to validate Returns: True if valid, False otherwise """ config = PARAMETER_LOOKUP.get(name) if not config: return False # Check type if config.param_type == "float": try: value = float(value) except (TypeError, ValueError): return False elif config.param_type == "int": try: value = int(value) except (TypeError, ValueError): return False elif config.param_type == "bool": if not isinstance(value, bool): return False elif config.param_type == "str": if not isinstance(value, str): return False # Check range (if applicable) if config.min_val is not None and value < config.min_val: return False if config.max_val is not None and value > config.max_val: return False return True
[docs] def reset_to_defaults(self) -> None: """Reset all parameters to their default values.""" self.params = AnalysisParameters()
[docs] def to_dict(self) -> Dict[str, Any]: """Convert parameters to dictionary. Returns: Dictionary mapping parameter names to values """ return asdict(self.params)
[docs] def from_dict(self, params_dict: Dict[str, Any]) -> None: """Update parameters from dictionary. Args: params_dict: Dictionary mapping parameter names to values Raises: ValueError: If any value fails validation """ for name, value in params_dict.items(): if hasattr(self.params, name): if not self.validate_parameter(name, value): raise ValueError(f"Invalid value for {name}: {value}") setattr(self.params, name, value)
[docs] def get_parameters_by_category(self) -> Dict[str, Dict[str, ParameterConfig]]: """Get all parameters grouped by category. Returns: Dictionary mapping categories to parameter configs. Example structure:: { "Hydrogen Bonds": { "hb_distance_cutoff": ParameterConfig(...), ... }, ... } """ grouped = {} for config in PARAMETER_CONFIGS: category = config.category if category not in grouped: grouped[category] = {} grouped[category][config.name] = config return grouped
[docs] def get_parameters_list(self) -> List[ParameterConfig]: """Get all parameter configurations. Returns: List of ParameterConfig objects """ return PARAMETER_CONFIGS
[docs] def get_category_parameters(self, category: str) -> Dict[str, ParameterConfig]: """Get all parameters for a specific category. Args: category: Category name Returns: Dictionary mapping parameter names to configs for the category """ by_category = self.get_parameters_by_category() return by_category.get(category, {})