Skip to content

Biological Concepts

This page explains the key biological and software design concepts a developer needs to understand before extending REvoDesign. Each entry links to the relevant API reference for deeper detail.

Biological Concepts

1. Mutant

A Mutant is the core data model representing a point mutation or a set of mutations on a protein sequence. It extends RosettaPy.common.mutation.Mutant (RpMutant) via simple inheritance and adds REvoDesign-specific fields.

  • Fields: Inherits mutations (a list of Mutation objects, each specifying position, wild-type residue, and mutant residue), plus REvoDesign additions: mutant_score (float, the computed fitness score), pdb_fp (str, path to the mutated PDB file), and mutant_description (str, a human-readable label).
  • Construction: Created directly or via helper functions in REvoDesign.tools.mutant_tools (extract_mutants_from_mutant_id, extract_mutant_from_sequences). The .empty property checks whether the mutant carries any mutations.
  • Role: Mutants flow through the entire design pipeline -- generated by a designer, packed by a mutate runner, scored by a scorer, collected into a tree, evaluated interactively, and visualized in PyMOL.

API reference: REvoDesign.common


2. MutantTree

MutantTree provides hierarchical navigation across mutant designs organized by branch. It is the data structure that backs the interactive evaluation UI.

  • Structure: A dict[str, dict[str, Mutant]] mapping branch IDs to mutant IDs to Mutant objects. Each branch corresponds to an exploration trajectory (e.g., one round of design).
  • Navigation: current_branch_id and current_mutant_id track the user's position in the tree. Utilities like refresh_mutants(), all_mutant_objects, all_mutant_scores, and all_mutant_ids provide bulk access.
  • Integration: The MutateRunnerAbstract.mutated_pdb_mapping() static method associates output PDB file paths back to their Mutant objects in the tree. The evaluator (Evaluator) uses the tree to walk through scored designs.

API reference: REvoDesign.common


3. Designers (Gimmicks)

Designers are external design/scoring tools wrapped as subclasses of ExternalDesignerAbstract. They are colloquially called "gimmicks" inside the Magician orchestration system.

  • ExternalDesignerAbstract: An abstract class (extending ThirdPartyModuleAbstract) that defines the contract for a designer or scorer. Key class-level flags control behavior:
  • scorer_only: bool -- if True, the gimmick can only score, not generate new designs.
  • prefer_lower: bool -- whether lower scores are better (for ranking).
  • no_need_to_score_wt: bool -- whether the wild-type sequence needs no separate scoring.

  • Core methods (subclasses override as needed):

  • designer(*args, **kwargs) -- generate new mutant designs.
  • scorer(mutant, **kwargs) -> float -- evaluate a single mutant's fitness.
  • parallel_scorer(mutants, nproc, **kwargs) -> list[Mutant] -- parallelized batch scoring via joblib.Parallel.
  • initialize() -- one-time setup (load models, verify credentials).

  • Discovery: Subclasses are auto-discovered in the REvoDesign.magician.designers package by DESIGNER_REGISTRY (a PluginRegistry). Each subclass must set name: str to a unique identifier. To be listed as installed, set installed: bool = True.

  • Available designers: ProteinMPNN (ProteinMPNN-based sequence design via ColabDesign, exported as ColabDesigner_MPNN), Cartesian-ddG (Cartesian ddG scoring, exported as ddg), and the openkinetics OpenMM-based kinetic/thermodynamic scorer suite.

  • Magician orchestration: The Magician singleton manages the lifecycle of the currently active gimmick. See Magician Orchestration Protocol below.

API reference: REvoDesign.magician | Magician README

Magician Orchestration Protocol (MGOP)

Magician(SingletonAbstract) is the central orchestrator for gimmicks:

  1. Setup: magician.setup(name_cfg_term="ui.interact.use_external_scorer") reads the config, resolves the gimmick name, and calls initialize() on the selected ExternalDesignerAbstract subclass.
  2. Usage: Access magician.gimmick.scorer(mutant=...) for scoring or magician.gimmick.designer(...) for sequence generation.
  3. Cooldown: Call magician.setup() with no arguments to clear the active gimmick.
  4. Assistant: MagicianAssistant (a frozen dataclass) holds the list of installed workers and provides get(name, **kwargs) to instantiate a gimmick by name.

4. Mutate Runners

