Exemplo n.º 1
0
def get_dsoft():
    '''
    This functions is in charge of reading the file
    mesc.txt where the available softwares are listed
    '''
    # defined here:
    if False:
        dsoft = {'clhbrpot': 'mpilgrim.itf_asurf', \
                 'gaussian': 'mpilgrim.itf_gau'  ,\
                 'orca'    : 'mpilgrim.itf_orca'   \
                }
    # read from file
    if True:
        TXTFILE = os.path.dirname(os.path.realpath(__file__)) + "/mesc.txt"
        # read file
        lines = read_file(TXTFILE)
        lines = clean_lines(lines, "#", True)
        # get info from lines
        dsoft = {}
        for line in lines:
            if line == "\n": continue
            software, module = line.split()
            dsoft[software] = module
    # return dictionary
    return dsoft
Exemplo n.º 2
0
def read_tes(filename=PN.IFILE4):
    lines  = read_file(filename)
    dtesLL = {}
    dtesHL = {}
    bkeep = False
    sk1 = "start_meppoint"
    sk2 = "start_highlevel"
    ek1 = "end_meppoint"
    ek2 = "end_highlevel"
    for line in lines:
        # save LL data
        if   line.startswith(ek1):
             dtesLL[software] = dtesLL.get(software,{})
             dtesLL[software].update({ctc:string})
             bkeep = False
        # save HL data
        elif line.startswith(ek2):
             dtesHL[software] = dtesHL.get(software,{})
             dtesHL[software].update({ctc:string})
             bkeep = False
        elif bkeep:
             string += line
        elif line.startswith(sk1) or line.startswith(sk2):
             ctc, software = line.split()[1:]
             string = ""
             bkeep  = True
        else: continue
    if not os.path.exists(filename)   : status = -1
    elif dtesLL == {} and dtesHL == {}: status =  0
    else                              : status =  1
    return (dtesLL,dtesHL), (filename,status)
Exemplo n.º 3
0
def file2lines(filename):
    if not os.path.exists(filename):
        lines  = []
        status = -1
    else:
        lines = read_file(filename)
        lines = clean_lines(lines,"#",True)
        lines = [line for line in lines if line != "\n"]
        if lines == []: status = 0
        else          : status = 1
    return lines, status
Exemplo n.º 4
0
def read_orcaengrad(orca_engrad):
    # Initialize
    natoms   = None
    atonums  = []   ; Etot = None
    x_cc     = []   ; g_cc = []
    # Read lines
    if not os.path.exists(orca_engrad): return g_cc, (x_cc, atonums, Etot)
    lines  = read_file(orca_engrad)
    # Read natoms, Etot, g_cc, atonums, xcc
    natoms = int(lines[3])
    Etot   = float(lines[7])
    g_cc   = [float(line)  for line in lines[11:11+3*natoms]]
    Zxyz   = [line.split() for line in lines[-natoms:]]
    for Z,x,y,z in Zxyz:
       x_cc = x_cc + [float(x),float(y),float(z)]
       atonums = atonums + [int(Z)]
    # Return data
    return g_cc, (x_cc, atonums, Etot)
