tooba_f.py 7.48 KB
Newer Older
Stelios Karozis's avatar
Stelios Karozis committed
1 2 3
import numpy as np
import scipy.optimize

4
#from mpl_toolkits.mplot3d import Axes3D
Stelios Karozis's avatar
Stelios Karozis committed
5 6
import matplotlib.pyplot as plt

Stelios Karozis's avatar
Stelios Karozis committed
7 8 9 10 11 12
from pytrr import (
    read_trr_header,
    read_trr_data,
    skip_trr_data,
    )

Stelios Karozis's avatar
Stelios Karozis committed
13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
def fitPlaneLTSQ(XYZ):
    (rows, cols) = XYZ.shape
    G = np.ones((rows, 3))
    G[:, 0] = XYZ[:, 0]  #X
    G[:, 1] = XYZ[:, 1]  #Y
    Z = XYZ[:, 2]
    (a, b, c),resid,rank,s = np.linalg.lstsq(G, Z, rcond=None)
    normal = (a, b, -1)
    nn = np.linalg.norm(normal)
    normal = normal / nn
    return (c, normal)

def angle_between2D(p1, p2):
    #arctan2 is anticlockwise
    ang1 = np.arctan2(*p1[::-1])
    ang2 = np.arctan2(*p2[::-1])
    angle=np.rad2deg((ang1 - ang2) % (2 * np.pi)) #degree
    if angle<180:
        return angle
    else:
        return 360 - angle

def angle_between3D(v1, v2):
# v1 is your firsr vector
# v2 is your second vector
    angle = np.arccos(np.dot(v1, v2) / (np.linalg.norm(v1) * np.linalg.norm(v2))) #rad
    angle=180*angle/np.pi #degrees
    if angle<180:
        return angle
    else:
        return 360 - angle

Stelios Karozis's avatar
Stelios Karozis committed
45
def plot_surf(data, normal, c):
Stelios Karozis's avatar
Stelios Karozis committed
46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
    #Plot surface
    fig = plt.figure()
    ax = fig.gca(projection='3d')

    # plot fitted plane
    maxx = np.max(data[:,0])
    maxy = np.max(data[:,1])
    minx = np.min(data[:,0])
    miny = np.min(data[:,1])

    point = np.array([0.0, 0.0, c])
    d = -point.dot(normal)

    # plot original points
    ax.scatter(data[:, 0], data[:, 1], data[:, 2])

    # compute needed points for plane plotting
    xx, yy = np.meshgrid([minx, maxx], [miny, maxy])
    z = (-normal[0]*xx - normal[1]*yy - d)*1. / normal[2]

    # plot plane
    ax.plot_surface(xx, yy, z, alpha=0.2)

    ax.set_xlabel('x')
    ax.set_ylabel('y')
    ax.set_zlabel('z')
    plt.show()

def count_frames(trajfile='traj.trr'):
75 76 77 78 79
    """
    Count total frames of .trr file

    parameters:     trajfile = [.trr]
    """
Stelios Karozis's avatar
Stelios Karozis committed
80 81 82 83 84 85 86 87 88 89 90 91
    cnt_fr=0
    with open(trajfile, 'rb') as inputfile:
        for i in range(1000):
            try: 
                header = read_trr_header(inputfile)
                #print('Step: {step}, time: {time}'.format(**header))
                skip_trr_data(inputfile, header)
                cnt_fr=cnt_fr+1
            except EOFError:
                pass
    return cnt_fr

Stelios Karozis's avatar
Stelios Karozis committed
92
def fr_export(trajfile='traj.trr', num_frames=1):
93 94 95 96 97 98 99
    """
    Export frames from gromacs .trr file. 

    parameters:     trajfile = [.trr]
                    num_frames = [number of frames to keep
                                  counting from the end of file]
    """
Stelios Karozis's avatar
Stelios Karozis committed
100
    cnt_fr=count_frames(trajfile)
101
    data_all={}
Stelios Karozis's avatar
Stelios Karozis committed
102
    with open(trajfile, 'rb') as inputfile:
Stelios Karozis's avatar
Stelios Karozis committed
103
        for i in range(cnt_fr-num_frames):
Stelios Karozis's avatar
Stelios Karozis committed
104 105 106
            header = read_trr_header(inputfile)
            #print('Step: {step}, time: {time}'.format(**header))
            skip_trr_data(inputfile, header)
107 108
        for i in range(cnt_fr-num_frames,cnt_fr):
            header = read_trr_header(inputfile)
109
            #print('Step: {step}, time: {time}'.format(**header))
110 111 112 113
            data = read_trr_data(inputfile, header)
            step='{step}'.format(**header)
            data_all[step]=data
        return data_all
Stelios Karozis's avatar
Stelios Karozis committed
114

Stelios Karozis's avatar
Stelios Karozis committed
115
def read_gro(gro):
116 117 118 119 120 121 122 123 124 125 126 127 128
    """
    Read .gro file and exports 
    1. system name
    2. data number
    3. box size
    4. residue number
    5. residue type
    6. atom type
    7. atom number
    8. free format data (x,y,z,v,u,w)

    parameters:     gro = [.gro]
    """
