def test_same_nodes(left, right, expected): left_mol = Molecule() left_mol.add_nodes_from(left) right_mol = Molecule() right_mol.add_nodes_from(right) assert left_mol.same_nodes(right_mol) == expected assert right_mol.same_nodes(left_mol) == expected
def test_no_residue_crossing(): """ Make sure we don't cross residue boundaries """ mapping = {'C1': {'B1': 1}, 'C2': {'B1': 1}, 'C3': {'B1': 1}} extra = () mappings = {'universal': {'martini22': {'IPO': Mapping(FF_UNIVERSAL.blocks['IPO'], FF_MARTINI.blocks['IPO'], mapping=mapping, references={}, ff_from=FF_UNIVERSAL, ff_to=FF_MARTINI, names=('IPO',), extra=extra)}}} cg = do_mapping(AA_MOL, mappings, FF_MARTINI, attribute_keep=['chain']) expected = Molecule(force_field=FF_MARTINI) expected.add_nodes_from(( (0, {'resid': 1, 'resname': 'IPO', 'atomname': 'B1', 'chain': 'A', 'charge_group': 1}), (1, {'resid': 2, 'resname': 'IPO', 'atomname': 'B1', 'chain': 'A', 'charge_group': 2}), (2, {'resid': 3, 'resname': 'IPO', 'atomname': 'B1', 'chain': 'A', 'charge_group': 3}), )) expected.add_edges_from(([0, 1], [1, 2])) print(cg.nodes(data=True)) print(cg.edges()) print('-'*80) print(expected.nodes(data=True)) print(expected.edges()) assert equal_graphs(cg, expected)
def test_no_residue_crossing(): """ Make sure we don't cross residue boundaries """ mapping = { (0, 'C1'): [(0, 'B1')], (0, 'C2'): [(0, 'B1')], (0, 'C3'): [(0, 'B1')] } weights = { (0, 'B1'): { (0, 'C1'): 1, (0, 'C2'): 1, (0, 'C3'): 1, } } extra = () mappings = {'universal': {'martini22': {'IPO': (mapping, weights, extra)}}} cg = do_mapping(AA_MOL, mappings, FF_MARTINI) expected = Molecule(force_field=FF_MARTINI) expected.add_nodes_from(( (0, { 'resid': 1, 'resname': 'IPO', 'atomname': 'B1', 'chain': 'A', 'charge_group': 1 }), (1, { 'resid': 2, 'resname': 'IPO', 'atomname': 'B1', 'chain': 'A', 'charge_group': 2 }), (2, { 'resid': 3, 'resname': 'IPO', 'atomname': 'B1', 'chain': 'A', 'charge_group': 3 }), )) expected.add_edges_from(([0, 1], [1, 2])) print(cg.nodes(data=True)) print(cg.edges()) print('-' * 80) print(expected.nodes(data=True)) print(expected.edges()) assert _equal_graphs(cg, expected)
def example_mol(): mol = Molecule(force_field=ForceField(FF_UNIVERSAL_TEST)) nodes = [ { 'chain': 'A', 'resname': 'A', 'resid': 1 }, # 0, R1 { 'chain': 'A', 'resname': 'A', 'resid': 2 }, # 1, R2 { 'chain': 'A', 'resname': 'A', 'resid': 2 }, # 2, R2 { 'chain': 'A', 'resname': 'B', 'resid': 2 }, # 3, R3 { 'chain': 'B', 'resname': 'A', 'resid': 1 }, # 4, R4 { 'chain': 'B', 'resname': 'A', 'resid': 2 }, # 5, R5 { 'chain': 'B', 'resname': 'A', 'resid': 2 }, # 6, R5 { 'chain': 'B', 'resname': 'B', 'resid': 2 }, # 7, R6 { 'chain': 'A', 'resname': 'C', 'resid': 3 }, # 8, R7 ] mol.add_nodes_from(enumerate(nodes)) mol.add_edges_from([(0, 1), (1, 2), (2, 3), (3, 4), (4, 5), (5, 6), (4, 7), (3, 8)]) return mol
def test_single_residue_mol(): mol = Molecule(force_field=ForceField(FF_UNIVERSAL_TEST)) nodes = [ {'chain': 'A', 'resname': 'A', 'resid': 2}, {'chain': 'A', 'resname': 'A', 'resid': 2}, ] mol.add_nodes_from(enumerate(nodes)) mol.add_edges_from([(0, 1)]) modification = [({'resname': 'A', 'resid': 2}, 'C-ter'),] annotate_modifications(mol, modification, []) assert mol.nodes[0] == {'modification': ['C-ter'], 'resname': 'A', 'resid': 2, 'chain': 'A'} assert mol.nodes[1] == {'modification': ['C-ter'], 'resname': 'A', 'resid': 2, 'chain': 'A'}
def modified_molecule(modifications): """ Provides a molecule with modifications """ mol = Molecule(force_field=FF_UNIVERSAL) mol.add_nodes_from(enumerate(( # Lone PTM {'atomname': 'A', 'resid': 1, 'modifications': [modifications['mA']]}, {'atomname': 'mA', 'resid': 1, 'PTM_atom': True, 'modifications': [modifications['mA']]}, {'atomname': 'B', 'resid': 2}, # Spacer # Two PTMs on neighbouring residues {'atomname': 'C', 'resid': 3, 'modifications': [modifications['mC']]}, {'atomname': 'mC', 'resid': 3, 'PTM_atom': True, 'modifications': [modifications['mC']]}, {'atomname': 'D', 'resid': 4, 'modifications': [modifications['mD']]}, {'atomname': 'mD', 'resid': 4, 'PTM_atom': True, 'modifications': [modifications['mD']]}, {'atomname': 'E', 'resid': 5}, # Spacer # Bridging PTMs {'atomname': 'F', 'resid': 6, 'modifications': [modifications['mFG']]}, {'atomname': 'mF', 'resid': 6, 'PTM_atom': True, 'modifications': [modifications['mFG']]}, {'atomname': 'G', 'resid': 7, 'modifications': [modifications['mFG']]}, {'atomname': 'mG', 'resid': 7, 'PTM_atom': True, 'modifications': [modifications['mFG']]}, {'atomname': 'H', 'resid': 8}, # Spacer # Two PTMs for one residue {'atomname': 'I', 'resid': 9, 'modifications': [modifications['mI'], modifications['mI2']]}, {'atomname': 'mI', 'resid': 9, 'PTM_atom': True, 'modifications': [modifications['mI']]}, {'atomname': 'mI2', 'resid': 9, 'PTM_atom': True, 'modifications': [modifications['mI2']]}, # Two PTMs for one residue, but a single mod mapping {'atomname': 'J', 'resid': 10, 'modifications': [modifications['mJ'], modifications['mJ2']]}, {'atomname': 'mJ', 'resid': 10, 'PTM_atom': True, 'modifications': [modifications['mJ']]}, {'atomname': 'mJ2', 'resid': 10, 'PTM_atom': True, 'modifications': [modifications['mJ2']]} ))) mol.add_edges_from(( (0, 1), (0, 2), # A (2, 3), # B (3, 4), (3, 5), # C (5, 6), (5, 7), # D (7, 8), # E (8, 9), (8, 10), # F (9, 11), # Bridge between mF and mG (10, 11), (10, 12), # G (12, 13), # H (13, 14), (13, 15), (13, 16), # I (16, 17), (16, 18) # J )) return mol
def test_nter_cter_modifications(node_data, edge_data, expected): """ Tests that 'nter' and 'cter' specifications only match protein N and C termini """ mol = Molecule(force_field=ForceField(FF_UNIVERSAL_TEST)) mol.add_nodes_from(enumerate(node_data)) mol.add_edges_from(edge_data) modification = [({'resname': 'cter'}, 'C-ter'), ({'resname': 'nter'}, 'N-ter')] annotate_modifications(mol, modification, []) found = {} for node_idx in mol: node = mol.nodes[node_idx] if 'modification' in node: found[node['resid']] = node['modification'] assert found == expected
def test_residue_crossing(): ''' Make sure we do cross residue boundaries and can rename residues ''' mapping = {'C1': {'B1': 1}, 'C2': {'B1': 1}, 'C3': {'B1': 1}, 'C4': {'B2': 1}, 'C5': {'B2': 1}, 'C6': {'B2': 1}, 'C7': {'B3': 1}, 'C8': {'B3': 1}, 'C9': {'B3': 1}, } extra = () mappings = { 'universal': { 'martini22': { 'IPO_large': Mapping(FF_UNIVERSAL.blocks['IPO_large'], FF_MARTINI.blocks['IPO_large'], mapping=mapping, references={}, ff_from=FF_UNIVERSAL, ff_to=FF_MARTINI, names=('IPO', 'IPO', 'IPO'), extra=extra) } } } cg = do_mapping(AA_MOL, mappings, FF_MARTINI, attribute_keep=('chain',)) expected = Molecule() expected.add_nodes_from(( (0, {'resid': 1, 'resname': 'IPO_large', 'atomname': 'B1', 'chain': 'A', 'charge_group': 1}), (1, {'resid': 2, 'resname': 'IPO_large', 'atomname': 'B1', 'chain': 'A', 'charge_group': 1}), (2, {'resid': 3, 'resname': 'IPO_large', 'atomname': 'B1', 'chain': 'A', 'charge_group': 1}), )) expected.add_edges_from(([0, 1], [1, 2])) print(cg.nodes(data=True)) print(cg.edges()) print('-'*80) print(expected.nodes(data=True)) print(expected.edges()) assert equal_graphs(cg, expected)
def test_make_bonds(nodes, edges, expected_edges): """ Test to make sure that make_bonds makes the bonds it is expected to, and not too many. nodes is a List[List[Dict]], allowing for multiple molecules edges is a List[List[Tuple[Int, Int, Dict]]], allowing for multiple molecules expected_edges is a List[Dict[Tuple[Int, Int], Dict]], allowing for multiple molecules """ system = System(force_field=get_native_force_field('universal')) for node_set, edge_set in zip(nodes, edges): mol = Molecule() mol.add_nodes_from(enumerate(node_set)) mol.add_edges_from(edge_set) system.add_molecule(mol) MakeBonds().run_system(system) # Make sure number of connected components is the same assert len(system.molecules) == len(expected_edges) # Make sure that for every molecule found, the edges are correct for found_mol, ref_edges in zip(system.molecules, expected_edges): assert dict(found_mol.edges) == ref_edges
def test_apply_mod_mapping(modified_molecule, modifications): """ Test apply_mod_mapping """ graph_out = Molecule(force_field=FF_UNIVERSAL) graph_out.add_nodes_from([ (0, {'atomname': 'A', 'resid': 1}) ]) mol_to_out = {0: {0: 1}} out_to_mol = {0: {0: 1}} match = ({1: {'mA': 1}}, modifications['mA'], {}) out = apply_mod_mapping(match, modified_molecule, graph_out, mol_to_out, out_to_mol) print(mol_to_out) print(out_to_mol) print(graph_out.nodes[1]) print(modifications['mA'].nodes['mA']) for key in modifications['mA'].nodes['mA']: assert graph_out.nodes[1][key] == modifications['mA'].nodes['mA'][key] assert out == ({}, {}) assert mol_to_out == {0: {0: 1}, 1: {1: 1}} assert out_to_mol == {0: {0: 1}, 1: {1: 1}} graph_out.add_node(2, atomname='J', resid=2) mol_to_out[16] = {2: 1} out_to_mol[2] = {16: 1} out = apply_mod_mapping(( {16: {'J': 1}, 17: {'mJ': 1}, 18: {'mJ2': 1}}, modifications['mJ', 'mJ2'], {} ), modified_molecule, graph_out, mol_to_out, out_to_mol) print(mol_to_out) print(out_to_mol) assert out == ({}, {}) assert mol_to_out == {0: {0: 1}, 1: {1: 1}, 16: {2: 1}, 17: {3: 1}, 18: {4: 1}} assert out_to_mol == {0: {0: 1}, 1: {1: 1}, 2: {16: 1}, 3: {17: 1}, 4: {18: 1}}
def build_ref_molecule(velocities=False): """ Build the molecule graph corresponding to the reference data. Parameters ---------- velocities: bool Set if velocities must be written. Return ------ Molecule """ nodes = ( { 'resid': 1, 'resname': 'ALA', 'atomname': 'N', 'atomid': 1, 'element': 'N' }, { 'resid': 1, 'resname': 'ALA', 'atomname': 'CA', 'atomid': 2, 'element': 'C' }, { 'resid': 1, 'resname': 'ALA', 'atomname': 'C', 'atomid': 3, 'element': 'C' }, { 'resid': 1, 'resname': 'ALA', 'atomname': 'O', 'atomid': 4, 'element': 'O' }, { 'resid': 1, 'resname': 'ALA', 'atomname': 'CB', 'atomid': 5, 'element': 'C' }, { 'resid': 1, 'resname': 'ALA', 'atomname': 'H', 'atomid': 6, 'element': 'H' }, { 'resid': 1, 'resname': 'ALA', 'atomname': 'HA', 'atomid': 7, 'element': 'H' }, { 'resid': 1, 'resname': 'ALA', 'atomname': 'HB1', 'atomid': 8, 'element': 'H' }, { 'resid': 1, 'resname': 'ALA', 'atomname': 'HB2', 'atomid': 9, 'element': 'H' }, { 'resid': 1, 'resname': 'ALA', 'atomname': 'HB3', 'atomid': 10, 'element': 'H' }, { 'resid': 2, 'resname': 'VAL', 'atomname': 'N', 'atomid': 11, 'element': 'N' }, { 'resid': 2, 'resname': 'VAL', 'atomname': 'CA', 'atomid': 12, 'element': 'C' }, { 'resid': 2, 'resname': 'VAL', 'atomname': 'C', 'atomid': 13, 'element': 'C' }, { 'resid': 2, 'resname': 'VAL', 'atomname': 'O', 'atomid': 14, 'element': 'O' }, { 'resid': 2, 'resname': 'VAL', 'atomname': 'CB', 'atomid': 15, 'element': 'C' }, { 'resid': 2, 'resname': 'VAL', 'atomname': 'CG1', 'atomid': 16, 'element': 'C' }, { 'resid': 2, 'resname': 'VAL', 'atomname': 'CG2', 'atomid': 17, 'element': 'C' }, { 'resid': 2, 'resname': 'VAL', 'atomname': 'H', 'atomid': 18, 'element': 'H' }, { 'resid': 2, 'resname': 'VAL', 'atomname': 'HA', 'atomid': 19, 'element': 'H' }, { 'resid': 2, 'resname': 'VAL', 'atomname': 'HB', 'atomid': 20, 'element': 'H' }, { 'resid': 2, 'resname': 'VAL', 'atomname': 'HG11', 'atomid': 21, 'element': 'H' }, { 'resid': 2, 'resname': 'VAL', 'atomname': 'HG12', 'atomid': 22, 'element': 'H' }, { 'resid': 2, 'resname': 'VAL', 'atomname': 'HG13', 'atomid': 23, 'element': 'H' }, { 'resid': 2, 'resname': 'VAL', 'atomname': 'HG21', 'atomid': 24, 'element': 'H' }, { 'resid': 2, 'resname': 'VAL', 'atomname': 'HG22', 'atomid': 25, 'element': 'H' }, { 'resid': 2, 'resname': 'VAL', 'atomname': 'HG23', 'atomid': 26, 'element': 'H' }, { 'resid': 3, 'resname': 'SOL', 'atomname': 'OW', 'atomid': 27, 'element': 'O' }, { 'resid': 3, 'resname': 'SOL', 'atomname': 'HW1', 'atomid': 28, 'element': 'H' }, { 'resid': 3, 'resname': 'SOL', 'atomname': 'HW2', 'atomid': 29, 'element': 'H' }, { 'resid': 4, 'resname': 'SOL', 'atomname': 'OW', 'atomid': 30, 'element': 'O' }, { 'resid': 4, 'resname': 'SOL', 'atomname': 'HW1', 'atomid': 31, 'element': 'H' }, { 'resid': 4, 'resname': 'SOL', 'atomname': 'HW2', 'atomid': 32, 'element': 'H' }, { 'resid': 5, 'resname': 'SOL', 'atomname': 'OW', 'atomid': 33, 'element': 'O' }, { 'resid': 5, 'resname': 'SOL', 'atomname': 'HW1', 'atomid': 34, 'element': 'H' }, { 'resid': 5, 'resname': 'SOL', 'atomname': 'HW2', 'atomid': 35, 'element': 'H' }, { 'resid': 6, 'resname': 'SOL', 'atomname': 'OW', 'atomid': 36, 'element': 'O' }, { 'resid': 6, 'resname': 'SOL', 'atomname': 'HW1', 'atomid': 37, 'element': 'H' }, { 'resid': 6, 'resname': 'SOL', 'atomname': 'HW2', 'atomid': 38, 'element': 'H' }, { 'resid': 7, 'resname': 'SOL', 'atomname': 'OW', 'atomid': 39, 'element': 'O' }, { 'resid': 7, 'resname': 'SOL', 'atomname': 'HW1', 'atomid': 40, 'element': 'H' }, { 'resid': 7, 'resname': 'SOL', 'atomname': 'HW2', 'atomid': 41, 'element': 'H' }, { 'resid': 8, 'resname': 'SOL', 'atomname': 'OW', 'atomid': 42, 'element': 'O' }, { 'resid': 8, 'resname': 'SOL', 'atomname': 'HW1', 'atomid': 43, 'element': 'H' }, { 'resid': 8, 'resname': 'SOL', 'atomname': 'HW2', 'atomid': 44, 'element': 'H' }, ) for node, coords, vels in zip(nodes, COORDINATES, VELOCITIES): node['chain'] = '' node['position'] = np.array(coords) if velocities: node['velocity'] = np.array(vels) molecule = Molecule() molecule.add_nodes_from(enumerate(nodes)) return molecule
def test_peptide(): """ Test multiple cg beads in residue """ gly = {'C': {'BB': 1}, 'N': {'BB': 1}, 'O': {'BB': 1}, 'CA': {'BB': 1}} ile = {'C': {'BB': 1}, 'N': {'BB': 1}, 'O': {'BB': 1}, 'CA': {'BB': 1}, 'CB': {'SC1': 1}, 'CG1': {'SC1': 1}, 'CG2': {'SC1': 1}, 'CD': {'SC1': 1}} leu = {'C': {'BB': 1}, 'N': {'BB': 1}, 'O': {'BB': 1}, 'CA': {'BB': 1}, 'CB': {'SC1': 1}, 'CG': {'SC1': 1}, 'CD1': {'SC1': 1}, 'CD2': {'SC1': 1}} extra = () mappings = {'universal': {'martini22': {}}} mappings['universal']['martini22']['GLY'] = Mapping(FF_UNIVERSAL.blocks['GLY'], FF_MARTINI.blocks['GLY'], mapping=gly, references={}, ff_from=FF_UNIVERSAL, ff_to=FF_MARTINI, names=('GLY',), extra=extra) mappings['universal']['martini22']['ILE'] = Mapping(FF_UNIVERSAL.blocks['ILE'], FF_MARTINI.blocks['ILE'], mapping=ile, references={}, ff_from=FF_UNIVERSAL, ff_to=FF_MARTINI, names=('ILE',), extra=extra) mappings['universal']['martini22']['LEU'] = Mapping(FF_UNIVERSAL.blocks['LEU'], FF_MARTINI.blocks['LEU'], mapping=leu, references={}, ff_from=FF_UNIVERSAL, ff_to=FF_MARTINI, names=('LEU',), extra=extra) peptide = Molecule(force_field=FF_UNIVERSAL) aa = FF_UNIVERSAL.blocks['GLY'].to_molecule() peptide.merge_molecule(aa) aa = FF_UNIVERSAL.blocks['ILE'].to_molecule() peptide.merge_molecule(aa) aa = FF_UNIVERSAL.blocks['LEU'].to_molecule() peptide.merge_molecule(aa) peptide.add_edge(list(peptide.find_atoms(atomname='N', resid=1))[0], list(peptide.find_atoms(atomname='C', resid=2))[0]) peptide.add_edge(list(peptide.find_atoms(atomname='N', resid=2))[0], list(peptide.find_atoms(atomname='C', resid=3))[0]) for node in peptide: peptide.nodes[node]['atomid'] = node + 1 peptide.nodes[node]['chain'] = '' cg = do_mapping(peptide, mappings, FF_MARTINI, attribute_keep=('chain',)) expected = Molecule(force_field=FF_MARTINI) expected.add_nodes_from({1: {'atomname': 'BB', 'atype': 'P5', 'chain': '', 'charge': 0.0, 'charge_group': 1, 'resid': 1, 'resname': 'GLY'}, 2: {'atomname': 'BB', 'atype': 'P5', 'chain': '', 'charge': 0.0, 'charge_group': 2, 'resid': 2, 'resname': 'ILE'}, 3: {'atomname': 'SC1', 'atype': 'AC1', 'chain': '', 'charge': 0.0, 'charge_group': 3, 'resid': 2, 'resname': 'ILE'}, 4: {'atomname': 'BB', 'atype': 'P5', 'chain': '', 'charge': 0.0, 'charge_group': 4, 'resid': 3, 'resname': 'LEU'}, 5: {'atomname': 'SC1', 'atype': 'AC1', 'chain': '', 'charge': 0.0, 'charge_group': 5, 'resid': 3, 'resname': 'LEU'}}.items() ) expected.add_edges_from([(1, 2), (2, 3), (2, 4), (4, 5)]) for node in expected: expected.nodes[node]['atomid'] = node + 1 print(cg.nodes(data=True)) print(cg.edges()) print('-'*80) print(expected.nodes(data=True)) print(expected.edges()) assert equal_graphs(cg, expected)
from vermouth.tests.helper_functions import equal_graphs # Pylint does *not* like pytest fixtures # pylint: disable=redefined-outer-name FF_MARTINI = vermouth.forcefield.get_native_force_field(name='martini22') FF_UNIVERSAL = vermouth.forcefield.get_native_force_field(name='universal') AA_MOL = Molecule(force_field=FF_UNIVERSAL) AA_MOL.add_nodes_from(( (0, {'resid': 1, 'resname': 'IPO', 'atomname': 'C1', 'chain': 'A', 'element': 'C'}), (1, {'resid': 1, 'resname': 'IPO', 'atomname': 'C2', 'chain': 'A', 'element': 'C'}), (2, {'resid': 1, 'resname': 'IPO', 'atomname': 'C3', 'chain': 'A', 'element': 'C'}), (3, {'resid': 2, 'resname': 'IPO', 'atomname': 'C1', 'chain': 'A', 'element': 'C'}), (4, {'resid': 2, 'resname': 'IPO', 'atomname': 'C2', 'chain': 'A', 'element': 'C'}), (5, {'resid': 2, 'resname': 'IPO', 'atomname': 'C3', 'chain': 'A', 'element': 'C'}), (6, {'resid': 3, 'resname': 'IPO', 'atomname': 'C1', 'chain': 'A', 'element': 'C'}), (7, {'resid': 3, 'resname': 'IPO', 'atomname': 'C2', 'chain': 'A', 'element': 'C'}), (8, {'resid': 3, 'resname': 'IPO', 'atomname': 'C3', 'chain': 'A', 'element': 'C'}), )) AA_MOL.add_edges_from([(0, 1), (1, 2), (1, 3), (3, 4), (4, 5), (4, 6), (6, 7), (7, 8)]) block_aa = Block(force_field=FF_UNIVERSAL) block_aa.name = 'IPO' block_aa.add_nodes_from(( ('C1', {'resid': 1, 'resname': 'IPO', 'atomname': 'C1'}), ('C2', {'resid': 1, 'resname': 'IPO', 'atomname': 'C2'}), ('C3', {'resid': 1, 'resname': 'IPO', 'atomname': 'C3'}), )) block_aa.add_edges_from([('C1', 'C2'), ('C2', 'C3')])
def make_mol(mol_nodes, mol_edges=[], **kwargs): mol = Molecule(**kwargs) mol.add_nodes_from(mol_nodes) mol.add_edges_from(mol_edges) return mol
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
def test_peptide(): """ Test multiple cg beads in residue """ gly = { (0, 'C'): [(0, 'BB')], (0, 'N'): [(0, 'BB')], (0, 'O'): [(0, 'BB')], (0, 'CA'): [(0, 'BB')] } ile = { (0, 'C'): [(0, 'BB')], (0, 'N'): [(0, 'BB')], (0, 'O'): [(0, 'BB')], (0, 'CA'): [(0, 'BB')], (0, 'CB'): [(0, 'SC1')], (0, 'CG1'): [(0, 'SC1')], (0, 'CG2'): [(0, 'SC1')], (0, 'CD'): [(0, 'SC1')] } leu = { (0, 'C'): [(0, 'BB')], (0, 'N'): [(0, 'BB')], (0, 'O'): [(0, 'BB')], (0, 'CA'): [(0, 'BB')], (0, 'CB'): [(0, 'SC1')], (0, 'CG1'): [(0, 'SC1')], (0, 'CD1'): [(0, 'SC1')], (0, 'CD2'): [(0, 'SC1')] } extra = () mappings = { 'universal': { 'martini22': { 'GLY': (gly, _map_weights(gly), extra), 'ILE': (ile, _map_weights(ile), extra), 'LEU': (leu, _map_weights(leu), extra), } } } peptide = Molecule(force_field=FF_UNIVERSAL) aa = FF_UNIVERSAL.blocks['GLY'].to_molecule() peptide.merge_molecule(aa) aa = FF_UNIVERSAL.blocks['ILE'].to_molecule() peptide.merge_molecule(aa) aa = FF_UNIVERSAL.blocks['LEU'].to_molecule() peptide.merge_molecule(aa) peptide.add_edge( list(peptide.find_atoms(atomname='N', resid=1))[0], list(peptide.find_atoms(atomname='C', resid=2))[0]) peptide.add_edge( list(peptide.find_atoms(atomname='N', resid=2))[0], list(peptide.find_atoms(atomname='C', resid=3))[0]) for node in peptide: peptide.nodes[node]['atomid'] = node + 1 peptide.nodes[node]['chain'] = '' cg = do_mapping(peptide, mappings, FF_MARTINI) expected = Molecule(force_field=FF_MARTINI) expected.add_nodes_from({ 1: { 'atomname': 'BB', 'atype': 'P5', 'chain': '', 'charge': 0.0, 'charge_group': 1, 'resid': 1, 'resname': 'GLY' }, 2: { 'atomname': 'BB', 'atype': 'P5', 'chain': '', 'charge': 0.0, 'charge_group': 2, 'resid': 2, 'resname': 'ILE' }, 3: { 'atomname': 'SC1', 'atype': 'AC1', 'chain': '', 'charge': 0.0, 'charge_group': 2, 'resid': 2, 'resname': 'ILE' }, 4: { 'atomname': 'BB', 'atype': 'P5', 'chain': '', 'charge': 0.0, 'charge_group': 3, 'resid': 3, 'resname': 'LEU' }, 5: { 'atomname': 'SC1', 'atype': 'AC1', 'chain': '', 'charge': 0.0, 'charge_group': 3, 'resid': 3, 'resname': 'LEU' } }.items()) expected.add_edges_from([(1, 2), (2, 3), (2, 4), (4, 5)]) for node in expected: expected.nodes[node]['atomid'] = node + 1 assert _equal_graphs(cg, expected)
def charged_molecule(force_field): """ A molecule with charged termini. """ nodes = [(1, { 'charge_group': 1, 'resid': 1, 'resname': 'ALA', 'atomname': 'BB', 'charge': 1, 'atype': 'Qd', 'modification': force_field.modifications['N-ter'], 'mapping_weights': { 0: 1, 5: 1, 1: 1, 4: 1.0, 2: 1, 3: 1, 6: 1, 7: 1 }, 'chain': 'A', 'position': [0.12170435, 0.06658551, -0.0208] }), (2, { 'charge_group': 2, 'resid': 2, 'resname': 'ALA', 'atomname': 'BB', 'charge': 0.0, 'atype': 'P4', 'mapping_weights': { 12: 1.0, 17: 1.0, 13: 1.0, 16: 1.0, 14: 1.0, 15: 1.0 }, 'chain': 'A', 'position': [0.45269104, 0.23552239, 0.0214209] }), (3, { 'charge_group': 3, 'resid': 3, 'resname': 'ALA', 'atomname': 'BB', 'charge': 0.0, 'atype': 'P4', 'mapping_weights': { 22: 1.0, 27: 1.0, 23: 1.0, 26: 1.0, 24: 1.0, 25: 1.0 }, 'chain': 'A', 'position': [0.74704179, 0.45218955, -0.0214209] }), (4, { 'charge_group': 4, 'resid': 4, 'resname': 'ALA', 'atomname': 'BB', 'charge': 0.0, 'atype': 'P4', 'mapping_weights': { 32: 1.0, 37: 1.0, 33: 1.0, 36: 1.0, 34: 1.0, 35: 1.0 }, 'chain': 'A', 'position': [1.07289104, 0.61778657, 0.0214209] }), (5, { 'charge_group': 5, 'resid': 5, 'resname': 'ALA', 'atomname': 'BB', 'charge': -1, 'atype': 'Qa', 'modification': force_field.modifications['C-ter'], 'mapping_weights': { 42: 1.0, 48: 1.0, 43: 1, 47: 1.0, 44: 1, 45: 1, 46: 1 }, 'chain': 'A', 'position': [1.40449639, 0.85126265, -0.01729157] })] mol = Molecule() mol.add_nodes_from(nodes) mol.add_edges_from([(1, 2), (2, 3), (3, 4), (4, 5)]) return mol