Beispiel #1
0
def getSubstructureFromPath(refmol: Molecule, path: np.ndarray) -> Molecule:
    """Create a molecules object from a substructure of given molecule."""

    # initialize
    refat = refmol.get_atomic_numbers()
    refxyz = refmol.get_positions()

    # atoms from complex excluding old substrate
    atoms = []
    for elem in path:
        atom = Atom(symbol=refat[elem], position=refxyz[elem, :])
        atoms.append(atom)

    # create molecule from atoms
    return Molecule(symbols=atoms)
Beispiel #2
0
def getClassicalSterimol(mol: Molecule, origin: int, partner: int):
    """Verloop definitions for L, B1, and B5 steric parameter.
    We apply kallisto van der Waals radii."""

    # initialize coordinates
    coords = mol.get_positions()

    # get number of atoms
    nat = mol.get_number_of_atoms()

    # get van der Waals radii in Bohr
    vdw = np.zeros(shape=(nat, ), dtype=np.float64)
    vdw = mol.get_vdw(charge=0, vdwtype="rahm", scale=1)

    # shift all atoms wrt origin
    coords -= coords[origin]

    # extract vector origin -> attachted and normalize
    vector = np.zeros(shape=(3, ), dtype=np.float64)
    vector = coords[partner] - coords[origin]
    vector /= np.linalg.norm(vector)

    # align vector and x-axis
    xaxis = np.array([1, 0, 0])
    dot = np.dot(vector, xaxis).reshape(1) + 1

    # define zaxis and cover antiparallel case
    zaxis = np.array([0, 0, 1])
    epsilon = 1e-06
    if dot < epsilon:
        w = np.cross(vector, zaxis)
        if np.linalg.norm(w) < epsilon:
            w = np.cross(vector, xaxis)
    else:
        w = np.cross(vector, xaxis)

    # define quaternion q and normalize
    q = np.concatenate((w, dot))
    q /= np.linalg.norm(q)

    # rotate coordinates according to q
    u = R.from_quat(q)
    coords = u.apply(coords)

    # project coordinates on vector
    vector = coords[partner] - coords[origin]
    unitVector = vector / np.linalg.norm(vector)

    # project coordinates on vectors
    vdw = np.vstack(vdw).reshape(-1)
    cvalues = np.dot(unitVector.reshape(1, -1), coords.T)
    projected = cvalues + vdw

    lval = np.max(projected)
    L = unitVector * lval
    L = L.reshape(-1)

    # B min and max values
    r = 1
    slices = 360
    theta = np.linspace(0, 2 * np.pi, slices)
    x = np.zeros(shape=(len(theta), ), dtype=np.float64)
    y = r * np.cos(theta)
    z = r * np.sin(theta)
    vectors = np.column_stack((x, y, z))

    cvalues = np.dot(vectors, coords.T)
    projected = cvalues + vdw

    maxValues = np.max(projected, axis=1)
    bminVal = np.min(maxValues)
    bmaxVal = np.max(maxValues)

    return lval, bminVal, bmaxVal
Beispiel #3
0
def matchSubstrates(
    bonds: np.ndarray,
    new: Molecule,
    bondsNewSub: np.ndarray,
    old: Molecule,
    bondsOldSub,
    center: np.ndarray,
) -> np.ndarray:
    """Match substrates by root mean squared deviation measure."""

    # check is central atom given
    centered = False
    count = 1
    if center is not None:
        centered = True
        count = 2

    newnat = new.get_number_of_atoms()
    newxyz = np.zeros(shape=(newnat, 3), dtype=np.float64)
    newxyz = new.get_positions()

    oldnat = old.get_number_of_atoms()
    oldxyz = np.zeros(shape=(oldnat, 3), dtype=np.float64)
    oldxyz = old.get_positions()

    # shift to first atom of old substrate
    shift = np.zeros(shape=(3, ), dtype=np.float64)
    shift = oldxyz[0, :]
    oldShift = shift
    oldxyz2 = np.zeros(shape=(oldnat, 3), dtype=np.float64)
    for i in range(oldnat):
        oldxyz2[i][:] = oldxyz[i][:] - shift

    # shift to first atom of new substrate
    shift = newxyz[0, :]
    newxyz2 = np.zeros(shape=(newnat, 3), dtype=np.float64)
    for i in range(newnat):
        newxyz2[i][:] = newxyz[i][:] - shift

    # covalent bonding partner in old substrate
    covOld = len(bondsOldSub[0][:])

    # covalent bonding partner in new substrate
    covNew = len(bondsNewSub[0][:])

    # Check for linear moleule case
    if covNew != 1:
        isNotLinear = True
    else:
        isNotLinear = False

    covOld += count
    covNew += count

    # get structures for RMSD alignment
    shiftOldSub = np.zeros(shape=(covOld, 3), dtype=np.float64)
    shiftOldSub[0, :] = oldxyz2[0, :]
    shiftNewSub = np.zeros(shape=(covNew, 3), dtype=np.float64)
    shiftNewSub[0, :] = newxyz2[0, :]

    # shift old substrate
    i = 0
    for j in range(len(bondsOldSub[0][:])):
        i += 1
        k = bondsOldSub[0][j]
        shiftOldSub[i, :] = oldxyz2[k, :]

    # shift new substrate
    i = 0
    for j in range(len(bondsNewSub[0][:])):
        i += 1
        k = bondsNewSub[0][j]
        shiftNewSub[i, :] = newxyz2[k, :]

    if centered:
        indexOld = covOld - 1
        indexNew = covNew - 1
        shiftOldSub[indexOld, :] = center - oldShift
        distRef = getDist(shiftOldSub[0, :], shiftOldSub[indexOld, :])
        shiftNewSub[indexNew][:] = 0
        shift = getNewSubstrateCenter(indexNew, shiftNewSub, distRef)

    bdim = np.minimum(covOld, covNew)
    print(bdim)

    if bdim >= 3:
        bdim = 3
        b1xyz = np.zeros(shape=(bdim, 3), dtype=np.ndarray)
        b2xyz = np.zeros(shape=(bdim, 3), dtype=np.ndarray)
        indexOld = covOld - 1
        indexNew = covNew - 1
        b1xyz[0][:] = shiftOldSub[0][:]
        b1xyz[1][:] = shiftOldSub[1][:]
        b1xyz[2][:] = shiftOldSub[indexOld][:]
        b2xyz[0][:] = shiftNewSub[0][:]
        b2xyz[1][:] = shiftNewSub[1][:]
        b2xyz[2][:] = shiftNewSub[indexNew][:]
    else:
        bdim = 2
        b1xyz = np.zeros(shape=(bdim, 3), dtype=np.ndarray)
        b2xyz = np.zeros(shape=(bdim, 3), dtype=np.ndarray)
        indexOld = covOld - 1
        indexNew = covNew - 1
        b1xyz[0][:] = shiftOldSub[0][:]
        b1xyz[1][:] = shiftOldSub[indexOld][:]
        b2xyz[0][:] = shiftNewSub[0][:]
        b2xyz[1][:] = shiftNewSub[indexNew][:]

    tmpxyz = np.zeros(shape=(newnat, 3), dtype=np.float64)
    outxyz = np.zeros(shape=(newnat, 3), dtype=np.float64)

    if isNotLinear:
        u = np.zeros(shape=(3, 3), dtype=np.float64)
        error = 0.0
        # get RMSD value and rotation matrix
        error, u = rmsd(bdim, b2xyz, b1xyz)
        tmpxyz = np.matmul(u.T, newxyz2[:][0:newnat].T)
        # shift
        for i in range(newnat):
            outxyz[i, :] = tmpxyz.T[i, :] + oldShift

        return outxyz

    tmpxyz = newxyz2[:][0:newnat]
    # shift
    for i in range(newnat):
        outxyz[i, :] = tmpxyz[i, :] + oldShift

    return outxyz
