"""
Absolute binding FEP command line UI
Copyright Schrodinger, LLC. All rights reserved.
"""
import argparse
import sys
from typing import List
from schrodinger.application.desmond import constants
from schrodinger.application.desmond import struc
from schrodinger.application.desmond import util
from schrodinger.infra import mm
from schrodinger.utils import fileutils
from . import cmdline
from .cmdline import Option
[docs]class Args(cmdline.BaseArgs):
[docs] def __init__(self, opt: argparse.Namespace):
self.copy_parser_attributes(opt)
super(Args, self).__init__(opt)
[docs] def validate(self):
from schrodinger.application.scisol.packages.fep import fepmae
from schrodinger.application.scisol.packages.fep import graph
if not (self.inp_file or self.checkpoint):
sys.exit(
'ERROR: Must provide <pv-or-fmp-file> for running a new job.')
if self.inp_file:
util.ensure_file_exists(self.inp_file)
if not self.inp_file.endswith("fmp"):
if not fileutils.is_maestro_file(self.inp_file):
sys.exit(
f"ERROR: The {self.inp_file} must be a poseviewer structure with "
"a protein and at least one ligand. It may optionally contain separate "
"solvent and membrane structures for membrane systems.")
# Make sure ligand titles are unique
input_sts = struc.read_all_structures(self.inp_file)
_, _, _, ligand_sts = fepmae.filter_receptors_and_ligands(
input_sts)
duplicate_titles = struc.find_duplicate_titles(ligand_sts)
if duplicate_titles:
for idx, title in duplicate_titles:
print(
f'Duplicate title "{title}" found at index {idx}.')
sys.exit(
f"ERROR: The {self.inp_file} contains ligands with duplicate names."
)
else:
g = graph.Graph.deserialize(self.inp_file)
if g.fep_type != constants.FEP_TYPES.ABSOLUTE_BINDING:
sys.exit(f"ERROR: {self.inp_file} uses FEP type "
f"{g.fep_type} but needs to be generated "
f"for Absolute Binding FEP")
self.check_ppj()
if self.extend:
util.ensure_file_exists(self.extend)
# needed for prepare_files_and_command_for_fep_restart_extend
self.time_solvent = self.time_complex = self.fep_sim_time
self.time_vacuum = self.time = 0
super().validate()
[docs]def ui(argv: List[str]) -> Args:
usage = """
Absolute binding FEP driver (experimental)
Report issues to Desmond.
* Run a new job:
$SCHRODINGER/fep_absolute_binding -HOST <main-host> -SUBHOST <subhost> -JOBNAME <jobname> <input_pv>.mae
* Restart a previously interrupted job:
$SCHRODINGER/fep_absolute_binding -HOST <main-host> -SUBHOST <subhost> -JOBNAME <jobname> -RESTART -checkpoint <multisim-checkpoint-file>
Note that the following options have no effect when restarting:
-ppj
* Extend a completed job:
$SCHRODINGER/fep_absolute_binding -HOST <main-host> -SUBHOST <subhost> -JOBNAME <jobname> -extend <extend.ligand> -checkpoint <multisim-checkpoint-file> -fep-sim-time 5000.0
Note that the following options have no effect when extending:
-md-sim-time
-ppj
* Prepare the input files for multisim without running the job.
$SCHRODINGER/fep_absolute_binding -HOST <main-host> -SUBHOST <subhost> -JOBNAME <jobname> <input_pv>.mae -prepare
"""
options = cmdline.get_common_options()
options.extend([
Option(
"inp_file", None,
"A Maestro pv structure file containing one or more ligand structures.",
{"nargs": "?"}),
Option(
"-md-sim-time", 1000.0,
"Specify the MD production simulation time (in ps). Min value: 500.0. "
"Default: %(default)s."),
Option(
"-fep-sim-time", 5000.0,
"Specify the FEP production simulation time (in ps). Min value: 500.0. "
"Default: %(default)s."),
Option(
"-custom-charge-mode", constants.CUSTOM_CHARGE_MODE.ASSIGN,
"Set the custom charge calculation mode when using the "
f"{mm.OPLS_NAME_F16} forcefield. "
"Valid values are 'assign' to assign custom charges based on the input geometries, "
"'clear' to clear existing custom charges, and "
"'keep' to keep existing custom charges. "
"Default: %(default)s.\n",
{"metavar": "{%s}" % '|'.join(constants.CUSTOM_CHARGE_MODE)}),
Option(
"-ensemble",
constants.Ensembles.MUVT,
"Specify the ensemble class. Default: %(default)s.",
{"metavar": "{muVT|NPT|NVT}"},
),
Option("-ligand-restraint", False,
"Apply dihedral restraints on the ligand molecule."),
Option("-adaptive-ligand-restraint", False,
"Apply adaptive dihedral restraints on the ligand molecule."),
Option(
"-use-final-frame", False,
"Use the final frame as the structure for FEP, instead of the representative structure."
),
Option(
"-extend",
"",
"Extend production simulations of specified ligands.",
{
"metavar": "<ligand-file>",
},
)
])
cmdline.suppress_options(options, {
"-skip_traj",
"-buffer",
"-no_concat",
"-lambda-windows",
})
opt = cmdline.parse_options(usage, options, argv[1:], add_subhost=True)
return Args(opt)