diff --git a/polyply/src/build_file_parser.py b/polyply/src/build_file_parser.py index ce39977c..3a2416fb 100644 --- a/polyply/src/build_file_parser.py +++ b/polyply/src/build_file_parser.py @@ -41,6 +41,7 @@ def __init__(self, molecules, topology): self.persistence_length = {} self.templates = {} self.current_template = None + self.resnames_to_hash = {} @SectionLineParser.section_parser('molecule') def _molecule(self, line, lineno=0): @@ -211,6 +212,7 @@ def finalize_section(self, previous_section, ended_section): # center of geometry mapped_coords = map_from_CoG(coords) self.templates[graph_hash] = mapped_coords + self.resnames_to_hash[resname] = graph_hash self.current_template = None def finalize(self, lineno=0): @@ -232,6 +234,13 @@ def finalize(self, lineno=0): super().finalize(lineno=lineno) + # if template graphs and volumes are provided + # make sure that volumes are indexed by the hash + for resname, graph_hash in self.resnames_to_hash.items(): + if resname in self.topology.volumes: + self.topology.volumes[graph_hash] = self.topology.volumes[resname] + del self.topology.volumes[resname] + @staticmethod def _tag_nodes(molecule, keyword, option, molname=""): resids = np.arange(option['start'], option['stop'], 1.) diff --git a/polyply/src/check_residue_equivalence.py b/polyply/src/check_residue_equivalence.py index 57d2c9e2..279eb203 100644 --- a/polyply/src/check_residue_equivalence.py +++ b/polyply/src/check_residue_equivalence.py @@ -63,10 +63,6 @@ def group_residues_by_hash(meta_molecule, template_graphs={}): keys are the hash of the graph """ unique_graphs = template_graphs -# for graph in template_graphs.values(): -# graph_hash = nx.algorithms.graph_hashing.weisfeiler_lehman_graph_hash(graph, node_attr='atomname') -# unique_graphs[graph_hash] = graph - for node in meta_molecule.nodes: graph = meta_molecule.nodes[node]["graph"] graph_hash = nx.algorithms.graph_hashing.weisfeiler_lehman_graph_hash(graph, node_attr='atomname') diff --git a/polyply/src/generate_templates.py b/polyply/src/generate_templates.py index 0dd06fd2..646b41a4 100644 --- a/polyply/src/generate_templates.py +++ b/polyply/src/generate_templates.py @@ -337,8 +337,8 @@ class variable. self.templates self.volumes """ - for resname, template_graph in tqdm(template_graphs.items()): - if resname not in self.templates: + for graph_hash, template_graph in tqdm(template_graphs.items()): + if graph_hash not in self.templates: block = extract_block(meta_molecule.molecule, template_graph, self.topology.defines) @@ -364,13 +364,15 @@ class variable. break else: opt_counter += 1 - - if resname not in self.volumes: - self.volumes[resname] = compute_volume(block, + resname = block.nodes[list(block.nodes)[0]]['resname'] + if resname in self.volumes: + self.volumes[graph_hash] = self.volumes[resname] + else: + self.volumes[graph_hash] = compute_volume(block, coords, self.topology.nonbond_params) coords = map_from_CoG(coords) - self.templates[resname] = coords + self.templates[graph_hash] = coords def run_molecule(self, meta_molecule): """ diff --git a/polyply/tests/test_build_file_parser.py b/polyply/tests/test_build_file_parser.py index a56ecf53..c55a657d 100644 --- a/polyply/tests/test_build_file_parser.py +++ b/polyply/tests/test_build_file_parser.py @@ -403,12 +403,25 @@ def test_template_volume_parsing(test_system, line, names, edges, positions, out polyply.src.build_file_parser.read_build_file(lines, test_system, test_system.molecules) - for mol in test_system.molecules: - assert len(mol.templates) == len(names) - for idx, name in enumerate(names): - template = mol.templates[name] - for node_pos in positions[idx]: - node = node_pos[0] - assert np.all(np.array(node_pos[1:], dtype=float) == template[node]) + # verify results parsing based on hashes + idx = 0 + for name, edge_list in zip(names, edges): + template_graph = nx.Graph() + template_graph.add_edges_from(edge_list) + atomnames = {node: node for node in template_graph.nodes} + nx.set_node_attributes(template_graph, atomnames, 'atomname') + graph_hash = nx.algorithms.graph_hashing.weisfeiler_lehman_graph_hash(template_graph, + node_attr='atomname') - assert test_system.volumes == out_vol + mol = test_system.molecules[idx] + assert graph_hash in mol.templates + + for node_pos in positions[idx]: + template = mol.templates[graph_hash] + node = node_pos[0] + assert np.all(np.array(node_pos[1:], dtype=float) == template[node]) + + assert graph_hash in test_system.volumes + assert test_system.volumes[graph_hash] == out_vol[name] + + idx += 1 diff --git a/polyply/tests/test_load_library.py b/polyply/tests/test_load_library.py index 86d2857a..d13ee7e7 100644 --- a/polyply/tests/test_load_library.py +++ b/polyply/tests/test_load_library.py @@ -20,6 +20,7 @@ import pytest from pathlib import Path from contextlib import contextmanager +import networkx as nx import vermouth from polyply import TEST_DATA from polyply.src.logging import LOGGER @@ -72,6 +73,16 @@ def test_read_ff_from_files(caplog): def test_read_build_options_from_files(): + # PMMA template edge_list + edges = [('C1', 'C2'), ('C2', 'C3'), ('C2', 'C4'), + ('C4', 'O1'), ('C4', 'O2'), ('O2', 'C5')] + g = nx.Graph() + g.add_edges_from(edges) + + atomnames = {node: node for node in g.nodes} + nx.set_node_attributes(g, atomnames, 'atomname') + graph_hash = nx.algorithms.graph_hashing.weisfeiler_lehman_graph_hash(g, node_attr='atomname') + topfile = Path('topology_test/system.top') bldfile = Path('topology_test/test.bld') lib_name = '2016H66' @@ -83,6 +94,6 @@ def test_read_build_options_from_files(): load_build_files(topology, lib_name, user_files) # check if build files are parsed - assert topology.volumes == {'PMMA': 1.0} + assert topology.volumes[graph_hash] == 1.0 molecule = topology.molecules[0] - assert molecule.templates + assert graph_hash in molecule.templates diff --git a/polyply/tests/test_residue_equivalence.py b/polyply/tests/test_residue_equivalence.py index 4ae276df..7ff0340a 100644 --- a/polyply/tests/test_residue_equivalence.py +++ b/polyply/tests/test_residue_equivalence.py @@ -28,8 +28,9 @@ def test_group_by_hash(example_meta_molecule, resnames, gen_template_graphs): template_graphs = {} for node in gen_template_graphs: graph = example_meta_molecule.nodes[node]['graph'] + graph_hash = nx.algorithms.graph_hashing.weisfeiler_lehman_graph_hash(graph, node_attr='atomname') nx.set_node_attributes(graph, True, 'template') - template_graphs[example_meta_molecule.nodes[node]['resname']] = graph + template_graphs[graph_hash] = graph # perfrom the grouping unique_graphs = group_residues_by_hash(example_meta_molecule, template_graphs) @@ -37,8 +38,7 @@ def test_group_by_hash(example_meta_molecule, resnames, gen_template_graphs): # check the outcome assert len(unique_graphs) == 2 - for graph in template_graphs.values(): - graph_hash = nx.algorithms.graph_hashing.weisfeiler_lehman_graph_hash(graph, node_attr='atomname') + for graph_hash in template_graphs: templated = list(nx.get_node_attributes(unique_graphs[graph_hash], 'template').values()) assert all(templated)