Esempio n. 1
0
def getOctBondDistances(mol):
    ## This function gets
    ## ax and equitorial
    ## min and max bond lengths
    liglist, ligdents, ligcons = ligand_breakdown(mol)
    ax_ligand_list, eq_ligand_list, ax_natoms_list, eq_natoms_list, ax_con_int_list, eq_con_int_list, ax_con_list, eq_con_list, built_ligand_list = ligand_assign_consistent(
        mol, liglist, ligdents, ligcons, False, False)
    ax_dist = list()
    eq_dist = list()
    for ax_ligs in ax_con_list:
        tempList = list()
        for conatms in ax_ligs:
            tempList.append(
                distance(
                    mol.getAtom(mol.findMetal()[0]).coords(),
                    mol.getAtom(conatms).coords()))
        ax_dist.append(tempList)
    for eq_ligs in eq_con_list:
        tempList = list()
        for conatms in eq_ligs:
            tempList.append(
                distance(
                    mol.getAtom(mol.findMetal()[0]).coords(),
                    mol.getAtom(conatms).coords()))
        eq_dist.append(tempList)
    return ax_dist, eq_dist
Esempio n. 2
0
def normalize_vector(v):
    length = distance(v, [0, 0, 0])
    if length:
        nv = [float(i)/length for i in v]
    else:
        nv = [0, 0, 0]
    return nv
Esempio n. 3
0
def DistErr(x, *args):
    """Computes distance error function for scipy optimization. 
    Copied from E3 in pp. 311 of ref. [1]
        
    Parameters
    ----------
        x : np.array
            1D array of coordinates to be optimized.
        *args : dict
            Other parameters (refer to scipy.optimize docs)
        
    Returns
    -------
        E : np.array
            Objective function

    """
    E = 0
    LB, UB, natoms = args
    for i in range(natoms - 1):
        for j in range(i + 1, natoms):
            ri = [x[3 * i], x[3 * i + 1], x[3 * i + 2]]
            rj = [x[3 * j], x[3 * j + 1], x[3 * j + 2]]
            dij = distance(ri, rj)
            uij = UB[i][j]
            lij = LB[i][j]
            E += (dij**2 / (uij**2) - 1)**2
            E += (2 * lij**2 / (lij**2 + dij**2) - 1)**2
    return np.asarray(E)
Esempio n. 4
0
def minimum_ML_dist(mol):
    core = mol.getAtom(mol.findMetal()[0]).coords()
    min_dist = 1000
    for atom_inds in mol.getBondedAtomsSmart(mol.findMetal()[0]):
        dist = distance(core, mol.getAtom(atom_inds).coords())
        if (dist < min_dist) and (dist > 0):
            min_dist = dist
    return min_dist
Esempio n. 5
0
def maximum_any_dist(mol):
    core = mol.getAtom(mol.findMetal()[0])
    max_dist = 0
    for atoms in mol.getAtoms():
        dist = distance(core.coords(), atoms.coords())
        if (dist > max_dist):
            max_dist = dist
    return max_dist
Esempio n. 6
0
def maximum_ML_dist(mol):
    core = mol.getAtom(mol.findMetal()[0]).coords()
    max_dist = 0
    for atom_inds in mol.getBondedAtomsSmart(mol.findMetal()[0]):
        dist = distance(core, mol.getAtom(atom_inds).coords())
        if (dist > max_dist):
            max_dist = dist
    return max_dist
Esempio n. 7
0
def mean_ML_dist(mol):
    core = mol.getAtom(mol.findMetal()[0]).coords()
    mean_dist = 0.0
    for atom_inds in mol.getBondedAtomsSmart(mol.findMetal()[0]):
        dist = distance(core, mol.getAtom(atom_inds).coords())
        mean_dist += float(dist)
    mean_dist = mean_dist / float(len(mol.getBondedAtomsSmart(mol.findMetal()[0])))
    return mean_dist
Esempio n. 8
0
def periodic_mindist(mol, surf, dim):
    ### calculates minimum distance between atoms in 2 molecules ###
    # INPUT
    #   - mol: mol3D class,  molecule
    #   - surf: mol3D class, the surface
    #   - dim: list of float, replication
    # OUTPUT
    #   - mind: minimum distance between atoms of the 2 mol objects
    mind = 1000
    for atom1 in mol.getAtoms():
        for atom0 in surf.getAtoms():
            if (distance_2d_torus(atom1.coords(), atom0.coords(), dim) < mind):
                mind = distance(atom1.coords(), atom0.coords())
    return mind
Esempio n. 9
0
def periodic_selfdist(mol, dim):
    ### calculates minimum distance between atoms in 2 molecules ##
    # INPUT
    #   - mol: mol3D class,  molecule
    #   - dim: list of floats, replication
    # OUTPUT
    #   - mind: minimum distance between atoms of the 2 mol and periodic
    #             images
    mind = 1000
    for ii, atom1 in enumerate(mol.getAtoms()):
        for jj, atom0 in enumerate(mol.getAtoms()):
            if (distance_2d_torus(atom1.coords(), atom0.coords(), dim) < mind) and (ii != jj):
                mind = distance(atom1.coords(), atom0.coords())
    return mind
Esempio n. 10
0
def substplacecheap(core, connPts, catom):
    corerem = mol3D()
    corerem.copymol3D(core)
    corerem.deleteatom(catom)  # complex less O atom
    mdist = -1
    cpoint = [0, 0, 0]
    for P in connPts:
        if corerem.mindisttopoint(P) < 1:  # auto-reject if too close
            d0 = -2
        else:
            d0 = distance(core.centermass(), P)+0.5 * \
                log(corerem.mindisttopoint(P)-1)
        if d0 > mdist:
            mdist = d0
            cpoint = P
    return cpoint
