Ejemplo n.º 1
0
def main():
    utils.TITLE("Proximity Analysis")

    FILENAME = input("Enter .pdb file path...\t\t")
    PRT = utils.PDB(FILENAME).prot
    SEL_CHAIN = input("Select chain...\t\t\t")
    SEL_RSN = input("Select residue...\t\t")
    print("\nDetected Atom Type in", SEL_RSN, PRT[SEL_CHAIN][SEL_RSN][0][2],
          ":\n")
    for i in PRT[SEL_CHAIN][SEL_RSN]:
        print(">> ", i[1])

    SEL_AT = input("\nSelect Atom Type:\t\t")

    TGT = [i for i in PRT[SEL_CHAIN][SEL_RSN] if i[1] == SEL_AT][0]

    DIST_TGT = {}

    for i in PRT[SEL_CHAIN]:
        for j in PRT[SEL_CHAIN][i]:
            distance = utils.dist([TGT[5], TGT[6], TGT[7]], [j[5], j[6], j[7]])
            if j[4] not in DIST_TGT:
                DIST_TGT[j[4]] = distance
            elif j[4] in DIST_TGT:
                if distance < float(DIST_TGT[j[4]]):
                    DIST_TGT[j[4]] = distance
            else:
                print("ERROR!")

    RES = []
    try:
        THR_DIST = float(input("Select cutoff distance...\t"))

        for i in DIST_TGT:
            if DIST_TGT[i] <= THR_DIST and PRT[SEL_CHAIN][i][0][2] in POS_AA:
                RES.append(i)
                print("{}\t{:.3f}\t{}\t+1".format(i, DIST_TGT[i],
                                                  PRT[SEL_CHAIN][i][0][2]))
            elif DIST_TGT[i] <= THR_DIST and PRT[SEL_CHAIN][i][0][2] in NEG_AA:
                RES.append(i)
                print("{}\t{:.3f}\t{}\t-1".format(i, DIST_TGT[i],
                                                  PRT[SEL_CHAIN][i][0][2]))
            elif DIST_TGT[i] <= THR_DIST:
                RES.append(i)
                print("{}\t{:.3f}\t{}".format(i, DIST_TGT[i],
                                              PRT[SEL_CHAIN][i][0][2]))
    except KeyboardInterrupt:
        print("Interrupted by user")
        try:
            sys.exit(0)
        except SystemExit:
            os._exit(0)

    cps = input(
        "\nPass the selected residues to the Catalytic Pocket Selector module? [y/n]:\t"
    )
    if cps == 'y':
        pro_pru.main(FILENAME, SEL_CHAIN, RES)
    else:
        utils.NT()
Ejemplo n.º 2
0
def main():
    def multiple_parser(inp_list):
        """Multiple input parser"""
        out_list = []
        for k in inp_list:
            if "-" in k:
                for li in range(int(k.split("-")[0]),
                                int(k.split("-")[1]) + 1):
                    if int(li) not in out_list:
                        out_list.append(int(li))
            else:
                if int(k) not in out_list:
                    out_list.append(int(k))
        return out_list

    utils.TITLE("Trajectory Pruning")

    TRJ = utils.TRJ(input("Enter trajectory file path...\t"))
    K_LIST = input("\nSnapshot groups to extract? (e.g. 1-5 6-10)\t").split()
    K_LISTD = [multiple_parser([i]) for i in K_LIST]

    for trj_n, sna_list in enumerate(K_LISTD):
        with open("./TRJ_{}.xyz".format(str(trj_n)), 'a') as out:
            for idx_i, val_i in enumerate(TRJ.trajectory):
                if idx_i + 1 in sna_list:
                    out.write("{}\n".format(str(TRJ.natoms)))
                    out.write("Trajectory {}\n".format(idx_i + 1))
                    for j in val_i:
                        out.write("{} \t{:.10f}\t {:.10f}\t {:.10f} \n".format(
                            j[0], j[1], j[2], j[3]))
    utils.NT()
