Skip to content

Commit 5611407

Browse files
authored
Merge pull request #6 from Pranavkhade/compliance-integration
Compliance integration
2 parents d0cc14b + c800128 commit 5611407

File tree

6 files changed

+195
-6
lines changed

6 files changed

+195
-6
lines changed

packman/anm/__init__.py

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
from .anm import ANM

packman/anm/anm.py

+143
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
'''
2+
Author: Pranav Khade (pranavk@iastate.edu)
3+
'''
4+
5+
import numpy
6+
7+
8+
'''
9+
##################################################################################################
10+
# ANM #
11+
##################################################################################################
12+
'''
13+
14+
class ANM:
15+
def __init__(self, coords , gamma=1.0, dr=15.0, power=0, pf=None):
16+
"""
17+
Author: Pranav Khade
18+
Part Credits: Ambuj Kumar (ambuj@iastate.edu)
19+
"""
20+
self.gamma = gamma
21+
self.dr = dr
22+
self.power = power
23+
self.pf = pf
24+
self.coords = numpy.array(coords)
25+
if self.pf != None and self.pf <= 0:
26+
raise Exception("pf value cannot be zero or negative")
27+
if self.gamma <= 0:
28+
raise Exception("gamma value cannot be zero or negative")
29+
if self.dr <= 0:
30+
raise Exception("distance cutoff value cannot be zero or negative")
31+
32+
self.fluctuations = None
33+
self.stiffness_map = None
34+
self.compliance_map = None
35+
self.stiffness_profile = None
36+
self.compliance_profile = None
37+
38+
39+
'''Get Functions'''
40+
def get_hessian(self):
41+
return self.hessian
42+
43+
def get_eigenvalues(self):
44+
return self.eigen_values
45+
46+
def get_eigenvectors(self):
47+
return self.eigen_vectors
48+
49+
def get_fluctuations(self):
50+
return self.fluctuations
51+
52+
def get_stiffness_map(self):
53+
return self.stiffness_map
54+
55+
def get_compliance_map(self):
56+
return self.compliance_map
57+
58+
def get_stiffness_profile(self):
59+
return self.stiffness_profile
60+
61+
def get_compliance_profile(self):
62+
return self.compliance_profile
63+
64+
65+
'''Calculate Functions'''
66+
def calculate_hessian(self):
67+
n_atoms=len(self.coords)
68+
hessian=numpy.zeros((n_atoms*3, n_atoms*3), float)
69+
distance_mat=numpy.ones((n_atoms*3, n_atoms*3), float)
70+
for i in range(len(self.coords)):
71+
diff = self.coords[i+1:, :] - self.coords[i]
72+
squared_diff = diff**2
73+
for j, s_ij in enumerate(squared_diff.sum(1)):
74+
if s_ij <= self.dr**2:
75+
diff_coords = diff[j]
76+
j = j + i + 1
77+
derivative = numpy.outer(diff_coords, diff_coords)*(float(-self.gamma)/numpy.sqrt(s_ij)**(2+self.power))
78+
hessian[i*3:i*3+3, j*3:j*3+3] = derivative
79+
hessian[j*3:j*3+3, i*3:i*3+3] = derivative
80+
hessian[i*3:i*3+3, i*3:i*3+3] = hessian[i*3:i*3+3, i*3:i*3+3] - derivative
81+
hessian[j*3:j*3+3, j*3:j*3+3] = hessian[j*3:j*3+3, j*3:j*3+3] - derivative
82+
#abs added to avoid negative numbers
83+
d = numpy.sqrt(s_ij)
84+
lobj = [[d,d,d],[d,d,d], [d,d,d]]
85+
dmat = numpy.array(lobj)
86+
distance_mat[i*3:i*3+3, j*3:j*3+3] = dmat
87+
88+
if self.pf != None:
89+
hessian = numpy.divide(hessian, distance_mat)
90+
91+
self.hessian=hessian
92+
return True
93+
94+
def calculate_decomposition(self):
95+
'''
96+
'''
97+
self.eigen_values,self.eigen_vectors=numpy.linalg.eigh(self.hessian)
98+
return True
99+
100+
def calculate_fluctuations(self,endmode=None):
101+
'''
102+
'''
103+
EVec=self.eigen_vectors.T
104+
mode_bfactors=[]
105+
for numi,i in enumerate(self.eigen_values[6:]):
106+
evec_row=EVec[numi+6]
107+
mode_bfactors.append([ float(evec_row[j]**2 + evec_row[j+1]**2 + evec_row[j+2]**2)/i for j in range(0,len(self.eigen_values),3)])
108+
109+
mode_bfactors=numpy.array(mode_bfactors)
110+
self.fluctuations=[numpy.sum(i) for i in mode_bfactors.T]
111+
return True
112+
113+
114+
def calculate_stiffness_compliance(self):
115+
'''
116+
'''
117+
EVec=self.eigen_vectors.T
118+
hessian_inv= numpy.matmul( numpy.matmul( EVec[6:].transpose() , numpy.diag(1/self.get_eigenvalues()[6:]) ) , EVec[6:] )
119+
compliance_map=numpy.zeros((len(self.coords),len(self.coords)))
120+
stiffness_map=numpy.zeros((len(self.coords),len(self.coords)))
121+
122+
for numi,i in enumerate(self.coords):
123+
for numj,j in enumerate(self.coords):
124+
if(numi!=numj):
125+
FMAT=numpy.zeros((len(self.coords),3))
126+
Fij=(j-i)/numpy.linalg.norm(i-j)
127+
FMAT[numi]=-Fij
128+
FMAT[numj]=Fij
129+
FMAT=FMAT.flatten()
130+
131+
d=numpy.matmul(hessian_inv,FMAT)
132+
133+
compliance= (d[(numj*3)+0]-d[(numi*3)+0])*Fij[0] + (d[(numj*3)+1]-d[(numi*3)+1])*Fij[1] + (d[(numj*3)+2]-d[(numi*3)+2])*Fij[2]
134+
stiffness= 1/ compliance
135+
136+
compliance_map[numi][numj]= compliance
137+
stiffness_map[numi][numj] = stiffness
138+
139+
self.stiffness_map = stiffness_map
140+
self.compliance_map = compliance_map
141+
self.stiffness_profile = [numpy.nanmean(i) for i in stiffness_map]
142+
self.compliance_profile = [numpy.nanmean(i) for i in compliance_map]
143+
return True

