def generate_vacuum_hybrid_topology(mol_name="naphthalene", ref_mol_name="benzene"): from topology_proposal import SmallMoleculeSetProposalEngine, TopologyProposal import simtk.openmm.app as app from openmoltools import forcefield_generators from perses.tests.utils import createOEMolFromIUPAC, createSystemFromIUPAC, get_data_filename m, unsolv_old_system, pos_old, top_old = createSystemFromIUPAC(mol_name) refmol = createOEMolFromIUPAC(ref_mol_name) initial_smiles = oechem.OEMolToSmiles(m) final_smiles = oechem.OEMolToSmiles(refmol) gaff_xml_filename = get_data_filename("data/gaff.xml") forcefield = app.ForceField(gaff_xml_filename, 'tip3p.xml') forcefield.registerTemplateGenerator(forcefield_generators.gaffTemplateGenerator) solvated_system = forcefield.createSystem(top_old) gaff_filename = get_data_filename('data/gaff.xml') system_generator = SystemGenerator([gaff_filename, 'amber99sbildn.xml', 'tip3p.xml']) geometry_engine = FFAllAngleGeometryEngine() proposal_engine = SmallMoleculeSetProposalEngine( [initial_smiles, final_smiles], system_generator, residue_name=mol_name) #generate topology proposal topology_proposal = proposal_engine.propose(solvated_system, top_old) #generate new positions with geometry engine new_positions, _ = geometry_engine.propose(topology_proposal, pos_old, beta) return topology_proposal, pos_old, new_positions
def generate_solvated_hybrid_test_topology(current_mol_name="naphthalene", proposed_mol_name="benzene"): """ Generate a test solvated topology proposal, current positions, and new positions triplet from two IUPAC molecule names. Parameters ---------- current_mol_name : str, optional name of the first molecule proposed_mol_name : str, optional name of the second molecule Returns ------- topology_proposal : perses.rjmc.topology_proposal The topology proposal representing the transformation current_positions : np.array, unit-bearing The positions of the initial system new_positions : np.array, unit-bearing The positions of the new system """ import simtk.openmm.app as app from openmoltools import forcefield_generators from perses.tests.utils import createOEMolFromIUPAC, createSystemFromIUPAC, get_data_filename current_mol, unsolv_old_system, pos_old, top_old = createSystemFromIUPAC(current_mol_name) proposed_mol = createOEMolFromIUPAC(proposed_mol_name) initial_smiles = oechem.OEMolToSmiles(current_mol) final_smiles = oechem.OEMolToSmiles(proposed_mol) gaff_xml_filename = get_data_filename("data/gaff.xml") forcefield = app.ForceField(gaff_xml_filename, 'tip3p.xml') forcefield.registerTemplateGenerator(forcefield_generators.gaffTemplateGenerator) modeller = app.Modeller(top_old, pos_old) modeller.addSolvent(forcefield, model='tip3p', padding=9.0*unit.angstrom) solvated_topology = modeller.getTopology() solvated_positions = modeller.getPositions() solvated_system = forcefield.createSystem(solvated_topology, nonbondedMethod=app.PME, removeCMMotion=False) barostat = openmm.MonteCarloBarostat(1.0*unit.atmosphere, temperature, 50) solvated_system.addForce(barostat) gaff_filename = get_data_filename('data/gaff.xml') system_generator = SystemGenerator([gaff_filename, 'amber99sbildn.xml', 'tip3p.xml'], barostat=barostat, forcefield_kwargs={'removeCMMotion': False, 'nonbondedMethod': app.PME}) geometry_engine = geometry.FFAllAngleGeometryEngine() proposal_engine = SmallMoleculeSetProposalEngine( [initial_smiles, final_smiles], system_generator, residue_name=current_mol_name) #generate topology proposal topology_proposal = proposal_engine.propose(solvated_system, solvated_topology) #generate new positions with geometry engine new_positions, _ = geometry_engine.propose(topology_proposal, solvated_positions, beta) return topology_proposal, solvated_positions, new_positions
def generate_vacuum_hostguest_proposal(current_mol_name="B2", proposed_mol_name="MOL"): """ Generate a test vacuum topology proposal, current positions, and new positions triplet from two IUPAC molecule names. Parameters ---------- current_mol_name : str, optional name of the first molecule proposed_mol_name : str, optional name of the second molecule Returns ------- topology_proposal : perses.rjmc.topology_proposal The topology proposal representing the transformation current_positions : np.array, unit-bearing The positions of the initial system new_positions : np.array, unit-bearing The positions of the new system """ from openmoltools import forcefield_generators from openmmtools import testsystems from perses.tests.utils import createOEMolFromIUPAC, createSystemFromIUPAC, get_data_filename host_guest = testsystems.HostGuestVacuum() unsolv_old_system, pos_old, top_old = host_guest.system, host_guest.positions, host_guest.topology ligand_topology = [res for res in top_old.residues()] current_mol = forcefield_generators.generateOEMolFromTopologyResidue(ligand_topology[1]) # guest is second residue in topology proposed_mol = createOEMolFromSMILES('C1CC2(CCC1(CC2)C)C') initial_smiles = oechem.OEMolToSmiles(current_mol) final_smiles = oechem.OEMolToSmiles(proposed_mol) gaff_xml_filename = get_data_filename("data/gaff.xml") forcefield = app.ForceField(gaff_xml_filename, 'tip3p.xml') forcefield.registerTemplateGenerator(forcefield_generators.gaffTemplateGenerator) solvated_system = forcefield.createSystem(top_old, removeCMMotion=False) gaff_filename = get_data_filename('data/gaff.xml') system_generator = SystemGenerator([gaff_filename, 'amber99sbildn.xml', 'tip3p.xml'], forcefield_kwargs={'removeCMMotion': False, 'nonbondedMethod': app.NoCutoff}) geometry_engine = geometry.FFAllAngleGeometryEngine() proposal_engine = SmallMoleculeSetProposalEngine( [initial_smiles, final_smiles], system_generator, residue_name=current_mol_name) #generate topology proposal topology_proposal = proposal_engine.propose(solvated_system, top_old, current_mol=current_mol, proposed_mol=proposed_mol) #generate new positions with geometry engine new_positions, _ = geometry_engine.propose(topology_proposal, pos_old, beta) return topology_proposal, pos_old, new_positions
def generate_vacuum_topology_proposal(current_mol_name="benzene", proposed_mol_name="toluene"): """ Generate a test vacuum topology proposal, current positions, and new positions triplet from two IUPAC molecule names. Parameters ---------- current_mol_name : str, optional name of the first molecule proposed_mol_name : str, optional name of the second molecule Returns ------- topology_proposal : perses.rjmc.topology_proposal The topology proposal representing the transformation current_positions : np.array, unit-bearing The positions of the initial system new_positions : np.array, unit-bearing The positions of the new system """ from openmoltools import forcefield_generators from perses.tests.utils import createOEMolFromIUPAC, createSystemFromIUPAC, get_data_filename current_mol, unsolv_old_system, pos_old, top_old = createSystemFromIUPAC(current_mol_name) proposed_mol = createOEMolFromIUPAC(proposed_mol_name) initial_smiles = oechem.OEMolToSmiles(current_mol) final_smiles = oechem.OEMolToSmiles(proposed_mol) gaff_xml_filename = get_data_filename("data/gaff.xml") forcefield = app.ForceField(gaff_xml_filename, 'tip3p.xml') forcefield.registerTemplateGenerator(forcefield_generators.gaffTemplateGenerator) solvated_system = forcefield.createSystem(top_old, removeCMMotion=False) gaff_filename = get_data_filename('data/gaff.xml') system_generator = SystemGenerator([gaff_filename, 'amber99sbildn.xml', 'tip3p.xml'], forcefield_kwargs={'removeCMMotion': False, 'nonbondedMethod': app.NoCutoff}) geometry_engine = geometry.FFAllAngleGeometryEngine() proposal_engine = SmallMoleculeSetProposalEngine( [initial_smiles, final_smiles], system_generator, residue_name=current_mol_name) #generate topology proposal topology_proposal = proposal_engine.propose(solvated_system, top_old, current_mol=current_mol, proposed_mol=proposed_mol) #generate new positions with geometry engine new_positions, _ = geometry_engine.propose(topology_proposal, pos_old, beta) return topology_proposal, pos_old, new_positions
def oemol_to_omm_ff(oemol, molecule_name): from perses.rjmc import topology_proposal from openmoltools import forcefield_generators gaff_xml_filename = get_data_filename('data/gaff.xml') system_generator = topology_proposal.SystemGenerator([gaff_xml_filename]) topology = forcefield_generators.generateTopologyFromOEMol(oemol) system = system_generator.build_system(topology) positions = extractPositionsFromOEMOL(oemol) return system, positions, topology
def createSystemFromIUPAC(iupac_name): """ Create an openmm system out of an oemol Parameters ---------- iupac_name : str IUPAC name Returns ------- molecule : openeye.OEMol OEMol molecule system : openmm.System object OpenMM system positions : [n,3] np.array of floats Positions topology : openmm.app.Topology object Topology """ # Create OEMol molecule = createOEMolFromIUPAC(iupac_name) # Generate a topology. from openmoltools.forcefield_generators import generateTopologyFromOEMol topology = generateTopologyFromOEMol(molecule) # Initialize a forcefield with GAFF. # TODO: Fix path for `gaff.xml` since it is not yet distributed with OpenMM from simtk.openmm.app import ForceField gaff_xml_filename = get_data_filename('data/gaff.xml') forcefield = ForceField(gaff_xml_filename) # Generate template and parameters. from openmoltools.forcefield_generators import generateResidueTemplate [template, ffxml] = generateResidueTemplate(molecule) # Register the template. forcefield.registerResidueTemplate(template) # Add the parameters. forcefield.loadFile(StringIO(ffxml)) # Create the system. system = forcefield.createSystem(topology, removeCMMotion=False) # Extract positions positions = extractPositionsFromOEMOL(molecule) return (molecule, system, positions, topology)
def prepare_topology_proposal(): from perses.tests.utils import get_data_filename gaff_xml_filename = get_data_filename("data/gaff.xml") forcefield = app.ForceField(gaff_xml_filename, 'tip3p.xml', 'amber99sbildn.xml') forcefield.registerTemplateGenerator( forcefield_generators.gaffTemplateGenerator) oemol_list = load_mol_file("p38_ligands.sdf") mol_a = oemol_list[0] mol_b = oemol_list[1] modeller = combine_mol_with_receptor(mol_a, "p38_protein.pdb") modeller.addSolvent(forcefield, model='tip3p', padding=9.0 * unit.angstrom) topology = modeller.getTopology() positions = modeller.getPositions() system = forcefield.createSystem(topology, nonbondedMethod=app.PME)
def generate_solvated_hybrid_test_topology(mol_name="naphthalene", ref_mol_name="benzene"): from perses.rjmc.topology_proposal import SmallMoleculeSetProposalEngine, TopologyProposal import simtk.openmm.app as app from openmoltools import forcefield_generators from perses.tests.utils import createOEMolFromIUPAC, createSystemFromIUPAC, get_data_filename mol = createOEMolFromIUPAC(mol_name) m, unsolv_system, pos, top = createSystemFromIUPAC(mol_name) refmol = createOEMolFromIUPAC(ref_mol_name) gaff_xml_filename = get_data_filename("data/gaff.xml") forcefield = app.ForceField(gaff_xml_filename, 'tip3p.xml') forcefield.registerTemplateGenerator( forcefield_generators.gaffTemplateGenerator) #map one of the rings atom_map = SmallMoleculeSetProposalEngine._get_mol_atom_map(mol, refmol) #now use the mapped atoms to generate a new and old system with identical atoms mapped. This will result in the #same molecule with the same positions for lambda=0 and 1, and ensures a contiguous atom map effective_atom_map = {value: value for value in atom_map.values()} modeller = app.Modeller(top, pos) modeller.addSolvent(forcefield, model='tip3p', padding=9.0 * unit.angstrom) topology = modeller.getTopology() positions = modeller.getPositions() system = forcefield.createSystem(topology, nonbondedMethod=app.PME) n_atoms_old_system = unsolv_system.getNumParticles() n_atoms_after_solvation = system.getNumParticles() for i in range(n_atoms_old_system, n_atoms_after_solvation): effective_atom_map[i] = i top_proposal = TopologyProposal(new_topology=topology, new_system=system, old_topology=topology, old_system=system, new_to_old_atom_map=effective_atom_map, new_chemical_state_key="n1", old_chemical_state_key='n2') return top_proposal, positions
def generate_solvated_hybrid_test_topology(mol_name="naphthalene", ref_mol_name="benzene"): from perses.rjmc.topology_proposal import SmallMoleculeSetProposalEngine, TopologyProposal import simtk.openmm.app as app from openmoltools import forcefield_generators from perses.tests.utils import createOEMolFromIUPAC, createSystemFromIUPAC, get_data_filename mol = createOEMolFromIUPAC(mol_name) m, unsolv_system, pos, top = createSystemFromIUPAC(mol_name) refmol = createOEMolFromIUPAC(ref_mol_name) gaff_xml_filename = get_data_filename("data/gaff.xml") forcefield = app.ForceField(gaff_xml_filename, 'tip3p.xml') forcefield.registerTemplateGenerator(forcefield_generators.gaffTemplateGenerator) #map one of the rings atom_map = SmallMoleculeSetProposalEngine._get_mol_atom_map(mol, refmol) #now use the mapped atoms to generate a new and old system with identical atoms mapped. This will result in the #same molecule with the same positions for lambda=0 and 1, and ensures a contiguous atom map effective_atom_map = {value : value for value in atom_map.values()} modeller = app.Modeller(top, pos) modeller.addSolvent(forcefield, model='tip3p', padding=9.0*unit.angstrom) topology = modeller.getTopology() positions = modeller.getPositions() system = forcefield.createSystem(topology, nonbondedMethod=app.PME) n_atoms_old_system = unsolv_system.getNumParticles() n_atoms_after_solvation = system.getNumParticles() for i in range(n_atoms_old_system, n_atoms_after_solvation): effective_atom_map[i] = i top_proposal = TopologyProposal(new_topology=topology, new_system=system, old_topology=topology, old_system=system, new_to_old_atom_map=effective_atom_map, new_chemical_state_key="n1", old_chemical_state_key='n2') return top_proposal, positions
def generate_topology_proposal(old_mol_iupac="pentane", new_mol_iupac="butane"): """ Utility function to generate a topologyproposal for tests Parameters ---------- old_mol_iupac : str, optional name of old mol, default pentane new_mol_iupac : str, optional name of new mol, default butane Returns ------- topology_proposal : perses.rjmc.topology_proposal.TopologyProposal the topology proposal corresponding to the given transformation old_positions : [n, 3] np.ndarray of float positions of old mol new_positions : [m, 3] np.ndarray of float positions of new mol """ from perses.rjmc.topology_proposal import TwoMoleculeSetProposalEngine, SystemGenerator from perses.rjmc.geometry import FFAllAngleGeometryEngine from perses.tests.utils import createSystemFromIUPAC, get_data_filename import openmoltools.forcefield_generators as forcefield_generators from io import StringIO from openmmtools.constants import kB temperature = 300.0 * unit.kelvin kT = kB * temperature beta = 1.0 / kT gaff_filename = get_data_filename("data/gaff.xml") forcefield_files = [gaff_filename, 'amber99sbildn.xml'] #generate systems and topologies old_mol, old_system, old_positions, old_topology = createSystemFromIUPAC( old_mol_iupac) new_mol, new_system, new_positions, new_topology = createSystemFromIUPAC( new_mol_iupac) #set names old_mol.SetTitle("MOL") new_mol.SetTitle("MOL") #generate forcefield and ProposalEngine #ffxml=forcefield_generators.generateForceFieldFromMolecules([old_mol, new_mol]) system_generator = SystemGenerator( forcefield_files, forcefield_kwargs={'removeCMMotion': False}) proposal_engine = TwoMoleculeSetProposalEngine(old_mol, new_mol, system_generator, residue_name="pentane") geometry_engine = FFAllAngleGeometryEngine() #create a TopologyProposal topology_proposal = proposal_engine.propose(old_system, old_topology) new_positions_geometry, _ = geometry_engine.propose( topology_proposal, old_positions, beta) return topology_proposal, old_positions, new_positions_geometry
def generate_vacuum_topology_proposal(current_mol_name="benzene", proposed_mol_name="toluene", forcefield_kwargs=None, system_generator_kwargs=None): """ Generate a test vacuum topology proposal, current positions, and new positions triplet from two IUPAC molecule names. Constraints are added to the system by default. To override this, set ``forcefield_kwargs = None``. Parameters ---------- current_mol_name : str, optional name of the first molecule proposed_mol_name : str, optional name of the second molecule forcefield_kwargs : dict, optional, default=None Additional arguments to ForceField in addition to 'removeCMMotion': False, 'nonbondedMethod': app.NoCutoff system_generator_kwargs : dict, optional, default=None Dict passed onto SystemGenerator Returns ------- topology_proposal : perses.rjmc.topology_proposal The topology proposal representing the transformation current_positions : np.array, unit-bearing The positions of the initial system new_positions : np.array, unit-bearing The positions of the new system """ from openmoltools import forcefield_generators from perses.tests.utils import createOEMolFromIUPAC, createSystemFromIUPAC, get_data_filename gaff_filename = get_data_filename('data/gaff.xml') default_forcefield_kwargs = {'removeCMMotion': False, 'nonbondedMethod': app.NoCutoff, 'constraints' : app.HBonds} forcefield_kwargs = default_forcefield_kwargs.update(forcefield_kwargs) if (forcefield_kwargs is not None) else default_forcefield_kwargs system_generator_kwargs = system_generator_kwargs if (system_generator_kwargs is not None) else dict() system_generator = SystemGenerator([gaff_filename, 'amber99sbildn.xml', 'tip3p.xml'], forcefield_kwargs=forcefield_kwargs, **system_generator_kwargs) old_oemol = createOEMolFromIUPAC(current_mol_name) from openmoltools.forcefield_generators import generateTopologyFromOEMol old_topology = generateTopologyFromOEMol(old_oemol) old_positions = extractPositionsFromOEMOL(old_oemol) old_smiles = oechem.OEMolToSmiles(old_oemol) old_system = system_generator.build_system(old_topology) new_oemol = createOEMolFromIUPAC(proposed_mol_name) new_smiles = oechem.OEMolToSmiles(new_oemol) geometry_engine = geometry.FFAllAngleGeometryEngine() proposal_engine = SmallMoleculeSetProposalEngine( [old_smiles, new_smiles], system_generator, residue_name=current_mol_name) #generate topology proposal topology_proposal = proposal_engine.propose(old_system, old_topology, current_mol=old_oemol, proposed_mol=new_oemol) # show atom mapping filename = str(current_mol_name)+str(proposed_mol_name)+'.pdf' render_atom_mapping(filename, old_oemol, new_oemol, topology_proposal.new_to_old_atom_map) #generate new positions with geometry engine new_positions, _ = geometry_engine.propose(topology_proposal, old_positions, beta) # DEBUG: Zero out bonds and angles for one system #print('Zeroing bonds of old system') #for force in topology_proposal.old_system.getForces(): # if force.__class__.__name__ == 'HarmonicAngleForce': # for index in range(force.getNumAngles()): # p1, p2, p3, angle, K = force.getAngleParameters(index) # K *= 0.0 # force.setAngleParameters(index, p1, p2, p3, angle, K) # if False and force.__class__.__name__ == 'HarmonicBondForce': # for index in range(force.getNumBonds()): # p1, p2, r0, K = force.getBondParameters(index) # K *= 0.0 # force.setBondParameters(index, p1, p2, r0, K) # DEBUG : Box vectors #box_vectors = np.eye(3) * 100 * unit.nanometers #topology_proposal.old_system.setDefaultPeriodicBoxVectors(box_vectors[0,:], box_vectors[1,:], box_vectors[2,:]) #topology_proposal.new_system.setDefaultPeriodicBoxVectors(box_vectors[0,:], box_vectors[1,:], box_vectors[2,:]) return topology_proposal, old_positions, new_positions
def test_logp_forward_check_for_vacuum_topology_proposal(current_mol_name = 'propane', proposed_mol_name = 'octane', num_iterations = 100, neglect_angles = True): """ Generate a test vacuum topology proposal, current positions, and new positions triplet from two IUPAC molecule names. Assert that the logp_forward < 1e3. This assertion will fail if the proposal order tool proposed the placement of the a carbon before a previously defined carbon in the alkane. Parameters ---------- current_mol_name : str, optional name of the first molecule proposed_mol_name : str, optional name of the second molecule Returns ------- topology_proposal : perses.rjmc.topology_proposal The topology proposal representing the transformation current_positions : np.array, unit-bearing The positions of the initial system new_positions : np.array, unit-bearing The positions of the new system """ from openmoltools import forcefield_generators from perses.tests.utils import createOEMolFromIUPAC, createSystemFromIUPAC, get_data_filename current_mol, unsolv_old_system, pos_old, top_old = createSystemFromIUPAC(current_mol_name) proposed_mol = createOEMolFromIUPAC(proposed_mol_name) initial_smiles = oechem.OEMolToSmiles(current_mol) final_smiles = oechem.OEMolToSmiles(proposed_mol) gaff_xml_filename = get_data_filename("data/gaff.xml") forcefield = app.ForceField(gaff_xml_filename, 'tip3p.xml') forcefield.registerTemplateGenerator(forcefield_generators.gaffTemplateGenerator) solvated_system = forcefield.createSystem(top_old, removeCMMotion=False) gaff_filename = get_data_filename('data/gaff.xml') system_generator = SystemGenerator([gaff_filename, 'amber99sbildn.xml', 'tip3p.xml'], forcefield_kwargs={'removeCMMotion': False, 'nonbondedMethod': app.NoCutoff}) geometry_engine = geometry.FFAllAngleGeometryEngine(n_bond_divisions=100, n_angle_divisions=180, n_torsion_divisions=360, neglect_angles = neglect_angles) proposal_engine = SmallMoleculeSetProposalEngine( [initial_smiles, final_smiles], system_generator, residue_name=current_mol_name) #generate topology proposal topology_proposal = proposal_engine.propose(solvated_system, top_old, current_mol=current_mol, proposed_mol=proposed_mol) # show atom mapping filename = str(current_mol_name)+str(proposed_mol_name)+'.pdf' render_atom_mapping(filename,current_mol,proposed_mol,topology_proposal.new_to_old_atom_map) total_works = [] for _ in range(num_iterations): #generate new positions with geometry engine new_positions, logp_forward = geometry_engine.propose(topology_proposal, pos_old, beta) logp_reverse = geometry_engine.logp_reverse(topology_proposal, new_positions, pos_old, beta) #now just render forward and backward work work_fwd = logp_forward + geometry_engine.forward_final_context_reduced_potential - geometry_engine.forward_atoms_with_positions_reduced_potential work_bkwd = logp_reverse + geometry_engine.reverse_atoms_with_positions_reduced_potential - geometry_engine.reverse_final_context_reduced_potential total_work = logp_forward - logp_reverse + geometry_engine.forward_final_context_reduced_potential - geometry_engine.reverse_final_context_reduced_potential total_works.append(total_work) print("forward, backward works : {}, {}".format(work_fwd, work_bkwd)) print("total_work: {}".format(total_work)) assert abs(work_fwd - work_bkwd - total_work) < 1, "The difference of fwd and backward works is not equal to the total work (within 1kT)" assert logp_forward < 1e3, "A heavy atom was proposed in an improper order"