Ejemplo n.º 3
0
def main(path):
    utils.TITLE("NEB Visualizer (ORCA)")
    fig = go.Figure()

    with open(path) as file:
        lines = file.readlines()

    idx_pts = []
    idx_int = []

    for idx, val in enumerate(lines):
        if "Images:" in val:
            idx_pts.append(idx + 1)
        elif "Interp.:" in val:
            idx_int.append(idx + 1)

    pts_n = idx_int[0] - 6

    if len(idx_pts) != 1:
        int_n = idx_pts[1] - idx_int[0] - 3
    else:
        int_n = len(lines) - idx_int[0]

    for i in idx_pts:
        if i == idx_pts[0]:
            x = [float(lines[j].split()[0]) for j in range(i, i + pts_n)]
            y = [float(lines[j].split()[2]) * utils.ha2kcal for j in range(i, i + pts_n)]
            fig.add_trace(go.Scatter(x=x, y=y, mode='markers', name='markers', marker=dict(color='darkorange')))
        elif i == idx_pts[-1]:
            x = [float(lines[j].split()[0]) for j in range(i, i + pts_n)]
            y = [float(lines[j].split()[2]) * utils.ha2kcal for j in range(i, i + pts_n)]
            fig.add_trace(go.Scatter(x=x, y=y, mode='markers', name='markers', marker=dict(color='cornflowerblue')))
        else:
            x = [float(lines[j].split()[0]) for j in range(i, i + pts_n)]
            y = [float(lines[j].split()[2]) * utils.ha2kcal for j in range(i, i + pts_n)]
            fig.add_trace(go.Scatter(x=x, y=y, mode='markers', name='markers', marker=dict(color='gainsboro')))

    for i in idx_int:
        if i == idx_int[0]:
            x = [float(lines[j].split()[0]) for j in range(i, i + int_n)]
            y = [float(lines[j].split()[2]) * utils.ha2kcal for j in range(i, i + int_n)]
            fig.add_trace(go.Scatter(x=x, y=y, mode='lines', name='lines', line=dict(color='darkorange')))
        elif i == idx_int[-1]:
            x = [float(lines[j].split()[0]) for j in range(i, i + int_n)]
            y = [float(lines[j].split()[2]) * utils.ha2kcal for j in range(i, i + int_n)]
            fig.add_trace(go.Scatter(x=x, y=y, mode='lines', name='lines', line=dict(color='cornflowerblue')))
        else:
            x = [float(lines[j].split()[0]) for j in range(i, i + int_n)]
            y = [float(lines[j].split()[2]) * utils.ha2kcal for j in range(i, i + int_n)]
            fig.add_trace(go.Scatter(x=x, y=y, mode='lines', name='lines', line=dict(color='gainsboro')))

    fig.update_layout(
        title="ORCA Nudged Elastic Band ",
        xaxis_title="Iteration",
        yaxis_title="E / kcal mol<sup>-1</sup>",
        template="plotly_white",
        showlegend=False
    )
    fig.show()
    utils.NT()