Exemplo n.º 5
0
def read_orcahess(orca_hess):
    if not os.path.exists(orca_hess): return []
    # Read lines
    lines = read_file(orca_hess)
    # Read hessian
    for idx in range(len(lines)):
        line = lines[idx]
        if "$hessian" in line:
            nrows = int(lines[idx + 1])
            idx_hessian = idx
    F_cc = [[0.0] * nrows for i in range(nrows)]
    fcol = int(lines[idx_hessian + 2].split()[0])  # first column
    lcol = int(lines[idx_hessian + 2].split()[-1])  # last  column
    row = 0
    for line in lines[idx_hessian + 3:]:
        if row == nrows - 1:
            fcol = int(line.split()[0])  # first column
            lcol = int(line.split()[-1])  # last  column
            row = 0
            continue
        # Split data in line
        line_data = line.split()
        # Save data
        row = int(line_data[0])
        F_cc[row][fcol:lcol + 1] = [float(value) for value in line_data[1:]]
        # Finished?
        if row == nrows - 1 and lcol == nrows - 1: break
    # Promediate hessian
    for i in range(1, nrows, 1):
        for j in range(i):
            Fij = F_cc[i][j]
            Fji = F_cc[j][i]
            average = 0.5 * (Fij + Fji)
            F_cc[i][j] = average
            F_cc[j][i] = average
    # Get lower triangle
    F_lt = []
    for i in range(nrows):
        for j in range(0, i + 1):
            F_lt.append(F_cc[i][j])
    F_cc = F_lt
    # Return data
    return F_cc
Exemplo n.º 6
0
def read_ispe(filename):
    '''
    read input file for ispe
    '''
    # read lines
    lines = ff.read_file(filename)
    lines = fncs.clean_lines(lines, strip=True)
    # initialize data
    ispe_xy = []
    VR, VP = None, None
    tension = 0.0
    # find data in lines
    for line in lines:
        if line == "\n": continue
        label, val = line.split()
        val = float(val)
        if label.lower() == "tension": tension = val
        elif label.lower() == "reac": VR = val
        elif label.lower() == "prod": VP = val
        else: ispe_xy.append((label, val))
    return ispe_xy, tension, VR, VP
Exemplo n.º 7
0
def set_EXE():
    global EXE
    txt = os.path.dirname(os.path.realpath(__file__))+"/paths.txt"
    # Defined in this file
    if 'EXE' in globals():
        return
    # Try to export it from bashrc
    elif "OrcaExe" in os.environ:
        # in .bashrc: export OrcaExe="$MYHOME/Software/orca_4_0_1_2/orca"
        EXE = os.environ["OrcaExe"]
        return
    # Export it from file
    elif os.path.exists(txt):
        lines = read_file(txt)
        lines = clean_lines(lines,"#",True)
        for line in lines:
            if line == "\n": continue
            name, path = line.split()
            if name == "orca":
                EXE = path
                return
    # Not found
    else: raise Exc.ExeNotDef(Exception)
Exemplo n.º 8
0
def normal_termination(ofile):
    lines = read_file(ofile)
    if len(lines) == 0: return False
    lastline = lines[-1].lower()
    if "normal termination" in lastline: return True
    else                               : return False