packman/molecule/__init__.py

+25
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,28 @@
1+
# -*- coding: utf-8 -*-
2+
# Author: Pranav Khade, Iowa State University
3+
# Please read the project licence file for the Copyrights.
4+
5+
"""The 'packman.molecule' module is used to read, write, manipulate and analyze the molecule.
6+
7+
This module is the base of the tool packman. It is used as a base module for all the packman utilities
8+
such as HingePrediction, Compliance and Right Domain ANM. The molecule module can also be an API to utilize the objects such
9+
as Atom, Residue, Chain, Model and Protein. Please read the documentation and tutorials for more details.
10+
11+
Example:
12+
To Load the
13+
14+
>>>from packman import molecule
15+
>>>molecule.download_structure('1prw','1prw.pdb')
16+
>>>molecule.load_structure('1prw.pdb')
17+
<packman.molecule.protein.Protein object at Memory>
18+
19+
Todo:
20+
* Add new features
21+
* Use ``sphinx.ext.todo`` extension
22+
23+
"""
24+
25+
126
#Parser Functions
227
from .molecule import download_structure
328
from .molecule import load_structure

packman/molecule/atom.py

+20-3
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,15 @@
66

77

88
class Atom():
9-
"""
10-
This class contains the information about the Atom.
9+
"""This class contains the information about the Atom.
10+
11+
This class contains all the information available about the Atom. The Atom class is the lowest in the hierarchy of the 'molecule' API classes.
12+
the order of hierarchy being: Protein> Model> Chain> Residue> Atom. This class is also the component of the 'molecule' module API.
13+
Please read the Tutorials and Documentation for more details.
14+
15+
Properties created with the ``@property`` decorator should be documented
16+
in the property's getter method.
17+
1118
"""
1219
def __init__(self,id,AtomName,Coordinates,Occupancy,bfactor,Element,Charge,parent):
1320
self.__id=id
@@ -21,60 +28,70 @@ def __init__(self,id,AtomName,Coordinates,Occupancy,bfactor,Element,Charge,paren
2128
self.__Element=Element
2229

2330
#Get Functions
31+
@property
2432
def get_id(self):
2533
"""
26-
:returns: ID of an 'Atom' object
34+
:returns: ID of an 'packman.molecule.atom.Atom' object
2735
"""
2836
return self.__id
2937

38+
@property
3039
def get_name(self):
3140
"""
3241
:returns: Name of an 'Atom' object
3342
"""
3443
return self.__AtomName
3544

45+
@property
3646
def get_alternatelocationindicator(self):
3747
"""
3848
:returns: Alternate Location Indicator
3949
"""
4050
return self.__AlternateLocationIndicator
4151

52+
@property
4253
def get_parent(self):
4354
"""
4455
:returns: Parent residue of an 'Atom' Object. (If available)
4556
"""
4657
return self.__parent
4758

59+
@property
4860
def get_location(self):
4961
"""
5062
:returns: Cartesian Coordinates of an 'Atom'
5163
"""
5264
return self.__Coordinates
5365

66+
@property
5467
def get_occupancy(self):
5568
"""
5669
:returns: Occupancy of an 'Atom'
5770
"""
5871
return self.__Occupancy
5972

73+
@property
6074
def get_bfactor(self):
6175
"""
6276
:returns: B-Factor value of an 'Atom'
6377
"""
6478
return self.__bfactor
6579

80+
@property
6681
def get_segmentidentifier(self):
6782
"""
6883
:returns: Segment Identifier of an 'Atom'
6984
"""
7085
return self.__SegmentIdentifier
7186

87+
@property
7288
def get_element(self):
7389
"""
7490
:returns: Element of an 'Atom'
7591
"""
7692
return self.__Element
7793

94+
@property
7895
def get_domain_id(self):
7996
"""
8097
:returns: Domain ID of the parent Residue