Stelios Karozis's avatar
Stelios Karozis committed
129 130
    cnt=0
    data_num=0
Stelios Karozis's avatar
Stelios Karozis committed
131 132 133 134 135
    res_num = [] 
    res_type = []  
    atom_type = [] 
    atom_num  = []
    rest_dt = []
Stelios Karozis's avatar
Stelios Karozis committed
136 137 138
    with open(gro, 'r') as F:
        for line in F:
            cnt=cnt+1
139 140
            #print(cnt)
            if cnt>2 and cnt<=data_num+2:
Stelios Karozis's avatar
Stelios Karozis committed
141 142 143 144 145
                res_num.append(line[:5])  
                res_type.append(line[5:10])  
                atom_type.append(line[10:15]) 
                atom_num.append(line[15:20])
                rest_dt.append(line[20:])
Stelios Karozis's avatar
Stelios Karozis committed
146 147 148 149
            elif cnt==1:
                system=line[:10]
            elif cnt==2:
                data_num=int(line[:7])
150
            elif cnt>data_num+2:
Stelios Karozis's avatar
Stelios Karozis committed
151
                box_size=line[:50]
Stelios Karozis's avatar
Stelios Karozis committed
152
        #print(system,data_num,box_size)
153 154 155 156
        return system,data_num,box_size,res_num,res_type,atom_type,atom_num,rest_dt

def domain_decomposition(data,dx,dy,dz):
    """
157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216
    Identify subdomain for each frame of 
    of .trr frame

    parameters:     data = {dictionary input from 'def fr_export'}
                    dx = desired size X of subdomain {units of input}
                    dy = desired size Y of subdomain {units of input}
                    dz = desired size Z of subdomain {units of input}
    
    output:         dictionary of x,y,z grid points per step (frame)
    """
    box_p={}
    for step in data.keys():
        box_p[step]={}
        xs=int(round(data[step]['box'][0][0]+0.1)) #to round always to bigger number
        ys=int(round(data[step]['box'][1][1]+0.1))
        zs=int(round(data[step]['box'][2][2]+0.1))
        box_x=int(xs/dx)
        box_y=int(ys/dy)
        box_z=int(zs/dz)

        xx=[]
        for i in range(0,xs+1,box_x):
            xx.append(i)
        box_p[step]['x']=xx

        yy=[]
        for i in range(0,ys+1,box_y):
            yy.append(i)
        box_p[step]['y']=yy

        zz=[]
        for i in range(0,zs+1,box_z):
            zz.append(i)
        box_p[step]['z']=zz


        xyz=[]
        for ix in range(0,xs+1,box_x):
          for iy in range(0,ys+1,box_y):
            for iz in range(0,zs+1,box_z):
                xyz.append([ix,iy,iz])
        box_p[step]['xyz']=xyz

    return box_p

def resid_data(atom_type, group=[]):
    """
    Finds the index in list that 'def read_gro' returns,
    and correspond to the atom types in group list

    parameters:     atom_type=[]
                    group=[]

    output:         dictionary
    """
    ndx={}
    for element in group:
        ndx[element]=[i for i, e in enumerate(atom_type) if e.strip() == element.strip()]
        #print(element,ndx)
    return ndx
217

218
def res2grid(data, atom_num, box_p, ndx):
219
    """
220 221 222 223 224 225 226 227 228 229 230 231 232
    Assign residue that corresponds to ndx (see 'def resid_data')
    to sudomains created from 'def domain_decomposition'. The output
    is a the box location (non zero based) in xyz-space for each atom number.

    parameters:     data = {dictionary input from 'def fr_export'}
                    atom_num = [list from 'def read_gro']
                    box_p = {dictionary input from 'def domain_decomposition'}
                    ndx = {dictionary input from 'def resid_data'}

    output:         dictionary
    """

    box_res={}
233
    for step in data.keys():
234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266
        box_res[step]={}
        for key in ndx.keys():
            for i in ndx[key]:
                #data[step]['x'][atom_num][x(0),y(1),z(2)]

                xx=data[step]['x'][i][0]
                cnt_x=-1
                prev=-1
                for ix in box_p[step]['x']:
                    cnt_x=cnt_x+1
                    if xx<ix and xx>prev:
                        prev=ix
                        break

                yy=data[step]['x'][i][1]
                cnt_y=-1
                prev=-1
                for iy in box_p[step]['y']:
                    cnt_y=cnt_y+1
                    if yy<iy and yy>prev:
                        prev=iy
                        break

                zz=data[step]['x'][i][2]
                cnt_z=-1
                prev=-1
                for iz in box_p[step]['z']:
                    cnt_z=cnt_z+1
                    if zz<iz and zz>prev:
                        prev=iz
                        break
                box_res[step][atom_num[i]]=[cnt_x,cnt_y,cnt_z]
    return box_res