Exemplo n.º 9
0
def read_gauout_old(gauout):
    '''
    Read Gaussian output (data in final message)
    and return important data
    '''
    # check extension
    end_out = (gauout.lower()).endswith(".out")
    end_log = (gauout.lower()).endswith(".log")
    if (not end_out) and (not end_log):
        raise Exc.FileType(Exception)
    # read lines
    lines = read_file(gauout)
    # CHECK FILE IS GAUSSIAN OUT
    correct = False
    for line in lines:
        if "Entering Gaussian System" in line:
           correct = True
           break
    if not correct: raise Exc.FileType(Exception)
    # ONIOM energy?
    try:
       E_ONIOM = None
       for line in lines[::-1]:
           if "ONIOM: extrapolated energy" in line:
               E_ONIOM = float(line.split()[-1])
               break
    except: E_ONIOM = None
    # Get Forces if exists
    key1 = "Forces (Hartrees/Bohr)"
    key2 = "Cartesian Forces:"
    try:
       gcc = []
       for line in extract_string(lines,key1,key2).split("\n")[3:-3]:
           dummy, dummy, gx, gy, gz = line.split()
           gcc += [float(gx),float(gy),float(gz)]
       # forces to gradient
       gcc = [-g_i for g_i in gcc]
    except: gcc = None
    if gcc == []: gcc = None
    # Read string from gaussian output
    DATA_LAST = []
    DATA_WFCC = []
    key1, key2 = "\GINC-","@"
    strings = extract_string(lines,key1,key2,accumulate=True)
    for string in strings:
        lines = "".join([line.strip() for line in string.split()])
        lines = lines.split("\\\\")
        if lines == [""]: return None, None, None, None, None, None

        # lines[3]: ch, mtp, symbols, xcc
        str_geom = lines[3].split("\\")
        ch , mtp = str_geom[0].split(",")
        xcc      = []
        symbols  = []
        ch  = int(ch)
        mtp = int(mtp)
        E   = None
        masses = []
        for line in str_geom[1:]:
            coords = line.split(",")
            if   len(coords) == 4:
               symbol, x, y, z = line.split(",")
            else:
               symbol, tmp, x, y, z = line.split(",")
            xcc += [float(x),float(y),float(z)]
            symbols.append(symbol)
        xcc = [xi/ANGSTROM for xi in xcc] # in bohr
        # lines[4]: energy
        E = float(lines[4].split("HF=")[1].split("\\")[0])
        # Gradient
        if gcc is None or len(gcc) == 0: gcc = [0.0 for x in xcc]
        # Hessian
        Fcc = []
        for idx in range(len(lines)):
            line = lines[idx]
            if "NImag" not in line: continue
            Fcc = [float(fij) for fij in lines[idx+1].split(",")]
        # other lists
        atonums = get_atonums(symbols)
        masses  = atonums2masses(atonums)
        calclevel = ""
        # Does it have hessian?
        if Fcc != []: DATA_WFCC = [xcc, atonums, ch, mtp, E, gcc, Fcc, masses, calclevel]
        # Save data
        DATA_LAST = [xcc, atonums, ch, mtp, E, gcc, Fcc, masses, calclevel]
    # Use ONIOM extrapolated energy if found!
    if E_ONIOM is not None:
       if len(DATA_WFCC) != 0: DATA_WFCC[4] = E_ONIOM
       if len(DATA_LAST) != 0: DATA_LAST[4] = E_ONIOM
    # return
    if DATA_WFCC != []: return DATA_WFCC
    else              : return DATA_LAST
