def test_hybrid_scheme(): """ Test ncmc hybrid switching """ from perses.tests.testsystems import AlanineDipeptideTestSystem niterations = 5 # number of iterations to run if 'TESTSYSTEMS' in os.environ: testsystem_names = os.environ['TESTSYSTEMS'].split(' ') if 'AlanineDipeptideTestSystem' not in testsystem_names: return # Instantiate test system. testsystem = AlanineDipeptideTestSystem() # Test MCMCSampler samplers. testsystem.environments = ['vacuum'] # Test ExpandedEnsembleSampler samplers. from perses.samplers.samplers import ExpandedEnsembleSampler for environment in testsystem.environments: chemical_state_key = testsystem.proposal_engines[ environment].compute_state_key(testsystem.topologies[environment]) testsystem.exen_samplers[environment] = ExpandedEnsembleSampler( testsystem.mcmc_samplers[environment], testsystem.topologies[environment], chemical_state_key, testsystem.proposal_engines[environment], geometry.FFAllAngleGeometryEngine(metadata={}), scheme='geometry-ncmc-geometry', options={'nsteps': 1}) exen_sampler = testsystem.exen_samplers[environment] exen_sampler.verbose = True f = partial(exen_sampler.run, niterations) f.description = "Testing expanded ensemble sampler with AlanineDipeptideTestSystem '%s'" % environment yield f
def test_mutate_quick(): """ Abbreviated version of test_mutate_all for travis. """ import perses.rjmc.topology_proposal as topology_proposal import perses.rjmc.geometry as geometry from perses.tests.utils import compute_potential_components from openmmtools import testsystems as ts geometry_engine = geometry.FFAllAngleGeometryEngine() aminos = ['ALA','VAL','GLY','PHE','PRO','TRP'] for aa in aminos: topology, positions = _get_capped_amino_acid(amino_acid=aa) modeller = app.Modeller(topology, positions) ff_filename = "amber99sbildn.xml" max_point_mutants = 1 ff = app.ForceField(ff_filename) system = ff.createSystem(modeller.topology) chain_id = '1' system_generator = topology_proposal.SystemGenerator([ff_filename]) pm_top_engine = topology_proposal.PointMutationEngine(modeller.topology, system_generator, chain_id, max_point_mutants=max_point_mutants) current_system = system current_topology = modeller.topology current_positions = modeller.positions minimize_integrator = openmm.VerletIntegrator(1.0*unit.femtosecond) platform = openmm.Platform.getPlatformByName("Reference") minimize_context = openmm.Context(current_system, minimize_integrator, platform) minimize_context.setPositions(current_positions) initial_state = minimize_context.getState(getEnergy=True) initial_potential = initial_state.getPotentialEnergy() openmm.LocalEnergyMinimizer.minimize(minimize_context) final_state = minimize_context.getState(getEnergy=True, getPositions=True) final_potential = final_state.getPotentialEnergy() current_positions = final_state.getPositions() print("Minimized initial structure from %s to %s" % (str(initial_potential), str(final_potential))) for k, proposed_amino in enumerate(aminos): pm_top_engine._allowed_mutations = [[('2',proposed_amino)]] pm_top_proposal = pm_top_engine.propose(current_system, current_topology) new_positions, logp = geometry_engine.propose(pm_top_proposal, current_positions, beta) new_system = pm_top_proposal.new_system if np.isnan(logp): raise Exception("NaN in the logp") integrator = openmm.VerletIntegrator(1*unit.femtoseconds) platform = openmm.Platform.getPlatformByName("Reference") context = openmm.Context(new_system, integrator, platform) context.setPositions(new_positions) state = context.getState(getEnergy=True) print(compute_potential_components(context)) potential = state.getPotentialEnergy() potential_without_units = potential / potential.unit print(str(potential)) if np.isnan(potential_without_units): raise Exception("Energy after proposal is NaN")
def test_coordinate_conversion(): """ test that the `_internal_to_cartesian` and `_cartesian_to_internal` functions in `geometry.py` convert with correct dimensionality and within an error of 1e-12 for random inputs """ import perses.rjmc.geometry as geometry geometry_engine = geometry.FFAllAngleGeometryEngine({'test': 'true'}) #try to transform random coordinates to and from cartesian for i in range(200): indices = np.random.randint(100, size=4) atom_position = unit.Quantity(np.array( [0.80557722, -1.10424644, -1.08578826]), unit=unit.nanometers) bond_position = unit.Quantity(np.array([0.0765, 0.1, -0.4005]), unit=unit.nanometers) angle_position = unit.Quantity(np.array([0.0829, 0.0952, -0.2479]), unit=unit.nanometers) torsion_position = unit.Quantity(np.array([-0.057, 0.0951, -0.1863]), unit=unit.nanometers) rtp, detJ = geometry_engine._cartesian_to_internal( atom_position, bond_position, angle_position, torsion_position) # Check internal coordinates do not have units r, theta, phi = rtp assert isinstance(r, float) assert isinstance(theta, float) assert isinstance(phi, float) # Check that we can reproduce original unit-bearing positions xyz, _ = geometry_engine._internal_to_cartesian( bond_position, angle_position, torsion_position, r, theta, phi) assert check_dimensionality(xyz, unit.nanometers) assert np.linalg.norm(xyz - atom_position) < 1.0e-12
def test_logp_reverse(): """ Make sure logp_reverse and logp_forward are consistent """ molecule_name_1 = 'erlotinib' molecule_name_2 = 'imatinib' #molecule_name_1 = 'benzene' #molecule_name_2 = 'biphenyl' molecule1 = generate_initial_molecule(molecule_name_1) molecule2 = generate_initial_molecule(molecule_name_2) new_to_old_atom_mapping = align_molecules(molecule1, molecule2) sys1, pos1, top1 = oemol_to_openmm_system(molecule1, molecule_name_1) sys2, pos2, top2 = oemol_to_openmm_system(molecule2, molecule_name_2) test_pdb_file = open("reverse_test1.pdb", 'w') app.PDBFile.writeFile(top1, pos1, file=test_pdb_file) test_pdb_file.close() import perses.rjmc.geometry as geometry import perses.rjmc.topology_proposal as topology_proposal sm_top_proposal = topology_proposal.TopologyProposal(new_topology=top2, new_system=sys2, old_topology=top1, old_system=sys1, logp_proposal=0.0, new_to_old_atom_map=new_to_old_atom_mapping, new_chemical_state_key="CCC", old_chemical_state_key="CC", metadata={'test':0.0}) geometry_engine = geometry.FFAllAngleGeometryEngine({'test': 'true'}) new_positions, logp_proposal = geometry_engine.propose(sm_top_proposal, pos1, beta) logp_reverse = geometry_engine.logp_reverse(sm_top_proposal, pos2, pos1, beta) print(logp_proposal) print(logp_reverse) print(logp_reverse-logp_proposal)
def test_try_random_itoc(): """ test whether a perturbed four-atom system gives the same internal and cartesian coords when recomputed with `_internal_to_cartesian` and `_cartesian_to_internal` as compared to the values output by `_get_internal_from_omm` """ import perses.rjmc.geometry as geometry geometry_engine = geometry.FFAllAngleGeometryEngine({'test': 'true'}) import simtk.openmm as openmm integrator = openmm.VerletIntegrator(1.0*unit.femtoseconds) sys = openmm.System() force = openmm.CustomTorsionForce("theta") for i in range(4): sys.addParticle(1.0*unit.amu) force.addTorsion(0,1,2,3,[]) sys.addForce(force) atom_position = unit.Quantity(np.array([ 0.10557722 ,-1.10424644 ,-1.08578826]), unit=unit.nanometers) bond_position = unit.Quantity(np.array([ 0.0765, 0.1 , -0.4005]), unit=unit.nanometers) angle_position = unit.Quantity(np.array([ 0.0829 , 0.0952 ,-0.2479]) ,unit=unit.nanometers) torsion_position = unit.Quantity(np.array([-0.057 , 0.0951 ,-0.1863] ) ,unit=unit.nanometers) for i in range(1000): atom_position += unit.Quantity(np.random.normal(size=3), unit=unit.nanometers) r, theta, phi = _get_internal_from_omm(atom_position, bond_position, angle_position, torsion_position) recomputed_xyz, _ = geometry_engine._internal_to_cartesian(bond_position, angle_position, torsion_position, r, theta, phi) new_r, new_theta, new_phi = _get_internal_from_omm(recomputed_xyz,bond_position, angle_position, torsion_position) TOLERANCE = 1e-10 difference = np.linalg.norm(np.array(atom_position/unit.nanometers) - np.array(recomputed_xyz/unit.nanometers)) assert difference < TOLERANCE, f"the norm of the difference in positions recomputed with original cartesians ({difference}) is greater than tolerance of {TOLERANCE}" difference = np.linalg.norm(np.array([r, theta, phi]) - np.array([new_r, new_theta, new_phi])) assert difference < TOLERANCE, f"the norm of the difference in internals recomputed with original sphericals ({difference}) is greater than tolerance of {TOLERANCE}"
def test_try_random_itoc(): import perses.rjmc.geometry as geometry geometry_engine = geometry.FFAllAngleGeometryEngine({'test': 'true'}) import simtk.openmm as openmm integrator = openmm.VerletIntegrator(1.0*unit.femtoseconds) sys = openmm.System() force = openmm.CustomTorsionForce("theta") for i in range(4): sys.addParticle(1.0*unit.amu) force.addTorsion(0,1,2,3,[]) sys.addForce(force) atom_position = unit.Quantity(np.array([ 0.10557722 ,-1.10424644 ,-1.08578826]), unit=unit.nanometers) bond_position = unit.Quantity(np.array([ 0.0765, 0.1 , -0.4005]), unit=unit.nanometers) angle_position = unit.Quantity(np.array([ 0.0829 , 0.0952 ,-0.2479]) ,unit=unit.nanometers) torsion_position = unit.Quantity(np.array([-0.057 , 0.0951 ,-0.1863] ) ,unit=unit.nanometers) for i in range(1000): atom_position += unit.Quantity(np.random.normal(size=3), unit=unit.nanometers) r, theta, phi = _get_internal_from_omm(atom_position, bond_position, angle_position, torsion_position) r = (r/r.unit)*unit.nanometers theta = (theta/theta.unit)*unit.radians phi = (phi/phi.unit)*unit.radians recomputed_xyz, _ = geometry_engine._internal_to_cartesian(bond_position, angle_position, torsion_position, r, theta, phi) new_r, new_theta, new_phi = _get_internal_from_omm(recomputed_xyz,bond_position, angle_position, torsion_position) crtp = geometry_engine._cartesian_to_internal(recomputed_xyz,bond_position, angle_position, torsion_position)
def test_openmm_dihedral(): import perses.rjmc.geometry as geometry geometry_engine = geometry.FFAllAngleGeometryEngine({'test': 'true'}) import simtk.openmm as openmm integrator = openmm.VerletIntegrator(1.0*unit.femtoseconds) sys = openmm.System() force = openmm.CustomTorsionForce("theta") for i in range(4): sys.addParticle(1.0*unit.amu) force.addTorsion(0,1,2,3,[]) sys.addForce(force) atom_position = unit.Quantity(np.array([ 0.10557722 ,-1.10424644 ,-1.08578826]), unit=unit.nanometers) bond_position = unit.Quantity(np.array([ 0.0765, 0.1 , -0.4005]), unit=unit.nanometers) angle_position = unit.Quantity(np.array([ 0.0829 , 0.0952 ,-0.2479]) ,unit=unit.nanometers) torsion_position = unit.Quantity(np.array([-0.057 , 0.0951 ,-0.1863] ) ,unit=unit.nanometers) rtp, detJ = geometry_engine._cartesian_to_internal(atom_position, bond_position, angle_position, torsion_position) platform = openmm.Platform.getPlatformByName("Reference") context = openmm.Context(sys, integrator, platform) positions = [atom_position, bond_position, angle_position, torsion_position] context.setPositions(positions) state = context.getState(getEnergy=True) potential = state.getPotentialEnergy() #rotate about the torsion: n_divisions = 100 phis = unit.Quantity(np.arange(0, 2.0*np.pi, (2.0*np.pi)/n_divisions), unit=unit.radians) omm_phis = np.zeros(n_divisions) for i, phi in enumerate(phis): xyz_atom1, _ = geometry_engine._internal_to_cartesian(bond_position, angle_position, torsion_position, rtp[0]*unit.nanometers, rtp[1]*unit.radians, phi) context.setPositions([xyz_atom1, bond_position, angle_position, torsion_position]) state = context.getState(getEnergy=True) omm_phis[i] = state.getPotentialEnergy()/unit.kilojoule_per_mole return 0
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_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 test_coordinate_conversion(): import perses.rjmc.geometry as geometry geometry_engine = geometry.FFAllAngleGeometryEngine({'test': 'true'}) #try to transform random coordinates to and from cartesian for i in range(200): indices = np.random.randint(100, size=4) atom_position = unit.Quantity(np.array([ 0.80557722 ,-1.10424644 ,-1.08578826]), unit=unit.nanometers) bond_position = unit.Quantity(np.array([ 0.0765, 0.1 , -0.4005]), unit=unit.nanometers) angle_position = unit.Quantity(np.array([ 0.0829 , 0.0952 ,-0.2479]) ,unit=unit.nanometers) torsion_position = unit.Quantity(np.array([-0.057 , 0.0951 ,-0.1863] ) ,unit=unit.nanometers) rtp, detJ = geometry_engine._cartesian_to_internal(atom_position, bond_position, angle_position, torsion_position) r = rtp[0]*unit.nanometers theta = rtp[1]*unit.radians phi = rtp[2]*unit.radians xyz, _ = geometry_engine._internal_to_cartesian(bond_position, angle_position, torsion_position, r, theta, phi) assert np.linalg.norm(xyz-atom_position) < 1.0e-12
def __init__(self, **kwargs): super(Selectivity, self).__init__(**kwargs) solvents = ['explicit'] # DEBUG components = ['src-imatinib', 'abl-imatinib'] # TODO: Add 'ATP:kinase' complex to enable resistance design padding = 9.0*unit.angstrom explicit_solvent_model = 'tip3p' setup_path = 'data/abl-src' thermodynamic_states = dict() temperature = 300*unit.kelvin pressure = 1.0*unit.atmospheres geometry_engine = geometry.FFAllAngleGeometryEngine() # Construct list of all environments environments = list() for solvent in solvents: for component in components: environment = solvent + '-' + component environments.append(environment) # Read SMILES from CSV file of clinical kinase inhibitors. from pkg_resources import resource_filename smiles_filename = resource_filename('perses', 'data/clinical-kinase-inhibitors.csv') import csv molecules = list() with open(smiles_filename, 'r') as csvfile: csvreader = csv.reader(csvfile, delimiter=',', quotechar='"') for row in csvreader: name = row[0] smiles = row[1] molecules.append(smiles) # Add current molecule molecules.append('Cc1ccc(cc1Nc2nccc(n2)c3cccnc3)NC(=O)c4ccc(cc4)C[NH+]5CCN(CC5)C') self.molecules = molecules # Expand molecules without explicit stereochemistry and make canonical isomeric SMILES. molecules = sanitizeSMILES(self.molecules) # Create a system generator for desired forcefields from perses.rjmc.topology_proposal import SystemGenerator from pkg_resources import resource_filename gaff_xml_filename = resource_filename('perses', 'data/gaff.xml') system_generators = dict() system_generators['explicit'] = SystemGenerator([gaff_xml_filename, 'amber99sbildn.xml', 'tip3p.xml'], forcefield_kwargs={'nonbondedCutoff' : 9.0 * unit.angstrom, 'implicitSolvent' : None, 'constraints' : None },periodic_forcefield_kwargs = {'nonbondedMethod': app.CutoffPeriodic}) use_antechamber=True)
def test_existing_coordinates(): """ for each torsion, calculate position of atom1 """ molecule_name_2 = 'butane' molecule2 = generate_initial_molecule(molecule_name_2) sys, pos, top = oemol_to_openmm_system(molecule2, molecule_name_2) import perses.rjmc.geometry as geometry geometry_engine = geometry.FFAllAngleGeometryEngine({'test': 'true'}) structure = parmed.openmm.load_topology(top, sys) torsions = [torsion for torsion in structure.dihedrals if not torsion.improper] for torsion in torsions: atom1_position = pos[torsion.atom1.idx] atom2_position = pos[torsion.atom2.idx] atom3_position = pos[torsion.atom3.idx] atom4_position = pos[torsion.atom4.idx] _internal_coordinates, _ = geometry_engine._cartesian_to_internal(atom1_position, atom2_position, atom3_position, atom4_position) internal_coordinates = internal_in_unit(_internal_coordinates) recalculated_atom1_position, _ = geometry_engine._internal_to_cartesian(atom2_position, atom3_position, atom4_position, internal_coordinates[0], internal_coordinates[1], internal_coordinates[2]) n = np.linalg.norm(atom1_position-recalculated_atom1_position) print(n)
def test_openmm_dihedral(): """ Test FFAllAngleGeometryEngine _internal_to_cartesian and _cartesian_to_internal are consistent with OpenMM torsion angles. """ TORSION_TOLERANCE = 1.0e-4 # permitted disagreement in torsions # Create geometry engine from perses.rjmc import geometry geometry_engine = geometry.FFAllAngleGeometryEngine({'test': 'true'}) # Create a four-bead test system with a single custom force that measures the OpenMM torsion import simtk.openmm as openmm integrator = openmm.VerletIntegrator(1.0 * unit.femtoseconds) sys = openmm.System() force = openmm.CustomTorsionForce("theta") for i in range(4): sys.addParticle(1.0 * unit.amu) force.addTorsion(0, 1, 2, 3, []) sys.addForce(force) positions = unit.Quantity( np.array([ [0.10557722, -1.10424644, -1.08578826], [0.0765, 0.1, -0.4005], [0.0829, 0.0952, -0.2479], [-0.057, 0.0951, -0.1863], ]), unit.nanometers) atom_position = positions[0, :] bond_position = positions[1, :] angle_position = positions[2, :] torsion_position = positions[3, :] #atom_position = unit.Quantity(np.array([ 0.10557722 ,-1.10424644 ,-1.08578826]), unit=unit.nanometers) #bond_position = unit.Quantity(np.array([ 0.0765, 0.1 , -0.4005]), unit=unit.nanometers) #angle_position = unit.Quantity(np.array([ 0.0829 , 0.0952 ,-0.2479]) ,unit=unit.nanometers) #torsion_position = unit.Quantity(np.array([-0.057 , 0.0951 ,-0.1863] ) ,unit=unit.nanometers) # Compute the dimensionless internal coordinates consistent with this geometry rtp, detJ = geometry_engine._cartesian_to_internal(atom_position, bond_position, angle_position, torsion_position) (r, theta, phi) = rtp # dimensionless internal coordinates # Create a reference context platform = openmm.Platform.getPlatformByName("Reference") context = openmm.Context(sys, integrator, platform) context.setPositions( [atom_position, bond_position, angle_position, torsion_position]) openmm_phi = context.getState(getEnergy=True).getPotentialEnergy( ) / unit.kilojoule_per_mole # this system converts torsion radians -> kJ/mol assert np.linalg.norm( openmm_phi - phi ) < TORSION_TOLERANCE, '_cartesian_to_internal and OpenMM disagree on torsions' # Test _internal_to_cartesian by rotating around the torsion n_divisions = 100 phis = np.arange( -np.pi, np.pi, (2.0 * np.pi) / n_divisions ) # _internal_to_cartesian only accepts dimensionless quantities for i, phi in enumerate(phis): # Note that (r, theta, phi) are dimensionless here xyz_atom1, _ = geometry_engine._internal_to_cartesian( bond_position, angle_position, torsion_position, r, theta, phi) positions[0, :] = xyz_atom1 context.setPositions(positions) openmm_phi = context.getState(getEnergy=True).getPotentialEnergy( ) / unit.kilojoule_per_mole # this system converts torsion radians -> kJ/mol msg = '_internal_to_cartesian and OpenMM disagree on torsions: \n' msg += '_internal_to_cartesian generated positions for: {}\n'.format( phi) msg += 'OpenMM: {}\n'.format(openmm_phi) msg += 'positions: {}'.format(positions) assert np.linalg.norm(openmm_phi - phi) < TORSION_TOLERANCE, msg # Check that _cartesian_to_internal agrees rtp, detJ = geometry_engine._cartesian_to_internal( xyz_atom1, bond_position, angle_position, torsion_position) assert np.linalg.norm( phi - rtp[2] ) < TORSION_TOLERANCE, '_internal_to_cartesian disagrees with _cartesian_to_internal' # Clean up del context
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.utils.openeye import smiles_to_oemol from perses.utils.data import get_data_filename host_guest = testsystems.HostGuestVacuum() unsolv_old_system, old_positions, 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 = smiles_to_oemol('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, old_positions, beta) return topology_proposal, old_positions, new_positions
def test_mutate_from_all_to_all(): """ Make sure mutations are successful between every possible pair of before-and-after residues Mutate Ecoli F-ATPase alpha subunit to all 20 amino acids (test going FROM all possibilities) Mutate each residue to all 19 alternatives """ import perses.rjmc.topology_proposal as topology_proposal import perses.rjmc.geometry as geometry from perses.tests.utils import compute_potential_components from openmmtools import testsystems as ts geometry_engine = geometry.FFAllAngleGeometryEngine() aminos = ['ALA','ARG','ASN','ASP','CYS','GLN','GLU','GLY','HIS','ILE','LEU','LYS','MET','PHE','PRO','SER','THR','TRP','TYR','VAL'] for aa in aminos: topology, positions = _get_capped_amino_acid(amino_acid=aa) modeller = app.Modeller(topology, positions) ff_filename = "amber99sbildn.xml" max_point_mutants = 1 ff = app.ForceField(ff_filename) system = ff.createSystem(modeller.topology) chain_id = '1' system_generator = topology_proposal.SystemGenerator([ff_filename]) pm_top_engine = topology_proposal.PointMutationEngine(modeller.topology, system_generator, chain_id, max_point_mutants=max_point_mutants) current_system = system current_topology = modeller.topology current_positions = modeller.positions minimize_integrator = openmm.VerletIntegrator(1.0*unit.femtosecond) platform = openmm.Platform.getPlatformByName("Reference") minimize_context = openmm.Context(current_system, minimize_integrator, platform) minimize_context.setPositions(current_positions) initial_state = minimize_context.getState(getEnergy=True) initial_potential = initial_state.getPotentialEnergy() openmm.LocalEnergyMinimizer.minimize(minimize_context) final_state = minimize_context.getState(getEnergy=True, getPositions=True) final_potential = final_state.getPotentialEnergy() current_positions = final_state.getPositions() print("Minimized initial structure from %s to %s" % (str(initial_potential), str(final_potential))) for k, proposed_amino in enumerate(aminos): pm_top_engine._allowed_mutations = [[('2',proposed_amino)]] pm_top_proposal = pm_top_engine.propose(current_system, current_topology) new_positions, logp = geometry_engine.propose(pm_top_proposal, current_positions, beta) new_system = pm_top_proposal.new_system if np.isnan(logp): raise Exception("NaN in the logp") integrator = openmm.VerletIntegrator(1*unit.femtoseconds) platform = openmm.Platform.getPlatformByName("Reference") context = openmm.Context(new_system, integrator, platform) context.setPositions(new_positions) state = context.getState(getEnergy=True) print(compute_potential_components(context)) potential = state.getPotentialEnergy() potential_without_units = potential / potential.unit print(str(potential)) if np.isnan(potential_without_units): raise Exception("Energy after proposal is NaN")
def __init__(self, molecules: List[str], output_filename: str, ncmc_switching_times: Dict[str, int], equilibrium_steps: Dict[str, int], timestep: unit.Quantity, initial_molecule: str=None, geometry_options: Dict=None): self._molecules = [SmallMoleculeSetProposalEngine.canonicalize_smiles(molecule) for molecule in molecules] environments = ['explicit', 'vacuum'] temperature = 298.15 * unit.kelvin pressure = 1.0 * unit.atmospheres constraints = app.HBonds self._storage = NetCDFStorage(output_filename) self._ncmc_switching_times = ncmc_switching_times self._n_equilibrium_steps = equilibrium_steps self._geometry_options = geometry_options # Create a system generator for our desired forcefields. from perses.rjmc.topology_proposal import SystemGenerator system_generators = dict() from pkg_resources import resource_filename gaff_xml_filename = resource_filename('perses', 'data/gaff.xml') barostat = openmm.MonteCarloBarostat(pressure, temperature) system_generators['explicit'] = SystemGenerator([gaff_xml_filename, 'tip3p.xml'], forcefield_kwargs={'nonbondedCutoff': 9.0 * unit.angstrom, 'implicitSolvent': None, 'constraints': constraints, 'ewaldErrorTolerance': 1e-5, 'hydrogenMass': 3.0*unit.amu}, periodic_forcefield_kwargs = {'nonbondedMethod': app.PME} barostat=barostat) system_generators['vacuum'] = SystemGenerator([gaff_xml_filename], forcefield_kwargs={'implicitSolvent': None, 'constraints': constraints, 'hydrogenMass': 3.0*unit.amu}, nonperiodic_forcefield_kwargs = {'nonbondedMethod': app.NoCutoff}) # # Create topologies and positions # topologies = dict() positions = dict() from openmoltools import forcefield_generators forcefield = app.ForceField(gaff_xml_filename, 'tip3p.xml') forcefield.registerTemplateGenerator(forcefield_generators.gaffTemplateGenerator) # Create molecule in vacuum. from perses.utils.openeye import extractPositionsFromOEMol from openmoltools.openeye import smiles_to_oemol, generate_conformers if initial_molecule: smiles = initial_molecule else: smiles = np.random.choice(molecules) molecule = smiles_to_oemol(smiles) molecule = generate_conformers(molecule, max_confs=1) topologies['vacuum'] = forcefield_generators.generateTopologyFromOEMol(molecule) positions['vacuum'] = extractPositionsFromOEMol(molecule) # Create molecule in solvent. modeller = app.Modeller(topologies['vacuum'], positions['vacuum']) modeller.addSolvent(forcefield, model='tip3p', padding=9.0 * unit.angstrom) topologies['explicit'] = modeller.getTopology() positions['explicit'] = modeller.getPositions() # Set up the proposal engines. proposal_metadata = {} proposal_engines = dict() for environment in environments: proposal_engines[environment] = SmallMoleculeSetProposalEngine(self._molecules, system_generators[environment]) # Generate systems systems = dict() for environment in environments: systems[environment] = system_generators[environment].build_system(topologies[environment]) # Define thermodynamic state of interest. thermodynamic_states = dict() thermodynamic_states['explicit'] = states.ThermodynamicState(system=systems['explicit'], temperature=temperature, pressure=pressure) thermodynamic_states['vacuum'] = states.ThermodynamicState(system=systems['vacuum'], temperature=temperature) # Create SAMS samplers from perses.samplers.samplers import ExpandedEnsembleSampler, SAMSSampler mcmc_samplers = dict() exen_samplers = dict() sams_samplers = dict() for environment in environments: storage = NetCDFStorageView(self._storage, envname=environment) if self._geometry_options: n_torsion_divisions = self._geometry_options['n_torsion_divsions'][environment] use_sterics = self._geometry_options['use_sterics'][environment] else: n_torsion_divisions = 180 use_sterics = False geometry_engine = geometry.FFAllAngleGeometryEngine(storage=storage, n_torsion_divisions=n_torsion_divisions, use_sterics=use_sterics) move = mcmc.LangevinSplittingDynamicsMove(timestep=timestep, splitting="V R O R V", n_restart_attempts=10) chemical_state_key = proposal_engines[environment].compute_state_key(topologies[environment]) if environment == 'explicit': sampler_state = states.SamplerState(positions=positions[environment], box_vectors=systems[environment].getDefaultPeriodicBoxVectors()) else: sampler_state = states.SamplerState(positions=positions[environment]) mcmc_samplers[environment] = mcmc.MCMCSampler(thermodynamic_states[environment], sampler_state, move) exen_samplers[environment] = ExpandedEnsembleSampler(mcmc_samplers[environment], topologies[environment], chemical_state_key, proposal_engines[environment], geometry_engine, options={'nsteps': self._ncmc_switching_times[environment]}, storage=storage, ncmc_write_interval=self._ncmc_switching_times[environment]) exen_samplers[environment].verbose = True sams_samplers[environment] = SAMSSampler(exen_samplers[environment], storage=storage) sams_samplers[environment].verbose = True # Create test MultiTargetDesign sampler. from perses.samplers.samplers import MultiTargetDesign target_samplers = {sams_samplers['explicit']: 1.0, sams_samplers['vacuum']: -1.0} designer = MultiTargetDesign(target_samplers, storage=self._storage) # Store things. self.molecules = molecules self.environments = environments self.topologies = topologies self.positions = positions self.system_generators = system_generators self.proposal_engines = proposal_engines self.thermodynamic_states = thermodynamic_states self.mcmc_samplers = mcmc_samplers self.exen_samplers = exen_samplers self.sams_samplers = sams_samplers self.designer = designer
def run(): # Create initial model system, topology, and positions. smiles_list = ["CC", "CCC", "CCCC"] initial_molecule = smiles_to_oemol("CC") molecules = [Molecule.from_openeye(initial_molecule)] system_generator = SystemGenerator(molecules=molecules) initial_sys, initial_pos, initial_top = OEMol_to_omm_ff( initial_molecule, system_generator) smiles = "CC" stats = {ms: 0 for ms in smiles_list} # Run parameters temperature = 300.0 * unit.kelvin # temperature pressure = 1.0 * unit.atmospheres # pressure collision_rate = 5.0 / unit.picoseconds # collision rate for Langevin dynamics # Create proposal metadata, such as the list of molecules to sample (SMILES here) # proposal_metadata = {"smiles_list": smiles_list} list_of_oemols = [] for smile in smiles_list: oemol = smiles_to_oemol(smile) list_of_oemols.append(oemol) transformation = topology_proposal.SmallMoleculeSetProposalEngine( list_of_oemols=list_of_oemols, system_generator=system_generator) # transformation = topology_proposal.SingleSmallMolecule(proposal_metadata) # Initialize weight calculation engine, along with its metadata bias_calculator = bias_engine.MinimizedPotentialBias(smiles_list) # Initialize NCMC engines. switching_timestep = (1.0 * unit.femtosecond ) # Timestep for NCMC velocity Verlet integrations switching_nsteps = 10 # Number of steps to use in NCMC integration switching_functions = { # Functional schedules to use in terms of `lambda`, which is switched from 0->1 for creation and 1->0 for deletion "lambda_sterics": "lambda", "lambda_electrostatics": "lambda", "lambda_bonds": "lambda", "lambda_angles": "sqrt(lambda)", "lambda_torsions": "lambda", } ncmc_engine = ncmc_switching.NCMCEngine( temperature=temperature, timestep=switching_timestep, nsteps=switching_nsteps, functions=switching_functions, ) # Initialize GeometryEngine geometry_metadata = {"data": 0} # currently ignored geometry_engine = geometry.FFAllAngleGeometryEngine(geometry_metadata) # Run a number of iterations. niterations = 50 system = initial_sys topology = initial_top positions = initial_pos current_log_weight = bias_calculator.g_k(smiles) n_accepted = 0 propagate = True for i in range(niterations): # Store old (system, topology, positions). # Propose a transformation from one chemical species to another. state_metadata = {"molecule_smiles": smiles} top_proposal = transformation.propose( system, topology, positions, state_metadata) # Get a new molecule # QUESTION: What about instead initializing StateWeight once, and then using # log_state_weight = state_weight.computeLogStateWeight(new_topology, new_system, new_metadata)? log_weight = bias_calculator.g_k( top_proposal.metadata["molecule_smiles"]) # Perform alchemical transformation. # Alchemically eliminate atoms being removed. [ncmc_old_positions, ncmc_elimination_logp] = ncmc_engine.integrate(top_proposal, positions, direction="delete") # Generate coordinates for new atoms and compute probability ratio of old and new probabilities. # QUESTION: Again, maybe we want to have the geometry engine initialized once only? geometry_proposal = geometry_engine.propose( top_proposal.new_to_old_atom_map, top_proposal.new_system, system, ncmc_old_positions, ) # Alchemically introduce new atoms. [ncmc_new_positions, ncmc_introduction_logp ] = ncmc_engine.integrate(top_proposal, geometry_proposal.new_positions, direction="insert") # Compute total log acceptance probability, including all components. logp_accept = (top_proposal.logp_proposal + geometry_proposal.logp + ncmc_elimination_logp + ncmc_introduction_logp + log_weight / log_weight.unit - current_log_weight / current_log_weight.unit) # Accept or reject. if ((logp_accept >= 0.0) or (np.random.uniform() < np.exp(logp_accept))) and not np.any( np.isnan(ncmc_new_positions)): # Accept. n_accepted += 1 (system, topology, positions, current_log_weight, smiles) = ( top_proposal.new_system, top_proposal.new_topology, ncmc_new_positions, log_weight, top_proposal.metadata["molecule_smiles"], ) else: # Reject. logging.debug("reject") stats[smiles] += 1 print(positions) if propagate: p_system = copy.deepcopy(system) integrator = openmm.LangevinIntegrator(temperature, collision_rate, switching_timestep) context = openmm.Context(p_system, integrator) context.setPositions(positions) print(context.getState(getEnergy=True).getPotentialEnergy()) integrator.step(1000) state = context.getState(getPositions=True) positions = state.getPositions(asNumpy=True) del context, integrator, p_system print("The total number accepted was %d out of %d iterations" % (n_accepted, niterations)) print(stats)
def __init__(self, **kwargs): super(Selectivity, self).__init__(**kwargs) solvents = ['explicit'] # DEBUG components = ['src-imatinib', 'abl-imatinib'] # TODO: Add 'ATP:kinase' complex to enable resistance design padding = 9.0*unit.angstrom explicit_solvent_model = 'tip3p' setup_path = 'data/abl-src' thermodynamic_states = dict() temperature = 300*unit.kelvin pressure = 1.0*unit.atmospheres geometry_engine = geometry.FFAllAngleGeometryEngine() # Construct list of all environments environments = list() for solvent in solvents: for component in components: environment = solvent + '-' + component environments.append(environment) # Read SMILES from CSV file of clinical kinase inhibitors. from pkg_resources import resource_filename smiles_filename = resource_filename('perses', 'data/clinical-kinase-inhibitors.csv') import csv molecules = list() with open(smiles_filename, 'r') as csvfile: csvreader = csv.reader(csvfile, delimiter=',', quotechar='"') for row in csvreader: name = row[0] smiles = row[1] molecules.append(smiles) # Add current molecule molecules.append('Cc1ccc(cc1Nc2nccc(n2)c3cccnc3)NC(=O)c4ccc(cc4)C[NH+]5CCN(CC5)C') self.molecules = molecules # Expand molecules without explicit stereochemistry and make canonical isomeric SMILES. molecules = sanitizeSMILES(self.molecules) # Create a system generator for desired forcefields from perses.rjmc.topology_proposal import SystemGenerator from pkg_resources import resource_filename gaff_xml_filename = resource_filename('perses', 'data/gaff.xml') system_generators = dict() system_generators['explicit'] = SystemGenerator([gaff_xml_filename, 'amber99sbildn.xml', 'tip3p.xml'], forcefield_kwargs={ 'nonbondedMethod' : app.CutoffPeriodic, 'nonbondedCutoff' : 9.0 * unit.angstrom, 'implicitSolvent' : None, 'constraints' : None }, use_antechamber=True) # NOTE implicit solvent not supported by this SystemGenerator # system_generators['implicit'] = SystemGenerator([gaff_xml_filename, 'amber99sbildn.xml', 'amber99_obc.xml'], # forcefield_kwargs={ 'nonbondedMethod' : app.NoCutoff, 'implicitSolvent' : app.OBC2, 'constraints' : None }, # use_antechamber=True) system_generators['vacuum'] = SystemGenerator([gaff_xml_filename, 'amber99sbildn.xml'], forcefield_kwargs={ 'nonbondedMethod' : app.NoCutoff, 'implicitSolvent' : None, 'constraints' : None }, use_antechamber=True) # Copy system generators for all environments for solvent in solvents: for component in components: environment = solvent + '-' + component system_generators[environment] = system_generators[solvent] # Load topologies and positions for all components from simtk.openmm.app import PDBFile, Modeller topologies = dict() positions = dict() for component in components: pdb_filename = resource_filename('perses', os.path.join(setup_path, '%s.pdb' % component)) print(pdb_filename) pdbfile = PDBFile(pdb_filename) topologies[component] = pdbfile.topology positions[component] = pdbfile.positions # Construct positions and topologies for all solvent environments for solvent in solvents: for component in components: environment = solvent + '-' + component if solvent == 'explicit': # Create MODELLER object. modeller = app.Modeller(topologies[component], positions[component]) modeller.addSolvent(system_generators[solvent].getForceField(), model='tip3p', padding=9.0*unit.angstrom) topologies[environment] = modeller.getTopology() positions[environment] = modeller.getPositions() else: environment = solvent + '-' + component topologies[environment] = topologies[component] positions[environment] = positions[component] # Set up the proposal engines. from perses.rjmc.topology_proposal import SmallMoleculeSetProposalEngine proposal_metadata = { } proposal_engines = dict() for environment in environments: storage = None if self.storage: storage = NetCDFStorageView(self.storage, envname=environment) proposal_engines[environment] = SmallMoleculeSetProposalEngine(molecules, system_generators[environment], residue_name='MOL', storage=storage) # Generate systems systems = dict() for environment in environments: systems[environment] = system_generators[environment].build_system(topologies[environment]) # Define thermodynamic state of interest. from perses.samplers.thermodynamics import ThermodynamicState thermodynamic_states = dict() temperature = 300*unit.kelvin pressure = 1.0*unit.atmospheres for component in components: for solvent in solvents: environment = solvent + '-' + component if solvent == 'explicit': thermodynamic_states[environment] = ThermodynamicState(system=systems[environment], temperature=temperature, pressure=pressure) else: thermodynamic_states[environment] = ThermodynamicState(system=systems[environment], temperature=temperature) # Create SAMS samplers from perses.samplers.samplers import SamplerState, MCMCSampler, ExpandedEnsembleSampler, SAMSSampler mcmc_samplers = dict() exen_samplers = dict() sams_samplers = dict() for solvent in solvents: for component in components: environment = solvent + '-' + component chemical_state_key = proposal_engines[environment].compute_state_key(topologies[environment]) storage = None if self.storage: storage = NetCDFStorageView(self.storage, envname=environment) if solvent == 'explicit': thermodynamic_state = ThermodynamicState(system=systems[environment], temperature=temperature, pressure=pressure) sampler_state = SamplerState(system=systems[environment], positions=positions[environment], box_vectors=systems[environment].getDefaultPeriodicBoxVectors()) else: thermodynamic_state = ThermodynamicState(system=systems[environment], temperature=temperature) sampler_state = SamplerState(system=systems[environment], positions=positions[environment]) mcmc_samplers[environment] = MCMCSampler(thermodynamic_state, sampler_state, storage=storage) mcmc_samplers[environment].nsteps = 5 # reduce number of steps for testing mcmc_samplers[environment].verbose = True exen_samplers[environment] = ExpandedEnsembleSampler(mcmc_samplers[environment], topologies[environment], chemical_state_key, proposal_engines[environment], options={'nsteps':10}, geometry_engine=geometry_engine, storage=storage) exen_samplers[environment].verbose = True sams_samplers[environment] = SAMSSampler(exen_samplers[environment], storage=storage) sams_samplers[environment].verbose = True thermodynamic_states[environment] = thermodynamic_state # Create test MultiTargetDesign sampler. from perses.samplers.samplers import MultiTargetDesign target_samplers = {sams_samplers['explicit-src-imatinib']: 1.0, sams_samplers['explicit-abl-imatinib']: -1.0} designer = MultiTargetDesign(target_samplers, storage=self.storage) designer.verbose = True # Store things. self.molecules = molecules self.environments = environments self.topologies = topologies self.positions = positions self.system_generators = system_generators self.systems = systems self.proposal_engines = proposal_engines self.thermodynamic_states = thermodynamic_states self.mcmc_samplers = mcmc_samplers self.exen_samplers = exen_samplers self.sams_samplers = sams_samplers self.designer = designer # This system must currently be minimized. minimize(self)
def test_run_geometry_engine(index=0): """ Run the geometry engine a few times to make sure that it actually runs without exceptions. Convert n-pentane to 2-methylpentane """ import logging logging.basicConfig(level=logging.DEBUG) import copy molecule_name_1 = 'benzene' molecule_name_2 = 'biphenyl' #molecule_name_1 = 'imatinib' #molecule_name_2 = 'erlotinib' molecule1 = generate_initial_molecule(molecule_name_1) molecule2 = generate_initial_molecule(molecule_name_2) new_to_old_atom_mapping = align_molecules(molecule1, molecule2) sys1, pos1, top1 = oemol_to_openmm_system(molecule1, molecule_name_1) sys2, pos2, top2 = oemol_to_openmm_system(molecule2, molecule_name_2) import perses.rjmc.geometry as geometry import perses.rjmc.topology_proposal as topology_proposal from perses.tests.utils import compute_potential_components sm_top_proposal = topology_proposal.TopologyProposal(new_topology=top2, new_system=sys2, old_topology=top1, old_system=sys1, old_chemical_state_key='',new_chemical_state_key='', logp_proposal=0.0, new_to_old_atom_map=new_to_old_atom_mapping, metadata={'test':0.0}) sm_top_proposal._beta = beta geometry_engine = geometry.FFAllAngleGeometryEngine(metadata={}) # Turn on PDB file writing. geometry_engine.write_proposal_pdb = True geometry_engine.pdb_filename_prefix = 't13geometry-proposal' test_pdb_file = open("%s_to_%s_%d.pdb" % (molecule_name_1, molecule_name_2, index), 'w') valence_system = copy.deepcopy(sys2) valence_system.removeForce(3) valence_system.removeForce(3) integrator = openmm.VerletIntegrator(1*unit.femtoseconds) integrator_1 = openmm.VerletIntegrator(1*unit.femtoseconds) ctx_1 = openmm.Context(sys1, integrator_1) ctx_1.setPositions(pos1) ctx_1.setVelocitiesToTemperature(300*unit.kelvin) integrator_1.step(1000) pos1_new = ctx_1.getState(getPositions=True).getPositions(asNumpy=True) context = openmm.Context(sys2, integrator) context.setPositions(pos2) state = context.getState(getEnergy=True) print("Energy before proposal is: %s" % str(state.getPotentialEnergy())) openmm.LocalEnergyMinimizer.minimize(context) new_positions, logp_proposal = geometry_engine.propose(sm_top_proposal, pos1_new, beta) logp_reverse = geometry_engine.logp_reverse(sm_top_proposal, new_positions, pos1, beta) print(logp_reverse) app.PDBFile.writeFile(top2, new_positions, file=test_pdb_file) test_pdb_file.close() context.setPositions(new_positions) state2 = context.getState(getEnergy=True) print("Energy after proposal is: %s" %str(state2.getPotentialEnergy())) print(compute_potential_components(context)) valence_integrator = openmm.VerletIntegrator(1*unit.femtoseconds) platform = openmm.Platform.getPlatformByName("Reference") valence_ctx = openmm.Context(valence_system, valence_integrator, platform) valence_ctx.setPositions(new_positions) vstate = valence_ctx.getState(getEnergy=True) print("Valence energy after proposal is %s " % str(vstate.getPotentialEnergy())) final_potential = state2.getPotentialEnergy() return final_potential / final_potential.unit