def _build_system(mol, constrained): if constrained: parsley = ForceField("openff-1.0.0.offxml") else: parsley = ForceField("openff_unconstrained-1.0.0.offxml") mol = Molecule.from_file(get_data_file_path("molecules/" + mol), file_format="sdf") if type(mol) == Molecule: off_top = mol.to_topology() positions = mol.conformers[0] elif type(mol) == list: # methane_multiconformer case is a list of two mols off_top = Topology() for mol_i in mol: off_top.add_molecule(mol_i) positions = (np.vstack([mol[0].conformers[0], mol[1].conformers[0]]) * unit.angstrom) from openff.toolkit.utils.toolkits import ( AmberToolsToolkitWrapper, RDKitToolkitWrapper, ToolkitRegistry, ) toolkit_registry = ToolkitRegistry( toolkit_precedence=[RDKitToolkitWrapper, AmberToolsToolkitWrapper]) omm_sys = parsley.create_openmm_system(off_top, toolkit_registry=toolkit_registry) return omm_sys, positions, off_top
def test_get_virtual_site(self): """Test Topology.virtual_site function (get virtual site from index)""" topology = Topology() topology.add_molecule(self.ethane_from_smiles_w_vsites) assert topology.n_topology_virtual_sites == 2 topology.add_molecule(self.propane_from_smiles_w_vsites) assert topology.n_topology_virtual_sites == 4 with self.assertRaises(Exception) as context: topology_vsite = topology.virtual_site(-1) with self.assertRaises(Exception) as context: topology_vsite = topology.virtual_site(4) topology_vsite1 = topology.virtual_site(0) topology_vsite2 = topology.virtual_site(1) topology_vsite3 = topology.virtual_site(2) topology_vsite4 = topology.virtual_site(3) assert topology_vsite1.type == "BondChargeVirtualSite" assert topology_vsite2.type == "MonovalentLonePairVirtualSite" assert topology_vsite3.type == "MonovalentLonePairVirtualSite" assert topology_vsite4.type == "BondChargeVirtualSite" n_equal_atoms = 0 for topology_atom in topology.topology_atoms: for vsite in topology.topology_virtual_sites: for vsite_atom in vsite.atoms: if topology_atom == vsite_atom: n_equal_atoms += 1 # There are four virtual sites -- Two BondCharges with 2 atoms, and two MonovalentLonePairs with 3 atoms assert n_equal_atoms == 10
def test_n_topology_atoms(self): """Test n_atoms function""" topology = Topology() assert topology.n_topology_atoms == 0 assert topology.n_topology_bonds == 0 topology.add_molecule(self.ethane_from_smiles) assert topology.n_topology_atoms == 8 assert topology.n_topology_bonds == 7
def test_to_from_openmm(self): """Test a round-trip OpenFF -> OpenMM -> OpenFF Topology.""" from simtk.openmm.app import Aromatic # Create OpenFF topology with 1 ethanol and 2 benzenes. ethanol = Molecule.from_smiles("CCO") benzene = Molecule.from_smiles("c1ccccc1") off_topology = Topology.from_molecules( molecules=[ethanol, benzene, benzene]) # Convert to OpenMM Topology. omm_topology = off_topology.to_openmm() # Check that bond orders are preserved. n_double_bonds = sum([b.order == 2 for b in omm_topology.bonds()]) n_aromatic_bonds = sum( [b.type is Aromatic for b in omm_topology.bonds()]) assert n_double_bonds == 6 assert n_aromatic_bonds == 12 # Check that there is one residue for each molecule. assert omm_topology.getNumResidues() == 3 assert omm_topology.getNumChains() == 3 # Convert back to OpenFF Topology. off_topology_copy = Topology.from_openmm( omm_topology, unique_molecules=[ethanol, benzene]) # The round-trip OpenFF Topology is identical to the original. # The reference molecules are the same. assert (off_topology.n_reference_molecules == off_topology_copy.n_reference_molecules) reference_molecules_copy = list(off_topology_copy.reference_molecules) for ref_mol_idx, ref_mol in enumerate( off_topology.reference_molecules): assert ref_mol == reference_molecules_copy[ref_mol_idx] # The number of topology molecules is the same. assert (off_topology.n_topology_molecules == off_topology_copy.n_topology_molecules) # Check atoms. assert off_topology.n_topology_atoms == off_topology_copy.n_topology_atoms for atom_idx, atom in enumerate(off_topology.topology_atoms): atom_copy = off_topology_copy.atom(atom_idx) assert atom.atomic_number == atom_copy.atomic_number # Check bonds. for bond_idx, bond in enumerate(off_topology.topology_bonds): bond_copy = off_topology_copy.bond(bond_idx) bond_atoms = [a.atomic_number for a in bond.atoms] bond_atoms_copy = [a.atomic_number for a in bond_copy.atoms] assert bond_atoms == bond_atoms_copy assert bond.bond_order == bond_copy.bond_order assert bond.bond.is_aromatic == bond_copy.bond.is_aromatic
def test_from_toolkit_packmol_boxes(self, pdb_path, unique_molecules): """ Test loading some pre-prepared PACKMOL-generated systems. These use PDB files already prepared in the toolkit because PDB files are a pain. """ pdb_file_path = get_data_file_path("systems/packmol_boxes/" + pdb_path) pdbfile = openmm.app.PDBFile(pdb_file_path) Topology.from_openmm( pdbfile.topology, unique_molecules=unique_molecules, )
def test_topology_virtual_site_n_particles(self): """ Test if the virtual sites report the correct number of particles """ topology = Topology() topology.add_molecule(self.propane_from_smiles_w_vsites) assert topology.virtual_site(0).n_particles == 2 assert topology.virtual_site(1).n_particles == 1 topology = Topology() topology.add_molecule(self.tip5_water) assert topology.virtual_site(0).n_particles == 2
def test_to_file_units_check(self): """ Checks whether writing pdb with unitless positions, Angstrom positions, nanometer positions, result in the same output """ from tempfile import NamedTemporaryFile from simtk.unit import nanometer from openff.toolkit.topology import Molecule, Topology topology = Topology() mol = Molecule.from_pdb_and_smiles( get_data_file_path("systems/test_systems/1_ethanol.pdb"), "CCO") topology.add_molecule(mol) positions_angstrom = mol.conformers[0] count = 1 # Write the molecule to PDB and ensure that the X coordinate of the first atom is 10.172 with NamedTemporaryFile(suffix=".pdb") as iofile: topology.to_file(iofile.name, positions_angstrom) data = open(iofile.name).readlines() for line in data: if line.startswith("HETATM") and count == 1: count = count + 1 coord = line.split()[-6] assert coord == "10.172" # Do the same check, but feed in equivalent positions measured in nanometers and ensure the PDB is still the same count = 1 coord = None with NamedTemporaryFile(suffix=".pdb") as iofile: positions_nanometer = positions_angstrom.in_units_of(nanometer) topology.to_file(iofile.name, positions_nanometer) data = open(iofile.name).readlines() for line in data: if line.startswith("HETATM") and count == 1: count = count + 1 coord = line.split()[-6] assert coord == "10.172" count = 1 coord = "abc" with NamedTemporaryFile(suffix=".pdb") as iofile: positions_unitless = positions_angstrom._value topology.to_file(iofile.name, positions_unitless) data = open(iofile.name).readlines() for line in data: if line.startswith("HETATM") and count == 1: count = count + 1 coord = line.split()[-6] assert coord == "10.172"
def test_to_file_no_molecules(self): """ Checks if Topology.to_file() writes a file with no topology and no coordinates """ from tempfile import NamedTemporaryFile from openff.toolkit.topology import Topology topology = Topology() lines = [] with NamedTemporaryFile(suffix=".pdb") as iofile: topology.to_file(iofile.name, []) data = open(iofile.name).readlines() for line in data: lines.append(line.split()) assert lines[1] == ["END"]
def test_constraint_reassignment(self, parsley): """Test that constraints already existing in a parametrized system can be updated against new force field data""" # TODO: Replace with more minimal force field top = Topology.from_molecules(Molecule.from_smiles("CCO")) constrained = parsley.create_openff_system(top) assert len(constrained.handlers["Constraints"].slot_map.keys()) == 6 # Update Parsley to also constrain C-O bonds parsley["Constraints"].add_parameter({"smirks": "[#6:1]-[#8:2]"}) constrained.handlers["Constraints"].store_matches( parameter_handler=parsley["Constraints"], topology=top, ) from openff.system.components.smirnoff import SMIRNOFFBondHandler bond_handler = SMIRNOFFBondHandler() bond_handler.store_matches(parameter_handler=parsley["Bonds"], topology=top) bond_handler.store_potentials(parameter_handler=parsley["Bonds"]) constrained.handlers["Constraints"].store_constraints( parameter_handler=parsley["Constraints"], bond_handler=bond_handler, ) assert len(constrained.handlers["Constraints"].slot_map.keys()) == 7
def _off_handler(cls, molecule, **kwargs): forcefield = cls._get_forcefield(**kwargs) topology = Topology.from_molecules(molecule) openmm_system = forcefield.create_openmm_system( topology, charge_from_molecules=[molecule]) # ligand_pmd.title = cls.smiles # for i in ligand_pmd.residues: # i.name = 'LIG' #XXX no longer needed when using omm_top to create parmed structure tmp_dir = tempfile.mkdtemp() # We need all molecules as both pdb files (as packmol input) # and mdtraj.Trajectory for restoring bonds later. pdb_filename = tempfile.mktemp(suffix=".pdb", dir=tmp_dir) # XXX legacy code for save a pdb copy for simulation box creation # Chem.MolToPDBFile(mol, pdb_filename) # from openeye import oechem # OpenEye Python toolkits # oechem.OEWriteMolecule( oechem.oemolostream( pdb_filename ), mol) # XXX swtich to off save pdb # ligand_pmd.save(pdb_filename, overwrite=True) molecule.to_file(pdb_filename, "pdb") omm_top = PDBFile(pdb_filename).topology # ligand_pmd = parmed.openmm.topsystem.load_topology(topology.to_openmm(), openmm_system, molecule._conformers[0]) #XXX off topology does not keep atom names and resnames, use omm topology instead ligand_pmd = parmed.openmm.topsystem.load_topology( omm_top, openmm_system, molecule._conformers[0]) return pdb_filename, ligand_pmd
def test_from_openmm_pdbfile(self, argon_ff, argon_top): pdb_file_path = get_test_file_path("10-argons.pdb") pdbfile = openmm.app.PDBFile(pdb_file_path) mol = Molecule.from_smiles("[#18]") top = Topology.from_openmm(pdbfile.topology, unique_molecules=[mol]) box = pdbfile.topology.getPeriodicBoxVectors() box = box.value_in_unit(nm) * unit.nanometer out = argon_ff.create_openff_system(top) out.box = box out.positions = pdbfile.getPositions() assert np.allclose( out.positions.to(unit.nanometer).magnitude, pdbfile.getPositions().value_in_unit(nm), ) get_openmm_energies(out, hard_cutoff=True).compare( _get_openmm_energies( omm_sys=argon_ff.create_openmm_system(top), box_vectors=pdbfile.topology.getPeriodicBoxVectors(), positions=pdbfile.getPositions(), hard_cutoff=True, ))
def test_cutoff_electrostatics(): ion_ff = ForceField(get_test_file_path("ions.offxml")) ions = Topology.from_molecules([ Molecule.from_smiles("[#3]"), Molecule.from_smiles("[#17]"), ]) out = Interchange.from_smirnoff(ion_ff, ions) out.box = [4, 4, 4] * unit.nanometer gmx = [] lmp = [] for d in np.linspace(0.75, 0.95, 5): positions = np.zeros((2, 3)) * unit.nanometer positions[1, 0] = d * unit.nanometer out.positions = positions out["Electrostatics"].method = "cutoff" gmx.append( get_gromacs_energies(out, mdp="auto").energies["Electrostatics"].m) lmp.append( get_lammps_energies(out).energies["Electrostatics"].m_as( unit.kilojoule / unit.mol)) assert np.sum(np.sqrt(np.square(np.asarray(lmp) - np.asarray(gmx)))) < 1e-3
def test_from_toolkit_packmol_boxes(self, pdb_path, unique_molecules): """ Test loading some pre-prepared PACKMOL-generated systems. These use PDB files already prepared in the toolkit because PDB files are a pain. """ ff = ForceField("openff-1.0.0.offxml") pdb_file_path = get_data_file_path("systems/packmol_boxes/" + pdb_path) pdbfile = openmm.app.PDBFile(pdb_file_path) top = Topology.from_openmm( pdbfile.topology, unique_molecules=unique_molecules, ) box = pdbfile.topology.getPeriodicBoxVectors() box = box.value_in_unit(nm) * unit.nanometer out = ff.create_openff_system(top) out.box = box out.positions = pdbfile.getPositions() assert np.allclose( out.positions.to(unit.nanometer).magnitude, pdbfile.getPositions().value_in_unit(nm), ) get_openmm_energies(out, hard_cutoff=True).compare( _get_openmm_energies( omm_sys=ff.create_openmm_system(top), box_vectors=pdbfile.topology.getPeriodicBoxVectors(), positions=pdbfile.getPositions(), hard_cutoff=True, ))
def test_chemical_environments_matches_RDK(self): """Test Topology.chemical_environment_matches""" from simtk.openmm import app toolkit_wrapper = RDKitToolkitWrapper() pdbfile = app.PDBFile( get_data_file_path( "systems/packmol_boxes/cyclohexane_ethanol_0.4_0.6.pdb")) # toolkit_wrapper = RDKitToolkitWrapper() # molecules = [Molecule.from_file(get_data_file_path(name)) for name in ('molecules/ethanol.mol2', # 'molecules/cyclohexane.mol2')] molecules = [] molecules.append(Molecule.from_smiles("CCO")) molecules.append(Molecule.from_smiles("C1CCCCC1")) topology = Topology.from_openmm(pdbfile.topology, unique_molecules=molecules) # Count CCO matches matches = topology.chemical_environment_matches( "[C:1]-[C:2]-[O:3]", toolkit_registry=toolkit_wrapper) assert len(matches) == 143 assert matches[0].topology_atom_indices == (1728, 1729, 1730) matches = topology.chemical_environment_matches( "[H][C:1]([H])([H])-[C:2]([H])([H])-[O:3][H]", toolkit_registry=toolkit_wrapper, ) assert (len(matches) == 1716 ) # 143 * 12 (there are 12 possible hydrogen mappings) assert matches[0].topology_atom_indices == (1728, 1729, 1730) # Search for a substructure that isn't there matches = topology.chemical_environment_matches( "[C][C:1]-[C:2]-[O:3]", toolkit_registry=toolkit_wrapper) assert len(matches) == 0
def test_to_openmm_assign_unique_atom_names_some_duplicates(self): """ Ensure that OFF topologies where some molecules have invalid/duplicate atom names have unique atom names applied while the other molecules are unaffected. """ # Create OpenFF topology with 1 ethanol and 2 benzenes. ethanol = Molecule.from_smiles("CCO") # Assign duplicate atom names in ethanol (two AT0s) ethanol_atom_names_with_duplicates = [ f"AT{i}" for i in range(ethanol.n_atoms) ] ethanol_atom_names_with_duplicates[1] = "AT0" for atom, atom_name in zip(ethanol.atoms, ethanol_atom_names_with_duplicates): atom.name = atom_name # Assign unique atom names in benzene benzene = Molecule.from_smiles("c1ccccc1") benzene_atom_names = [f"AT{i}" for i in range(benzene.n_atoms)] for atom, atom_name in zip(benzene.atoms, benzene_atom_names): atom.name = atom_name off_topology = Topology.from_molecules( molecules=[ethanol, benzene, benzene]) omm_topology = off_topology.to_openmm() atom_names = set() for atom in omm_topology.atoms(): atom_names.add(atom.name) # There should be 12 "AT#"-labeled atoms (from benzene), 2 unique Cs, # 1 unique O, and 6 unique Hs, for a total of 21 unique atom names assert len(atom_names) == 21
def top_from_smiles( smiles: str, n_molecules: int = 1, ) -> Topology: """Create a gas phase OpenFF Topology from a single-molecule SMILES Parameters ---------- smiles : str The SMILES of the input molecule n_molecules : int, optional, default = 1 The number of copies of the SMILES molecule from which to compose a topology Returns ------- top : opennff.toolkit.topology.Topology A single-molecule, gas phase-like topology """ mol = Molecule.from_smiles(smiles) mol.generate_conformers(n_conformers=1) top = Topology.from_molecules(n_molecules * [mol]) # Add dummy box vectors # TODO: Revisit if/after Topology.is_periodic top.box_vectors = np.eye(3) * 10 * unit.nanometer return top
def test_from_openmm_single_mols(mol, n_mols): """ Test that ForceField.create_openmm_system and System.to_openmm produce objects with similar energies TODO: Tighten tolerances TODO: Test periodic and non-periodic """ parsley = ForceField(get_test_file_path("parsley.offxml")) mol = Molecule.from_smiles(mol) mol.generate_conformers(n_conformers=1) top = Topology.from_molecules(n_mols * [mol]) mol.conformers[0] -= np.min(mol.conformers) * unit.angstrom top.box_vectors = np.eye(3) * np.asarray([10, 10, 10]) * unit.nanometer if n_mols == 1: positions = mol.conformers[0] elif n_mols == 2: positions = np.vstack( [mol.conformers[0], mol.conformers[0] + 3 * unit.nanometer]) positions = positions * unit.angstrom toolkit_system = parsley.create_openmm_system(top) native_system = parsley.create_openff_system(topology=top).to_openmm() compare_system_energies( system1=toolkit_system, system2=native_system, positions=positions, box_vectors=top.box_vectors, )
def get_assigned_torsion_param(molecule, forcefield, dihedrals): """ for a molecule and specific dihedral check the assigned torsion parameter Parameters ---------- molecule: openforcefield molecule object ff: ForceField offxml file dihedrals: list of atom indices in the dihedral Returns ------- parameter.id: str of the torsion parameter associated with the dihedral """ topology = Topology.from_molecules([molecule]) # Run the molecule labeling molecule_force_list = forcefield.label_molecules(topology) # Print out a formatted description of the parameters applied to this molecule for mol_idx, mol_forces in enumerate(molecule_force_list): for force_tag, force_dict in mol_forces.items(): if force_tag == "ProperTorsions": for (atom_indices, parameter) in force_dict.items(): if atom_indices == tuple(dihedrals) or tuple( reversed(atom_indices) ) == tuple(dihedrals): return parameter.id
def test_gro_file_all_zero_positions(self, parsley): top = Topology.from_molecules(Molecule.from_smiles("CC")) zero_positions = Interchange.from_smirnoff(force_field=parsley, topology=top) zero_positions.positions = np.zeros( (top.n_topology_atoms, 3)) * unit.nanometer with pytest.warns(UserWarning, match="seem to all be zero"): zero_positions.to_gro("foo.gro")
def _create_impropers_only_system( smiles: str = "CC1=C(C(=O)C2=C(C1=O)N3CC4C(C3(C2COC(=O)N)OC)N4)N", ) -> mm.System: """Create a simulation that contains only improper torsion terms, by parameterizing with openff-1.2.0 and deleting all terms but impropers """ molecule = Molecule.from_smiles(smiles, allow_undefined_stereo=True) g = esp.Graph(molecule) topology = Topology.from_molecules(molecule) forcefield = ForceField("openff-1.2.0.offxml") openmm_system = forcefield.create_openmm_system(topology) # delete all forces except PeriodicTorsionForce is_torsion = ( lambda force: "PeriodicTorsionForce" in force.__class__.__name__ ) for i in range(openmm_system.getNumForces())[::-1]: if not is_torsion(openmm_system.getForce(i)): openmm_system.removeForce(i) assert openmm_system.getNumForces() == 1 torsion_force = openmm_system.getForce(0) assert is_torsion(torsion_force) # set k = 0 for any torsion that's not an improper indices = set( map( tuple, esp.graphs.utils.offmol_indices.improper_torsion_indices( molecule ), ) ) num_impropers_retained = 0 for i in range(torsion_force.getNumTorsions()): ( p1, p2, p3, p4, periodicity, phase, k, ) = torsion_force.getTorsionParameters(i) if (p1, p2, p3, p4) in indices: num_impropers_retained += 1 else: torsion_force.setTorsionParameters( i, p1, p2, p3, p4, periodicity, phase, 0.0 ) assert ( num_impropers_retained > 0 ) # otherwise this molecule is not a useful test case! return openmm_system, topology, g
def test_from_openmm(self): """Test creation of an OpenFF Topology object from an OpenMM Topology and component molecules""" from simtk.openmm import app pdbfile = app.PDBFile( get_data_file_path( "systems/packmol_boxes/cyclohexane_ethanol_0.4_0.6.pdb")) with pytest.raises(MissingUniqueMoleculesError, match="requires a list of Molecule objects"): Topology.from_openmm(pdbfile.topology) molecules = [create_ethanol(), create_cyclohexane()] topology = Topology.from_openmm(pdbfile.topology, unique_molecules=molecules) assert topology.n_reference_molecules == 2 assert topology.n_topology_molecules == 239
def test_parmed_openmm(tmpdir, smiles): tmpdir.chdir() parsley = ForceField("openff_unconstrained-1.0.0.offxml") mol = Molecule.from_smiles(smiles) mol.generate_conformers(n_conformers=1) top = Topology.from_molecules(mol) box = 4 * np.eye(3) * unit.nanometer with tempfile.TemporaryDirectory() as omm_tempdir: with temporary_cd(omm_tempdir): openff_openmm_pmd_gmx( topology=top, forcefield=parsley, box=box, prefix="via_openmm", ) ener1, ener1_file = gmx_energy( top="via_openmm.top", gro="via_openmm.gro", mdp=resource_filename("intermol", "tests/gromacs/grompp.mdp"), ) with tempfile.TemporaryDirectory() as off_tempdir: with temporary_cd(off_tempdir): openff_pmd_gmx_indirect( topology=top, forcefield=parsley, box=box, prefix="via_conversion", ) ener2, ener2_file = gmx_energy( top="via_conversion.top", gro="via_conversion.gro", mdp=resource_filename("intermol", "tests/gromacs/grompp.mdp"), ) compare_energies(ener1, ener2) with tempfile.TemporaryDirectory() as off_tempdir: with temporary_cd(off_tempdir): openff_pmd_gmx_direct( topology=top, forcefield=parsley, box=box, prefix="via_call", ) ener3, ener3_file = gmx_energy( top="via_call.top", gro="via_call.gro", mdp=resource_filename("intermol", "tests/gromacs/grompp.mdp"), ) compare_energies(ener2, ener3)
def test_force_field_no_constraints(self, parsley_unconstrained): """Test that a force field _without_ a Constraints tag does not add a Constraints handler""" # TODO: Replace with more minimal force field top = Topology.from_molecules(Molecule.from_smiles("CC")) sys_out = parsley_unconstrained.create_openff_system(top) assert "Constraints" not in sys_out.handlers.keys()
def test_n_topology_virtual_sites(self): """Test n_atoms function""" topology = Topology() assert topology.n_topology_virtual_sites == 0 topology.add_molecule(self.ethane_from_smiles_w_vsites) assert topology.n_topology_virtual_sites == 2 topology = Topology() assert topology.n_topology_virtual_sites == 0 topology.add_molecule(self.tip5_water) assert topology.n_topology_virtual_sites == 1 assert topology.n_topology_particles == 5
def test_nth_degree_neighbors(n_degrees, num_pairs): pass smiles = ["c1ccccc1", "N1ONON1"] topology = Topology.from_molecules( [Molecule.from_smiles(smi) for smi in smiles]) # See test_molecule.TestMolecule.test_nth_degree_neighbors_rings for values num_pairs_found = len( [*topology.nth_degree_neighbors(n_degrees=n_degrees)]) assert num_pairs_found == num_pairs
def test_from_mdtraj(self): """Test construction of an OpenFF Topology from an MDTraj Topology object""" import mdtraj as md pdb_path = get_data_file_path( "systems/test_systems/1_cyclohexane_1_ethanol.pdb") trj = md.load(pdb_path) with pytest.raises(MissingUniqueMoleculesError, match="requires a list of Molecule objects"): Topology.from_mdtraj(trj.top) unique_molecules = [ Molecule.from_smiles(mol_name) for mol_name in ["C1CCCCC1", "CCO"] ] top = Topology.from_mdtraj(trj.top, unique_molecules=unique_molecules) assert top.n_topology_molecules == 2 assert top.n_topology_bonds == 26
def test_library_charge_assignment(self): from openff.toolkit.tests.test_forcefield import xml_ethanol_library_charges_ff from openff.system.stubs import ForceField forcefield = ForceField("openff-1.3.0.offxml") top = Topology.from_molecules( [Molecule.from_smiles(smi) for smi in ["[Na+]", "[Cl-]"]]) forcefield.create_openff_system(top)
def test_default_am1bcc_charge_assignment(self, parsley): top = Topology.from_molecules([ Molecule.from_smiles("C"), Molecule.from_smiles("C=C"), Molecule.from_smiles("CCO"), ]) reference = parsley.create_openmm_system(top) new = parsley.create_openff_system(top) compare_charges_omm_off(reference, new)
def test_to_file_multi_molecule_different_order(self): """ Checks for the following if Topology.to_write maintains the order of atoms for the same molecule with different indexing """ from tempfile import NamedTemporaryFile from openff.toolkit.tests.test_forcefield import ( create_ethanol, create_reversed_ethanol, ) from openff.toolkit.topology import Molecule, Topology topology = Topology() topology.add_molecule(create_ethanol()) topology.add_molecule(create_reversed_ethanol()) mol = Molecule.from_pdb_and_smiles( get_data_file_path("systems/test_systems/1_ethanol.pdb"), "CCO") positions = mol.conformers[0] # Make up coordinates for the second ethanol by translating the first by 10 angstroms # (note that this will still be a gibberish conformation, since the atom order in the second molecule is different) positions = np.concatenate( [positions, positions + 10.0 * unit.angstrom]) element_order = [] with NamedTemporaryFile(suffix=".pdb") as iofile: topology.to_file(iofile.name, positions) data = open(iofile.name).readlines() for line in data: if line.startswith("HETATM"): element_order.append(line.strip()[-1]) assert element_order == [ "C", "C", "O", "H", "H", "H", "H", "H", "H", "H", "H", "H", "H", "H", "H", "O", "C", "C", ]
def test_empty(self): """Test creation of empty topology""" topology = Topology() assert topology.n_reference_molecules == 0 assert topology.n_topology_molecules == 0 assert topology.n_topology_atoms == 0 assert topology.n_topology_bonds == 0 assert topology.n_topology_particles == 0 assert topology.n_topology_virtual_sites == 0 assert topology.box_vectors is None assert not topology.is_periodic assert len(topology.constrained_atom_pairs.items()) == 0