Mutate runners wrap sidechain packing and protein modeling tools. Each is a subclass of MutateRunnerAbstract (extending ThirdPartyModuleAbstract).

  • MutateRunnerAbstract: Defines the contract with two required methods:
  • run_mutate(mutant: Mutant) -> str -- perform mutations and return the PDB path.
  • run_mutate_parallel(mutants: list[Mutant], nproc: int = 2) -> list[str] -- batch mutation in parallel.
  • Optionally reconstruct() -- rebuild sidechains on the wild-type structure.

  • Runner registry: RUNNER_REGISTRY (a PluginRegistry) auto-discovers subclasses in the REvoDesign.sidechain.mutate_runner package. MutateRunnerManager is a frozen dataclass providing get(name, **kwargs) for instantiation.

  • Available runners (class name → registration name):

  • MutateRelax_worker ("Rosetta-MutateRelax") — Rosetta mutate_relax protocol (requires Rosetta installation).
  • DLPacker_worker ("DLPacker") — DLPacker deep-learning sidechain packing.
  • DLPackerPytorch_worker ("DLPackerPytorch") — PyTorch port of DLPacker.
  • PIPPack_worker ("PIPPack") — PIPPack rotamer-based packing (configured via pippack.yaml).
  • DiffPack_worker ("DiffPack") — DiffPack diffusion-based packing.
  • PyMOL_mutate ("Dunbrack Rotamer Library") — Dunbrack rotamer library via PyMOL's cmd.get_wizard().do_pick().

API reference: REvoDesign.sidechain | Mutate Runner README


5. Design Hotspots

Identifying which residues to mutate is handled by two complementary PyMOL-driven modules:

  • PocketSearcher (REvoDesign.structure): Detects ligand/cofactor binding pockets. It uses PyMOL selections to identify:
  • hetatm_pocket -- residues within ligand_radius of any heteroatom.
  • substrate_pocket -- residues around a named substrate residue (e.g., "UNK").
  • cofactor_pocket -- residues around named cofactors.
  • Outputs are saved as PyMOL selection objects and optionally written to a .pse session file.

  • SurfaceFinder (REvoDesign.structure): Computes solvent-accessible surface area (SASA) via PyMOL's get_area() with a dot_solvent parameter. findSurfaceResidues() returns residue positions with exposure above a configurable cutoff (default 2.5 A^2). Used to restrict mutations to surface-exposed positions.

  • Inter-chain contacts: During the design workflow, inter-chain distance constraints from the GREMLIN co-evolution analysis (see below) can further refine hotspot selection.

API reference: REvoDesign.structure


6. Profiles