Esempio n. 11
0
def fdistance(xyzf):
    # setting properties
    xyz = mol3D()
    xyz.readfromxyz(xyzf)
    # getting idxs of interest
    midx = xyz.findMetal()[0]  # monometallic complexes
    mcoord = xyz.getAtom(midx).coords()
    # list of idx of the first-coord sphere
    fidx_list = xyz.getBondedAtoms(midx)
    fdistance_list = []
    for idx in fidx_list:
        fcoord = xyz.getAtom(idx).coords()
        d = distance(mcoord, fcoord)
        fdistance_list.append(float(d))

    return fdistance_list
Esempio n. 12
0
def DistErrGrad(x, *args):
    """Computes gradient of distance error function for scipy optimization.
    Copied from E3 in pp. 311 of ref. [1]
        
    Parameters
    ----------
        x : np.array
            1D array of coordinates to be optimized.
        *args : dict
            Other parameters (refer to scipy.optimize docs)
        
    Returns
    -------
        g : np.array
            Objective function gradient

    """
    LB, UB, natoms = args
    g = np.zeros(3 * natoms)
    for i in range(natoms):
        jr = list(range(natoms))
        jr.remove(i)
        for j in jr:
            ri = [x[3 * i], x[3 * i + 1], x[3 * i + 2]]
            rj = [x[3 * j], x[3 * j + 1], x[3 * j + 2]]
            dij = distance(ri, rj)
            uij = UB[i][j]
            lij = LB[i][j]
            g[3 * i] += (4 * ((dij / uij)**2 - 1) / (uij**2) - (8 / lij**2) *
                         (2 * (lij**2 / (lij**2 + dij**2)) - 1) /
                         ((1 +
                           (dij / lij)**2)**2)) * (x[3 * i] - x[3 * j])  # xi
            g[3 * i +
              1] += (4 * ((dij / uij)**2 - 1) / (uij**2) - (8 / lij**2) *
                     (2 * (lij**2 / (lij**2 + dij**2)) - 1) /
                     ((1 + (dij / lij)**2)**2)) * (x[3 * i + 1] - x[3 * j + 1]
                                                   )  # yi
            g[3 * i +
              2] += (4 * ((dij / uij)**2 - 1) / (uij**2) - (8 / lij**2) *
                     (2 * (lij**2 / (lij**2 + dij**2)) - 1) /
                     ((1 + (dij / lij)**2)**2)) * (x[3 * i + 2] - x[3 * j + 2]
                                                   )  # zi
    return g
def autocorrelation(mol, prop_vec, orig, d, oct=True, catoms=None, use_dist=False):
    ## this function returns the autocorrelation
    ## for one atom
    # Inputs:
    #	mol - mol3D class
    #	prop_vec - vector, property of atoms in mol in order of index
    #	orig -  int, zero-indexed starting atom
    #	d - int, number of hops to travel
    #	oct - bool, if complex is octahedral, will use better bond checks
    result_vector = np.zeros(d + 1)
    hopped = 0
    active_set = set([orig])
    historical_set = set()
    if not use_dist:
        result_vector[hopped] = prop_vec[orig] * prop_vec[orig]
    else:
        result_vector[hopped] = 0.5 * abs(prop_vec[orig]) ** 2.4 / mol.natoms
    while hopped < (d):

        hopped += 1
        new_active_set = set()
        for this_atom in active_set:
            ## prepare all atoms attached to this connection
            # print('called in AC')
            this_atoms_neighbors = mol.getBondedAtomsSmart(this_atom, oct=oct)
            for bound_atoms in this_atoms_neighbors:
                if (bound_atoms not in historical_set) and (bound_atoms not in active_set):
                    new_active_set.add(bound_atoms)
        # print('new active set at hop = ' +str(hopped) + ' is ' +str(new_active_set))
        for inds in new_active_set:
            if not use_dist:
                result_vector[hopped] += prop_vec[orig] * prop_vec[inds]
            else:
                this_dist = distance(mol.getAtom(orig).coords(), mol.getAtom(inds).coords())
                result_vector[hopped] += prop_vec[orig] * prop_vec[inds] / (this_dist * mol.natoms)
            historical_set.update(active_set)
        active_set = new_active_set
    return (result_vector)
Esempio n. 14
0
def create_columb_matrix(mol):
    ## create Coulomb matrix from mol3D information
    index_set = list(range(0, mol.natoms))
    ## fetch the database of nuclear charges
    globs = globalvars()
    amassdict = globs.amass()
    A = numpy.matrix(numpy.zeros((mol.natoms, mol.natoms)))
    ## main build
    for i in index_set:
        for j in index_set:
            if i == j:
                A[i, j] = 0.5 * numpy.power(
                    float(amassdict[mol.getAtom(i).symbol()][1]), (2.4))
            else:
                this_dist = distance(
                    mol.getAtom(i).coords(),
                    mol.getAtom(j).coords())
                if this_dist != 0.0:
                    A[i, j] = float(
                        amassdict[mol.getAtom(i).symbol()][1]) * float(
                            amassdict[mol.getAtom(j).symbol()][1]) / float(
                                this_dist)
                else:
                    A[i, j] = 0
    ## sort by columns in increasing order
    weights = []
    for col in A.T:
        weights.append(numpy.linalg.norm(col))
    sort_weights = (numpy.argsort(weights))[::-1]
    A = A[:, sort_weights]
    ## sort by rows in increasing order
    weights = []
    for row in A:
        weights.append(numpy.linalg.norm(row))
    sort_weights = (numpy.argsort(weights))[::-1]
    A = A[sort_weights, :]
    return A