Exemplo n.º 10
0
def read_fchk(fchkfile):
    #------------------------#
    # The labels to look for #
    #------------------------#
    labels     = {}                              ; found_dict    = {}
    labels[0]  = "Number of atoms"               ; found_dict[0] = False
    labels[1]  = "Charge"                        ; found_dict[1] = False
    labels[2]  = "Multiplicity"                  ; found_dict[2] = False
    labels[3]  = "Total Energy"                  ; found_dict[3] = False
    labels[4]  = "Atomic numbers"                ; found_dict[4] = False
    labels[5]  = "Current cartesian coordinates" ; found_dict[5] = False
    labels[6]  = "Real atomic weights"           ; found_dict[6] = False
    labels[7]  = "Cartesian Gradient"            ; found_dict[7] = False
    labels[8]  = "Cartesian Force Constants"     ; found_dict[8] = False
    # mandatory labels in fchk
    idx_basic_labels = [0,1,2,3,4,5,6]
    # initialization
    natoms   = None ; ch     = None ; mtp  = None  ; E = None
    atonums  = []   ; masses = []
    xcc      = []   ; gcc    = []   ; Fcc  = []
    # read file
    lines = read_file(fchkfile)
    # check extension
    end_fchk = (fchkfile.lower()).endswith(".fchk")
    if (not end_fchk): raise Exc.FileType(Exception)
    # CHECK FILE IS FCHK
    correct = False
    for line in lines:
        if line.startswith("Current cartesian coordinates  "):
           correct = True
           break
    if not correct: raise Exc.FileType(Exception)
    # Get level of calculation
    calclevel = " ".join(lines[1].split()[1:])
    # get data from lines
    for idx in range(len(lines)):
        line = lines[idx]
        # Number of atoms
        if line.startswith(labels[0]):
            found_dict[0] = True
            natoms = int(line.split()[-1])
        # Charge
        elif line.startswith(labels[1]):
            found_dict[1] = True
            ch = int(line.split()[-1])
        # Spin multiplicity
        elif line.startswith(labels[2]):
            found_dict[2] = True
            mtp = int(line.split()[-1])
        # Total Energy
        elif line.startswith(labels[3]):
            found_dict[3] = True
            E = float(line.split()[-1])
        # Atomic Numbers
        elif line.startswith(labels[4]):
            found_dict[4] = True
            length = int(line.split()[-1])
            idx2   = idx+1
            while len(atonums) != length:
                  nextline = lines[idx2]
                  atonums += [int(i) for i in nextline.split()]
                  idx2    += 1
        # Cartesian Coordinates
        elif line.startswith(labels[5]):
            found_dict[5] = True
            length = int(line.split()[-1])
            idx2   = idx+1
            while len(xcc) != length:
                  nextline = lines[idx2]
                  xcc     += [float(i) for i in nextline.split()]
                  idx2    += 1
        # List of atomic masses
        elif line.startswith(labels[6]):
            found_dict[6] = True
            length = int(line.split()[-1])
            idx2   = idx+1
            while len(masses) != length:
                  nextline = lines[idx2]
                  masses  += [float(i) for i in nextline.split()]
                  idx2    += 1
        # Cartesian Gradient
        elif line.startswith(labels[7]) and natoms != 1:
            found_dict[7] = True
            length = int(line.split()[-1])
            idx2   = idx+1
            while len(gcc) != length:
                  nextline = lines[idx2]
                  gcc     += [float(i) for i in nextline.split()]
                  idx2    += 1
        # Cartesian Force Constant Matrix
        elif line.startswith(labels[8]) and natoms != 1:
            found_dict[8] = True
            length = int(line.split()[-1])
            idx2   = idx+1
            while len(Fcc) != length:
                  nextline = lines[idx2]
                  Fcc     += [float(fij) for fij in nextline.split()]
                  idx2    += 1
    # Return data
    #if gcc == []: gcc = None
    #if Fcc == []: Fcc = None
    return xcc,atonums,ch,mtp,E,gcc,Fcc,masses, calclevel.strip()
Exemplo n.º 11
0
def read_orcaout(orca_out):
    # Read lines
    lines = read_file(orca_out)
    # CHECK FILE IS ORCA OUT
    correct = False
    for line in lines:
        if "This ORCA versions uses" in line:
            correct = True
            break
    if not correct: raise Exc.FileType(Exception)
    # Initialize
    ch, mtp, E = None, None, None
    xcc, symbols, atonums = [], [], []
    # basis set
    basisset = ""
    try:
        for line in lines:
            if "utilizes the basis" in line:
                basisset = line.split(":")[1]
                break
    except:
        pass
    # hamiltonian
    hamiltonian = ""
    try:
        for idx, line in enumerate(lines):
            if "Hamiltonian:" in line:
                hamiltonian = lines[idx + 1].split()[-1]
                break
    except:
        pass
    # level of calculation
    calclevel = hamiltonian + " " + basisset
    # Get ch, mtp, E
    pos_cart = None
    pos_zmat = None
    for idx in range(len(lines)):
        line = lines[idx]
        if "Total Charge           Charge" in line: ch = int(line.split()[-1])
        if "Multiplicity           Mult" in line: mtp = int(line.split()[-1])
        if "FINAL SINGLE POINT ENERGY " in line: E = float(line.split()[-1])
        if "CARTESIAN COORDINATES (A.U.)" in line: pos_cart = idx
        if "INTERNAL COORDINATES (ANGST" in line: pos_zmat = idx
    # Get xcc, symbols, atonums
    if pos_cart is None:
        sys.exit(
            "Unable to find 'CARTESIAN COORDINATES (A.U.)' label in file!")
    pos_cart += 3
    for line in lines[pos_cart:]:
        line = line.strip()
        if line == "": break
        idx, symbol, atonum, dummy, mass, x, y, z = line.split()
        if symbol == "-": symbol = "XX"
        xcc += [float(x), float(y), float(z)]
        symbols.append(symbol)
        atonums.append(int(atonum.split(".")[0]))
    # data in internal coordinates
    lzmat = None
    if pos_zmat is not None:
        pos_zmat += 2
        lzmat = []
        for idx, line in enumerate(lines[pos_zmat:]):
            line = line.strip()
            if line == "": break
            symbol, atk, atj, ati, dist, angle, dihedral = line.split()
            if symbol == "-": symbol = "XX"
            atk, atj, ati = int(atk) - 1, int(atj) - 1, int(ati) - 1
            dist, angle, dihedral = float(dist), float(angle), float(dihedral)
            if idx == 0: connections, values = (), ()
            elif idx == 1: connections, values = (atk, ), (dist, )
            elif idx == 2: connections, values = (atk, atj), (dist, angle)
            else:
                connections, values = (atk, atj, ati), (dist, angle, dihedral)
            data = (symbol, connections, values)
            lzmat += [data]
    # Return
    return xcc, lzmat, atonums, ch, mtp, E, calclevel.strip()