Ejemplo n.º 4
0
def main():
    utils.TITLE("Trajectory Analyzer/Freezer")

    cat_d = [[], [], [], []]

    TRJ = utils.TRJ(input("Enter trajectory file path...\t"))
    print("\nATOM\tELEM\tSTD\t\tSTATUS\n")
    for i in range(0, TRJ.natoms):
        tmp = []
        for j in range(0, TRJ.nspas):
            tmp.append(TRJ.trajectory[j][i][1:])
        atom_std = np.std(tmp, axis=0)
        if np.sum(atom_std) < 0.001:
            FRZ_STATUS = "FROZEN"
            cat_d[0].append(i + 1)
        elif np.sum(atom_std) >= 0.001 and np.sum(atom_std) < 0.3:
            FRZ_STATUS = "+"
            cat_d[1].append(i + 1)
        elif np.sum(atom_std) >= 0.3 and np.sum(atom_std) < 0.5:
            FRZ_STATUS = "++"
            cat_d[2].append(i + 1)
        elif np.sum(atom_std) >= 0.5:
            FRZ_STATUS = "+++"
            cat_d[3].append(i + 1)

        print("{}\t{}\t{:.5f}\t\t{}".format(i + 1, TRJ.trajectory[j][i][0],
                                            np.sum(atom_std), FRZ_STATUS))

    print("\nDISPLACEMENTS\tATOMS\n")
    print("FROZEN:\t\t{}".format(" ".join([str(i) for i in cat_d[0]])))
    print("LOW:\t\t{}".format(" ".join([str(i) for i in cat_d[1]])))
    print("MEDIUM:\t\t{}".format(" ".join([str(i) for i in cat_d[2]])))
    print("HIGH:\t\t{}".format(" ".join([str(i) for i in cat_d[3]])))

    FRZ_LIST = input(
        "\nDo you want to CONSTRAIN some particular atom along the TRJ?\n\n"
    ).split()
    FRZ_LIST = [int(i) for i in FRZ_LIST]
    with open("./newTRAJ.xyz", 'a') as out:
        for idx_i, val_i in enumerate(TRJ.trajectory):
            out.write("{}\n".format(str(TRJ.natoms)))
            out.write("Trajectory {}\n".format(idx_i + 1))
            for idx_j, val_j in enumerate(val_i):
                if idx_j + 1 in FRZ_LIST:
                    out.write("{} \t{:.10f}\t {:.10f}\t {:.10f} \n".format(
                        TRJ.trajectory[0][idx_j][0],
                        TRJ.trajectory[0][idx_j][1],
                        TRJ.trajectory[0][idx_j][2],
                        TRJ.trajectory[0][idx_j][3]))
                else:
                    out.write("{} \t{:.10f}\t {:.10f}\t {:.10f} \n".format(
                        val_j[0], val_j[1], val_j[2], val_j[3]))

    utils.NT()