Esempio n. 15
0
def fpriority(mol):
    # setting up variables
    fidx_list = []
    sidx_list = []
    satno_list = []
    ref_list = []
    fd_list = []
    fa_list = []
    idx_list = [0] * 6
    exit_signal = True
    # getting bond-order matrix
    mol.convert2OBMol()
    BOMatrix = mol.populateBOMatrix()

    # preping for the loop
    fidx_list.append(mol.findMetal())
    for i in range(len(fidx_list)):
        for fidx in fidx_list[i]:
            for sidx in mol.getBondedAtoms(fidx):
                sidx_list.append([sidx])

    for i in range(len(fidx_list)):
        for fidx in fidx_list[i]:
            for j in range(len(sidx_list)):
                for sidx in sidx_list[j]:
                    BO = int(BOMatrix[fidx][sidx])
                    if BO == 0:
                        BO = 1
                    satno_str = str(mol.getAtom(sidx).atno)
                    satno_list.append(int(BO * satno_str))

    for satno in set(satno_list):
        satnocount = satno_list.count(satno)
        if satnocount > 1:
            s_sel_list = [
                i for i, atno in enumerate(satno_list) if atno is satno
            ]
            exit_signal = False

    for i in range(len(fidx_list)):
        for fidx in fidx_list[i]:
            ref_list.append(fidx)

    # starting the loop
    tidx_list = []
    tatno_list = []
    for i in range(len(sidx_list)):
        tidx_list.append([])
        tatno_list.append([])

    while not exit_signal:
        fpriority_list = []
        for i in s_sel_list:
            t_list = []
            for sidx in sidx_list[i]:
                for tidx in mol.getBondedAtoms(sidx):
                    if tidx not in ref_list:
                        t_list.append(tidx)
            tidx_list[i] = t_list
        # print(sidx_list)
        # print(tidx_list)
        for i in s_sel_list:
            for sidx in sidx_list[i]:
                atno_list = tatno_list[i]
                ls = []
                for j in s_sel_list:
                    for tidx in tidx_list[j]:
                        BO = int(BOMatrix[sidx][tidx])
                        tatno_str = str(mol.getAtom(tidx).atno)
                        ls.append(BO * tatno_str)
                sorted(ls, reverse=True)
                for j in ls:
                    atno_list.append(j)
                a = ''.join(atno_list)
            tatno_list[i] = [a]
        sidx_list = []
        for i in range(len(tidx_list)):
            sidx_list.append(tidx_list[i])
        for i in s_sel_list:
            for sidx in sidx_list[i]:
                ref_list.append(sidx)
        test_list = []
        for i in range(len(sidx_list)):
            test_list.append([])
        # get priorities
        for i in range(len(satno_list)):
            atno_list = []
            atno_list.append(str(satno_list[i]))
            if tatno_list[i] == []:
                atno_list.append('')
            else:
                atno_list.append(tatno_list[i][0])
            a = '.'.join(atno_list)
            fpriority_list.append(float(a))
        if tidx_list == test_list or len(set(fpriority_list)) == 6:
            exit_signal = True
    # get distance
    fd_list = []
    mcoord = mol.atoms[mol.findMetal()[0]].coords()
    idx_list = np.argsort(np.array(fpriority_list))
    fpriority_list = np.array(fpriority_list)[idx_list].tolist()
    sidx_list = mol.getBondedAtoms(fidx_list[0][0])
    for idx in idx_list:
        scoord = mol.getAtom(sidx_list[idx]).coords()
        r = distance(mcoord, scoord)
        fd_list.append(r)

    # idx = np.argsort(np.array(fpriority_list))[-1]
    # sidx_list = mol.getBondedAtomsByCoordNo(fidx_list[0][0],6)
    # refcoord = mol.getAtom(sidx_list[idx]).coords()
    # mcoord = mol.getAtom(fidx_list[0][0]).coords()
    # idx0 = 0
    # dist5 = 0
    # idx5 = 0
    # idx1_4 = []
    # fprio1_4 = []
    # sxyzs = []
    # ssd_list = []
    # for i, sidx in enumerate(sidx_list):
    #     sxyz = mol.getAtom(sidx).coords()
    #     dist = distance(refcoord,sxyz)
    #     if dist == 0:
    #         idx0 = i
    #     elif dist > dist5:
    #         dist5 = dist
    #         idx5 = i
    #     idx1_4.append(i)
    #     fprio1_4.append(fpriority_list[i])
    #     sxyzs.append(sxyz)
    #     ssd_list.append(dist)
    #     fd_list.append(distance(mcoord,sxyz))
    # idx1_4.pop(idx0)
    # idx1_4.pop(idx5)
    # fprio1_4.pop(idx0)
    # fprio1_4.pop(idx5)
    # idx_list[0] = idx0
    # idx_list[5] = idx5
    # idx1 = idx1_4[np.argsort(np.array(fprio1_4))[3]]
    # sxyz1 = sxyzs[idx1]
    # idx2_ = idx1_4[np.argsort(np.array(fprio1_4))[2]]
    # sxyz2_ = sxyzs[idx2_]
    # idx3_ = idx1_4[np.argsort(np.array(fprio1_4))[1]]
    # sxyz3_ = sxyzs[idx3_]
    # idx4_ = idx1_4[np.argsort(np.array(fprio1_4))[0]]
    # sxyz4_ = sxyzs[idx4_]
    # fd1_4 = []
    # fd1_4.append(distance(sxyz1, sxyz1))
    # fd1_4.append(distance(sxyz1, sxyz2_))
    # fd1_4.append(distance(sxyz1, sxyz3_))
    # fd1_4.append(distance(sxyz1, sxyz4_))
    # idx3 = idx1_4[np.argsort(np.array(fd1_4))[-1]] + idx1 - 4
    # if idx3 == idx2_:
    #     if fpriority_list[idx3_] > fpriority_list[idx4_]:
    #         idx2 = idx3_
    #         idx4 = idx4_
    #     else:
    #         idx2 = idx4_
    #         idx4 = idx2_
    # elif idx3 == idx4_:
    #     if fpriority_list[idx2_] > fpriority_list[idx3_]:
    #         idx2 = idx2_
    #         idx4 = idx3_
    #     else:
    #         idx2 = idx3_
    #         idx4 = idx2_
    # else:
    #     if fpriority_list[idx2_] > fpriority_list[idx4_]:
    #         idx2 = idx2_
    #         idx4 = idx4_
    #     else:
    #         idx2 = idx4_
    #         idx4 = idx2_
    # # get ax, eq, ax idxes
    # idx_list[1] = idx1
    # idx_list[2] = idx2
    # idx_list[3] = idx3
    # idx_list[4] = idx4
    # fpriority_list = np.array(fpriority_list)[idx_list].tolist()
    # fd_list = np.array(fd_list)[idx_list].tolist()

    return fpriority_list, fd_list, idx_list
