def extract(s, bonds, save_info): elems = np.array(s.get_chemical_symbols()) hybrid = np.zeros(len(elems)).astype(int) if (elems == 'C').any(): # Only do this if there is any carbon... if bonds is None: # Recalculate bonds bonds = Bonds.get(s) C_i = set(list(np.where(elems == 'C')[0])) for b in bonds: C_b = C_i.intersection(b[:2]) hybrid[list(C_b)] += 1 # Now go from number of bonds to hybridation state hybrid[list(C_i)] = np.where( (hybrid[list(C_i)] > 1) * (hybrid[list(C_i)] <= 4), hybrid[list(C_i)] - 1, 0) if save_info: s.new_array(CarbonHybridationState.default_name, hybrid) return hybrid
def test_linkageprops(self): from soprano.properties.linkage import (LinkageList, Bonds, Molecules, MoleculeNumber, MoleculeMass, MoleculeCOMLinkage, MoleculeRelativeRotation, MoleculeSpectralSort, CoordinationHistogram, HydrogenBonds, HydrogenBondsNumber) from soprano.properties.transform import Rotate a = read(os.path.join(_TESTDATA_DIR, 'mol_crystal.cif')) # Test bonds testAtoms = Atoms(['C', 'C', 'C', 'C'], cell=[5, 5, 5], positions=np.array([[0, 0, 0], [4, 0, 0], [3, 3, 3], [3, 3.5, 3]]), pbc=True) testBonds = Bonds.get(testAtoms) self.assertTrue(testBonds[0][:2] == (0, 1)) self.assertTrue(testBonds[1][:2] == (2, 3)) self.assertTrue(np.all(testBonds[0][2] == (-1, 0, 0))) self.assertAlmostEqual(testBonds[0][3], 2*testBonds[1][3]) # Also test coordination histogram coord_hist = CoordinationHistogram.get(a) # Testing some qualities of the Alanine crystal... self.assertTrue(coord_hist['H']['C'][1], 16) # 16 H bonded to a C self.assertTrue(coord_hist['H']['N'][1], 12) # 12 H bonded to a N self.assertTrue(coord_hist['C']['H'][3], 4) # 4 CH3 groups self.assertTrue(coord_hist['C']['O'][2], 4) # 4 COO groups # Test molecules mols = Molecules.get(a) self.assertTrue(MoleculeNumber.get(a) == 4) self.assertTrue(np.isclose(MoleculeMass.get(a), 89.09408).all()) self.assertTrue(len(MoleculeCOMLinkage.get(a)) == 6) # Spectral sorting elems = np.array(a.get_chemical_symbols()) mol_specsort = MoleculeSpectralSort.get(a) for i in range(len(mols)-1): for j in range(i+1,len(mols)): self.assertTrue((elems[mol_specsort[i].indices] == elems[mol_specsort[j].indices]).all()) # Now testing hydrogen bonds hbs = HydrogenBonds.get(a) hbn = HydrogenBondsNumber.get(a) self.assertTrue(hbn['NH..O'] == 12) self.assertTrue(hbn['OH..O'] == 0)
def additionGen(struct, add, to_addition=None, n=1, add_r=1.2, accept=None): """Generator function to create multiple structures with an atom of a given element added in the existing cell. The atoms will be attached to the atoms passed in the to_addition selection. If none is passed, all atoms will be additioned in turn. Multiple defects can be included, in which case all permutations will be generated. The algorithm will try adding the atom in the direction that seems most compatible with all the already existing bonds. If multiple directions satisfy the condition, they will all be tested. It is also possible to reject some configurations based on the output of a filter function. | Args: | struct (ase.Atoms): the starting structure. All atoms will be added | to it. | add (str): element symbol of the atom to add. | to_replace (AtomSelection): if present, only atoms belonging to this | selection will be substituted. | n (int): number of new atoms to include in each structure. Default | is 1. | add_r (float): distance, in Angstroms, at which to add the atoms. | Default is 1.2 Ang | accept (function): a function that determines whether a generated | structure should be accepted or rejected. Takes as | input the generated structure and a tuple of | the indices of the atoms to which the new atoms | were added, and must return a bool. The newly added | atoms will always be the last n of the structure. | If False, the structure will be rejected. | Returns: | defectGenerator (generator): an iterator object that yields | structures with all possible additions. """ if to_addition is None: to_addition = AtomSelection.all(struct) # Compute bonds bonds = Bonds.get(struct) cell = struct.get_cell() pos = struct.get_positions() # Separate bonds by atoms atom_bonds = [[] if i in to_addition.indices else None for i in range(len(struct))] for b in bonds: v = pos[b[1]] - pos[b[0]] + np.dot(b[2], cell) try: atom_bonds[b[0]].append(v.copy()) except AttributeError: pass try: atom_bonds[b[1]].append(-v.copy()) except AttributeError: pass # Compute possible attachment points for each atom attach_v = [None] * len(struct) for i, bset in enumerate(atom_bonds): if bset is None: continue if len(bset) == 0: rndv = np.random.random((1, 3)) - 0.5 rndv /= np.linalg.norm(rndv, axis=1)[:, None] attach_v[i] = rndv else: attach_v[i] = utils.rep_alg(bset) attach_v = np.array(attach_v) addconfs = itertools.combinations(to_addition.indices, n) for ac in addconfs: addpos = itertools.product(*attach_v[list(ac)]) for ap in addpos: astruct = struct.copy() astruct += Atoms(add * n, positions=pos[list(ac)] + np.array(ap) * add_r) if accept is not None: if not accept(astruct, ac): continue yield astruct