Beispiel #4
0
def exchangeSubstructure(
    n: int,
    center: int,
    subnr: int,
    bonds: np.ndarray,
    ref: Molecule,
    newsub: Molecule,
    newSubBonds: np.ndarray,
    name: str,
    rotate: int,
    exclude: bool,
):
    """Exchange substructure (subnr) from ref with substrate."""

    # setup initial complex
    refxyz = ref.get_positions()
    refat = ref.get_atomic_numbers()
    refnat = ref.get_number_of_atoms()

    # match new and old substrate
    newat = newsub.get_atomic_numbers()
    newnat = newsub.get_number_of_atoms()

    # extract coordinates of central atom
    centralAtom = np.zeros(shape=(1, 3), dtype=np.float64)
    centralAtom = refxyz[center, :]

    for i in range(len(bonds[center])):
        if i == subnr:
            path = np.zeros(shape=(n, ), dtype=np.int32)
            # set all elements to -1
            path.fill(-1)
            partner = bonds[center][i]
            count = Counter()  # type: ignore
            count["step"] = -1
            getSubstructures(n, bonds, center, partner, path, count=count)
            # get rid of -1 elements
            path = [x for x in path if x != -1]
            path = np.array(path)
            # create molecule from given path
            oldsub = getSubstructureFromPath(ref, path)
            # get all bonding partner
            oldSubBonds = oldsub.get_bonds(partner="X")
            outxyz = np.zeros(shape=(newnat, 3), dtype=np.float64)
            outxyz = matchSubstrates(
                bonds,
                newsub,
                newSubBonds,
                oldsub,
                oldSubBonds,
                centralAtom,
            )

            # atoms from complex excluding old substrate
            atoms = []
            for i in range(refnat):
                if i in path:
                    continue
                atom = Atom(symbol=refat[i], position=refxyz[i, :])
                atoms.append(atom)

            # atoms from new substrate

            # Should we rotate the substrate around covalent bond?
            if rotate:
                theta = rotate
                origin = refxyz[center, :]
                partner = outxyz[0, :]
                outxyz2 = np.zeros(shape=outxyz.shape, dtype=np.float64)
                # reference shift
                refShift = getRodriguezRotation(partner, origin, partner,
                                                theta)
                shift = outxyz[0, :] - refShift
                for i in range(newnat):
                    outxyz2[i, :] = getRodriguezRotation(
                        outxyz[i, :],
                        origin,
                        partner,
                        theta,
                    )
                    outxyz2[i, :] += shift

                    atom = Atom(symbol=newat[i], position=outxyz2[i, :])
                    atoms.append(atom)
            else:
                for i in range(newnat):
                    atom = Atom(symbol=newat[i], position=outxyz[i, :])
                    atoms.append(atom)

            # create molecule from atoms
            mol = Molecule(symbols=atoms)

            # write new structure in xyz format
            mol.writeMolecule(name + ".xyz")

            # write constrain file
            refnat = ref.get_number_of_atoms()
            oldnat = oldsub.get_number_of_atoms()
            nat = refnat - oldnat
            writeTransitionMetalConstrains(nat, newnat, newSubBonds, exclude)