Ejemplo n.º 5
0
def main():
    def multiple_parser(inp_list):
        """Multiple input parser"""
        out_list = []
        for k in inp_list:
            if "-" in k:
                for li in range(int(k.split("-")[0]),
                                int(k.split("-")[1]) + 1):
                    if int(li) not in out_list:
                        out_list.append(int(li))
            else:
                if int(k) not in out_list:
                    out_list.append(int(k))
        return out_list

    utils.TITLE("CONSTRAINTS GENERATOR")

    FILENAME = input("Enter .xyz file path...\t\t")
    XMOL = molecule.MOL(FILENAME)
    INPUT_INDEX = input(
        "\nEnter the element(s) to constrain.\nMultiple elements constraints are possible (e.g.: C O).\nDifferent elements must be separated by a SPACE.\nSpecial tokens are allowed (e.g.: All)\n\nSelection\n"
    ).split()
    CONST_INDEX = []

    for idx, val in enumerate(XMOL.element):
        if val in INPUT_INDEX:
            CONST_INDEX.append(idx + 1)
    if "All" in INPUT_INDEX:
        CONST_INDEX = [i for i in range(1, XMOL.natoms + 1)]

    INPUT_INDEX = input(
        "\nDo you want to CONSTRAIN some particular atom?\n\n").split()

    for i in multiple_parser(INPUT_INDEX):
        if int(i) not in CONST_INDEX:
            CONST_INDEX.append(int(i))

    INPUT_INDEX = input(
        "\nDo you want to UN-CONSTRAIN some particular atom?\n\n").split()

    for i in multiple_parser(INPUT_INDEX):
        if int(i) in CONST_INDEX:
            CONST_INDEX.remove(int(i))

    FREE_INDEX = list({int(i)
                       for i in range(1, XMOL.natoms + 1)} - set(CONST_INDEX))

    SOFT = input("\nSelect software:\n1)\tORCA\n2)\tGaussian\n3)\txTB\n")

    if SOFT == "1":
        print("\nFROZEN ATOMS:", " ".join([str(x - 1) for x in CONST_INDEX]))
        print("\n%GEOM")
        print("  Constraints")
        for i in CONST_INDEX:
            print("    {C", i - 1, "C}")
        print("  End")
        print("END")
        CONST_INDEX[:] = [x - 1 for x in CONST_INDEX]
        FREE_INDEX[:] = [x - 1 for x in FREE_INDEX]
        print(
            "\nTo project-out the immaginary frequencies due to frozen atoms in a vibrational analysis use:\n"
        )
        print("%FREQ")
        print("  AnFreq    False")
        print("  NumFreq   True")
        print("  Partial_Hess")
        print("    {", " ".join(map(str, CONST_INDEX)), "}")
        print("  End")
        print("END")

    elif SOFT == "2":
        print("\nFROZEN ATOMS:", " ".join([str(x) for x in CONST_INDEX]))
        print(
            "\nModredundant syntax is available below but it is suggested to use the classical frozen syntax (Atom 0/-1 X Y Z) at the end of this report:\n"
        )
        for i in CONST_INDEX:
            print("X", i, "F")
        print(
            "\nTo project-out the immaginary frequencies due to frozen atoms in a vibrational analysis change the coordinates using the frozen syntax (Atom 0/-1 X Y Z):\n"
        )
        for idx, val in enumerate(XMOL.element):
            if idx + 1 in FREE_INDEX:
                print("{}   {} \t{:.10f}\t {:.10f}\t {:.10f}".format(
                    val, "0", XMOL.xyz[idx][0], XMOL.xyz[idx][1],
                    XMOL.xyz[idx][2]))
            elif idx + 1 in CONST_INDEX:
                print("{}  {} \t{:.10f}\t {:.10f}\t {:.10f}".format(
                    val, "-1", XMOL.xyz[idx][0], XMOL.xyz[idx][1],
                    XMOL.xyz[idx][2]))
            else:
                print("ERROR!!! Something wrong just happened... :(")

    elif SOFT == "3":
        print("\nFROZEN ATOMS:", " ".join([str(x) for x in CONST_INDEX]))
        XTB_OPT = input(
            "\nDo you like to freeze atoms in hessian calculation? (All immaginary mode due to frozen atoms will be projected out) [y/n]\n"
        )
        print("\n$fix")
        for i in CONST_INDEX:
            print("atoms:", i)
        if XTB_OPT == "y":
            for i in CONST_INDEX:
                print("freeze:", i)
        print("end")

    utils.NT()
