FEP API¶
The PRISM FEP module provides tools for:
- distance-based atom mapping
- hybrid topology construction with A/B-state parameters
- scaffold generation for bound and unbound legs
- FEP post-processing for
window_*outputs
Core Classes¶
FEPScaffoldBuilder¶
FEPScaffoldBuilder stages a PRISM-style FEP workspace around an existing hybrid ligand package.
The most direct entry point is build(receptor_pdb, hybrid_ligand_dir). For PRISM-generated ligand force-field components, use build_from_components(...).
from prism.fep.modeling import FEPScaffoldBuilder
builder = FEPScaffoldBuilder(
output_dir="fep_output",
config={"replicas": 1},
lambda_windows=32,
lambda_strategy="decoupled",
lambda_distribution="nonlinear",
overwrite=False,
)
fep_dir = builder.build(
receptor_pdb="protein.pdb",
hybrid_ligand_dir="hybrid_ligand_dir",
)
Constructor Parameters¶
output_dir(str): output scaffold directoryconfig(dict | None): scaffold/build configurationlambda_windows(int): number of lambda windowslambda_strategy(str): typicallydecoupledorcoupledlambda_distribution(str): lambda spacing strategyoverwrite(bool): whether to overwrite existing files
Methods¶
build(...)¶
Build the complete FEP scaffold.
Returns: Path pointing to GMX_PROLIG_FEP/
Typical layout:
GMX_PROLIG_FEP/
├── run_fep.sh
├── fep_scaffold.json # scaffold manifest (metadata/debugging; not normally consumed at runtime)
├── common/
│ └── hybrid/
│ ├── hybrid.itp
│ ├── hybrid.gro
│ └── mapping.html
├── bound/
│ └── repeat1/
│ ├── build/
│ ├── input/
│ ├── mdps/
│ ├── run_prod_standard.sh
│ ├── run_prod_repex.sh
│ └── window_00/ ... window_N/
└── unbound/
└── repeat1/
└── window_00/ ... window_N/
Two HTML outputs are relevant in normal use:
common/hybrid/mapping.html: interactive atom-mapping and hybrid-topology inspection report generated during scaffold constructionfep_analysis_report.htmlorfep_multi_estimator_report.html: post-simulation analysis report generated fromdhdl.xvgdata
DistanceAtomMapper¶
DistanceAtomMapper performs distance-based atom mapping between ligand A and ligand B.
from prism.fep import DistanceAtomMapper
mapper = DistanceAtomMapper(
dist_cutoff=0.6,
charge_cutoff=0.05,
charge_common="mean",
charge_reception="surround",
)
mapping = mapper.map(ligand_a_atoms, ligand_b_atoms)
Parameters¶
dist_cutoff(float): atom-matching cutoff in nmcharge_cutoff(float): charge-difference thresholdcharge_common(str):ref,mut,mean, ornonecharge_reception(str): standard workflow values areunique,surround, ornone; the lower-level hybrid-topology layer also supportssurround_extfor charge redistribution extension.recharge_hydrogen(bool): whether hydrogen charges can be perturbed
Notes¶
- Matching candidates require the same element and a distance below
dist_cutoff. - Generic/sequential atom types such as OpenFF, OPLS/LigParGen, and SwissParam relax type-based compatibility checks.
- GAFF/GAFF2 remains type-aware.
Methods¶
map(ligand_a, ligand_b)¶
Returns an AtomMapping object containing the final classification.
from_config(config)¶
Constructs a mapper from a loaded PRISM config dictionary.
HybridTopologyBuilder¶
Builds the ligand hybrid topology using the atom mapping and the A/B ligand topologies.
from prism.fep import HybridTopologyBuilder
hybrid_builder = HybridTopologyBuilder(
mapping=atom_mapping,
ligand_a_topology=topology_a,
ligand_b_topology=topology_b,
charge_reception="surround",
)
hybrid_topology = hybrid_builder.build()
The generated hybrid topology stores A-state and B-state parameters in the same molecular description.2 3
Analysis Classes¶
FEPAnalyzer¶
Analyzes one set of bound and unbound FEP windows.
from prism.fep.analysis import FEPAnalyzer
analyzer = FEPAnalyzer(
bound_dir="fep_output/GMX_PROLIG_FEP/bound/repeat1",
unbound_dir="fep_output/GMX_PROLIG_FEP/unbound/repeat1",
temperature=310.0,
estimator="MBAR",
bootstrap_n_jobs=4,
)
results = analyzer.analyze()
report_path = analyzer.generate_html_report("fep_results.html")
Parameters¶
bound_dir(str | Path | list): bound repeat directory or repeat directoriesunbound_dir(str | Path | list): unbound repeat directory or repeat directoriestemperature(float): simulation temperature in Kelvinestimator(str):MBAR,BAR, orTIbackend(str):alchemlyborgmx_barenergy_components(list[str] | None): defaults to['elec', 'vdw']bootstrap_n_jobs(int): bootstrap worker count
analyze()¶
Runs the configured estimator and returns a FEResults object.
generate_html_report(output_path)¶
Generates an HTML report for the current results.
FEPMultiEstimatorAnalyzer¶
Runs multiple estimators and compares them in one report.
from prism.fep.analysis import FEPMultiEstimatorAnalyzer
multi = FEPMultiEstimatorAnalyzer(
bound_dirs="fep_output/GMX_PROLIG_FEP/bound/repeat1",
unbound_dirs="fep_output/GMX_PROLIG_FEP/unbound/repeat1",
estimators=["TI", "BAR", "MBAR"],
temperature=310.0,
bootstrap_n_jobs=4,
)
results = multi.analyze()
Parameters¶
bound_dirs(str | Path | list): bound repeat directory or directoriesunbound_dirs(str | Path | list): unbound repeat directory or directoriesestimators(list[str] | None): estimator listtemperature(float): simulation temperature in Kelvinbackend(str): currentlyalchemlybfor multi-estimator modebootstrap_n_jobs(int): bootstrap worker count
Configuration¶
FEPConfig¶
FEPConfig loads and merges PRISM FEP configuration from YAML files.
from prism.fep.common.config import FEPConfig
cfg = FEPConfig(work_dir=".")
print(cfg.get_mapping_params())
print(cfg.get_lambda_params())
print(cfg.get_simulation_params())
Current canonical YAML structure:
mapping:
dist_cutoff: 0.6 # nm
charge_cutoff: 0.05
charge_common: mean
charge_reception: surround
lambda:
strategy: decoupled
distribution: nonlinear
windows: 32
coul_windows: 12
vdw_windows: 20
simulation:
temperature: 310
pressure: 1.0
per_window_npt_time_ps: 100
production_time_ns: 2.0
dt: 0.002
equilibration_nvt_time_ps: 500
equilibration_npt_time_ps: 500
output:
trajectory_interval_ps: 500
energy_interval_ps: 10
log_interval_ps: 10
nstdhdl: 100
execution:
mode: standard
total_cpus: 56
num_gpus: 4
parallel_windows: 4
use_gpu_pme: true
read_fep_config(config_file)¶
Reads the legacy FEbuilder-compatible config format and returns a plain dictionary.
Data Structures¶
Atom¶
Represents a ligand atom.
Key fields:
indexnametypechargemasscoord
Coordinates used by the current mapper are interpreted in nm.
HybridAtom¶
Represents a hybrid-topology atom with A/B-state parameters.
Key fields:
type_a,type_bcharge_a,charge_bmass_a,mass_bclassification
AtomMapping¶
Container for the final atom-mapping classification.
Typical access patterns:
mapping = mapper.map(atoms_a, atoms_b)
print(mapping.common_atoms)
print(mapping.transformed_a_atoms)
print(mapping.transformed_b_atoms)
print(mapping.surrounding_atoms)
CLI Interface¶
FEP Analysis CLI¶
Current supported CLI entry points are:
prism --fep-analyze \
--bound-dir fep_output/GMX_PROLIG_FEP/bound \
--unbound-dir fep_output/GMX_PROLIG_FEP/unbound \
--estimator MBAR BAR TI \
--bootstrap-n-jobs 8 \
--output fep_results.html \
--json fep_results.json
Equivalent module entry point:
python -m prism.fep.analysis.cli \
--bound-dir fep_output/GMX_PROLIG_FEP/bound \
--unbound-dir fep_output/GMX_PROLIG_FEP/unbound \
--estimator MBAR BAR TI \
--bootstrap-n-jobs 8 \
--output fep_results.html
Arguments¶
--bound-dir: recommended form is the leg directory (.../bound); PRISM auto-discovers allrepeat*--unbound-dir: recommended form is the leg directory (.../unbound); PRISM auto-discovers allrepeat*- when leg directories are used, bound and unbound must resolve to the same number of repeats
--estimator: one or more ofBAR,MBAR,TI--all-estimators: run all estimators--bootstrap-n-jobs: bootstrap worker count--output: HTML report path--json: optional JSON output--temperature: simulation temperature in Kelvin--backend: analysis backend
Utility Functions¶
Naming Functions¶
from prism.fep import generate_fep_system_name, validate_fep_system_name
name = generate_fep_system_name("amber14sb_OL15", "gaff2")
assert validate_fep_system_name(name)