Esempio n. 16
0
def decorate_ligand(args, ligand_to_decorate, decoration, decoration_index):
    # structgen depends on decoration_manager, and decoration_manager depends on structgen.ffopt
    # Thus, this import needs to be placed here to avoid a circular dependence
    from molSimplify.Scripts.structgen import ffopt
    # INPUT
    #   - args: placeholder for input arguments
    #   - ligand_to_decorate: mol3D ligand
    #   - decoration: list of smiles/decorations
    #   - decoration_index: list of ligand atoms to replace
    # OUTPUT
    #   - new_ligand: built ligand
    #   - complex3D: list of all mol3D ligands and core
    #   - emsg: error messages
    #if args.debug:
    #    print  'decorating ligand'
    lig = ligand_to_decorate
    ## reorder to ensure highest atom index
    ## removed first
    sort_order = [
        i[0] for i in sorted(enumerate(decoration_index), key=lambda x: x[1])
    ]
    sort_order = sort_order[::-1]  ## reverse

    decoration_index = [decoration_index[i] for i in sort_order]
    decoration = [decoration[i] for i in sort_order]
    if args.debug:
        print(('decoration_index  is  ' + str(decoration_index)))
    licores = getlicores()
    if not isinstance(lig, mol3D):
        lig, emsg = lig_load(lig, licores)
    else:
        lig.convert2OBMol()
        lig.charge = lig.OBMol.GetTotalCharge()
    lig.convert2mol3D()  # convert to mol3D

    ## create new ligand
    merged_ligand = mol3D()
    merged_ligand.copymol3D(lig)
    for i, dec in enumerate(decoration):
        print(('** decoration number ' + str(i) + ' attaching ' + dec +
               ' at site ' + str(decoration_index[i]) + '**\n'))
        dec, emsg = lig_load(dec, licores)
        # dec.OBMol.AddHydrogens()
        dec.convert2mol3D()  # convert to mol3D
        if args.debug:
            print(i)
            print(decoration_index)

            print((merged_ligand.getAtom(decoration_index[i]).symbol()))
            print((merged_ligand.getAtom(decoration_index[i]).coords()))
            merged_ligand.writexyz('basic.xyz')
        #dec.writexyz('dec' + str(i) + '.xyz')
        Hs = dec.getHsbyIndex(0)
        if len(Hs) > 0 and (not len(dec.cat)):
            dec.deleteatom(Hs[0])
            dec.charge = dec.charge - 1

        #dec.writexyz('dec_noH' + str(i) + '.xyz')
        if len(dec.cat) > 0:
            decind = dec.cat[0]
        else:
            decind = 0
        dec.alignmol(dec.getAtom(decind),
                     merged_ligand.getAtom(decoration_index[i]))
        r1 = dec.getAtom(decind).coords()
        r2 = dec.centermass()  # center of mass
        rrot = r1
        decb = mol3D()
        decb.copymol3D(dec)
        ####################################
        # center of mass of local environment (to avoid bad placement of bulky ligands)
        auxmol = mol3D()
        for at in dec.getBondedAtoms(decind):
            auxmol.addAtom(dec.getAtom(at))
        if auxmol.natoms > 0:
            r2 = auxmol.centermass()  # overwrite global with local centermass
            ####################################
            # rotate around axis and get both images
            theta, u = rotation_params(merged_ligand.centermass(), r1, r2)
            #print('u = ' + str(u) + ' theta  = ' + str(theta))
            dec = rotate_around_axis(dec, rrot, u, theta)
            if args.debug:
                dec.writexyz('dec_ARA' + str(i) + '.xyz')
            decb = rotate_around_axis(decb, rrot, u, theta - 180)
            if args.debug:
                decb.writexyz('dec_ARB' + str(i) + '.xyz')
            d1 = distance(dec.centermass(), merged_ligand.centermass())
            d2 = distance(decb.centermass(), merged_ligand.centermass())
            dec = dec if (d2 < d1) else decb  # pick best one
        #####################################
        # check for linear molecule
        auxm = mol3D()
        for at in dec.getBondedAtoms(decind):
            auxm.addAtom(dec.getAtom(at))
        if auxm.natoms > 1:
            r0 = dec.getAtom(decind).coords()
            r1 = auxm.getAtom(0).coords()
            r2 = auxm.getAtom(1).coords()
            if checkcolinear(r1, r0, r2):
                theta, urot = rotation_params(
                    r1,
                    merged_ligand.getAtom(decoration_index[i]).coords(), r2)
                theta = vecangle(
                    vecdiff(
                        r0,
                        merged_ligand.getAtom(decoration_index[i]).coords()),
                    urot)
                dec = rotate_around_axis(dec, r0, urot, theta)

        ## get the default distance between atoms in question
        connection_neighbours = merged_ligand.getAtom(
            merged_ligand.getBondedAtomsnotH(decoration_index[i])[0])
        new_atom = dec.getAtom(decind)
        target_distance = connection_neighbours.rad + new_atom.rad
        position_to_place = vecdiff(new_atom.coords(),
                                    connection_neighbours.coords())
        old_dist = norm(position_to_place)
        missing = (target_distance - old_dist) / 2
        dec.translate([missing * position_to_place[j] for j in [0, 1, 2]])

        r1 = dec.getAtom(decind).coords()
        u = vecdiff(r1, merged_ligand.getAtom(decoration_index[i]).coords())
        dtheta = 2
        optmax = -9999
        totiters = 0
        decb = mol3D()
        decb.copymol3D(dec)
        # check for minimum distance between atoms and center of mass distance
        while totiters < 180:
            #print('totiters '+ str(totiters))
            dec = rotate_around_axis(dec, r1, u, dtheta)
            d0 = dec.mindist(
                merged_ligand)  # try to maximize minimum atoms distance
            d0cm = dec.distance(
                merged_ligand)  # try to maximize center of mass distance
            iteropt = d0cm + d0  # optimization function
            if (iteropt > optmax):  # if better conformation, keep
                decb = mol3D()
                decb.copymol3D(dec)
                optmax = iteropt
                #temp = mol3D()
                #temp.copymol3D(merged_ligand)
                #temp.combine(decb)
                #temp.writexyz('opt_iter_'+str(totiters)+'.xyz')
                #print('new max! ' + str(iteropt) )
            totiters += 1
        dec = decb
        if args.debug:
            dec.writexyz('dec_aligned' + str(i) + '.xyz')
            print(('natoms before delete ' + str(merged_ligand.natoms)))
            print(('obmol before delete at  ' + str(decoration_index[i]) +
                   ' is ' + str(merged_ligand.OBMol.NumAtoms())))
        ## store connectivity for deleted H
        BO_mat = merged_ligand.populateBOMatrix()
        row_deleted = BO_mat[decoration_index[i]]
        bonds_to_add = []

        # find where to put the new bonds ->>> Issue here.
        for j, els in enumerate(row_deleted):
            if els > 0:
                # if there is a bond with an atom number
                # before the deleted atom, all is fine
                # else, we subtract one as the row will be be removed
                if j < decoration_index[i]:
                    bond_partner = j
                else:
                    bond_partner = j - 1
                if len(dec.cat) > 0:
                    bonds_to_add.append(
                        (bond_partner, (merged_ligand.natoms - 1) + dec.cat[0],
                         els))
                else:
                    bonds_to_add.append(
                        (bond_partner, merged_ligand.natoms - 1, els))

        ## perfrom delete
        merged_ligand.deleteatom(decoration_index[i])

        merged_ligand.convert2OBMol()
        if args.debug:
            merged_ligand.writexyz('merged del ' + str(i) + '.xyz')
        ## merge and bond
        merged_ligand.combine(dec, bond_to_add=bonds_to_add)
        merged_ligand.convert2OBMol()

        if args.debug:
            merged_ligand.writexyz('merged' + str(i) + '.xyz')
            merged_ligand.printxyz()
            print('************')

    merged_ligand.convert2OBMol()
    merged_ligand, emsg = ffopt('MMFF94', merged_ligand, [], 0, [], False, [],
                                100)
    BO_mat = merged_ligand.populateBOMatrix()
    if args.debug:
        merged_ligand.writexyz('merged_relaxed.xyz')
        print(BO_mat)
    return (merged_ligand)