Ejemplo n.º 6
0
def main(FILENAME='', CHN='', RES=''):
    def multiple_parser(inp_list):
        """Multiple input parser"""
        out_list = []
        for k in inp_list:
            if "-" in k:
                for li in range(int(k.split('-')[0]),
                                int(k.split('-')[1]) + 1):
                    if int(li) not in out_list:
                        out_list.append(int(li))
            else:
                if int(k) not in out_list:
                    out_list.append(int(k))
        return out_list

    def group_ranges(L):
        """
        Collapses a list of integers into a list of the start and end of
        consecutive runs of numbers. Returns a generator of generators.
        """
        for w, z in itertools.groupby(
                L, lambda x, y=itertools.count(): next(y) - x):
            grouped = list(z)
            yield (x for x in [grouped[0], grouped[-1]][:len(grouped)])

    def saturate(C_tgt, ref_atom):
        """Saturate the valence of a carbon atom with hydrogen

        Args:
            C_tgt (list): Cartesian coordinate of C atom to saturate [X, Y, Z]
            ref_atom (list): Cartesian coordinate of an atom directly bonded to C_tgt. This is used to create a vector for the rotation of hydrogen atoms [X, Y, Z]
        Returns:
            [type]: Distance between atom_a and atom_b
        """
        MG = [['H', -0.510365374578, -0.883978759193, 0.399020000000],
              ['H', 1.020730749156, 0.000000000000, 0.399020000000],
              ['H', -0.510365374578, 0.883978759193, 0.399020000000]]

        vec_MG = [0.0, 0.0, -1.4]
        vec_TGT = [
            ref_atom[0] - C_tgt[0],
            ref_atom[1] - C_tgt[1],
            ref_atom[2] - C_tgt[2],
        ]

        rot_mat = utils.rot_mat_v(vec_MG, vec_TGT)
        H_end = []
        for i in MG:
            MG_rot = np.matmul(rot_mat, np.array(i[1:4]))
            MG_rot = MG_rot + C_tgt
            H_end.append([i[0], MG_rot[0], MG_rot[1], MG_rot[2]])

        return H_end

    utils.TITLE("Catalytic Pocket Selector")

    if FILENAME == '':
        filename = input('Enter .PDB file name...\t\t')
        PRO = utils.PDB(filename)
        SelC = input('Select chain...\t\t')
        SelRSN = multiple_parser(input('Select residues...\t\t').split())
    else:
        filename = FILENAME
        PRO = utils.PDB(filename)
        SelC = CHN
        SelRSN = multiple_parser(RES)

    SelRSN.sort()
    GrpRSN = [list(x) for x in group_ranges(SelRSN)]

    print('\nNumber of groups detected...\t{}'.format(len(GrpRSN)))
    print('Number of terminations...\t{}'.format(2 * len(GrpRSN)))

    for idx, val in enumerate(GrpRSN):
        print('\n>> Group:\t{}'.format(str(idx + 1)))
        for j in range(val[0], val[-1] + 1):
            print('\t', PRO.prot[SelC][str(j)][0][2], str(j))

    TGroup = input(
        '\nSelect terminations:\n1)   ACE/NME\n2)   Marker Atom\n3)   No Terminations\n\nSelection: '
    )

    if TGroup == '2':
        Mk_Atom = input('\nWhich atom do you like to place as a marker?...\t')

    MOL = []
    for GRP in GrpRSN:
        for AA in range(GRP[0], GRP[-1] + 1):
            for ATOM in PRO.prot[SelC][str(AA)]:
                MOL.append("{} \t{:.3f}\t {:.3f}\t {:.3f}".format(
                    ATOM[8], ATOM[5], ATOM[6], ATOM[7]))

            # ACE
            if AA == GRP[0] and TGroup == '1':
                for ATOM in PRO.prot[SelC][str(AA - 1)]:
                    if ATOM[1] == 'O':
                        MOL.append("{} \t{:.3f}\t {:.3f}\t {:.3f}".format(
                            ATOM[8], ATOM[5], ATOM[6], ATOM[7]))
                    elif ATOM[1] == 'C':
                        C_atom = ATOM
                        MOL.append("{} \t{:.3f}\t {:.3f}\t {:.3f}".format(
                            ATOM[8], ATOM[5], ATOM[6], ATOM[7]))
                    elif ATOM[1] == 'CA':
                        CA_atom = ATOM
                        MOL.append("{} \t{:.3f}\t {:.3f}\t {:.3f}".format(
                            ATOM[8], ATOM[5], ATOM[6], ATOM[7]))

                H_Met = saturate(CA_atom[5:8], C_atom[5:8])
                for i in H_Met:
                    MOL.append("{} \t{:.3f}\t {:.3f}\t {:.3f}".format(
                        i[0], i[1], i[2], i[3]))

            # NME
            if AA == GRP[-1] and TGroup == '1':
                for ATOM in PRO.prot[SelC][str(AA + 1)]:
                    if ATOM[1] == 'NH':
                        MOL.append("{} \t{:.3f}\t {:.3f}\t {:.3f}".format(
                            ATOM[8], ATOM[5], ATOM[6], ATOM[7]))
                    elif ATOM[1] == 'N':
                        C_atom = ATOM
                        MOL.append("{} \t{:.3f}\t {:.3f}\t {:.3f}".format(
                            ATOM[8], ATOM[5], ATOM[6], ATOM[7]))
                    elif ATOM[1] == 'CA':
                        CA_atom = ATOM
                        MOL.append("{} \t{:.3f}\t {:.3f}\t {:.3f}".format(
                            ATOM[8], ATOM[5], ATOM[6], ATOM[7]))

                H_Met = saturate(CA_atom[5:8], C_atom[5:8])
                for i in H_Met:
                    MOL.append("{} \t{:.3f}\t {:.3f}\t {:.3f}".format(
                        i[0], i[1], i[2], i[3]))

            if AA == GRP[0] and TGroup == '2':
                for ATOM in PRO.prot[SelC][str(AA - 1)]:
                    if ATOM[1] == 'C':
                        MOL.append("{} \t{:.3f}\t {:.3f}\t {:.3f}".format(
                            Mk_Atom, ATOM[5], ATOM[6], ATOM[7]))

            if AA == GRP[-1] and TGroup == '2':
                for ATOM in PRO.prot[SelC][str(AA + 1)]:
                    if ATOM[1] == 'N':
                        MOL.append("{} \t{:.3f}\t {:.3f}\t {:.3f}".format(
                            Mk_Atom, ATOM[5], ATOM[6], ATOM[7]))

    with open(filename + '.' + SelC + '.pruned.xyz', 'w') as out:
        out.write(str(len(MOL)) + '\n')
        out.write('AA: ' + str(SelRSN) + ' Chain: ' + SelC + '\n')
        for i in MOL:
            out.write(i + '\n')
        out.close()

    print("\nPruned structure has been saven in: {}\n".format(filename + '.' +
                                                              SelC +
                                                              '.pruned.xyz'))
    utils.NT()
