def test_is_bonded(self): site1 = Site("C", [0, 0, 0]) site2 = Site("H", [0, 0, 1]) self.assertTrue(CovalentBond.is_bonded(site1, site2)) site2 = Site("H", [0, 0, 1.5]) self.assertFalse(CovalentBond.is_bonded(site1, site2)) site1 = Site("U", [0, 0, 0]) self.assertRaises(ValueError, CovalentBond.is_bonded, site1, site2) self.assertTrue(CovalentBond.is_bonded(site1, site2, default_bl=2))
def make_graph(mol, tol=0.2): """ make graph object for the input molecule """ G = nx.Graph() names = {} for i, site in enumerate(mol._sites): names[i] = site.specie.value for i in range(len(mol) - 1): site1 = mol.sites[i] for j in range(i + 1, len(mol)): site2 = mol.sites[j] #remove short X-H distances if names[i] == "H" and names[j] == "H": factor = -0.5 elif [names[i], names[j]] in [["S", "S"], ["S", "O"], ["O", "S"], ["F", "O"], ["O", "F"]]: factor = 0.05 elif "H" in [names[i], names[j]]: factor = 0.5 else: factor = 1.0 try: if CovalentBond.is_bonded(site1, site2, factor * tol): G.add_edge(i, j) #print(names[i], names[j], mol.get_distance(i, j)) except ValueError: pass nx.set_node_attributes(G, names, 'name') return G
def make_bonds(scene, structure, line_width=0.08, tol=0.2, color=[.1, .1, .1]): bonds = [] for site0, site1 in itertools.combinations(structure, 2): if CovalentBond.is_bonded(site0, site1, default_bl=0.5): dist = site0.distance(site1) if np.isclose(np.linalg.norm(site0.coords - site1.coords), dist, rtol=5e-3): bonds.append([site0.coords.tolist(), site1.coords.tolist()]) # elif draw_pbc: # for p in itertools.product([1, 0, -1], repeat=3): # vec = site1.coords + np.dot(p, structure.lattice.matrix) # if np.isclose(np.linalg.norm(site0.coords - vec), # dist, rtol=5e-3): # bonds.append([site0.coords.tolist(), vec.tolist()]) # break # for p in itertools.product([1, 0, -1], repeat=3): # vec = site0.coords + np.dot(p, structure.lattice.matrix) # if np.isclose(np.linalg.norm(vec - site1.coords), # dist, rtol=5e-3): # bonds.append([vec.tolist(), site1.coords.tolist()]) # break bonds_geom = fresnel.geometry.Cylinder(scene, N=len(bonds)) bonds_geom.points[:] = bonds bonds_geom.radius[:] = line_width * np.ones(len(bonds)) bonds_geom.material = fresnel.material.Material( color=fresnel.color.linear(color)) return bonds_geom
def from_molecule(molecule, tol=0.1): """ Return Topology object from molecule. Args: molecule (Molecule) tol (float): Relative tolerance to test in determining the bonds in the molecule. Basically, the code checks if the distance between the sites is less than (1 + tol) * typical bond distances. Defaults to 0.1, i.e., 10% longer. Returns: Topology object """ bonds = molecule.get_covalent_bonds(tol=tol) angles = [] dihedrals = [] for bond1, bond2 in itertools.combinations(bonds, 2): bond1_sites = [bond1.site1, bond1.site2] bond2_sites = [bond2.site1, bond2.site2] s_bond1 = set(bond1_sites) s_bond2 = set(bond2_sites) common_site = s_bond1.intersection(s_bond2) if common_site: site1 = (s_bond1 - s_bond2).pop() site2 = common_site.pop() site3 = (s_bond2 - s_bond1).pop() angle = [ molecule.index(site1), molecule.index(site2), molecule.index(site3), (str(site1.specie), str(site2.specie), str(site3.specie)) ] angles.append(angle) else: for site1, site2 in itertools.product(bond1_sites, bond2_sites): if CovalentBond.is_bonded(site1, site2): bond1_sites.remove(site1) bond2_sites.remove(site2) dihedral = bond1_sites + [site1, site2] + bond2_sites dihedral = [ molecule.index(dihedral[0]), molecule.index(dihedral[1]), molecule.index(dihedral[2]), molecule.index(dihedral[3]), (str(dihedral[0].specie), str(dihedral[1].specie), str(dihedral[2].specie), str(dihedral[3].specie)) ] dihedrals.append(dihedral) break atoms = [[str(site.specie), str(site.specie)] for site in molecule] bonds = [[ molecule.index(b.site1), molecule.index(b.site2), (str(b.site1.specie), str(b.site2.specie)) ] for b in bonds] return Topology(atoms, bonds, angles, dihedrals=dihedrals)
def from_molecule(molecule, tol=0.1): """ Return Topology object from molecule. Args: molecule (Molecule) tol (float): Relative tolerance to test in determining the bonds in the molecule. Basically, the code checks if the distance between the sites is less than (1 + tol) * typical bond distances. Defaults to 0.1, i.e., 10% longer. Returns: Topology object """ bonds = molecule.get_covalent_bonds(tol=tol) angles = [] dihedrals = [] for bond1, bond2 in itertools.combinations(bonds, 2): bond1_sites = [bond1.site1, bond1.site2] bond2_sites = [bond2.site1, bond2.site2] s_bond1 = set(bond1_sites) s_bond2 = set(bond2_sites) common_site = s_bond1.intersection(s_bond2) if common_site: site1 = (s_bond1 - s_bond2).pop() site2 = common_site.pop() site3 = (s_bond2 - s_bond1).pop() angle = [molecule.index(site1), molecule.index(site2), molecule.index(site3), (str(site1.specie), str(site2.specie), str(site3.specie))] angles.append(angle) else: for site1, site2 in itertools.product(bond1_sites, bond2_sites): if CovalentBond.is_bonded(site1, site2, tol=tol): bond1_sites.remove(site1) bond2_sites.remove(site2) dihedral = bond1_sites + [site1, site2] + bond2_sites dihedral = [molecule.index(dihedral[0]), molecule.index(dihedral[1]), molecule.index(dihedral[2]), molecule.index(dihedral[3]), (str(dihedral[0].specie), str(dihedral[1].specie), str(dihedral[2].specie), str(dihedral[3].specie))] dihedrals.append(dihedral) break atoms = [[str(site.specie), str(site.specie)] for site in molecule] bonds = [[molecule.index(b.site1), molecule.index(b.site2), (str(b.site1.specie), str(b.site2.specie))] for b in bonds] charges = None if hasattr(molecule[0], "charge"): charges = [site.charge for site in molecule] return Topology(atoms, bonds, angles, charges=charges, dihedrals=dihedrals)
def find_covalent_bonds(molecule): import itertools from pymatgen.core.bonds import CovalentBond number_of_sites = len(molecule.sites) bonds=[] for a,b in itertools.combinations(range(number_of_sites),2): if CovalentBond.is_bonded(molecule.sites[a], molecule.sites[b], default_bl=2.0): bonds.append([a,b]) return np.array(bonds)
def check_one_site(struc, site0, visited): neigh_sites = struc.get_neighbors(site0, 3.0) ids = [m.index for m in visited] sites_add = [] ids_add = [] for site1 in neigh_sites: if (site1.index not in ids + ids_add): if CovalentBond.is_bonded(site0, site1, tol): sites_add.append(site1) ids_add.append(site1.index) if len(sites_add) > 0: visited.extend(sites_add) return sites_add, visited
def get_covalent_bonds(self, tol=0.2): """ Determines the covalent bonds in a molecule. Args: tol: The tol to determine bonds in a structure. See CovalentBond.is_bonded. Returns: List of bonds """ bonds = [] for site1, site2 in itertools.combinations(self._sites, 2): if CovalentBond.is_bonded(site1, site2, tol): bonds.append(CovalentBond(site1, site2)) return bonds
def check_one_site(struc, site0, visited, rmax=2.9): neigh_sites = struc.get_neighbors(site0, rmax) ids = [m.index for m in visited] sites_add = [] ids_add = [] for site1 in neigh_sites: if (site1.index not in ids+ids_add): if CovalentBond.is_bonded(site0, site1, tol): (d, image) = site0.distance_and_image(site1) site1.frac_coords += image #print(d, image, site1) sites_add.append(site1) ids_add.append(site1.index) if len(sites_add) > 0: visited.extend(sites_add) return sites_add, visited
def test_is_bonded(self): site1 = Site("C", [0, 0, 0]) site2 = Site("H", [0, 0, 1]) self.assertTrue(CovalentBond.is_bonded(site1, site2)) site2 = Site("H", [0, 0, 1.5]) self.assertFalse(CovalentBond.is_bonded(site1, site2))
def belongs_to_cluster(site, cluster): for test_site in cluster: if CovalentBond.is_bonded(site, test_site, tol=tol): return True return False
def from_molecule(molecule, tol=0.1, ff_map="ff_map"): """ Return Topology object from molecule. Charges are also set if the molecule has 'charge' site property. Args: molecule (Molecule) tol (float): Relative tolerance to test in determining the bonds in the molecule. Basically, the code checks if the distance between the sites is less than (1 + tol) * typical bond distances. Defaults to 0.1, i.e., 10% longer. ff_map (string): Ensure this site property is set for each site if atoms need to be mapped to its forcefield name. eg: Carbon atom, 'C', on different sites can be mapped to either 'Ce' or 'Cm' depending on how the forcefield parameters are set. Returns: Topology object """ type_attrib = ff_map if hasattr(molecule[0], ff_map) else "specie" bonds = molecule.get_covalent_bonds(tol=tol) angles = [] dihedrals = [] for bond1, bond2 in itertools.combinations(bonds, 2): bond1_sites = [bond1.site1, bond1.site2] bond2_sites = [bond2.site1, bond2.site2] s_bond1 = set(bond1_sites) s_bond2 = set(bond2_sites) common_site = s_bond1.intersection(s_bond2) if common_site: site1 = (s_bond1 - s_bond2).pop() site2 = common_site.pop() site3 = (s_bond2 - s_bond1).pop() angle = [molecule.index(site1), molecule.index(site2), molecule.index(site3), (str(getattr(site1, type_attrib)), str(getattr(site2, type_attrib)), str(getattr(site3, type_attrib)))] angles.append(angle) else: for site1, site2 in itertools.product(bond1_sites, bond2_sites): if CovalentBond.is_bonded(site1, site2, tol=tol): bond1_sites.remove(site1) bond2_sites.remove(site2) dihedral = bond1_sites + [site1, site2] + bond2_sites dihedral = [molecule.index(dihedral[0]), molecule.index(dihedral[1]), molecule.index(dihedral[2]), molecule.index(dihedral[3]), (str(getattr(dihedral[0], type_attrib)), str(getattr(dihedral[1], type_attrib)), str(getattr(dihedral[2], type_attrib)), str(getattr(dihedral[3], type_attrib)))] dihedrals.append(dihedral) break atoms = [[str(site.specie), str(getattr(site, type_attrib))] for site in molecule] bonds = [[molecule.index(b.site1), molecule.index(b.site2), (str(getattr(b.site1, type_attrib)), str(getattr(b.site2, type_attrib)))] for b in bonds] charges = None if hasattr(molecule[0], "charge"): charges = [site.charge for site in molecule] return Topology(atoms, bonds, angles, charges=charges, dihedrals=dihedrals)
def from_molecule(molecule, tol=0.1, ff_map="ff_map"): """ Return Topology object from molecule. Charges are also set if the molecule has 'charge' site property. Args: molecule (Molecule) tol (float): Relative tolerance to test in determining the bonds in the molecule. Basically, the code checks if the distance between the sites is less than (1 + tol) * typical bond distances. Defaults to 0.1, i.e., 10% longer. ff_map (string): Ensure this site property is set for each site if atoms need to be mapped to its forcefield name. eg: Carbon atom, 'C', on different sites can be mapped to either 'Ce' or 'Cm' depending on how the forcefield parameters are set. Returns: Topology object """ type_attrib = ff_map if hasattr(molecule[0], ff_map) else "specie" bonds = molecule.get_covalent_bonds(tol=tol) angles = [] dihedrals = [] for bond1, bond2 in itertools.combinations(bonds, 2): bond1_sites = [bond1.site1, bond1.site2] bond2_sites = [bond2.site1, bond2.site2] s_bond1 = set(bond1_sites) s_bond2 = set(bond2_sites) common_site = s_bond1.intersection(s_bond2) if common_site: site1 = (s_bond1 - s_bond2).pop() site2 = common_site.pop() site3 = (s_bond2 - s_bond1).pop() angle = [ molecule.index(site1), molecule.index(site2), molecule.index(site3), (str(getattr(site1, type_attrib)), str(getattr(site2, type_attrib)), str(getattr(site3, type_attrib))) ] angles.append(angle) else: for site1, site2 in itertools.product(bond1_sites, bond2_sites): if CovalentBond.is_bonded(site1, site2, tol=tol): bond1_sites.remove(site1) bond2_sites.remove(site2) dihedral = bond1_sites + [site1, site2] + bond2_sites dihedral = [ molecule.index(dihedral[0]), molecule.index(dihedral[1]), molecule.index(dihedral[2]), molecule.index(dihedral[3]), (str(getattr(dihedral[0], type_attrib)), str(getattr(dihedral[1], type_attrib)), str(getattr(dihedral[2], type_attrib)), str(getattr(dihedral[3], type_attrib))) ] dihedrals.append(dihedral) break atoms = [[str(site.specie), str(getattr(site, type_attrib))] for site in molecule] bonds = [[ molecule.index(b.site1), molecule.index(b.site2), (str(getattr(b.site1, type_attrib)), str(getattr(b.site2, type_attrib))) ] for b in bonds] charges = None if hasattr(molecule[0], "charge"): charges = [site.charge for site in molecule] return Topology(atoms, bonds, angles, charges=charges, dihedrals=dihedrals)