Profiles provide external data that guides or constrains the mutagenesis search. All parsers extend ProfileParserAbstract.

  • ProfileParserAbstract: Abstract base with parse() -> pd.DataFrame, plus properties for score normalization (score_max_abs, min_score_profile, max_score_profile).

  • Available parsers:

  • PSSM_Parser -- reads Position-Specific Scoring Matrix (PSSM) files from PSI-BLAST. Parses the 20-column amino acid probability table.
  • CSVProfileParser -- reads CSV-format profile data (e.g., ddG per-position scores). prefer_lower = True.
  • TSVProfileParser -- reads tab-separated profile data.

  • ProfileManager: A factory that selects and initializes the correct parser by profile_type name (string matched against each parser's name attribute).

  • ESM-1v: Zero-shot mutation effect predictions from the ESM-1v language model can be loaded as a profile table and integrated into the clustering workflow.

API reference: REvoDesign.common


7. MutantVisualizer

MutantVisualizer loads designed mutants into PyMOL sessions for interactive inspection.

  • Workflow: It takes a Mutant object, loads the input PyMOL session, colors residues by mutation score using a configurable colormap (cmap, default bwr_r), and generates temporary session files for each mutant.
  • Features: Profile scoring data can be overlaid on the structure. Wild-type and mutant residues are shown as sticks/mesh for side-by-side comparison. The visualizer is driven by MutateWorker / VisualizingWorker in the phylogenetics module.
  • Output: Temporary .pse sessions are written to disk and loaded into the active PyMOL instance.

API reference: REvoDesign.common


8. Evaluator

Evaluator is the interactive decision-making engine that lets users walk through scored mutants, accept or reject them, and guide the design trajectory.

  • Navigation: Relies on a MutantTree to track branches and current position. activate_focused() highlights the current mutant in PyMOL (mesh/sticks representation), hides other branches, and centers the view.
  • Decision flow: mutant_decision(decision_to_accept: bool) records accept/reject choices into the MutantTree. Accepted mutants can seed the next design round.
  • Integration: Instantiated in REvoDesignPlugin.__init__() as self.evaluator. Writes choices to a CSV log via save_mutant_choices().

API reference: REvoDesign.evaluate (core.md includes evaluate)


9. GREMLIN (Interact)

GREMLIN (Generative Reuglarized Model_s of_prote_INs) provides co-evolutionary analysis to identify residue pairs that evolve together, implying structural or functional coupling.

  • GREMLIN_Tools (REvoDesign.phylogenetics.gremlin_tools): Loads GREMLIN output (co-evolution scores, PDB structural data). Core data class:
  • CoevolvedPair -- stores a pair of positions (i, j), their amino acids, inter-chain distances (homochains_dist, supporting multi-chain/multi-state analysis), z-scores, and distance cutoffs. Methods like is_out_of_range(), all_out_of_range, and min_dist enable filtering.

  • GremlinAnalyser (REvoDesign.phylogenetics.evo_mutator): Wires co-evolved pairs into the REvoDesign workflow. Displays pair connections as PyMOL CGO (Cylinder-style) objects with state-based coloring (available / out-of-range / in-design).

  • MutateWorker / REvoDesigner (REvoDesign.phylogenetics.evo_mutator): Applies evolutionary constraints to drive mutagenesis using co-evolved pair information and the Magician's scoring gimmick. Supports multi-round iterative design.

  • Integration: PyTorch-based GREMLIN calculations via gremlin_pytorch.py. The GREMLIN interact tab (Interact) is wired into the main UI alongside the cluster and evaluate workflows.

API reference: REvoDesign.phylogenetics (core.md includes phylogenetics)


10. Clusters

Sequence clustering reduces large mutant sets to representative variants for experimental testing. Built around a ClusterMethodAbstract base class.

  • ClusterMethodAbstract(CitableModuleAbstract, ABC): Base class for all clustering algorithms. Key attributes: name, installed, spec (a ClusterMethodSpec describing inputs and display metadata). The global_alignment() method uses Bio.PairwiseAligner with configurable substitution matrices.

  • ClusterMethodManager: The registry/factory for cluster methods. Methods are discovered via build_plugin_registry in the REvoDesign.clusters.methods package.

  • Available methods (in REvoDesign.clusters.methods):

  • AgglomerativeCluster -- hierarchical agglomerative clustering.
  • KMeansCluster -- k-means clustering.
  • EvoCluster -- evolution-guided clustering that incorporates PSSM, ESM-1v, and spatial proximity weights.
  • LegacyCluster -- deprecated original Ward-linkage clustering based on the score matrix; retained for compatibility only. Prefer AgglomerativeCluster or EvoCluster for new work.

  • ClusterRunner: The top-level orchestrator instantiated by the plugin. Reads all config values from the UI, configures the selected method, runs clustering, scores representatives (via Rosetta score_clusters), and writes output variant tables.

API reference: REvoDesign.clusters


Software & API Design Concepts

1. SingletonAbstract

SingletonAbstract (in REvoDesign.basic.abc_singleton) is the Borg-like singleton base used throughout the codebase.

  • Mechanism: __new__ returns the cached _instance if one exists. __init__ calls singleton_init() only once, guarded by self.initialized. Subclasses must implement singleton_init().
  • derive(name): Creates a dynamically-named subclass with its own independent _instance, enabling multiple singleton instances of the same lineage (e.g., StoresWidget.derive("derived_name")).
  • reset_instance(): Sets _instance = None so the next __new__ creates a fresh instance. reset_singletons() iterates all subclasses and resets them.
  • Used by: ConfigBus, Magician, SidechainSolver, CitationManager, StoresWidget.

API reference: REvoDesign.basic


2. Config Tree

REvoDesign uses OmegaConf/Hydra for hierarchical, YAML-based configuration management.

  • Layout: YAML config files live in src/REvoDesign/config/ as templates. On first import, bootstrap/__init__.py copies them to a user config directory determined by platformdirs:
  • main.yaml -- top-level UI and workflow settings.
  • logger.yaml -- logging configuration (formatters, handlers, levels).
  • environ.yaml -- environment variables.
  • runtime.yaml -- runtime-only (non-persisted) settings.
  • openmm.yaml -- OpenMM simulation parameters.
  • Subdirectories: rfdiffusion/, rosetta-node/, sidechain-solver/.

  • Bootstrap sequence (REvoDesign.bootstrap):

  • set_REvoDesign_config_file() -- ensure user config dir exists.
  • hydra.initialize_config_dir() -- point Hydra at the user config dir.
  • verify_config_tree_structure() -- copy missing template files to user dir.
  • enforce_config_key_structure() -- add new keys that exist in templates but not in user config.
  • experiment_config() -- set up experiment output directories.
  • CACHE_CONFIG_DIR -- initialize YAML cache directory.

  • Access: Config dataclass (name, path, cfg). Config.from_name("main") loads a named config. reload_config_file("main") refreshes from disk.

API reference: REvoDesign.bootstrap | Config README


3. ConfigBus

ConfigBus(SingletonAbstract) is the bidirectional bridge between Qt UI widgets and the OmegaConf YAML config tree. It is the central nervous system of the application.

  • Headless mode: When instantiated without a UI (e.g., during tests), ConfigBus.headless = True and only get_value/set_value work. Widget access requires the @require_non_headless decorator.
  • Widget2ConfigMapper: Maps config item names to widget IDs, then to widget objects. Uses Config2WidgetIds (widget registry) and PushButtons (button registry).
  • Config dataclass: Config.from_name("main") loads a named config section. cfg_group on the bus holds all loaded configs by name.
  • StoresWidget: A companion singleton holding server-switch references for features like the OpenMM server and the Monaco editor server. Its reset_instance() cascades resets to all registered singleton controllers.

API reference: REvoDesign.driver


4. Logger System

The logging system uses Python's standard logging module, configured via logger.yaml.

  • Initialization: The root logger (ROOT_LOGGER) is initialized at import time (step 5 in REvoDesign/__init__.py). setup_logging() reads logger.yaml via logging.config.dictConfig().
  • REvoDesignLogFormatter: A custom JSON formatter that outputs structured log records with ISO 8601 timestamps, making logs machine-parseable. Built-in LOG_RECORD_BUILTIN_ATTRS defines the set of standard attributes.
  • Log channels: Each module creates a child logger via ROOT_LOGGER.getChild(__name__). This produces hierarchical names like REvoDesign.magician, REvoDesign.sidechain.sidechain_solver.
  • Config-driven: Formatters, handlers, levels, and filters are all specified in logger.yaml, allowing runtime reconfiguration by editing the YAML file.

API reference: REvoDesign.logger


5. Plugin Launch Order

The exact import and initialization sequence matters for correct behavior. It is orchestrated in REvoDesign/__init__.py and REvoDesign.REvoDesignPlugin.make_window().

Import-time sequence (in REvoDesign/__init__.py):

  1. SingletonAbstract -- base singleton class (step 1).
  2. Bootstrap -- config file initialization (step 2).
  3. File extensions -- register PyMOL file format handlers (step 3).
  4. ConfigBus -- UI-to-config bridge (step 4). Created without UI (headless).
  5. Logger -- ROOT_LOGGER and setup_logging (step 5). Must come after config so logger.yaml is available.
  6. Version -- __version__ = "X.Y.Z" (step 6).

Runtime init sequence (in REvoDesignPlugin.make_window()):

  1. load_runtime_ui() -- load REvoDesign.ui via RuntimeUiProxy.
  2. IconSetter -- set window icons.
  3. reload_configurations() -- load YAML configs into the bus.
  4. ClusterTabController -- install cluster tab.
  5. FontSetter -- set UI fonts.
  6. LanguageSwitch -- install i18n translator.
  7. MenuCollection -- bind menu actions (static + deferred config-file scanning).
  8. StoresWidget -- server-switch references.

API reference: REvoDesign.core


6. Issue System

REvoDesign defines a comprehensive hierarchy of custom exceptions and warnings for structured error handling.

  • Exceptions (REvoDesign.issues.exceptions): All inherit from REvoDesignException. Key types: ConfigurationError, PluginError, DependencyError, InvalidInputError, NoResultsError, NetworkError, UninstalledPackageError, FileFormatError, InternalError, EnzymeDesignError.
  • Warnings (REvoDesign.issues.warnings): All inherit from REvoDesignWarning. Key types: DisabledFunctionWarning, NoInputWarning, ConflictWarning, BadDataWarning. ConfigureOutofDateError lives in exceptions.
  • Usage: Exceptions are raised with descriptive messages and are caught at the UI layer to show notify_box dialogs. Warnings use Python's warnings.warn().

API reference: REvoDesign.issues


7. Qt Wrapper

All Qt imports must go through REvoDesign.Qt -- never import PyQt5 or PyQt6 directly. This compatibility layer handles differences between Qt5 and Qt6.

  • qt_wrapper.py: Detects the backend from pymol.Qt.PYQT_NAME. Exposes QtCore, QtGui, QtWidgets, QtNetwork, QtSvg, QtUiTools, QtWebSockets. QT_BACKEND is "PyQt5" or "PyQt6"; QT_MAJOR is 5 or 6.
  • QtCompat: Utility class providing unified access to enum values across Qt5/Qt6. install_qt6_aliases() adds Qt5Compat-style access for Qt6 scoped enums.
  • RuntimeUiProxy (ui_runtime_loader.py): Loads .ui files at runtime via uic.loadUiType (PyQt5) or QtUiTools.QUiLoader (PyQt6). Named widgets become proxy attributes; duplicate names are recorded in _duplicate_object_names. Supports retranslateUi() and refresh_bindings().
  • REvoDesignUiProtocol (in UI/types.py): Auto-generated typing contract from REvoDesign.ui -- provides IDE autocompletion without constructing the UI.

API reference: REvoDesign.Qt


8. Menu System

The menu system uses a declarative, dataclass-driven approach in REvoDesign.basic.menu_item.

  • MenuItem(action, func, args, kwargs): A frozen dataclass mapping a UI action name to a callable. Special cases: action="---" creates a separator. func can be a dotted string path or a "LAMBDA:..." expression for deferred resolution.
  • MenuCollection(ui, menu_items): Binds all MenuItem instances to their corresponding QAction objects at construction time. If an action doesn't exist on the UI, it can be created dynamically if a menu_section is provided.
  • Deferred registration: Dynamic actions (e.g., designer/scorer selection) are registered at config load time by group_registries.GroupRegistryItem, which scans config files for new items.

API reference: REvoDesign.basic


9. Citation System

REvoDesign tracks BibTeX citations for all third-party tools and algorithms used during a session.

  • CitableModuleAbstract: Abstract base class with a __bibtex__ dict attribute mapping citation keys to BibTeX strings (or tuples of strings). Provides:
  • notice() -- log citation information unless silenced.
  • cite() -- add citations to the global CitationManager and display notice.
  • get_citable_class(func) -- resolve the citable class from a function reference.

  • CitationManager(SingletonAbstract): Global singleton that collects citations from all cite() calls. Can output() a .bib file, clear() the collection, and dismiss() specific modules to suppress repeated notices.

  • get_cited decorator (in REvoDesign.tools.utils): A decorator that marks a function with __bibtex__ and automatically calls cite() on the owning class when the function is invoked.

API reference: REvoDesign.citations


10. Plugin Registries

REvoDesign uses package-scoped, auto-discovering registries for extensible plugin systems.

  • PluginRegistry(Generic[PluginT]): A frozen dataclass that discovers all non-abstract subclasses of a base class within a given Python package. Discovery uses pkgutil.iter_modules and inspect.getmembers. Key properties:
  • all_classes -- all discovered subclasses.
  • implemented_map -- mapping of name -> class.
  • installed_names -- names of classes where installed = True.

  • build_plugin_registry(): Convenience factory for creating a PluginRegistry with standard defaults.

  • Two registries exist:

  • DESIGNER_REGISTRY -- in REvoDesign.magician, discovers ExternalDesignerAbstract subclasses under REvoDesign.magician.designers.
  • RUNNER_REGISTRY -- in REvoDesign.sidechain, discovers MutateRunnerAbstract subclasses under REvoDesign.sidechain.mutate_runner.

  • Registration: Subclasses do not need explicit registration -- importing the package (done by __init__.py module-level imports like from . import designers as _designers) triggers pkgutil discovery automatically.

API reference: REvoDesign.basic