Esempio n. 17
0
def tsgen(mode, args, rootdir, core, substr, compreact, substreact, globs):
    emsg = False
    this_diag = run_diag()
    strfiles = []
    adjsidx = substr.getBondedAtoms(substreact)[0]
    adjcidx = core.getBondedAtoms(compreact)[0]
    # initialize connecting and frozen atoms for FF opt
    frozenats = []
    for i in range(0, core.natoms):
        frozenats.append(i)
    # also freeze the abstracted atom and the heavy atom bonded to it
    frozenats.append(core.natoms+substreact)
    frozenats.append(core.natoms+adjsidx)
    connected = [core.natoms+substreact]
    # START FUNCTIONALIZING
    sanity = False
    if mode == 2:
        emsg = 'Sorry, this mode is not supported yet. Exiting...'
        return strfiles, emsg, this_diag
    elif mode == 1:  # oxidative addition of a single group
                # get first connecting point
        MXBL = MXdistcoeff*(core.getAtom(compreact).rad +
                            substr.getAtom(substreact).rad)
        cpoint = getconnection(core, compreact, MXBL)
        # distort substrate molecule
        XYBL = XYcoeff*(substr.getAtom(substreact).rad +
                        substr.getAtom(adjsidx).rad)
        substr.BCM(adjsidx, substreact, XYBL)
        # align substrate molecule
        substr.alignmol(substr.getAtom(substreact), atom3D('H', cpoint))
        tmp3D = mol3D()
        tmp3D.copymol3D(core)
        tmp3D.addAtom(atom3D('Cl', cpoint))
        ligalignpts = getconnections(
            tmp3D, tmp3D.natoms-1, compreact, XYBL, MXYang)
        if args.substplaceff:
            # full FF substrate placement
            print('Full FF-based substrate placement specified.')
            en_min = 1e6
            for n, P in enumerate(ligalignpts):
                print(('Evaluating FF energy of point ' +
                       str(n+1)+' of '+str(len(ligalignpts))))
                coretmp = mol3D()
                coretmp.copymol3D(core)
                substrtmp = mol3D()
                substrtmp.copymol3D(substr)
                ts3Dtmp, enc = substplaceff_mode1(
                    coretmp, substrtmp, substreact, compreact, cpoint, P, args, connected, frozenats)
                if enc < en_min:
                    en_min = enc
                    ts3D = mol3D()
                    ts3D.copymol3D(ts3Dtmp)
        else:
            # cheap substrate placement
            print('Cheap substrate placement')
            ligalignpt = substplacecheap(core, ligalignpts, compreact)
            ts3D, enc = substplaceff_mode1(
                core, substr, substreact, compreact, cpoint, ligalignpt, args, connected, frozenats)
    elif mode == 3:  # abstraction
        # distort A-B bond
        ABBL = distance(core.getAtomCoords(compreact), core.getAtomCoords(
            adjcidx)) + 0.05*(core.getAtom(compreact).rad + core.getAtom(adjcidx).rad)
        core.BCM(compreact, adjcidx, ABBL)
        # set B-X distance
        BXBL = 1.1*(substr.getAtom(substreact).rad +
                    core.getAtom(compreact).rad)
        # get possible connecting points
        connPts = getconnections(core, compreact, adjcidx, BXBL, ABXang)
        if args.substplaceff:
            # full FF substrate placement
            print('Full FF-based substrate placement specified.')
            en_min = 1e6
            for n, P in enumerate(connPts):
                print(('Evaluating FF energy of point ' +
                       str(n+1)+' of '+str(len(connPts))))
                coretmp = mol3D()
                coretmp.copymol3D(core)
                substrtmp = mol3D()
                substrtmp.copymol3D(substr)
                ts3Dtmp, enc = substplaceff_mode3(
                    coretmp, substrtmp, substreact, compreact, P, args, connected, frozenats)
                if enc < en_min:
                    en_min = enc
                    ts3D = mol3D()
                    ts3D.copymol3D(ts3Dtmp)
        else:
            # cheap substrate placement
            print('Cheap substrate placement')
            cpoint = substplacecheap(core, connPts, compreact)
            ts3D, enc = substplaceff_mode3(
                core, substr, substreact, compreact, cpoint, args, connected, frozenats)
            if 'a' in args.ffoption:
                print('FF optimized remainder of substrate')
    ts3D.charge += substr.charge
    # END FUNCTIONALIZING
    fname = name_TS(rootdir, args.core, substr, args,
                    bind=args.bind, bsmi=args.nambsmi)
    ts3D.writexyz(fname)
    strfiles.append(fname)
    getinputargs(args, fname)
    pfold = rootdir.split('/', 1)[-1]
    # check for molecule sanity
    sanity, d0 = ts3D.sanitycheck(True)
    if args.debug:
        print(('setting sanity diag, min dist at ' +
               str(d0) + ' (higher is better)'))
    this_diag.set_sanity(sanity, d0)
    this_diag.set_mol(ts3D)
    this_diag.write_report(fname+'.report')
    del ts3D
    if sanity:
        print(('WARNING: Generated complex is not good! Minimum distance between atoms:' +
              "{0:.2f}".format(d0)+'A\n'))
    print(('\nIn folder '+pfold+' generated 1 structure(s)!'))
    return strfiles, emsg, this_diag
