def test_relabel_interaction(atom_defs): interaction = Interaction(atom_defs, ["1", "ga_2"], {"test": "value"}) mapping = {1: "A", 2: "B", 3: "C"} new_interaction = _relabel_interaction_atoms(interaction, mapping) assert new_interaction.atoms == ["A", "B", "C"] assert new_interaction.parameters == ["1", "ga_2"] assert new_interaction.meta == {"test": "value"}
def test_do_mapping_mods(modified_molecule, modifications): """ Test do_mapping on a molecule with modifications """ mappings = {} for name in 'ABCDEFGHIJ': block = Block(force_field=FF_UNIVERSAL, name=name) block.add_node(name, atomname=name, resid=1) mappings[name] = Mapping(block, block, mapping={name: {name: 1}}, references={}, ff_from=FF_UNIVERSAL, ff_to=FF_UNIVERSAL, names=(name,)) for mod in modifications.values(): name = (mod.name,) if isinstance(mod.name, str) else mod.name mappings[name] = Mapping(mod, mod, mapping={idx: {idx: 1} for idx in mod}, references={}, ff_from=FF_UNIVERSAL, ff_to=FF_UNIVERSAL, names=name, type='modification') mappings = {'universal': {'universal': mappings}} out = do_mapping(modified_molecule, mappings, FF_UNIVERSAL, attribute_keep=('chain', 'resid')) pprint.pprint(list(out.nodes(data=True))) pprint.pprint(list(out.edges)) expected = modified_molecule.copy() for node in expected.nodes: expected.nodes[node]['mapping_weights'] = {node: 1} expected.nodes[node]['graph'] = expected.subgraph([node]) expected = nx.relabel_nodes(expected, {idx: idx+1 for idx in expected}) pprint.pprint(list(expected.nodes(data='atomname'))) pprint.pprint(list(expected.edges)) assert equal_graphs(expected, out, node_attrs=['atomname', 'resid', 'mapping_weights']) assert out.interactions['bond'] == [Interaction(atoms=(10, 11), parameters=(3, 4), meta={})]
def test_IOError(): """ Tests if VS1 with function type 1 raises error. """ with pytest.raises(IOError): construct_vs("virtual_sites4", Interaction( atoms=[], parameters=["1"], meta={}), {})
def expand_excl(molecule): """ Given a `molecule` add exclusions for nodes that have the exclude attribute. Parameters: ----------- molecule: `:class:vermouth.molecule` Returns: -------- `:class:vermouth.molecule` """ exclude = nx.get_node_attributes(molecule, "exclude") nrexcl = molecule.nrexcl had_excl = [] for node, excl in exclude.items(): if excl > nrexcl: excluded_nodes = neighborhood(molecule, node, max_length=excl, min_length=nrexcl) for ndx in excluded_nodes: excl = Interaction(atoms=[node, ndx], parameters=[], meta={}) if frozenset([node, ndx]) not in had_excl and node != ndx: had_excl.append(frozenset([node, ndx])) molecule.interactions["exclusions"].append(excl) return molecule
def test_multiresidue_block(): lines = """ [ moleculetype ] ; name nexcl. PEO 1 ; [ atoms ] 1 SN1a 1 PEO CO1 1 0.000 45 [ moleculetype ] ; name nexcl. MIX 1 ; [ atoms ] 1 SN1a 1 R1 C1 1 0.000 45 2 SN1a 1 R1 C2 1 0.000 45 3 SC1 2 R2 C1 2 0.000 45 4 SC1 2 R2 C2 2 0.000 45 [ bonds ] ; back bone bonds 1 2 1 0.37 7000 2 3 1 0.37 7000 3 4 1 0.37 7000 """ lines = textwrap.dedent(lines).splitlines() ff = vermouth.forcefield.ForceField(name='test_ff') polyply.src.polyply_parser.read_polyply(lines, ff) meta_mol = MetaMolecule(name="test", force_field=ff) meta_mol.add_monomer(0,"PEO",[]) meta_mol.add_monomer(1,"MIX",[(1,0)]) new_meta_mol = polyply.src.map_to_molecule.MapToMolecule().run_molecule(meta_mol) bonds = [Interaction(atoms=(1, 2), parameters=['1', '0.37', '7000'], meta={}), Interaction(atoms=(2, 3), parameters=['1', '0.37', '7000'], meta={}), Interaction(atoms=(3, 4), parameters=['1', '0.37', '7000'], meta={})] edges = [(0,1), (1,2)] assert new_meta_mol.molecule.interactions['bonds'] == bonds assert len(new_meta_mol.nodes) == 3 assert list(new_meta_mol.edges) == edges assert nx.get_node_attributes(new_meta_mol, "resname") == {0: "PEO", 1: "R1", 2: "R2"}
def test_add_blocks(): lines = """ [ moleculetype ] ; name nexcl. PEO 1 ; [ atoms ] 1 SN1a 1 PEO CO1 1 0.000 45 2 SN1a 1 PEO CO2 1 0.000 45 3 SN1a 1 PEO CO3 1 0.000 45 4 SN1a 1 PEO CO4 1 0.000 45 [ bonds ] ; back bone bonds 1 2 1 0.37 7000 2 3 1 0.37 7000 2 4 1 0.37 7000 4 5 1 0.37 7000 """ lines = textwrap.dedent(lines).splitlines() ff = vermouth.forcefield.ForceField(name='test_ff') polyply.src.polyply_parser.read_polyply(lines, ff) meta_mol = MetaMolecule(name="test", force_field=ff) meta_mol.add_monomer(0,"PEO",[]) meta_mol.add_monomer(1,"PEO",[(1,0)]) new_meta_mol = polyply.src.map_to_molecule.MapToMolecule().run_molecule(meta_mol) bonds = [Interaction(atoms=(0, 1), parameters=['1', '0.37', '7000'], meta={}), Interaction(atoms=(1, 2), parameters=['1', '0.37', '7000'], meta={}), Interaction(atoms=(1, 3), parameters=['1', '0.37', '7000'], meta={}), Interaction(atoms=(4, 5), parameters=['1', '0.37', '7000'], meta={}), Interaction(atoms=(5, 6), parameters=['1', '0.37', '7000'], meta={}), Interaction(atoms=(5, 7), parameters=['1', '0.37', '7000'], meta={})] assert new_meta_mol.molecule.interactions['bonds'] == bonds
def test_sort_molecule_atoms(): """ Test the :class:`vermouth.processors.sort_molecule_atoms.SortMoleculeAtoms` processor in normal conditions. """ molecule = Molecule() nodes = [ (6, {'chain': 'C', 'resid': 2, 'resname': 'AA0', 'atomname': 'A5'}), (5, {'chain': 'A', 'resid': 2, 'resname': 'XX0', 'atomname': 'A0'}), (4, {'chain': 'B', 'resid': 1, 'resname': 'XX1', 'atomname': 'A2'}), (3, {'chain': 'C', 'resid': 1, 'resname': 'XX0', 'atomname': 'A4'}), (2, {'chain': 'C', 'resid': 2, 'resname': 'AA1', 'atomname': 'A6'}), (1, {'chain': 'A', 'resid': 2, 'resname': 'XX1', 'atomname': 'A1'}), (0, {'chain': 'B', 'resid': 2, 'resname': 'XX0', 'atomname': 'A3'}), ] edges = [ (0, 6, {'content': 'something'}), (1, 2, {'hello': 34}), ] interactions = { 'bonds': [ Interaction(atoms=[0, 1], parameters=['a', 'b'], meta={'a': 7}), Interaction(atoms=[3, 4], parameters=['c', 'd'], meta={'b': 5}), ], 'angles': [ Interaction(atoms=[0, 1, 2], parameters=['b', 'c'], meta={'a': 0}), ], } molecule.add_nodes_from(nodes) molecule.add_edges_from(edges) molecule.interactions = copy.copy(interactions) processor = SortMoleculeAtoms() processor.run_molecule(molecule) assert list(molecule.nodes) == [5, 1, 4, 0, 3, 6, 2] assert sorted(molecule.edges(data=True)) == edges assert molecule.interactions == interactions
def test_to_molecule(): """ Test if the to molecule function gives expected results. """ test_block = vermouth.molecule.Block() test_block.add_edges_from([('A', 'B'), ('B', 'C')]) test_block.interactions["bonds"] = [ Interaction(atoms=('A', 'B'), parameters=['a', '0.2', '200'], meta={'a': 0}), Interaction(atoms=('B', 'C'), parameters=['a', '0.1', '300'], meta={'b': 1}),] test_molecule = test_block.to_molecule() ref_bonds = [Interaction(atoms=(0, 1), parameters=['a', '0.2', '200'], meta={'a': 0}), Interaction(atoms=(1, 2), parameters=['a', '0.1', '300'], meta={'b': 1}),] assert ref_bonds == test_molecule.interactions['bonds']
def _base_parser(self, tokens, context, section, atom_idxs): """ Converts an interaction line into a vermouth interaction tuple. It updates the block interactions in place. Parameters ---------- tokens: collections.deque[str] Deque of token to inspect. The deque **can be modified** in place. context: :class:`vermouth.molecule.Block` The current block we parse section: str The current section header atom_idxs: list of ints or strings that are valid python slices """ # split atoms and parameters atoms, parameters = self._split_atoms_and_parameters(tokens, atom_idxs) # perform check on the atom ids treated_atoms = self._treat_block_interaction_atoms( atoms, context, section) if self.current_meta: meta = {self.current_meta['condition']: self.current_meta['tag']} else: meta = { } #dict(collections.ChainMap(meta, apply_to_all_interactions)) interaction = Interaction( atoms=treated_atoms, parameters=parameters, meta=meta, ) context.interactions[section] = context.interactions.get( section, []) + [interaction]
subgraph.edges[edge[0], edge[1]] for edge in sorted_expected ] expected_attributes = [ edges_between_molecule.edges[edge[0], edge[1]] for edge in sorted_expected ] assert found_attributes == expected_attributes @pytest.mark.parametrize('left, right, expected', ( ( # Same { 'bonds': [ Interaction(atoms=('A', 'B'), parameters=['a', '0.2', '200'], meta={'a': 0}), Interaction(atoms=('B', 'C'), parameters=['a', '0.1', '300'], meta={'b': 1}), ], 'angles': [ Interaction(atoms=('A', 'B', 'C'), parameters=['1', '0.2', '200'], meta={'a': 0}), ], }, { 'bonds': [ Interaction(atoms=('A', 'B'), parameters=['a', '0.2', '200'],
# limitations under the License. """ Test constructions of virutal-sites. Reference values come from a GROMACS energy minimization. """ import numpy as np import pytest from vermouth.molecule import Interaction from ..src.virtual_site_builder import construct_vs @pytest.mark.parametrize('vs_type, interaction, positions, result', ( # vsn ("virtual_sitesn", Interaction(atoms=[6, 1, 2, 3, 4, 5], parameters=["1"], meta={}), {1: np.array([4.924, 0.353, 0.036]), 2: np.array([5.191, 0.023, 0.208]), 3: np.array([5.190, -0.231, -0.162]), 4: np.array([4.734, -0.268, -0.131]), 5: np.array([4.548, 0.088, 0.046])}, np.array([4.917, -0.007, -0.001]) ), # vs2 ("virtual_sites2", Interaction(atoms=[3, 1, 2], parameters=["1", "0.5"], meta={}), {1: np.array([0.000, 0.000, 0.000]), 2: np.array([-0.012, 0.002, 0.024])}, np.array([-0.006, 0.001, 0.012]) ), # vs31 ("virtual_sites3", Interaction(atoms=[4, 1, 2, 3], parameters=[ "1", "0.223", "0.865"], meta={}),
class TestGenTemps: @staticmethod def test_find_atoms(): G = nx.Graph() G.add_edges_from([(1, 2), (2, 3), (3, 4)]) attrs = {1: {"resname": "test", "id": 'A'}, 2: {"resname": "test", "id": 'B'}, 3: {"resname": "testB", "id": 'A'}, 4: {"resname": "testB", "id": 'B'}} nx.set_node_attributes(G, attrs) nodes = find_atoms(G, "resname", "test") assert nodes == [1, 2] nodes = find_atoms(G, "id", "A") assert nodes == [1, 3] @staticmethod def test_expand_inital_coords(): lines = """ [ moleculetype ] GLY 1 [ atoms ] 1 P4 1 ALA BB 1 2 P3 1 ALA SC1 2 3 P2 1 ALA SC2 3 4 VS 1 ALA SC3 3 [ bonds ] 1 2 1 0.2 100 2 3 1 0.6 700 [ virtual_sitesn ] 4 2 3 1 """ lines = textwrap.dedent(lines).splitlines() ff = vermouth.forcefield.ForceField(name='test_ff') polyply.src.polyply_parser.read_polyply(lines, ff) block = ff.blocks['GLY'] coords = _expand_inital_coords(block) assert len(coords) == 4 for pos in coords.values(): assert len(pos) == 3 @staticmethod def test_compute_volume(): lines = """ [ moleculetype ] GLY 1 [ atoms ] 1 P1 1 ALA BB 1 2 P1 1 ALA SC1 2 3 P1 1 ALA SC2 3 4 P1 1 ALA SC3 3 [ bonds ] 1 2 1 0.2 100 2 3 1 0.6 700 3 4 1 0.2 700 """ meta_mol = polyply.MetaMolecule() nonbond_params = {frozenset(["P1", "P1"]): {"nb1": 0.47, "nb2":0.5}} lines = textwrap.dedent(lines).splitlines() ff = vermouth.forcefield.ForceField(name='test_ff') polyply.src.polyply_parser.read_polyply(lines, ff) block = ff.blocks['GLY'] coords = _expand_inital_coords(block) vol = compute_volume(meta_mol, block, coords, nonbond_params) assert vol > 0. @staticmethod def test_map_from_CoG(): lines = """ [ moleculetype ] GLY 1 [ atoms ] 1 P4 1 ALA BB 1 2 P3 1 ALA SC1 2 3 P2 1 ALA SC2 3 4 P2 1 ALA SC3 3 [ bonds ] 1 2 1 0.2 100 2 3 1 0.6 700 3 4 1 0.2 700 """ lines = textwrap.dedent(lines).splitlines() ff = vermouth.forcefield.ForceField(name='test_ff') polyply.src.polyply_parser.read_polyply(lines, ff) block = ff.blocks['GLY'] coords = _expand_inital_coords(block) points = np.array(list(coords.values())) CoG = center_of_geometry(points) new_coords = map_from_CoG(coords) for coord in coords: coords[coord] == new_coords[coord] + CoG @staticmethod @pytest.mark.parametrize('atom_defs', ( [1, 2, 3], (1, 2, 3))) def test_relabel_interaction(atom_defs): interaction = Interaction(atom_defs, ["1", "ga_2"], {"test": "value"}) mapping = {1: "A", 2: "B", 3: "C"} new_interaction = _relabel_interaction_atoms(interaction, mapping) assert new_interaction.atoms == ["A", "B", "C"] assert new_interaction.parameters == ["1", "ga_2"] assert new_interaction.meta == {"test": "value"} @staticmethod def test_extract_block(): lines = """ [ moleculetype ] test 1 [ atoms ] 1 P4 1 GLY BB 1 2 P3 1 GLY SC1 2 3 P2 1 ALA SC2 3 4 P2 1 ALA SC3 3 [ bonds ] 1 2 1 0.2 100 2 3 1 0.6 700 3 4 1 0.2 700 [ moleculetype ] GLY 1 [ atoms ] 1 P4 1 GLY BB 1 2 P3 1 GLY SC1 2 [ bonds ] 1 2 1 0.2 100 """ lines = textwrap.dedent(lines).splitlines() ff = vermouth.forcefield.ForceField(name='test_ff') polyply.src.polyply_parser.read_polyply(lines, ff) block = ff.blocks['test'] molecule = block.to_molecule() new_block = extract_block(molecule, "GLY", {}) for node in ff.blocks["GLY"]: atomname = ff.blocks["GLY"].nodes[node]["atomname"] assert ff.blocks["GLY"].nodes[node] == new_block.nodes[atomname] for inter_type in ff.blocks["GLY"].interactions: len(ff.blocks["GLY"].interactions[inter_type]) == len(new_block.interactions[inter_type]) @staticmethod def test_run_molecule(): top = polyply.src.topology.Topology.from_gmx_topfile(TEST_DATA + "/topology_test/system.top", "test") top.gen_pairs() top.convert_nonbond_to_sig_eps() GenerateTemplates(topology=top, max_opt=10).run_molecule(top.molecules[0]) assert "PMMA" in top.volumes assert "PMMA" in top.molecules[0].templates @staticmethod @pytest.mark.parametrize('lines, result', ( (""" [ moleculetype ] test 1 [ atoms ] 1 P4 1 GLY BB 1 2 P3 1 GLY SC1 2 3 P2 1 ALA SC2 3 [ bonds ] 1 2 1 0.2 100 2 3 1 0.2 100 """, (False, Interaction(atoms=["1", "2"], parameters=["1", "0.2", "100"], meta={}), "bonds")), (""" [ moleculetype ] test 1 [ atoms ] 1 P4 1 GLY BB 1 2 P3 1 GLY SC1 2 3 VS 1 ALA SC2 3 4 P3 1 ALA SC3 3 [ virtual_sitesn ] 3 1 4 2 1 """, (True, Interaction(atoms=["3", "4", "2", "1"], parameters=["1"], meta={}), "virtual_sitesn")))) def test_find_interaction_involving(lines, result): lines = textwrap.dedent(lines).splitlines() ff = vermouth.forcefield.ForceField(name='test_ff') polyply.src.polyply_parser.read_polyply(lines, ff) block = ff.blocks['test'] result = find_interaction_involving(block, 1, 2) assert result == result @staticmethod @pytest.mark.parametrize('lines', ( """ [ moleculetype ] test 1 [ atoms ] 1 P4 1 GLY BB 1 2 P3 1 GLY SC1 2 3 P2 1 ALA SC2 3 [ bonds ] 1 2 1 0.2 100 """, """ [ moleculetype ] test 1 [ atoms ] 1 P4 1 GLY BB 1 2 P3 1 GLY SC1 2 3 VS 1 ALA SC2 3 4 P3 1 ALA SC3 3 """)) def test_find_interaction_involving_error(lines): lines = textwrap.dedent(lines).splitlines() ff = vermouth.forcefield.ForceField(name='test_ff') polyply.src.polyply_parser.read_polyply(lines, ff) block = ff.blocks['test'] with pytest.raises(IOError): find_interaction_involving(block, 1, 2)
class TestTopology: @staticmethod def test_from_gmx_topfile(): top = Topology.from_gmx_topfile( TEST_DATA + "/topology_test/system.top", "test") assert len(top.molecules) == 1 @staticmethod def test_add_positions_from_gro(): top = Topology.from_gmx_topfile( TEST_DATA + "/topology_test/system.top", "test") top.add_positions_from_file(TEST_DATA + "/topology_test/test.gro") for node in top.molecules[0].molecule.nodes: if node < 14: assert "position" in top.molecules[0].molecule.nodes[ node].keys() for node in top.molecules[0].nodes: if node != 2: assert "position" in top.molecules[0].nodes[node].keys() assert top.molecules[0].nodes[node]["build"] == False else: assert top.molecules[0].nodes[node]["build"] == True @staticmethod def test_add_positions_from_pdb(): top = Topology.from_gmx_topfile(TEST_DATA + "/topology_test/pdb.top", "test") top.add_positions_from_file(TEST_DATA + "/topology_test/test.pdb") for meta_mol in top.molecules: for node in meta_mol.molecule.nodes: assert "position" in meta_mol.molecule.nodes[node].keys() for meta_mol in top.molecules: for node in meta_mol.nodes: assert "position" in meta_mol.nodes[node].keys() assert meta_mol.nodes[node]["build"] == False @staticmethod def test_convert_to_vermouth_system(): top = Topology.from_gmx_topfile( TEST_DATA + "/topology_test/system.top", "test") system = top.convert_to_vermouth_system() assert isinstance(system, vermouth.system.System) assert len(system.molecules) == 1 @staticmethod @pytest.mark.parametrize('lines, outcome', ((""" [ defaults ] 1.0 1.0 yes 1.0 1.0 [ atomtypes ] O 8 0.000 0.000 A 2.7106496e-03 9.9002500e-07 C 8 0.000 0.000 A 1.7106496e-03 9.9002500e-07 """, { frozenset(["O", "O"]): { "f": 1, "nb1": 2.7106496e-03, "nb2": 9.9002500e-07 }, frozenset(["C", "C"]): { "f": 1, "nb1": 1.7106496e-03, "nb2": 9.9002500e-07 }, frozenset(["C", "O"]): { "f": 1, "nb1": 0.0022106496, "nb2": 9.9002500e-07 } }), (""" [ defaults ] 1.0 3.0 yes 0.5 0.5 [ atomtypes ] C C 6 12.01100 0.500 A 3.75000e-01 4.39320e-01 ; SIG O O 8 15.99940 -0.500 A 2.96000e-01 8.78640e-01 ; SIG """, { frozenset(["C", "C"]): { "f": 1, "nb1": 3.75000e-01, "nb2": 4.39320e-01 }, frozenset(["O", "O"]): { "f": 1, "nb1": 2.96000e-01, "nb2": 8.78640e-01 }, frozenset(["O", "C"]): { "f": 1, "nb1": 0.3355, "nb2": 0.6212923022217481 } }), (""" [ defaults ] 1.0 1.0 yes 1.0 1.0 [ atomtypes ] O 8 0.000 0.000 A 2.7106496e-03 9.9002500e-07 C 8 0.000 0.000 A 1.7106496e-03 9.9002500e-07 [ nonbond_params ] C O 1 2.0 4.0 """, { frozenset(["O", "O"]): { "f": 1, "nb1": 2.7106496e-03, "nb2": 9.9002500e-07 }, frozenset(["C", "C"]): { "f": 1, "nb1": 1.7106496e-03, "nb2": 9.9002500e-07 }, frozenset(["C", "O"]): { "f": 1, "nb1": 2.0, "nb2": 4.0 } }))) def test_gen_pairs(lines, outcome): new_lines = textwrap.dedent(lines) new_lines = new_lines.splitlines() force_field = vermouth.forcefield.ForceField(name='test_ff') top = Topology(force_field, name="test") polyply.src.top_parser.read_topology(new_lines, top) top.gen_pairs() for atom_pair in outcome: assert atom_pair in top.nonbond_params nb1 = top.nonbond_params[atom_pair]["nb1"] nb2 = top.nonbond_params[atom_pair]["nb2"] nb1_ref = outcome[atom_pair]["nb1"] nb2_ref = outcome[atom_pair]["nb2"] assert math.isclose(nb1, nb1_ref) assert math.isclose(nb2, nb2_ref) @staticmethod @pytest.mark.parametrize( 'lines, outcome', ( (""" [ defaults ] 1.0 1.0 yes 1.0 1.0 [ atomtypes ] O 8 0.000 0.000 A 2.7106496e-03 9.9002500e-07 C 8 0.000 0.000 A 1.7106496e-03 9.9002500e-07 #define ga_1 100 250 [ moleculetype ] test 3 [ atoms ] 1 CH3 1 test C1 1 0.0 14.0 2 CH2 1 test C2 2 0.0 12.0 3 CH3 1 test C3 3 0.0 12.0 [ angles ] 1 2 3 2 ga_1 [ system ] some title [ molecules ] test 1 """, ["2", "100", "250"]), # different location of define statement (""" [ defaults ] 1.0 1.0 yes 1.0 1.0 #define ga_1 100 250 [ atomtypes ] O 8 0.000 0.000 A 2.7106496e-03 9.9002500e-07 C 8 0.000 0.000 A 1.7106496e-03 9.9002500e-07 [ moleculetype ] test 3 [ atoms ] 1 CH3 1 test C1 1 0.0 14.0 2 CH2 1 test C2 2 0.0 12.0 3 CH3 1 test C3 3 0.0 12.0 [ angles ] 1 2 3 2 ga_1 [ system ] some title [ molecules ] test 1 """, ["2", "100", "250"]), # two defines for one statement (""" [ defaults ] 1.0 1.0 yes 1.0 1.0 #define ga_1 100 #define gk_1 250 [ atomtypes ] O 8 0.000 0.000 A 2.7106496e-03 9.9002500e-07 C 8 0.000 0.000 A 1.7106496e-03 9.9002500e-07 [ moleculetype ] test 3 [ atoms ] 1 CH3 1 test C1 1 0.0 14.0 2 CH2 1 test C2 2 0.0 12.0 3 CH3 1 test C3 3 0.0 12.0 [ angles ] 1 2 3 2 ga_1 gk_1 [ system ] some title [ molecules ] test 1 """, ["2", "100", "250"]))) def test_replace_defines(lines, outcome): new_lines = textwrap.dedent(lines) new_lines = new_lines.splitlines() force_field = vermouth.forcefield.ForceField(name='test_ff') top = Topology(force_field, name="test") polyply.src.top_parser.read_topology(new_lines, top) top.replace_defines() assert top.molecules[0].molecule.interactions["angles"][ 0].parameters == outcome @staticmethod def test_convert_nonbond_to_sig_eps(): """ Simply test if the conversion from C6 C12 to simga epsilon is done properly. """ force_field = vermouth.forcefield.ForceField(name='test_ff') top = Topology(force_field, name="test") top.nonbond_params = { frozenset(["EO", "EO"]): { "nb1": 6.44779031E-02, "nb2": 4.07588234E-04 } } top.convert_nonbond_to_sig_eps() assert math.isclose(top.nonbond_params[frozenset(["EO", "EO"])]["nb1"], 0.43) assert math.isclose(top.nonbond_params[frozenset(["EO", "EO"])]["nb2"], 3.4 * 0.75) @staticmethod @pytest.mark.parametrize( 'lines, outcome', ( (""" [ defaults ] 1.0 1.0 yes 1.0 1.0 [ bondtypes ] C C 1 0.1335 502080.0 [ moleculetype ] test 3 [ atoms ] 1 C 1 test C1 1 0.0 14.0 2 C 1 test C2 2 0.0 12.0 [ bonds ] 1 2 1 [ system ] some title [ molecules ] test 1 """, { "bonds": [ Interaction(atoms=(0, 1), parameters=["1", "0.1335", "502080.0"], meta={}) ] }), # test three element define (""" [ defaults ] 1.0 1.0 yes 1.0 1.0 [ angletypes ] CE1 CE1 CT2 5 123.50 401.664 0.0 0.0 [ moleculetype ] test 3 [ atoms ] 1 CE1 1 test C1 1 0.0 14.0 2 CE1 1 test C2 2 0.0 12.0 3 CT2 1 test C3 3 0.0 12.0 [ angles ] 1 2 3 1 [ system ] some title [ molecules ] test 1 """, { "angles": [ Interaction( atoms=(0, 1, 2), parameters=["5", "123.50", "401.664", "0.0", "0.0"], meta={}) ] }), # test reverse match (""" [ defaults ] 1.0 1.0 yes 1.0 1.0 [ angletypes ] CE1 CE2 CT2 5 123.50 401.664 0.0 0.0 [ moleculetype ] test 3 [ atoms ] 1 CT2 1 test C1 1 0.0 14.0 2 CE2 1 test C2 2 0.0 12.0 3 CE1 1 test C3 3 0.0 12.0 [ angles ] 1 2 3 1 [ system ] some title [ molecules ] test 1 """, { "angles": [ Interaction( atoms=(0, 1, 2), parameters=["5", "123.50", "401.664", "0.0", "0.0"], meta={}) ] }), # test generic match (""" [ defaults ] 1.0 1.0 yes 1.0 1.0 [ dihedraltypes ] X CE2 CE1 X 5 123.50 401.664 0.0 0.0 X CT2 CE1 X 5 120 400 0.0 0.0 X QQQ QQQ X 5 150 400 0.0 0.0 [ moleculetype ] test 3 [ atoms ] 1 CT2 1 test C1 1 0.0 14.0 2 CE2 1 test C2 2 0.0 12.0 3 CE1 1 test C3 3 0.0 12.0 4 CT2 1 test C4 4 0.0 12.0 5 CT2 1 test C5 5 0.0 14.0 [ dihedrals ] 1 2 3 4 1 2 3 4 5 1 [ system ] some title [ molecules ] test 1 """, { "dihedrals": [ Interaction( atoms=(0, 1, 2, 3), parameters=["5", "123.50", "401.664", "0.0", "0.0"], meta={}), Interaction(atoms=(1, 2, 3, 4), parameters=["5", "120", "400", "0.0", "0.0"], meta={}) ] }), # test generic match plus defined match on same pattern (""" [ defaults ] 1.0 1.0 yes 1.0 1.0 [ dihedraltypes ] X CE2 CE1 X 5 123.50 401.664 0.0 0.0 X CT2 CE1 X 5 123.50 401.664 0.0 0.0 [ moleculetype ] test 3 [ atoms ] 1 CT2 1 test C1 1 0.0 14.0 2 CE2 1 test C2 2 0.0 12.0 3 CE1 1 test C3 3 0.0 12.0 4 CT2 1 test C4 4 0.0 12.0 5 CT2 1 test C5 5 0.0 14.0 [ dihedrals ] 1 2 3 4 1 2 3 4 5 1 150 60 0.0 0.0 [ system ] some title [ molecules ] test 1 """, { "dihedrals": [ Interaction( atoms=(0, 1, 2, 3), parameters=["5", "123.50", "401.664", "0.0", "0.0"], meta={}), Interaction(atoms=(1, 2, 3, 4), parameters=["1", "150", "60", "0.0", "0.0"], meta={}) ] }), # test priority of defined over generic match (""" [ defaults ] 1.0 1.0 yes 1.0 1.0 [ dihedraltypes ] CT2 CE2 CE1 CT2 5 123.50 401.664 0.0 0.0 X CE2 CE1 X 5 20 20 0.0 0.0 [ moleculetype ] test 3 [ atoms ] 1 CT2 1 test C1 1 0.0 14.0 2 CE2 1 test C2 2 0.0 12.0 3 CE1 1 test C3 3 0.0 12.0 4 CT2 1 test C4 4 0.0 12.0 5 CT2 1 test C5 5 0.0 14.0 [ dihedrals ] 1 2 3 4 1 [ system ] some title [ molecules ] test 1 """, { "dihedrals": [ Interaction( atoms=(0, 1, 2, 3), parameters=["5", "123.50", "401.664", "0.0", "0.0"], meta={}) ] }), # test reverse order for priority of defined over generic match (""" [ defaults ] 1.0 1.0 yes 1.0 1.0 [ dihedraltypes ] X CE2 CE1 X 5 20 20 0.0 0.0 CT2 CE2 CE1 CT2 5 123.50 401.664 0.0 0.0 [ moleculetype ] test 3 [ atoms ] 1 CT2 1 test C1 1 0.0 14.0 2 CE2 1 test C2 2 0.0 12.0 3 CE1 1 test C3 3 0.0 12.0 4 CT2 1 test C4 4 0.0 12.0 5 CT2 1 test C5 5 0.0 14.0 [ dihedrals ] 1 2 3 4 1 [ system ] some title [ molecules ] test 1 """, { "dihedrals": [ Interaction( atoms=(0, 1, 2, 3), parameters=["5", "123.50", "401.664", "0.0", "0.0"], meta={}) ] }), # test generic improper (""" [ defaults ] 1.0 1.0 yes 1.0 1.0 [ dihedraltypes ] CT2 X X CT2 5 123.50 401.664 0.0 0.0 CT2 X X CE2 5 123.50 401.664 0.0 0.0 [ moleculetype ] test 3 [ atoms ] 1 CT2 1 test C1 1 0.0 14.0 2 CE2 1 test C2 2 0.0 12.0 3 CE1 1 test C3 3 0.0 12.0 4 CT2 1 test C4 4 0.0 12.0 5 CT2 1 test C5 5 0.0 14.0 [ dihedrals ] 1 2 3 4 2 2 3 4 5 2 [ system ] some title [ molecules ] test 1 """, { "dihedrals": [ Interaction( atoms=(0, 1, 2, 3), parameters=["5", "123.50", "401.664", "0.0", "0.0"], meta={}), Interaction( atoms=(1, 2, 3, 4), parameters=["5", "123.50", "401.664", "0.0", "0.0"], meta={}) ] }), # multiple matchs and pairs and a meta parameters (""" [ defaults ] 1.0 1.0 yes 1.0 1.0 [ angletypes ] CE1 CE2 CT2 5 123.50 401.664 0.0 0.0 [ bondtypes ] CT2 CE2 1 0.1335 502080.0 #ifdef old CE2 CE1 1 0.1335 502080.0 #endif [ moleculetype ] test 3 [ atoms ] 1 CT2 1 test C1 1 0.0 14.0 2 CE2 1 test C2 2 0.0 12.0 3 CE1 1 test C3 3 0.0 12.0 [ bonds ] 1 2 1 2 3 1 [ pairs ] 1 2 1 [ angles ] #ifdef angle 1 2 3 1 #endif [ system ] some title [ molecules ] test 1 """, { "bonds": [ Interaction(atoms=(0, 1), parameters=["1", "0.1335", "502080.0"], meta={}), Interaction(atoms=(1, 2), parameters=["1", "0.1335", "502080.0"], meta={ 'tag': 'old', 'condition': 'ifdef' }) ], "pairs": [Interaction(atoms=(0, 1), parameters=["1"], meta={})], "angles": [ Interaction( atoms=(0, 1, 2), parameters=["5", "123.50", "401.664", "0.0", "0.0"], meta={"ifdef": "angle"}) ] }), # test bondtype usage (""" #define _FF_OPLS [ defaults ] 1.0 1.0 yes 1.0 1.0 [ atomtypes ] opls_001 C 6 12.01100 0.500 A 3.75000e-01 4.39320e-01 ; SIG [ bondtypes ] C C 1 0.1335 502080.0 [ moleculetype ] test 3 [ atoms ] 1 opls_001 1 test C1 1 0.0 14.0 2 opls_001 1 test C2 2 0.0 12.0 [ bonds ] 1 2 1 [ system ] some title [ molecules ] test 1 """, { "bonds": [ Interaction(atoms=(0, 1), parameters=["1", "0.1335", "502080.0"], meta={}) ] }), # test virtual_sites n,2,3,4 are skipped (""" #define _FF_OPLS [ defaults ] 1.0 1.0 yes 1.0 1.0 [ atomtypes ] opls_001 C 6 12.01100 0.500 A 3.75000e-01 4.39320e-01 ; SIG [ bondtypes ] C C 1 0.1335 502080.0 [ moleculetype ] test 3 [ atoms ] 1 opls_001 1 test C1 1 0.0 14.0 2 opls_001 1 test C2 2 0.0 12.0 3 opls_001 1 test C2 2 0.0 12.0 4 opls_001 1 test C2 2 0.0 12.0 5 opls_001 1 test C2 2 0.0 12.0 6 opls_001 1 test C2 2 0.0 12.0 7 opls_001 1 test C2 2 0.0 12.0 8 opls_001 1 test C2 2 0.0 12.0 9 opls_001 1 test C2 2 0.0 12.0 10 opls_001 1 test C2 2 0.0 12.0 [ bonds ] 1 2 1 1 8 1 1 9 1 2 9 1 8 9 1 ; currently not parsed accurately due to vermouth bug [ virtual_sites2 ] 4 1 9 1 0.5000 [ virtual_sites3 ] 5 4 8 1 1 0.200 0.200 6 4 9 2 1 0.200 0.200 [ virtual_sites4 ] 10 4 8 1 7 1 0.200 0.200 0.300 [ virtual_sitesn ] 3 1 4 4 1 2 7 1 4 4 8 9 [ system ] some title [ molecules ] test 1 """, { "bonds": [ Interaction(atoms=(0, 1), parameters=["1", "0.1335", "502080.0"], meta={}), Interaction(atoms=(0, 7), parameters=["1", "0.1335", "502080.0"], meta={}), Interaction(atoms=(0, 8), parameters=["1", "0.1335", "502080.0"], meta={}), Interaction(atoms=(1, 8), parameters=["1", "0.1335", "502080.0"], meta={}), Interaction(atoms=(7, 8), parameters=["1", "0.1335", "502080.0"], meta={}) ], "virtual_sitesn": [ Interaction( atoms=(2, 3, 3, 0, 1), parameters=["1"], meta={}), Interaction( atoms=(6, 3, 3, 7, 8), parameters=["1"], meta={}) ], "virtual_sites4": [ Interaction(atoms=(9, 3, 7, 0, 6), parameters=["1", "0.200", "0.200", "0.300"], meta={}) ], "virtual_sites2": [ Interaction( atoms=(3, 0, 8), parameters=["1", "0.5000"], meta={}) ], "virtual_sites3": [ Interaction(atoms=(4, 3, 7, 0), parameters=["1", "0.200", "0.200"], meta={}), Interaction(atoms=(5, 3, 8, 1), parameters=["1", "0.200", "0.200"], meta={}) ] }))) def test_replace_types(lines, outcome): new_lines = textwrap.dedent(lines) new_lines = new_lines.splitlines() force_field = vermouth.forcefield.ForceField(name='test_ff') top = Topology(force_field, name="test") polyply.src.top_parser.read_topology(new_lines, top) top.gen_bonded_interactions() for inter_type in outcome: assert top.molecules[0].molecule.interactions[ inter_type] == outcome[inter_type] @staticmethod def test_replace_types_fail(): lines = """ [ defaults ] 1.0 1.0 yes 1.0 1.0 [ dihedraltypes ] C Q Q Q 5 123.50 401.664 0.0 0.0 [ moleculetype ] test 3 [ atoms ] 1 CT2 1 test C1 1 0.0 14.0 2 CE2 1 test C2 2 0.0 12.0 3 CE1 1 test C3 3 0.0 12.0 4 CT2 1 test C4 4 0.0 12.0 [ dihedrals ] 1 2 3 4 2 [ system ] some title [ molecules ] test 1 """ new_lines = textwrap.dedent(lines) new_lines = new_lines.splitlines() force_field = vermouth.forcefield.ForceField(name='test_ff') top = Topology(force_field, name="test") polyply.src.top_parser.read_topology(new_lines, top) with pytest.raises(OSError): top.gen_bonded_interactions()
; name nexcl. PEO 1 ; [ atoms ] 1 SN1a 1 PEO CO1 1 0.000 45 2 SN1a 1 PEO CO2 1 0.000 45 3 SN1a 1 PEO CO3 1 0.000 45 4 SN1a 1 PEO CO4 1 0.000 45 [ bonds ] ; back bone bonds 1 2 1 0.37 7000 2 3 1 0.37 8000 3 4 1 0.37 9000 """, ["PEO", "PEO"], [Interaction(atoms=(0, 1), parameters=['1', '0.37', '7000'], meta={}), Interaction(atoms=(1, 2), parameters=['1', '0.37', '8000'], meta={}), Interaction(atoms=(2, 3), parameters=['1', '0.37', '9000'], meta={}), Interaction(atoms=(4, 5), parameters=['1', '0.37', '7000'], meta={}), Interaction(atoms=(5, 6), parameters=['1', '0.37', '8000'], meta={}), Interaction(atoms=(6, 7), parameters=['1', '0.37', '9000'], meta={})], [(0, 1), (1, 2), (2, 3), (4, 5), (5, 6), (6, 7)], 8, {}), # test multiblock from-itp (""" [ moleculetype ] ; name nexcl. PEO 1 ; [ atoms ]
def test_pre_post_section_lines(pre_meta, post_meta): """ :func:`vermouth.gmx.itp.write_molecule_itp` writes pre and post section lines. If `pre_meta` or `post_meta` is `True`, then "pre_section_lines" or "post_section_lines", respectively, is read from `molecule.meta`, otherwise it is passed as an argument. """ molecule = Molecule(nrexcl=1) molecule.add_nodes_from(( (0, { 'atype': 'Q5', 'resid': 1, 'resname': 'VAL', 'atomname': 'BB', 'charge_group': 1, 'charge': 1, }), (1, { 'atype': 'Q5', 'resid': 1, 'resname': 'VAL', 'atomname': 'BB', 'charge_group': 1, 'charge': 1, }), (2, { 'atype': 'Q5', 'resid': 1, 'resname': 'VAL', 'atomname': 'BB', 'charge_group': 1, 'charge': 1, }), )) # The molecule has 6 interaction sections. The sections are names # "interaction_<joint>_<part>", where <joint> can be "with" or "only", and # <part> can be "pre", "post", or "pre_post". The <part> indicates what # pre_section_lines and post_section_lines are defined for the section. # When <joint> in "with", then the section contains 2 interactions in # addition to the pre- and post- lines. When <joint> is "only", then the # section only has the pre/post lines defined, and no interactions. parts = ('pre', 'post', 'pre_post') molecule.interactions = {} for part in parts: name = 'interaction_with_{}'.format(part) molecule.interactions[name] = [ Interaction(atoms=[0, 1], parameters=[name], meta={}), Interaction(atoms=[1, 2], parameters=[name], meta={}), ] pre_section_lines = { 'atoms': ['test_atoms_0', 'test_atoms_1'], 'interaction_with_pre': ['test_pre_0', 'test_pre_1', 'test_pre_2'], 'interaction_with_pre_post': ['test_pre_post_0'], 'interaction_only_pre': ['test_pre_only_0', 'test_pre_only_1'], 'interaction_only_pre_post': ['test_prepost_only_0', 'test_prepost_only_1'], } post_section_lines = { 'atoms': ['after_atoms_0'], 'interaction_with_post': ['after_post_0', 'after_post_1'], 'interaction_with_pre_post': ['after_pre_post_0'], 'interaction_only_post': ['after_post_only_0', 'after_post_only_1'], 'interaction_only_pre_post': ['after_prepost_only_0'], } expected_segments = [ """ [ atoms ] test_atoms_0 test_atoms_1 1 Q5 1 VAL BB 1 1 2 Q5 1 VAL BB 1 1 3 Q5 1 VAL BB 1 1 after_atoms_0 """, """ [ interaction_with_pre ] test_pre_0 test_pre_1 test_pre_2 1 2 interaction_with_pre 2 3 interaction_with_pre """, """ [ interaction_with_post ] 1 2 interaction_with_post 2 3 interaction_with_post """, """ [ interaction_with_pre_post ] test_pre_post_0 1 2 interaction_with_pre_post 2 3 interaction_with_pre_post after_pre_post_0 """, """ [ interaction_only_pre ] test_pre_only_0 test_pre_only_1 """, """ [ interaction_only_post ] after_post_only_0 after_post_only_1 """, """ [ interaction_only_pre_post ] test_prepost_only_0 test_prepost_only_1 after_prepost_only_0 """, ] if post_meta: arg_post = post_section_lines molecule.meta['post_section_lines'] = 'invalid' else: arg_post = None molecule.meta['post_section_lines'] = post_section_lines if pre_meta: arg_pre = pre_section_lines molecule.meta['pre_section_lines'] = 'invalid' else: arg_pre = None molecule.meta['pre_section_lines'] = pre_section_lines outfile = io.StringIO() write_molecule_itp(molecule, outfile, moltype='test', post_section_lines=arg_post, pre_section_lines=arg_pre) itp_content = outfile.getvalue() # This could be a assert all(...), but it makes it more difficult to # understant what is happening in case of a failure. for segment in expected_segments: assert textwrap.dedent(segment)[:-1] in itp_content