Ejemplo n.º 7
0
def main():
    utils.TITLE("TRJ 2 Synchronous Transit-Guided Quasi-Newton")

    TRAJ = utils.TRJ(input("Enter trajectory file path...\t"))
    R_SNAP = int(input("\nSnapshot number before TS...\t")) - 1
    TS_SNAP = input("Snapshot number of TS guess...\t")
    if TS_SNAP == "":
        print("Switching to a QST2 input generation...")
    else:
        print("Switching to a QST3 input generation...")
        TS_SNAP = int(TS_SNAP) - 1
    P_SNAP = int(input("Snapshot number after TS...\t")) - 1
    CHARGE = int(input("Totale charge of the system...\t"))
    MULT = int(input("Multiplicity of the system...\t"))
    FROZ = input("List of frozen atoms (if any)...\t").split()
    FROZ = [int(i) for i in FROZ]

    if TS_SNAP == "":
        print("\n#Opt(QST2)")
    else:
        print("\n#Opt(QST3)")

    print("\nReactant Guess\n")
    print(CHARGE, MULT)
    for idx, val in enumerate(TRAJ.trajectory[R_SNAP]):
        if FROZ != []:
            if idx + 1 in FROZ:
                FROZ_STAT = "-1"
            else:
                FROZ_STAT = "0"
        else:
            FROZ_STAT = ""
        print("{} {} \t{:.10f}\t {:.10f}\t {:.10f}".format(
            val[0], FROZ_STAT, val[1], val[2], val[3]))

    if TS_SNAP == "":
        print("\n\nProduct Guess\n")
    else:
        print("\nProduct Guess\n")
    print(CHARGE, MULT)

    for idx, val in enumerate(TRAJ.trajectory[P_SNAP]):
        if FROZ != []:
            if idx + 1 in FROZ:
                FROZ_STAT = "-1"
            else:
                FROZ_STAT = "0"
        else:
            FROZ_STAT = ""
        print("{} {} \t{:.10f}\t {:.10f}\t {:.10f}".format(
            val[0], FROZ_STAT, val[1], val[2], val[3]))

    if TS_SNAP != "":
        print("\nTS Guess\n")
        print(CHARGE, MULT)
        for idx, val in enumerate(TRAJ.trajectory[TS_SNAP]):
            if FROZ != []:
                if idx + 1 in FROZ:
                    FROZ_STAT = "-1"
                else:
                    FROZ_STAT = "0"
            else:
                FROZ_STAT = ""
            print("{} {} \t{:.10f}\t {:.10f}\t {:.10f}".format(
                val[0], FROZ_STAT, val[1], val[2], val[3]))

    utils.NT()