Exemplo n.º 12
0
def normal_termination(ofile):
    olines = read_file(ofile)
    if len(olines) == 0: return False
    if "ORCA TERMINATED NORMALLY" not in olines[-2]:
        return False
    return True
Exemplo n.º 13
0
def start_end_blocks(plotfile):
    text = "".join(ff.read_file(plotfile))
    blocks = text.split("start_")[1:]
    blocks = [block.split("end_")[0] for block in blocks]
    return blocks
Exemplo n.º 14
0
def deal_with_anh(anhfile, ltemp, ZPEMSHO, QMSHO):
    RATIO = None
    DZPE = None
    string = ""
    while True:
        if anhfile is None: break
        anhfile = PN.ANHDIR + anhfile
        if not os.path.exists(anhfile):
            string += "Anharmonicity file '%s' NOT FOUND!\n" % anhfile
            string += "\n"
            break
        string += "Anharmonicity file '%s' FOUND!\n" % anhfile
        string += "\n"
        # read lines in file
        lines = read_file(anhfile)
        # type of file??
        itisq2dtor = False
        itismstor = False
        for line in lines[::-1]:
            if "End of Q2DTor output" in line:
                itisq2dtor = True
                break
            if "End of MSTor output" in line:
                itismstor = True
                break
        # get data
        if itisq2dtor:
            Tlist, ZPE_MSHO, Q_MSHO, ZPE_ANH, Q_ANH = read_q2dtorout(anhfile)
        elif itismstor:
            Tlist, ZPE_MSHO, Q_MSHO, ZPE_ANH, Q_ANH = read_mstorout(anhfile)
        else:
            string += "  * unable to identify the program where this file come from...\n"
            string += "\n"
            break
        # print info
        if None in (ZPE_MSHO, Q_MSHO, ZPE_ANH, Q_ANH):
            string += "  * unable to read the file properly...\n"
            string += "\n"
            break
        # print zpe
        string += "  * Data in file:\n"
        string += "\n"
        string += "      ZPE_MSHO: %.8f hartree\n" % ZPE_MSHO
        string += "      ZPE_ANH : %.8f hartree\n" % ZPE_ANH
        string += "\n"
        # compare list of temperatures
        string += "  * checking list of temperatures\n"
        common = []
        for idxT1, T1 in enumerate(Tlist):
            for idxT2, T2 in enumerate(ltemp):
                if abs(T1 - T2) < EPS_TEMP: common.append(idxT1)
        string += "    num_temps(%s) = %i\n" % (PN.IFILE2, len(ltemp))
        string += "    num_temps(%s) = %i\n" % (anhfile, len(Tlist))
        string += "    in common --> %i\n" % (len(common))
        if len(common) != len(ltemp):
            string += "    differences in temperatures detected [FAIL]\n"
            break
        elif len(common) != len(Tlist):
            Tlist = [Tlist[idxT] for idxT in common]
            Q_MSHO = [Q_MSHO[idxT] for idxT in common]
            Q_ANH = [Q_ANH[idxT] for idxT in common]
        string += "    temperatures match! [OK]\n"
        string += "\n"
        # print partition functions
        thead = "  T  (K)  |   Q_MSHO   |   Q_ANH    "
        tdivi = "-" * len(thead)
        string += "      " + tdivi + "\n"
        string += "      " + thead + "\n"
        string += "      " + tdivi + "\n"
        for idx, T in enumerate(Tlist):
            tline = " %8.2f | %10.3E | %10.3E " % (T, Q_MSHO[idx], Q_ANH[idx])
            string += "      " + tline + "\n"
        string += "      " + tdivi + "\n"
        string += "\n"
        # compare ZPE of MSHO
        string += "  * checking MSHO data...\n"
        maxdiff = abs(ZPE_MSHO - ZPEMSHO) * KCALMOL
        if maxdiff < 0.1:
            string += "    abs. diff. in ZPE is %.1E kcal/mol [OK]\n" % maxdiff
        else:
            string += "    abs. diff. in ZPE is %.1E kcal/mol [FAIL]\n" % maxdiff
            break
        # compare pfn of MSHO
        maxdiff = 100 * max(
            [abs(pi - pj) / pi for pi, pj in zip(QMSHO, Q_MSHO)])
        if maxdiff < 2.0:
            string += "    max. rel. diff in MSHO partition function is %.1E%% [OK]\n" % maxdiff
        else:
            string += "    max. rel. diff in MSHO partition function is %.1E%% [FAIL]\n" % maxdiff
            break
        string += "\n"
        # calculate ratio
        string += "  * Calculating anh. ratio = Q_ANH/Q_MSHO * exp(-(ZPE_ANH-ZPE_MSHO)*beta)\n"
        string += "\n"
        DZPE = ZPE_ANH - ZPE_MSHO
        RATIO = [(Q_ANH[idx] / Q_MSHO[idx]) * exp128(-DZPE / KB / T)
                 for idx, T in enumerate(ltemp)]
        # print partition functions
        thead = "  T  (K)  | ANH. RATIO "
        tdivi = "-" * len(thead)
        string += "      " + tdivi + "\n"
        string += "      " + thead + "\n"
        string += "      " + tdivi + "\n"
        for idx, T in enumerate(ltemp):
            tline = " %8.2f | %10.3E " % (T, RATIO[idx])
            string += "      " + tline + "\n"
        string += "      " + tdivi + "\n"
        string += "\n"
        break
    return RATIO, string