Esempio n. 18
0
def GetBoundsMatrices(mol, natoms, catoms=[], shape=[], A=[]):
    """Generate distance bounds matrices. The basic idea is outlined in ref [1].
    We first apply 1-2 (bond length) and 1-3 (bond angle) constraints, read from the FF-optimized initial conformer.
    Next, to bias the search towards coordinating conformers, approximate connection atom distance constraints based 
    on topological distances are also included.

    Parameters
    ----------
        mol : mol3D
            mol3D class instance of molecule.
        natoms : int
            Number of atoms in the molecule.
        catoms : list, optional
            List of ligand connection atoms. Default is Empty.
        shape : dict
            Dict containing angles.
        A : list
            List of lists making a distance 2 connectivity matrix.
        
    Returns
    -------
        LB : np.array
            Lower bound matrix.
        UB : np.array
            Upper bound matrix.

    """
    LB = np.zeros((natoms, natoms))  # lower bound
    UB = np.zeros((natoms, natoms))  # upper bound, both symmetric
    # Set constraints for all atoms excluding the dummy metal atom
    for i in range(natoms - 1):
        for j in range(natoms - 1):
            # 1-2 constraints: UB = LB = BL
            if mol.OBMol.GetBond(i + 1, j + 1) is not None:
                UB[i][j] = distance(mol.getAtomCoords(i), mol.getAtomCoords(j))
                UB[j][i] = distance(mol.getAtomCoords(i), mol.getAtomCoords(j))
                LB[i][j] = distance(mol.getAtomCoords(i), mol.getAtomCoords(j))
                LB[j][i] = distance(mol.getAtomCoords(i), mol.getAtomCoords(j))
    for i in range(natoms - 1):
        for j in range(natoms - 1):
            for k in range(natoms - 1):
                # 1-3 constraints: UB = LB = BL
                if mol.OBMol.GetBond(
                        i + 1, j + 1) is not None and mol.OBMol.GetBond(
                            j + 1, k + 1) is not None and j != k and i != k:
                    AB = vecdiff(mol.getAtomCoords(j), mol.getAtomCoords(i))
                    BC = vecdiff(mol.getAtomCoords(k), mol.getAtomCoords(j))
                    UB[i][k] = CosRule(norm(AB), norm(BC),
                                       180 - vecangle(AB, BC))
                    UB[k][i] = CosRule(norm(AB), norm(BC),
                                       180 - vecangle(AB, BC))
                    LB[i][k] = CosRule(norm(AB), norm(BC),
                                       180 - vecangle(AB, BC))
                    LB[k][i] = CosRule(norm(AB), norm(BC),
                                       180 - vecangle(AB, BC))

    # Set constraints for atoms bonded to the dummy metal atom
    # Currently assumes all M-L bonds are 2 Angstroms
    dummy_idx = natoms - 1
    M_L_bond = 2
    for catom in catoms:
        # Set 1-2 constraints
        UB[catom][dummy_idx] = M_L_bond
        UB[dummy_idx][catom] = M_L_bond
        LB[catom][dummy_idx] = M_L_bond
        LB[dummy_idx][catom] = M_L_bond
    if len(catoms) > 1:
        # Set 1-3 contraints for ligating atoms
        for i in range(len(catoms[:-1])):
            for j in range(i + 1, len(catoms)):
                angle = shape[str(i) + '-' + str(j)]
                lig_distance = CosRule(M_L_bond, M_L_bond, angle)
                UB[catoms[i]][catoms[j]] = lig_distance
                UB[catoms[j]][catoms[i]] = lig_distance
                LB[catoms[i]][catoms[j]] = lig_distance
                LB[catoms[j]][catoms[i]] = lig_distance

    expanded_vdwrad = vdwrad.copy()
    expanded_vdwrad[
        'Fe'] = 1.5  # Default vdw radius for the dummy metal is 1.5
    for i in range(natoms):
        for j in range(i):
            # fill LBs with sums of vdW radii and UBs with arbitrary large cutoff
            if LB[i][j] == 0:
                LB[i][j] = expanded_vdwrad[mol.getAtom(
                    i).sym] + expanded_vdwrad[mol.getAtom(j).sym]
                LB[j][i] = expanded_vdwrad[mol.getAtom(
                    i).sym] + expanded_vdwrad[mol.getAtom(j).sym]
                UB[i][j] = 100
                UB[j][i] = 100
    return LB, UB
