Пример #1
0
    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
Пример #2
0
    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)
Пример #3
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