packman/molecule/protein.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
Author: Pranav Khade(pranavk@iastate.edu)
33
'''
44

5+
from numpy import around
6+
57
class Protein():
68
def __init__(self,id,name,Models):
79
self.id=id
@@ -18,6 +20,6 @@ def write_pdb(self,filename):
1820
for num_,_ in enumerate(self):
1921
fh.write("Model\t"+str(num_)+'\n')
2022
for i in _.get_atoms():
21-
fh.write("ATOM %5s %-4s %3s %1s%4s %8s%8s%8s%6s%6s %-4s%2s%2s\n"%(i.get_id(),i.get_name(),i.get_parent().get_name(),i.get_parent().get_parent().get_id(),i.get_parent().get_id(),numpy.around(i.get_location()[0],decimals=3),numpy.around(i.get_location()[1],decimals=3),numpy.around(i.get_location()[2],decimals=3),i.get_occupancy(),i.get_bfactor(),'',i.get_element(),''))
23+
fh.write("ATOM %5s %-4s %3s %1s%4s %8s%8s%8s%6s%6s %-4s%2s%2s\n"%(i.get_id(),i.get_name(),i.get_parent().get_name(),i.get_parent().get_parent().get_id(),i.get_parent().get_id(),around(i.get_location()[0],decimals=3),around(i.get_location()[1],decimals=3),around(i.get_location()[2],decimals=3),i.get_occupancy(),i.get_bfactor(),'',i.get_element(),''))
2224
fh.write("ENDMDL\n")
2325
return True

setup.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
PACKAGES=['packman',
44
'packman.molecule',
5+
'packman.anm',
56
'packman.apps',
67
'packman.bin'
78
]
@@ -11,7 +12,7 @@
1112

1213

1314
setup(name='py-packman',
14-
version='1.0.0',
15+
version='1.1.0',
1516
description='A software package for molecular PACKing and Motion ANalysis (PACKMAN)',
1617
url='https://github.com/Pranavkhade/PACKMAN',
1718
author='Pranav Khade',
@@ -36,5 +37,5 @@
3637
entry_points = {
3738
'console_scripts': SCRIPTS,
3839
},
39-
install_requires=['numpy', 'scipy', 'networkx', 'mlxtend', 'sklearn'],
40+
install_requires=['numpy', 'scipy', 'networkx', 'mlxtend', 'scikit-learn'],
4041
)

0 commit comments

Comments
 (0)