Source code for perses.bias.bias_engine
"""
This is the base class for generating a biasing potential
for expanded ensemble simulation
"""
import openeye.oechem as oechem
import openeye.oeomega as oeomega
import openmoltools
import openeye.oeiupac as oeiupac
import simtk.openmm as openmm
import simtk.openmm.app as app
import simtk.unit as units
[docs]class BiasEngine(object):
"""
Generates the bias for expanded ensemble simulations
Arguments
---------
metadata : dict
Dictionary containing metadata relevant to the implementation
"""
[docs] def __init__(self, metadata):
pass
[docs] def g_k(self, molecule_smiles):
"""
Generate a biasing weight g_k for the state indicated.
Arguments
--------
molecule_smiles : string
SMILES string of molecule to calculate bias
Returns
-------
g_k : float
Bias for the given state
"""
return 0
[docs]class MinimizedPotentialBias(BiasEngine):
"""
This class calculates the bias potential for expanded ensemble simulations,
using a minimized potential energy as the bias.
Arguments
---------
smiles_list : list of str
list of smiles strings corresponding to molecules
implicit_solvent : simtk.openmm.app implicit solvent model, optional, default=OBC2
Implicit solvent model to use for computing bias.
constraints : simtk.openmm.app constraint choice, optional, default=HBonds
Constraints to use.
"""
[docs] def __init__(self, smiles_list, implicit_solvent=app.OBC2, constraints=app.HBonds):
self._smiles_list = smiles_list
self._mol_dict = self._create_molecule_list(smiles_list)
self._gk = dict()
self.implicit_solvent = implicit_solvent
self.constraints = constraints
def _create_molecule_list(self, smiles_list):
"""
Utility function to create oemols out of smiles strings
Returns
-------
oemol_list : dict of smiles : oemol
smile : oemols for the simulation
"""
oemol_dict ={}
omega = oeomega.OEOmega()
omega.SetMaxConfs(1)
for smiles in smiles_list:
mol = oechem.OEMol()
oechem.OESmilesToMol(mol, smiles)
oechem.OEAddExplicitHydrogens(mol)
omega(mol)
oemol_dict[smiles] = mol
return oemol_dict
def _create_implicit_solvent_openmm(self, mol):
"""
Take a list of oemols, and generate openmm systems
and positions for each.
Arguments
---------
mol : oemol
oemol to be turned into system, positions
Returns
--------
system : simtk.openmm.System
openmm system corresponding to molecule
positions : np.array, Quantity nm
array of atomic positions
"""
molecule_name = oeiupac.OECreateIUPACName(mol)
openmoltools.openeye.enter_temp_directory()
_ , tripos_mol2_filename = openmoltools.openeye.molecule_to_mol2(mol, tripos_mol2_filename=molecule_name + '.tripos.mol2', conformer=0, residue_name='MOL')
gaff_mol2, frcmod = openmoltools.amber.run_antechamber(molecule_name, tripos_mol2_filename)
prmtop_file, inpcrd_file = openmoltools.amber.run_tleap(molecule_name, gaff_mol2, frcmod)
prmtop = app.AmberPrmtopFile(prmtop_file)
crd = app.AmberInpcrdFile(inpcrd_file)
system = prmtop.createSystem(implicitSolvent=self.implicit_solvent, constraints=self.constraints, removeCMMotion=False)
positions = crd.getPositions(asNumpy=True)
return system, positions
[docs] def g_k(self, molecule_smiles):
"""
Retrieve or compute the g_k for the given molecule
Arguments
---------
molecule_smiles : string
SMILES representation of the molecule
Returns
-------
g_k : float
Bias weight
"""
if molecule_smiles in self._gk.keys():
return self._gk[molecule_smiles]
else:
system, positions = self._create_implicit_solvent_openmm(self._mol_dict[molecule_smiles])
timestep = 2*units.femtoseconds
integrator = openmm.VerletIntegrator(timestep)
platform = openmm.Platform.getPlatformByName("CPU")
context = openmm.Context(system, integrator, platform)
context.setPositions(positions)
openmm.LocalEnergyMinimizer.minimize(context)
state = context.getState(getEnergy=True)
g_k = state.getPotentialEnergy()
self._gk[molecule_smiles] = g_k
return g_k
[docs] def precompute_gk(self):
"""
A utility function to compute all the g_ks
and return them as a {smiles : g_k} dict
Returns
------
gks : dict of type {string : float}
dict of {smiles : g_k}
"""
gks = dict()
for smiles in self._smiles_list:
gks[smiles] = self.g_k(smiles)
return gks