Ejemplo n.º 8
0
def main():
    def Displacement(ndim, nim, R):
        """
        Computes straight line distances between adjacent pair of images
        and then sums up the distances
        """
        displ = np.zeros(shape=(nim, ))
        for i in range(1, nim):
            R0 = R[(i - 1) * ndim:(i) * ndim]
            R1 = R[(i) * ndim:(i + 1) * ndim]
            dR = R1 - R0
            displ[i] = displ[i - 1] + np.sqrt(np.dot(dR.T, dR))

        return displ

    def LinearInterpolateData(nlen, xData, yData, xnew):
        """
        Linear interpolation of data points (xData, yData) to point xnew
        """
        i = 0
        if (xnew >= xData[nlen - 2]):
            i = nlen - 2
        else:
            while (xnew > xData[i + 1]):
                i = i + 1

        xL = xData[i]
        yL = yData[i]
        xR = xData[i + 1]
        yR = yData[i + 1]

        if (xnew < xL):
            yR = yL
        if (xnew > xR):
            yL = yR
        dydx = (yR - yL) / (xR - xL)

        return yL + dydx * (xnew - xL)

    def GenerateNewPath(ndim, nim, npoints, S, R):
        """
        Generates new path, newR of npoints images, from path R with nim images
        """

        newR = np.zeros(shape=(ndim * npoints, 1))
        xi = np.linspace(S[0], S[-1], npoints)

        for i in range(ndim):
            Rdof = np.zeros(shape=(nim, 1))
            dRdof = np.zeros(shape=(nim, 1))
            for j in range(nim):
                Rdof[j] = R[j * ndim + i]

            for xpt in range(npoints):
                new_y = LinearInterpolateData(nim, S, Rdof, xi[xpt])
                newR[xpt * ndim + i] = new_y

        return newR

    def ReadFirstLineOfFile(fname):
        with open(fname) as f:
            first_line = f.readline()
        return first_line

    def WriteTraj(fname, ndim, nim, R, E, symb3, restart="n"):

        if len(symb3) != ndim:
            raise RuntimeError("Error in WriteTraj. Dimension mismatch: symb3")
        if len(E) != nim:
            raise RuntimeError("Error in WriteTraj. Dimension mismatch: E")
        if len(R) != ndim * nim:
            raise RuntimeError("Error in WriteTraj. Dimension mismatch: R")

        f = open(fname, 'w')
        natoms = ndim / 3
        for i in range(nim):
            hnit = R[i * ndim:(i + 1) * ndim]
            f.write("%i \n" % natoms)
            f.write('E=%12.8f \n' % E[i])
            for j in range(0, len(hnit), 3):
                f.write('%s %12.8f %12.8f %12.8f\n' %
                        (symb3[j].strip(), hnit[j], hnit[j + 1], hnit[j + 2]))
            if restart == "y" and i + 1 != nim:
                f.write('>\n')
        f.close()

        return None

    def ReadTraj(fname):
        if not os.path.isfile(fname):
            raise RuntimeError("File %s not found " % fname)

        extension = fname.split('.')[-1]

        # Get first line of the file (i.e. number of atoms)
        first_line = ReadFirstLineOfFile(fname)

        try:
            natoms = int(first_line)
        except:
            raise TypeError("%s is not correctly formatted trajectory file")

        ndim = natoms * 3

        # begin by reading the contents of the file to a list
        contents = []
        f = open(fname).readlines()
        for i, line in enumerate(f):
            contents.append(line)

        if ">\n" in contents:
            print('\n--ORCA Restart file detected!')
            contents = [i for i in contents if i != ">\n"]
        else:
            print('\n--Normal TRJ file detected!')

        # get number of lines and hence number of images
        number_of_lines = i + 1
        nim = int((number_of_lines) / (natoms + 2))

        RPATH = []
        ind = 0
        for i in range(nim):
            symb3 = []
            ind = ind + 2
            for j in range(natoms):
                geom_line = contents[ind]
                geom_line = geom_line.split()
                symb3.append(geom_line[0].strip())
                symb3.append(geom_line[0].strip())
                symb3.append(geom_line[0].strip())
                RPATH.append(float(geom_line[1]))
                RPATH.append(float(geom_line[2]))
                RPATH.append(float(geom_line[3]))
                ind += 1

        RPATH = np.reshape(RPATH, (nim * ndim, 1))

        return RPATH, ndim, nim, symb3

    utils.TITLE("Linear interpolation of a trajectory")

    # ============================================
    # default values
    # ============================================
    fname = input("Enter .xyz trajectory file path...\t")
    TRJ = utils.TRJ(fname)

    npts = int(input("\nNumber of final points...\t"))

    # ============================================
    # Get inp arguments
    # ============================================

    # Notice that the order of the arguments matters.
    for i in range(len(sys.argv)):
        if i == 1:
            fname = sys.argv[1]
        if i == 2:
            try:
                npts = int(sys.argv[2])
            except:
                raise TypeError("Int. expected as a second arg")

    file_extension = fname.split('.')[1]
    # ============================================
    # Read trajectory file
    # ============================================
    name_string = fname.split('.')
    basename = name_string[0]
    file_extension = name_string[1]

    R, ndim, nim, symb3 = ReadTraj(fname)
    print('--Found %i images with %i atoms' % (nim, ndim / 3))
    print('--Interpolating to %i points' % (npts))
    restart = input("\nSave as a ORCA Restart file? [y/n]...\t")
    if npts > nim:
        fname_output = basename + '_exte.' + file_extension
    elif npts == nim:
        fname_output = basename + '_redistri.' + file_extension
    else:
        fname_output = basename + '_reduc.' + file_extension

    if restart == "y":
        fname_output = 'restart.allxyz'

    print('--output file: %s' % fname_output)

    # ============================================
    # Perform interpolation
    # ============================================
    S = Displacement(ndim, nim, R)
    newR = GenerateNewPath(ndim, nim, npts, S, R)

    # ============================================
    # Write new trajectory file
    # ============================================
    E = np.zeros(shape=(npts, 1))
    if restart == "y":
        WriteTraj(fname_output, ndim, npts, newR, E, symb3, restart)
    else:
        WriteTraj(fname_output, ndim, npts, newR, E, symb3)

    RP_SAVE = input("\nSave R/P files? [y/n]...\t")
    if RP_SAVE == 'y':
        with open("./R.xyz", 'a') as out:
            out.write("{}\n".format(str(TRJ.natoms)))
            out.write("Reactants\n")
            for i in TRJ.trajectory[0]:
                out.write("{} \t{:.10f}\t {:.10f}\t {:.10f} \n".format(
                    i[0], i[1], i[2], i[3]))
        with open("./P.xyz", 'a') as out:
            out.write("{}\n".format(str(TRJ.natoms)))
            out.write("Products\n")
            for i in TRJ.trajectory[-1]:
                out.write("{} \t{:.10f}\t {:.10f}\t {:.10f} \n".format(
                    i[0], i[1], i[2], i[3]))

    utils.NT()