def from_networkx(graph): """Convert a networkx.Graph to a gmso.Topology Creates a topology from the graph where each node is a site and each edge becomes a connection. Parameters ---------- graph : networkX.Graph networkx.Graph instance that need to be converted Returns ------- top : gmso.Topology Notes ----- - While a lot of information is lost from converting to a graph object (e.g. metadata, mixing rules, etc.), the graph representation is a useful way to manipulate and extract connectivity information from Topology objects. - The edge has a `connection` attribute, which stores the Bond object it was created from """ if not isinstance(graph, nx.Graph): raise TypeError( "Type mismatch, graph object is expected to be " "an instance of networkx.Graph, was provided: {}".format( type(graph))) top = Topology() node_mapping = dict() for node in graph.nodes: if not isinstance(node, Site): raise TypeError("Nodes must be instances of gmso.abc.Site") else: top.add_site(node) for edge in graph.edges: try: conn = graph.get_edge_data(*edge)["connection"] if (isinstance(conn, Connection) and set(edge).issubset(set(conn.connection_members))): top.add_connection(conn) except KeyError: conn = Bond(connection_members=edge) top.add_connection(conn) warnings.simplefilter('once', UserWarning) for node in graph.nodes: try: graph.nodes[node]['angles'] or graph.nodes[node]['dihedrals'] warnings.warn("Angle and Dihedral information is not converted.") except KeyError: pass return top
def test_square(self): mytop = Topology() s1 = Atom(name="1") s2 = Atom(name="2") s3 = Atom(name="3") s4 = Atom(name="4") c12 = Bond(connection_members=[s1, s2]) c23 = Bond(connection_members=[s2, s3]) c34 = Bond(connection_members=[s3, s4]) c41 = Bond(connection_members=[s4, s1]) for site in [s1, s2, s3, s4]: mytop.add_site(site, update_types=False) for conn in [c12, c23, c34, c41]: mytop.add_connection(conn, update_types=False) assert mytop.n_bonds == 4 assert mytop.n_angles == 0 assert mytop.n_dihedrals == 0 assert mytop.n_impropers == 0 mytop.identify_connections() assert mytop.n_bonds == 4 assert mytop.n_angles == 4 assert mytop.n_dihedrals == 4 assert mytop.n_impropers == 0
def ethane(self): mytop = Topology() c1 = Atom(name='C1') h11 = Atom(name='H11') h12 = Atom(name='H12') h13 = Atom(name='H13') c2 = Atom(name='C2') h21 = Atom(name='H21') h22 = Atom(name='H22') h23 = Atom(name='H23') c1h11 = Bond(connection_members=[c1, h11]) c1h12 = Bond(connection_members=[c1, h12]) c1h13 = Bond(connection_members=[c1, h13]) c2h21 = Bond(connection_members=[c2, h21]) c2h22 = Bond(connection_members=[c2, h22]) c2h23 = Bond(connection_members=[c2, h23]) c1c2 = Bond(connection_members=[c1, c2]) mytop.add_connection(c1h11, update_types=False) mytop.add_connection(c1h12, update_types=False) mytop.add_connection(c1h13, update_types=False) mytop.add_connection(c2h21, update_types=False) mytop.add_connection(c2h22, update_types=False) mytop.add_connection(c2h23, update_types=False) mytop.add_connection(c1c2, update_types=False) mytop.update_topology() return mytop
def test_add_equivalent_connections(self): atom1 = Atom(name="AtomA") atom2 = Atom(name="AtomB") bond = Bond(connection_members=[atom1, atom2]) bond_eq = Bond(connection_members=[atom2, atom1]) top = Topology() top.add_connection(bond) top.add_connection(bond_eq) assert top.n_bonds == 1
def test_add_connection(self): top = Topology() atom1 = Atom(name='atom1') atom2 = Atom(name='atom2') connect = Bond(connection_members=[atom1, atom2]) top.add_connection(connect) top.add_site(atom1) top.add_site(atom2) assert len(top.connections) == 1
def test_add_connection(self): top = Topology() site1 = Site(name='site1') site2 = Site(name='site2') connect = Bond(connection_members=[site1, site2]) top.add_connection(connect) top.add_site(site1) top.add_site(site2) assert len(top.connections) == 1
def test_add_duplicate_connected_atom(self): top = Topology() atom1 = Atom(name="AtomA") atom2 = Atom(name="AtomB") bond = Bond(connection_members=[atom1, atom2]) bond_eq = Bond(connection_members=[atom1, atom2]) top.add_connection(bond) top.add_connection(bond_eq) top.update_topology() assert top.n_connections == 1
def test_add_untyped_bond_update(self): site1 = Site(atom_type=None) site2 = Site(atom_type=None) bond = Bond(connection_members=[site1, site2], connection_type=None) top = Topology() assert len(top.bond_types) == 0 top.add_connection(bond, update_types=False) assert len(top.bond_types) == 0 top = Topology() assert len(top.bond_types) == 0 top.add_connection(bond, update_types=True) assert len(top.bond_types) == 0
def test_add_typed_bond_update(self): atom1 = Atom(atom_type=None) atom2 = Atom(atom_type=None) bond = Bond(connection_members=[atom1, atom2], bond_type=BondType()) top = Topology() top.add_site(atom1) top.add_site(atom2) top.add_connection(bond, update_types=False) assert len(top.connection_types) == 0 top = Topology() top.add_connection(bond, update_types=True) assert len(top.bond_types) == 1
def test_top_update(self): top = Topology() top.update_topology() assert top.n_sites == 0 assert len(top.atom_types) == 0 assert len(top.atom_type_expressions) == 0 assert top.n_connections == 0 assert len(top.connection_types) == 0 assert len(top.connection_type_expressions) == 0 atomtype = AtomType() site1 = Site(name='site1', atom_type=atomtype) top.add_site(site1) site2 = Site(name='site2', atom_type=atomtype) top.add_site(site2) assert top.n_sites == 2 assert len(top.atom_types) == 1 assert len(top.atom_type_expressions) == 1 assert top.n_connections == 0 assert len(top.connection_types) == 0 assert len(top.connection_type_expressions) == 0 ctype = BondType() connection_12 = Bond(connection_members=[site1, site2], connection_type=ctype) top.add_connection(connection_12) assert top.n_sites == 2 assert len(top.atom_types) == 1 assert len(top.atom_type_expressions) == 1 assert top.n_connections == 1 assert len(top.connection_types) == 1 assert len(top.connection_type_expressions) == 1 site1.atom_type = AtomType(expression='sigma*epsilon') assert top.n_sites == 2 assert len(top.atom_types) == 1 assert len(top.atom_type_expressions) == 1 assert top.n_connections == 1 assert len(top.connection_types) == 1 assert len(top.connection_type_expressions) == 1 top.update_atom_types() assert top.n_sites == 2 assert len(top.atom_types) == 2 assert len(top.atom_type_expressions) == 2 assert top.n_connections == 1 assert len(top.connection_types) == 1 assert len(top.connection_type_expressions) == 1
def test_top_update(self): top = Topology() top.update_topology() assert top.n_sites == 0 assert len(top.atom_types) == 0 assert len(top.atom_type_expressions) == 0 assert top.n_connections == 0 assert len(top.connection_types) == 0 assert len(top.connection_type_expressions) == 0 atomtype = AtomType() atom1 = Atom(name='atom1', atom_type=atomtype) top.add_site(atom1) atom2 = Atom(name='atom2', atom_type=atomtype) top.add_site(atom2) assert top.n_sites == 2 assert len(top.atom_types) == 1 assert len(top.atom_type_expressions) == 1 assert top.n_connections == 0 assert len(top.connection_types) == 0 assert len(top.connection_type_expressions) == 0 ctype = BondType() connection_12 = Bond(connection_members=[atom1, atom2], bond_type=ctype) top.add_connection(connection_12) assert top.n_sites == 2 assert len(top.atom_types) == 1 assert len(top.atom_type_expressions) == 1 assert top.n_connections == 1 assert len(top.connection_types) == 1 assert len(top.connection_type_expressions) == 1 atom1.atom_type = AtomType(expression='sigma*epsilon*r') assert top.n_sites == 2 assert len(top.atom_types) == 1 assert len(top.atom_type_expressions) == 1 assert top.n_connections == 1 assert len(top.connection_types) == 1 assert len(top.connection_type_expressions) == 1 top.update_atom_types() assert top.n_sites == 2 assert len(top.atom_types) == 2 assert len(top.atom_type_expressions) == 2 assert top.n_connections == 1 assert len(top.connection_types) == 1 assert len(top.connection_type_expressions) == 1
def test_bond_bondtype_update(self): top = Topology() atype1 = AtomType(expression='sigma + epsilon') atype2 = AtomType(expression='sigma * epsilon') site1 = Site('a', atom_type=atype1) site2 = Site('b', atom_type=atype2) btype = BondType() bond = Bond(connection_members=[site1, site2], connection_type=btype) top.add_site(site1) top.add_site(site2) top.add_connection(bond) assert top.n_bonds == 1 assert len(top.bond_types) == 1 assert len(top.bond_type_expressions) == 1
def test_bond_bondtype_update(self): top = Topology() atype1 = AtomType(expression='sigma + epsilon*r') atype2 = AtomType(expression='sigma * epsilon*r') atom1 = Atom(name='a', atom_type=atype1) atom2 = Atom(name='b', atom_type=atype2) btype = BondType() bond = Bond(connection_members=[atom1, atom2], bond_type=btype) top.add_site(atom1) top.add_site(atom2) top.add_connection(bond) assert top.n_bonds == 1 assert len(top.bond_types) == 1 assert len(top.bond_type_expressions) == 1
def test_angle_angletype_update(self): top = Topology() atype1 = AtomType(expression='sigma + epsilon') atype2 = AtomType(expression='sigma * epsilon') site1 = Site('a', atom_type=atype1) site2 = Site('b', atom_type=atype2) site3 = Site('c', atom_type=atype2) atype = AngleType() angle = Angle(connection_members=[site1, site2, site3], connection_type=atype, name='angle_name') top.add_site(site1) top.add_site(site2) top.add_site(site3) top.add_connection(angle) assert top.n_angles == 1 assert len(top.angle_types) == 1 assert len(top.angle_type_expressions) == 1 assert len(top.atom_type_expressions) == 2
def test_dihedral_dihedraltype_update(self): top = Topology() atype1 = AtomType(expression='sigma + epsilon') atype2 = AtomType(expression='sigma * epsilon') site1 = Site('a', atom_type=atype1) site2 = Site('b', atom_type=atype2) site3 = Site('c', atom_type=atype2) site4 = Site('d', atom_type=atype1) atype = DihedralType() dihedral = Dihedral(connection_members=[site1, site2, site3, site4], connection_type=atype) top.add_site(site1) top.add_site(site2) top.add_site(site3) top.add_site(site4) top.add_connection(dihedral) assert top.n_dihedrals == 1 assert len(top.dihedral_types) == 1 assert len(top.dihedral_type_expressions) == 1 assert len(top.atom_type_expressions) == 2
def test_improper_impropertype_update(self): top = Topology() atype1 = AtomType(expression='sigma + epsilon') atype2 = AtomType(expression='sigma * epsilon') site1 = Site('a', atom_type=atype1) site2 = Site('b', atom_type=atype2) site3 = Site('c', atom_type=atype2) site4 = Site('d', atom_type=atype1) atype = ImproperType() improper = Improper(connection_members=[site1, site2, site3, site4], connection_type=atype) top.add_site(site1) top.add_site(site2) top.add_site(site3) top.add_site(site4) top.add_connection(improper) assert top.n_impropers == 1 assert len(top.improper_types) == 1 assert len(top.improper_type_expressions) == 1 assert len(top.atom_type_expressions) == 2
def test_angle_angletype_update(self): top = Topology() atype1 = AtomType(expression='sigma + epsilon*r') atype2 = AtomType(expression='sigma * epsilon*r') atom1 = Atom(name='a', atom_type=atype1) atom2 = Atom(name='b', atom_type=atype2) atom3 = Atom(name='c', atom_type=atype2) atype = AngleType() angle = Angle(connection_members=[atom1, atom2, atom3], angle_type=atype, name='angle_name') top.add_site(atom1) top.add_site(atom2) top.add_site(atom3) top.add_connection(angle) assert top.n_angles == 1 assert len(top.angle_types) == 1 assert len(top.angle_type_expressions) == 1 assert len(top.atom_type_expressions) == 2
def test_square_with_bridge(self): mytop = Topology() s1 = Atom(name="1") s2 = Atom(name="2") s3 = Atom(name="3") s4 = Atom(name="4") c12 = Bond(connection_members=[s1, s2]) c23 = Bond(connection_members=[s2, s3]) c34 = Bond(connection_members=[s3, s4]) c41 = Bond(connection_members=[s4, s1]) c24 = Bond(connection_members=[s2, s4]) mytop.add_site(s1, update_types=False) mytop.add_site(s2, update_types=False) mytop.add_site(s3, update_types=False) mytop.add_site(s4, update_types=False) mytop.add_connection(c12, update_types=False) mytop.add_connection(c23, update_types=False) mytop.add_connection(c34, update_types=False) mytop.add_connection(c41, update_types=False) mytop.add_connection(c24, update_types=False) assert mytop.n_bonds == 5 assert mytop.n_angles == 0 assert mytop.n_dihedrals == 0 assert mytop.n_impropers == 0 mytop.identify_connections() assert mytop.n_bonds == 5 assert mytop.n_angles == 8 assert mytop.n_dihedrals == 6 assert mytop.n_impropers == 2
def test_dihedral_dihedraltype_update(self): top = Topology() atype1 = AtomType(expression='sigma + epsilon*r') atype2 = AtomType(expression='sigma * epsilon*r') atom1 = Atom(name='a', atom_type=atype1) atom2 = Atom(name='b', atom_type=atype2) atom3 = Atom(name='c', atom_type=atype2) atom4 = Atom(name='d', atom_type=atype1) atype = DihedralType() dihedral = Dihedral(connection_members=[atom1, atom2, atom3, atom4], dihedral_type=atype) top.add_site(atom1) top.add_site(atom2) top.add_site(atom3) top.add_site(atom4) top.add_connection(dihedral) assert top.n_dihedrals == 1 assert len(top.dihedral_types) == 1 assert len(top.dihedral_type_expressions) == 1 assert len(top.atom_type_expressions) == 2
def test_improper_impropertype_update(self): top = Topology() atype1 = AtomType(expression='sigma + epsilon*r') atype2 = AtomType(expression='sigma * epsilon*r') atom1 = Atom(name='a', atom_type=atype1) atom2 = Atom(name='b', atom_type=atype2) atom3 = Atom(name='c', atom_type=atype2) atom4 = Atom(name='d', atom_type=atype1) atype = ImproperType() improper = Improper(connection_members=[atom1, atom2, atom3, atom4], improper_type=atype) top.add_site(atom1) top.add_site(atom2) top.add_site(atom3) top.add_site(atom4) top.add_connection(improper) assert top.n_impropers == 1 assert len(top.improper_types) == 1 assert len(top.improper_type_expressions) == 1 assert len(top.atom_type_expressions) == 2
def methane(self): mytop = Topology() c = Atom(name='c') h1 = Atom(name='h1') h2 = Atom(name='h2') h3 = Atom(name='h3') h4 = Atom(name='h4') ch1 = Bond(connection_members=[c, h1]) ch2 = Bond(connection_members=[c, h2]) ch3 = Bond(connection_members=[c, h3]) ch4 = Bond(connection_members=[c, h4]) mytop.add_site(c, update_types=False) mytop.add_site(h1, update_types=False) mytop.add_site(h2, update_types=False) mytop.add_site(h3, update_types=False) mytop.add_site(h4, update_types=False) mytop.add_connection(ch1, update_types=False) mytop.add_connection(ch2, update_types=False) mytop.add_connection(ch3, update_types=False) mytop.add_connection(ch4, update_types=False) mytop.update_topology() return mytop
def test_add_equivalent_connections(self): atom1 = Atom(name="AtomA") atom2 = Atom(name="AtomB") atom3 = Atom(name="AtomC") angle = Angle(connection_members=[atom1, atom2, atom3]) angle_eq = Angle(connection_members=[atom3, atom2, atom1]) angle_not_eq = Angle(connection_members=[atom1, atom3, atom2]) top = Topology() top.add_connection(angle) top.add_connection(angle_eq) assert top.n_angles == 1 top.add_connection(angle_not_eq) assert top.n_angles == 2
def test_add_equivalent_connections(self): atom1 = Atom(name="AtomA") atom2 = Atom(name="AtomB") atom3 = Atom(name="AtomC") atom4 = Atom(name="AtomD") improper = Improper(connection_members=[atom1, atom2, atom3, atom4]) improper_eq = Improper(connection_members=[atom1, atom3, atom2, atom4]) improper_not_eq = Improper( connection_members=[atom2, atom3, atom1, atom4]) top = Topology() top.add_connection(improper) top.add_connection(improper_eq) assert top.n_impropers == 1 top.add_connection(improper_not_eq) assert top.n_impropers == 2
def test_add_equivalent_connections(self): atom1 = Atom(name="AtomA") atom2 = Atom(name="AtomB") atom3 = Atom(name="AtomC") atom4 = Atom(name="AtomD") dihedral = Dihedral(connection_members=[atom1, atom2, atom3, atom4]) dihedral_eq = Dihedral(connection_members=[atom4, atom3, atom2, atom1]) dihedral_not_eq = Dihedral( connection_members=[atom4, atom2, atom3, atom1]) top = Topology() top.add_connection(dihedral) top.add_connection(dihedral_eq) assert top.n_dihedrals == 1 top.add_connection(dihedral_not_eq) assert top.n_dihedrals == 2
def from_mbuild(compound, box=None, search_method=element_by_symbol): """Convert an mbuild.Compound to a gmso.Topology This conversion makes the following assumptions about the inputted `Compound`: * All positional and box dimension values in compound are in nanometers * If the `Compound` has 4 or more levels of hierarchy, these are\ compressed to 3 levels of hierarchy in the resulting `Topology`. The\ top level `Compound` becomes the `Topology`, the second level\ Compounds become `SubTopologies`, and each particle becomes a `Site`,\ which are added to their corresponding `SubTopologies`.\ * Furthermore, `Sites` that do not belong to a sub-`Compound` are\ added to a single-`Site` `SubTopology`. * The box dimension are extracted from `compound.periodicity`. If the\ `compound.periodicity` is `None`, the box lengths are the lengths of\ the bounding box + a 0.5 nm buffer. * Only `Bonds` are added for each bond in the `Compound`. If `Angles`\ and `Dihedrals` are desired in the resulting `Topology`, they must be\ added separately from this function. Parameters ---------- compound : mbuild.Compound mbuild.Compound instance that need to be converted box : mbuild.Box, optional, default=None Box information to be loaded to a gmso.Topology search_method : function, optional, default=element_by_symbol Searching method used to assign element from periodic table to particle site. The information specified in the `search_method` argument is extracted from each `Particle`'s `name` attribute. Valid functions are element_by_symbol, element_by_name, element_by_atomic_number, and element_by_mass, which can be imported from `gmso.core.element' Returns ------- top : gmso.Topology """ msg = ("Argument compound is not an mbuild.Compound") assert isinstance(compound, mb.Compound), msg top = Topology() top.typed = False # Keep the name if it is not the default mBuild Compound name if compound.name != mb.Compound().name: top.name = compound.name site_map = dict() for child in compound.children: if len(child.children) == 0: continue else: subtop = SubTopology(name=child.name) top.add_subtopology(subtop) for particle in child.particles(): pos = particle.xyz[0] * u.nanometer ele = search_method(particle.name) site = Site(name=particle.name, position=pos, element=ele) site_map[particle] = site subtop.add_site(site) top.update_topology() for particle in compound.particles(): already_added_site = site_map.get(particle, None) if already_added_site: continue pos = particle.xyz[0] * u.nanometer ele = search_method(particle.name) site = Site(name=particle.name, position=pos, element=ele) site_map[particle] = site # If the top has subtopologies, then place this particle into # a single-site subtopology -- ensures that all sites are in the # same level of hierarchy. if len(top.subtops) > 0: subtop = SubTopology(name=particle.name) top.add_subtopology(subtop) subtop.add_site(site) else: top.add_site(site) for b1, b2 in compound.bonds(): new_bond = Bond(connection_members=[site_map[b1], site_map[b2]], connection_type=None) top.add_connection(new_bond) top.update_topology() if box: top.box = from_mbuild_box(box) # Assumes 2-D systems are not supported in mBuild # if compound.periodicity is None and not box: else: if np.allclose(compound.periodicity, np.zeros(3)): box = from_mbuild_box(compound.boundingbox) if box: box.lengths += [0.5, 0.5, 0.5] * u.nm top.box = box else: top.box = Box(lengths=compound.periodicity) return top
def test_topology_get_index(self): top = Topology() conn_members = [Atom() for _ in range(10)] for atom in conn_members: top.add_site(atom) for i in range(5): top.add_connection( Bond(connection_members=[conn_members[i], conn_members[i + 1]])) top.add_connection( Angle(connection_members=[ conn_members[i], conn_members[i + 1], conn_members[i + 2] ])) top.add_connection( Dihedral(connection_members=[ conn_members[i], conn_members[i + 1], conn_members[i + 2], conn_members[i + 3] ])) top.add_connection( Improper(connection_members=[ conn_members[i], conn_members[i + 1], conn_members[i + 2], conn_members[i + 3] ])) a_atom = Atom() a_bond = Bond(connection_members=[conn_members[6], conn_members[7]]) an_angle = Angle(connection_members=[ conn_members[6], conn_members[7], conn_members[8] ]) a_dihedral = Dihedral(connection_members=[ conn_members[6], conn_members[7], conn_members[8], conn_members[9] ]) an_improper = Improper(connection_members=[ conn_members[6], conn_members[7], conn_members[8], conn_members[9] ]) top.add_site(a_atom) top.add_connection(a_bond) top.add_connection(an_angle) top.add_connection(a_dihedral) top.add_connection(an_improper) assert top.get_index(a_atom) == 10 assert top.get_index(a_bond) == 5 assert top.get_index(an_angle) == 5 assert top.get_index(a_dihedral) == 5 assert top.get_index(an_improper) == 5
def test_topology_get_index(self): top = Topology() conn_members = [Site(), Site(), Site(), Site()] for i in range(5): top.add_site(Site()) top.add_connection( Bond(connection_members=[conn_members[0], conn_members[1]])) top.add_connection( Angle(connection_members=[ conn_members[0], conn_members[1], conn_members[2] ])) top.add_connection( Dihedral(connection_members=[ conn_members[0], conn_members[1], conn_members[2], conn_members[3] ])) top.add_connection( Improper(connection_members=[ conn_members[0], conn_members[1], conn_members[2], conn_members[3] ])) a_bond = Bond(connection_members=[conn_members[0], conn_members[1]]) an_angle = Angle(connection_members=[ conn_members[0], conn_members[1], conn_members[2] ]) a_site = Site() a_dihedral = Dihedral(connection_members=[ conn_members[0], conn_members[1], conn_members[2], conn_members[3] ]) an_improper = Improper(connection_members=[ conn_members[0], conn_members[1], conn_members[2], conn_members[3] ]) top.add_site(a_site) top.add_connection(a_bond) top.add_connection(an_angle) top.add_connection(a_dihedral) top.add_connection(an_improper) assert top.get_index(a_site) == 9 assert top.get_index(a_bond) == 5 assert top.get_index(an_angle) == 5 assert top.get_index(a_dihedral) == 5 assert top.get_index(an_improper) == 5