Esempio n. 19
0
def oct_comp(file_in, angle_ref=oct_angle_ref, catoms_arr=None, debug=False):
    my_mol = create_mol_with_xyz(_file_in=file_in)
    num_coord_metal, catoms = get_num_coord_metal(file_in=file_in)
    # metal_ind = my_mol.findMetal()[0]
    metal_coord = my_mol.getAtomCoords(my_mol.findMetal()[0])
    catom_coord = []
    if not catoms_arr == None:
        catoms = catoms_arr
        num_coord_metal = len(catoms_arr)
    theta_arr, oct_dist = [], []
    for atom in catoms:
        coord = my_mol.getAtomCoords(atom)
        catom_coord.append(coord)
    th_input_arr = []
    for idx1, coord1 in enumerate(catom_coord):
        delr1 = (np.array(coord1) - np.array(metal_coord)).tolist()
        theta_tmp = []
        for idx2, coord2 in enumerate(catom_coord):
            if idx2 != idx1:
                delr2 = (np.array(coord2) - np.array(metal_coord)).tolist()
                theta = vecangle(delr1, delr2)
                theta_tmp.append(theta)
        th_input_arr.append([catoms[idx1], theta_tmp])
    th_output_arr, sum_del_angle, catoms_arr, max_del_sig_angle = loop_target_angle_arr(
        th_input_arr, angle_ref)
    if debug:
        print(('th:', th_output_arr))
        print(('sum_del:', sum_del_angle))
        print(('catoms_arr:', catoms_arr))
        print(
            ('catoms_type:', [my_mol.getAtom(x).symbol() for x in catoms_arr]))
    for idx, ele in enumerate(th_output_arr):
        theta_arr.append([catoms_arr[idx], sum_del_angle[idx], ele])
    # theta_arr.sort(key=sort_sec_ele)
    # theta_trunc_arr = theta_arr[0:6]
    theta_trunc_arr = theta_arr
    # print('truncated theta array:', theta_trunc_arr)
    theta_trunc_arr_T = list(map(list, list(zip(*theta_trunc_arr))))
    oct_catoms = theta_trunc_arr_T[0]
    oct_angle_devi = theta_trunc_arr_T[1]
    oct_angle_all = theta_trunc_arr_T[2]
    if debug:
        print(('Summation of deviation angle for catoms:', oct_angle_devi))
        print(('Angle for catoms:', oct_angle_all))
    for atom in oct_catoms:
        coord = catom_coord[catoms.index(atom)]
        dist = distance(coord, metal_coord)
        oct_dist.append(dist)
    oct_dist.sort()
    # print('!!!oct_dist:', oct_dist)
    try:  # For Oct
        dist_del_arr = np.array([
            oct_dist[3] - oct_dist[0], oct_dist[4] - oct_dist[1],
            oct_dist[5] - oct_dist[2]
        ])
        min_posi = np.argmin(dist_del_arr)
        if min_posi == 0:
            dist_eq, dist_ax = oct_dist[:4], oct_dist[4:]
        elif min_posi == 1:
            dist_eq, dist_ax = oct_dist[1:5], [oct_dist[0], oct_dist[5]]
        else:
            dist_eq, dist_ax = oct_dist[2:], oct_dist[:2]
    except IndexError:  # For one empty site
        if (oct_dist[3] - oct_dist[0]) > (oct_dist[4] - oct_dist[1]):
            dist_ax, dist_eq = oct_dist[:1], oct_dist[1:]  # ax dist is smaller
        else:
            dist_ax, dist_eq = oct_dist[4:], oct_dist[:4]  # eq dist is smaller
    dist_del_all = oct_dist[-1] - oct_dist[0]
    if debug:
        print(('dist:', dist_eq, dist_ax))
    dist_del_eq = max(dist_eq) - min(dist_eq)
    dist_del_ax = max(dist_ax) - min(dist_ax)
    dist_del_eq_ax = max(abs(max(dist_eq) - min(dist_ax)),
                         abs(max(dist_ax) - min(dist_eq)))
    oct_dist_del = [dist_del_eq, dist_del_ax, dist_del_eq_ax, dist_del_all]
    if debug:
        print(('distance difference for catoms to metal (eq, ax, eq_ax):',
               oct_dist_del))
    return oct_angle_devi, oct_dist_del, max_del_sig_angle, catoms_arr