Exemplo n.º 15
0
def deal_with_anh(anhfile, ltemp, ZPEMSHO, QMSHO):
    RATIO = None
    DZPE = None
    string = ""
    while True:
        if anhfile is None: break
        anhfile = PN.ANHDIR + anhfile
        if not os.path.exists(anhfile):
            string += "Anharmonicity file '%s' NOT FOUND!\n" % anhfile
            string += "\n"
            break
        string += "Anharmonicity file '%s' FOUND!\n" % anhfile
        string += "\n"
        # read lines in file
        lines = read_file(anhfile)
        # type of file??
        itisq2dtor = False
        itismstor = False
        for line in lines[::-1]:
            if "End of Q2DTor output" in line:
                itisq2dtor = True
                break
            if "End of MSTor output" in line:
                itismstor = True
                break
        # get data
        if itisq2dtor:
            Tlist, ZPE_MSHO, Q_MSHO, ZPE_ANH, Q_ANH = read_q2dtorout(anhfile)
        elif itismstor:
            Tlist, ZPE_MSHO, Q_MSHO, ZPE_ANH, Q_ANH = read_mstorout(anhfile)
        else:
            string += "  * unable to identify the program where this file come from...\n"
            string += "\n"
            break
        # print info
        if None in (ZPE_MSHO, Q_MSHO, ZPE_ANH, Q_ANH):
            string += "  * unable to read the file properly...\n"
            string += "\n"
            break
        # print zpe
        string += "  * Data in file:\n"
        string += "\n"
        string += "      ZPE_MSHO: %.8f hartree\n" % ZPE_MSHO
        string += "      ZPE_ANH : %.8f hartree\n" % ZPE_ANH
        string += "\n"
        # print partition functions
        thead = "  T  (K)  |   Q_MSHO   |   Q_ANH    "
        tdivi = "-" * len(thead)
        string += "      " + tdivi + "\n"
        string += "      " + thead + "\n"
        string += "      " + tdivi + "\n"
        for idx, T in enumerate(Tlist):
            tline = " %8.2f | %10.3E | %10.3E " % (T, Q_MSHO[idx], Q_ANH[idx])
            string += "      " + tline + "\n"
        string += "      " + tdivi + "\n"
        string += "\n"
        # compare list of temperatures
        string += "  * checking list of temperatures\n"
        if len(Tlist) != len(ltemp):
            string += "    different size (%i vs %i) [FAIL]\n" % (len(ltemp),
                                                                  len(Tlist))
            break
        else:
            string += "    same number of temperatures (%i) [OK]\n" % (
                len(ltemp))
        maxdiff = max([abs(t1 - t2) for t1, t2 in zip(ltemp, Tlist)])
        if maxdiff > EPS_TEMP:
            string += "    temperatures differ more than %.2E Kelvin [FAIL]\n" % (
                EPS_TEMP)
            break
        else:
            string += "    max. abs. diff in temperatures is %.2E Kelvin [OK]\n" % (
                maxdiff)
        string += "\n"
        # compare ZPE of MSHO
        string += "  * checking MSHO data...\n"
        maxdiff = (ZPE_MSHO - ZPEMSHO) * KCALMOL
        if maxdiff < 0.1:
            string += "    abs. diff. in ZPE is %.1E kcal/mol [OK]\n" % maxdiff
        else:
            string += "    abs. diff. in ZPE is %.1E kcal/mol [FAIL]\n" % maxdiff
            break
        # compare pfn of MSHO
        maxdiff = 100 * max(
            [abs(pi - pj) / pi for pi, pj in zip(QMSHO, Q_MSHO)])
        if maxdiff < 1.0:
            string += "    max. rel. diff in MSHO partition function is %.1E%% [OK]\n" % maxdiff
        else:
            string += "    max. rel. diff in MSHO partition function is %.1E%% [FAIL]\n" % maxdiff
            break
        string += "\n"
        # calculate ratio
        string += "  * Calculating anh. ratio = Q_ANH/Q_MSHO * exp(-(ZPE_ANH-ZPE_MSHO)*beta)\n"
        string += "\n"
        DZPE = ZPE_ANH - ZPE_MSHO
        RATIO = [(Q_ANH[idx] / Q_MSHO[idx]) * np.exp(-DZPE / KB / T)
                 for idx, T in enumerate(ltemp)]
        # print partition functions
        thead = "  T  (K)  | ANH. RATIO "
        tdivi = "-" * len(thead)
        string += "      " + tdivi + "\n"
        string += "      " + thead + "\n"
        string += "      " + tdivi + "\n"
        for idx, T in enumerate(ltemp):
            tline = " %8.2f | %10.3E " % (T, RATIO[idx])
            string += "      " + tline + "\n"
        string += "      " + tdivi + "\n"
        string += "\n"
        break
    return RATIO, string