Пример #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 bondDistance(s, i, j, bond_matrix=None):
    """
    Return the distance in number of bonds between two atoms. Returns -1 if
    the two atoms are not connected. Requires NetworkX to be installed to
    work.

    | Parameters:
    |   s (ase.Atoms): the structure on which to compute the distance
    |   i (int): index of the first atom
    |   j (int): index of the second atom
    |   bond_matrix (np.ndarray): pre-computed bond matrix to use. If not
    |                             provided, will be calculated with default
    |                             parameters

    | Returns:
    |   r (int): computed bond distance
    """

    if bond_matrix is None:
        bprop = Bonds(return_matrix=True)
        _, bond_matrix = bprop(s)

    graph = get_bonding_graph(bond_matrix)
    r = get_bonding_distance(graph, i, j)

    return r
Пример #3
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)
Пример #4
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
Пример #5
0
def __main__():

    parser = ap.ArgumentParser(description="""
        Processes .magres files containing chemical groups of the form XH3
        (by default, CH3 and NH3), to average the required NMR tensors for the
        hydrogen atoms connected to such groups.
        """)
    # Main argument
    parser.add_argument('input_files',
                        type=str,
                        nargs='+',
                        default=None,
                        help="Magres files on which to carry out averages")
    # Optional arguments
    parser.add_argument('-X',
                        type=str,
                        nargs='+',
                        default=['C', 'N'],
                        help="Nuclei to consider for XH3 groups "
                        "(default: C and N)")
    parser.add_argument('-vdws',
                        type=float,
                        default=1.0,
                        help="Van der Waals radius scale for bond calculation."
                        " Increase for higher tolerance")
    parser.add_argument('-avg',
                        type=str,
                        nargs='+',
                        default=['ms', 'efg'],
                        help="Arrays to average over XH3 groups "
                        "(default: ms and efg)")
    parser.add_argument('-prefix',
                        type=str,
                        default='avg',
                        help="Prefix added to output files")

    args = parser.parse_args()

    bcalc = Bonds(vdw_scale=args.vdws, return_matrix=True)

    for f in args.input_files:
        try:
            a = io.read(f)
        except IOError:
            print('File {0} not found, skipping'.format(f))
            continue

        # Do they have magres data?
        if not any([a.has(k) for k in args.avg]):
            print('File {0} has no data to average, skipping'.format(f))
            continue

        # Find what to average
        bonds, bmat = bcalc(a)

        # Find XH3 groups
        symbs = np.array(a.get_chemical_symbols())
        hinds = np.where(symbs == 'H')[0]
        h3groups = []

        for xsymb in args.X:

            xinds = np.where(symbs == xsymb)[0]
            xinds = xinds[np.where(np.sum(bmat[xinds][:,
                                                      hinds], axis=1) == 3)[0]]
            if len(xinds) > 0:
                h3groups.append(np.where(bmat[xinds][:, hinds] == 1)[1])

        # Now average
        avg_a = a.copy()

        for k in args.avg:
            arr = a.get_array(k)
            for h3 in h3groups:
                arr[h3] = np.average(arr[h3], axis=0)
            avg_a.set_array(k, arr)

        io.write('{0}_{1}'.format(args.prefix, f), avg_a)