Esempio n. 20
0
def oct_comp(file_in, angle_ref=oct_angle_ref, catoms_arr=None,
             debug=False):
    my_mol = create_mol_with_xyz(_file_in=file_in)
    num_coord_metal, catoms = get_num_coord_metal(file_in=file_in)
    # metal_ind = my_mol.findMetal()[0]
    metal_coord = my_mol.getAtomCoords(my_mol.findMetal()[0])
    catom_coord = []
    if not catoms_arr == None:
        catoms = catoms_arr
        num_coord_metal = len(catoms_arr)
    theta_arr, oct_dist = [], []
    for atom in catoms:
        coord = my_mol.getAtomCoords(atom)
        catom_coord.append(coord)
    th_input_arr = []
    for idx1, coord1 in enumerate(catom_coord):
        delr1 = (np.array(coord1) - np.array(metal_coord)).tolist()
        theta_tmp = []
        for idx2, coord2 in enumerate(catom_coord):
            if idx2 != idx1:
                delr2 = (np.array(coord2) - np.array(metal_coord)).tolist()
                theta = vecangle(delr1, delr2)
                theta_tmp.append(theta)
        th_input_arr.append([catoms[idx1], theta_tmp])
    th_output_arr, sum_del_angle, catoms_arr, max_del_sig_angle = loop_target_angle_arr(th_input_arr, angle_ref)
    if debug:
        print('th:', th_output_arr)
        print('sum_del:', sum_del_angle)
        print('catoms_arr:', catoms_arr)
        print('catoms_type:', [my_mol.getAtom(x).symbol() for x in catoms_arr])
    for idx, ele in enumerate(th_output_arr):
        theta_arr.append([catoms_arr[idx], sum_del_angle[idx], ele])
    # theta_arr.sort(key=sort_sec_ele)
    # theta_trunc_arr = theta_arr[0:6]
    theta_trunc_arr = theta_arr
    # print('truncated theta array:', theta_trunc_arr)
    theta_trunc_arr_T = list(map(list, zip(*theta_trunc_arr)))
    oct_catoms = theta_trunc_arr_T[0]
    oct_angle_devi = theta_trunc_arr_T[1]
    oct_angle_all = theta_trunc_arr_T[2]
    if debug:
        print('Summation of deviation angle for catoms:', oct_angle_devi)
        print('Angle for catoms:', oct_angle_all)
    for atom in oct_catoms:
        coord = catom_coord[catoms.index(atom)]
        dist = distance(coord, metal_coord)
        oct_dist.append(dist)
    oct_dist.sort()
    # print('!!!oct_dist:', oct_dist)
    try:  ### For Oct
        dist_del_arr = np.array([oct_dist[3] - oct_dist[0], oct_dist[4] - oct_dist[1], oct_dist[5] - oct_dist[2]])
        min_posi = np.argmin(dist_del_arr)
        if min_posi == 0:
            dist_eq, dist_ax = oct_dist[:4], oct_dist[4:]
        elif min_posi == 1:
            dist_eq, dist_ax = oct_dist[1:5], [oct_dist[0], oct_dist[5]]
        else:
            dist_eq, dist_ax = oct_dist[2:], oct_dist[:2]
    except IndexError:  ## For one empty site
        if (oct_dist[3] - oct_dist[0]) > (oct_dist[4] - oct_dist[1]):
            dist_ax, dist_eq = oct_dist[:1], oct_dist[1:]  # ax dist is smaller
        else:
            dist_ax, dist_eq = oct_dist[4:], oct_dist[:4]  # eq dist is smaller
    dist_del_all = oct_dist[-1] - oct_dist[0]
    if debug:
        print('dist:', dist_eq, dist_ax)
    dist_del_eq = max(dist_eq) - min(dist_eq)
    dist_del_ax = max(dist_ax) - min(dist_ax)
    dist_del_eq_ax = max(abs(max(dist_eq) - min(dist_ax)), abs(max(dist_ax) - min(dist_eq)))
    oct_dist_del = [dist_del_eq, dist_del_ax, dist_del_eq_ax, dist_del_all]
    if debug:
        print('distance difference for catoms to metal (eq, ax, eq_ax):', oct_dist_del)
    return oct_angle_devi, oct_dist_del, max_del_sig_angle, catoms_arr