Structural bionformatics. Homework №5

Elen Tevanyan

In [2]:
%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt
from scipy import optimize
import math
import subprocess
In [4]:
def run_orca(inp):
    with open('orca.inp', 'w') as outfile:
        outfile.write(inp)
    p = subprocess.Popen("/home/shad/progs/bin/orca orca.inp", 
                          shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    out=p.communicate()[0]
    
    # extract energy: FINAL SINGLE POINT ENERGY'
    for i in out.splitlines():
        if i.startswith("FINAL SINGLE POINT ENERGY"):
            return(float(i[len("FINAL SINGLE POINT ENERGY"):]))
    # and return it as float
    return out.splitlines()
In [53]:
def dependency_plot (x,y,plt_title,lim1,lim2):
    x_o = x
    y_o = y
    #function is  f(x)=k(b-x)^2 + a
    fitfunc = lambda p, x: p[0]*pow(p[1]-x,2) + p[2] # Target function
    errfunc = lambda p, x, y: fitfunc(p, x) - y # Error function
    p0 = [1,1, -79] # Initial guess for the parameters
    
    p1, success = optimize.leastsq(errfunc, p0[:], args=(x_o, y_o))
    print "Optimized params:", p1
    #Plot it
    plt.plot(x_o, y_o, "ro", x_o,fitfunc(p1,x_o),"r-",c='blue',alpha=0.5)
    plt.xlim(lim1,lim2)
    plt.title(plt_title)
    plt.show()

1. Длины связей
Текущая длина связи "С-С" 1.52986. Генерируем 20 возможных длин связи с шагом в 0.02 ангстрема.

In [9]:
length = np.arange(-10,11)*0.02 + 1.52986
print (length)
[ 1.32986  1.34986  1.36986  1.38986  1.40986  1.42986  1.44986  1.46986
  1.48986  1.50986  1.52986  1.54986  1.56986  1.58986  1.60986  1.62986
  1.64986  1.66986  1.68986  1.70986  1.72986]

Записываем функцию для подготовки файлов с разными длинами связей

In [11]:
def inp_file(length):
    inp = '''!HF RHF 6-31G
    * int 0 1
    C 0 0 0 0 0 0 
    C 1 0 0 {} 0 0 
    H 1 2 0 1.08439 111.200 0
    H 1 2 3 1.08439 111.200 120
    H 1 2 3 1.08439 111.200 -120
    H 2 1 3 1.08439 111.200 180
    H 2 1 5 1.08439 111.200 120
    H 2 1 5 1.08439 111.200 -120
    *
    '''.format(length)
    return inp
    

Считаем энергию

In [13]:
energy = []
for i in length:
    energy.append(run_orca(inp_file(i)))

print('Energy levels')
print(energy)
In [54]:
name = 'Bond Length and Energy Dependency'
dependency_plot(length,energy, name,1,2)
Optimized params: [  0.63991948   1.55699288 -79.08219402]

Аппроксимация не идеальная, но вполне аккуратная и улавливающая суть колебаний

2. Валентные углы
Значения валентного угла должны изменяться от 109.2 до 113.2 Cчитаем, что все еще 20 различных значений ожидаются, поэтому шаг $$|\frac{113.2-109.2}{20}|=0.2$$

In [35]:
angle = np.arange(-10,11)*0.2+111.2
print(angle)
[ 109.2  109.4  109.6  109.8  110.   110.2  110.4  110.6  110.8  111.
  111.2  111.4  111.6  111.8  112.   112.2  112.4  112.6  112.8  113.
  113.2]

Записываем функцию для генерации файлов с разными валентными углами.

In [48]:
def inp_file_angle(angle):
    inp = '''!HF RHF 6-31G
    * int 0 1
    C 0 0 0 0 0 0 
    C 1 0 0 1.52986 0 0 
    H 1 2 0 1.08439 {0} 0
    H 1 2 3 1.08439 {0} 120
    H 1 2 3 1.08439 {0} -120
    H 2 1 3 1.08439 {0} 180
    H 2 1 5 1.08439 {0} 120
    H 2 1 5 1.08439 {0} -120
    *
    '''.format(angle)
    return inp
In [50]:
energy_angle = []
for i in angle:
    energy_angle.append(run_orca(inp_file_angle(i)))
print('Energy levels')
print(energy_angle)
Energy levels
[-79.078791124966, -79.079183399887, -79.079549472852, -79.07988931153, -79.080202891616, -79.080490187722, -79.080751172795, -79.080985818069, -79.08119409307, -79.081375965652, -79.081531402161, -79.081660366819, -79.081762822554, -79.081838730525, -79.081888050195, -79.081910739351, -79.081906754045, -79.081876048815, -79.081818576377, -79.081734287686, -79.081623132149]
In [56]:
name = 'Bond Angle and Energy Dependency'
dependency_plot(angle,energy_angle, name, 108,114)
Optimized params: [  3.31057582e-04   1.12270870e+02  -7.90819111e+01]

Подозрительно удачная аппроксимация

3. Торсионные углы
Торсионный угол CС изменяется от -180 до 180 c шагом 12

In [58]:
torsion = np.arange(-15,16)*12
print(torsion)
[-180 -168 -156 -144 -132 -120 -108  -96  -84  -72  -60  -48  -36  -24  -12
    0   12   24   36   48   60   72   84   96  108  120  132  144  156  168
  180]
In [61]:
def inp_file_torsion(torsion):
    torsion_1 = torsion - 60
    torsion_2 = torsion +60
    inp = '''!HF RHF 6-31G
    * int 0 1
    C 0 0 0 0 0 0 
    C 1 0 0 1.52986 0 0 
    H 1 2 0 1.08439 111.200 0
    H 1 2 3 1.08439 111.200 120
    H 1 2 3 1.08439 111.200 -120
    H 2 1 3 1.08439 111.200 {0}
    H 2 1 5 1.08439 111.200 {1}
    H 2 1 5 1.08439 111.200 {2}
    *
    '''.format(torsion, torsion_1, torsion_2)
    return inp
In [62]:
energy_torsion = []
for i in torsion:
    energy_torsion.append(run_orca(inp_file_torsion(i)))
print('Energy levels')
print(energy_torsion)
Energy levels
[-79.081531425441, -79.082613733242, -79.083665197014, -79.084283343101, -79.084235490395, -79.083542971541, -79.082468786938, -79.081419140127, -79.080793992197, -79.080835703972, -79.081531425731, -79.082613733261, -79.083665196902, -79.084283343103, -79.084235490374, -79.083542971544, -79.082468786883, -79.081419140194, -79.080793992237, -79.080835704057, -79.081531425784, -79.082613733277, -79.083665197014, -79.084283343103, -79.084235490391, -79.083542971545, -79.082468786931, -79.081419140068, -79.080793992183, -79.080835703989, -79.081531425729]
In [64]:
name = 'Torsion angle and Energy Dependency'
dependency_plot(torsion,energy_torsion, name, -190,190)
Optimized params: [  1.33506732e-08  -8.76801886e+01  -7.90827629e+01]

У функции три минимума.
Аппроксимируется квадратичной функцией из рук вон плохо; визуально похожа на циклическую функцию (синус, косинус).
Попробуем такую функцию
$$ f(x) = a\cdot sin(b\cdot x+c)+d$$

In [69]:
    x_o = torsion
    y_o = energy_torsion

    fitfunc = lambda p, x: p[0]*np.sin(p[1]*x+p[2]) + p[3] # Target function
    errfunc = lambda p, x, y: fitfunc(p, x) - y # Error function
    p0 = [1,1, -79,1] # Initial guess for the parameters
    
    p1, success = optimize.leastsq(errfunc, p0[:], args=(x_o, y_o))
    print "Optimized params:", p1
    #Plot it
    plt.plot(x_o, y_o, "ro", x_o,fitfunc(p1,x_o),"r-",c='blue',alpha=0.5)
    plt.xlim(-190,190)
    plt.title(name)
    plt.show()
Optimized params: [  1.81239041e-03   9.94840950e-01  -7.79514233e+01  -7.90825389e+01]

А вот теперь аппроксимация выглядит значительно лучше

4. Длины связи с увеличинным шагом
Текущая длина связи "С-С" 1.52986. Генерируем 20 возможных длин связи с шагом в 0.1 ангстрема.

In [71]:
length_2 = np.arange(-10,11)*0.1 + 1.52986
print (length_2)
[ 0.52986  0.62986  0.72986  0.82986  0.92986  1.02986  1.12986  1.22986
  1.32986  1.42986  1.52986  1.62986  1.72986  1.82986  1.92986  2.02986
  2.12986  2.22986  2.32986  2.42986  2.52986]
In [73]:
energy_2 = []
for i in length_2:
    energy_2.append(run_orca(inp_file(i)))

print('Energy levels')
print(energy_2)
Energy levels
[-73.376057908564, -75.600038674086, -76.986925190758, -77.840020402069, -78.364137030278, -78.683902686411, -78.875495245128, -78.986233920144, -79.045965568718, -79.07368949118, -79.081531419723, -79.077218664924, -79.065654757297, -79.049930677904, -79.031982697254, -79.013023521422, -78.993820247811, -78.974866462702, -78.956483580267, -78.938878296987, -78.922175247055]
In [78]:
name = 'Bond Length and Energy Dependency witn Increased Step'
dependency_plot(length_2,energy_2, name,0,3)
Optimized params: [  2.64135255   1.81379258 -79.55943724]

Квадратичная аппроксимация неудачна. Из стандартных функций можно попробовать что-то из семейства $e^{-x}$: $$f(x)=a\cdot e^{-b\cdot x+c}+d$$

In [79]:
lim1 = 0
lim2 = 3
x_o = length_2
y_o = energy_2

fitfunc = lambda p, x: p[0]*np.exp(p[1]*x+p[2]) + p[3] # Target function
errfunc = lambda p, x, y: fitfunc(p, x) - y # Error function
p0 = [1,1, 1,1] # Initial guess for the parameters
    
p1, success = optimize.leastsq(errfunc, p0[:], args=(x_o, y_o))
print "Optimized params:", p1
#Plot it
plt.plot(x_o, y_o, "ro", x_o,fitfunc(p1,x_o),"r-",c='blue',alpha=0.5)
plt.xlim(lim1,lim2)
plt.title(name)
plt.show()
Optimized params: [  3.24680361  -5.24264176   3.34318254 -79.04492107]

Экспонентой аппроксимируется куда лучше.

Сравнение констант со статьей
1) Длина связи

Эмпирическое уравнение для связей С-С (Figure_2) из статьи:
$$ ln(K_r) = -4.9575\cdot r +7.8187 $$ Оптимальная длиная связи (по статье): $$ r = 1.526 $$ Тогда $$K_r^1 = exp(-4.9526\cdot 1.526 +7.8187) = 306.582\,Ккал/моль$$ У меня: $$K_r^2 = 0.63991948 E_h$$ Переведем в Ккал/моль: $$1 \;Хартри = 627,51\,ккал/моль$$ $$K_r^2=0.63991948\cdot 627,51=401.56\,Ккал/моль$$

2) Валентные углы

В статье пишут, что когда один из крайних атомов - углерод, константа получается около 50 Ккал/моль/рад^-2 (стр.1165)

In [ ]: