Skip to content

Commit

Permalink
Merge pull request #2 from ResearchIT/master
Browse files Browse the repository at this point in the history
Changes needed for server rollout
  • Loading branch information
Pranavkhade authored Jun 11, 2019
2 parents 129c005 + d4244cc commit 167f0f6
Show file tree
Hide file tree
Showing 6 changed files with 147 additions and 65 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
*.pyc
21 changes: 21 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
FROM centos:7

# System dependencies
RUN yum -y install git which python-virtualenv gcc gcc-c++

# SSH deployment key
RUN mkdir ~/.ssh
COPY ppackman-key ~/.ssh/
RUN chmod 400 ~/.ssh/ppackman-key

# Setup virtualenv
RUN virtualenv ppackman-env
RUN source ppackman-env/bin/activate

# Clone the source
RUN git clone git@github.com:ResearchIT/PPACKMAN.git

# Install python requirements
WORKDIR PPACKMAN
RUN pip install -r requirements.txt

Binary file removed Molecule.pyc
Binary file not shown.
114 changes: 67 additions & 47 deletions PACKMAN.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import os
import sys
import functools
import urllib

import networkx as nx

Expand All @@ -32,7 +33,7 @@
'''


def HingePredict(atoms,Alpha=float('Inf'),method='AlphaShape',GenerateKirchoff=False,filename='Output.pdb',MinimumHingeLength=5,nclusters=4):
def HingePredict(atoms, outputfile, Alpha=float('Inf'),method='AlphaShape',GenerateKirchoff=False,filename='Output.pdb',MinimumHingeLength=5,nclusters=4):
"""
"""
if(method=='AlphaShape'):
Expand Down Expand Up @@ -74,13 +75,13 @@ def GetStats(atoms,SelectedHingeResidues,filename='Output'):

#Example\tGroup\tNumberofelements\tMin\tMax\tMean\tMode\tMedian\tStandardDeviation\n

sys.stdout.write('\nSTATISTICS\n\t\tN\tMin\tMax\tMean\tMode\tMedian\tSTDDev\n')
sys.stdout.write('Total '+'\t'+str(len(all_atoms_bfactor))+'\t'+str(numpy.min(all_atoms_bfactor))+'\t'+str(numpy.max(all_atoms_bfactor))+'\t'+str(numpy.mean(all_atoms_bfactor))+'\t'+str(stats.mode(all_atoms_bfactor)[0][0])+'\t'+str(numpy.median(all_atoms_bfactor))+'\t'+str(numpy.std(all_atoms_bfactor))+'\n')
sys.stdout.write('Hinge '+'\t'+str(len(hinge_atoms_bfactor))+'\t'+str(numpy.min(hinge_atoms_bfactor))+'\t'+str(numpy.max(hinge_atoms_bfactor))+'\t'+str(numpy.mean(hinge_atoms_bfactor))+'\t'+str(stats.mode(hinge_atoms_bfactor)[0][0])+'\t'+str(numpy.median(hinge_atoms_bfactor))+'\t'+str(numpy.std(hinge_atoms_bfactor))+'\n')
sys.stdout.write('NonHinge'+'\t'+str(len(non_hinge_atoms_bfactor))+'\t'+str(numpy.min(non_hinge_atoms_bfactor))+'\t'+str(numpy.max(non_hinge_atoms_bfactor))+'\t'+str(numpy.mean(non_hinge_atoms_bfactor))+'\t'+str(stats.mode(non_hinge_atoms_bfactor)[0][0])+'\t'+str(numpy.median(non_hinge_atoms_bfactor))+'\t'+str(numpy.std(non_hinge_atoms_bfactor))+'\n')
outputfile.write('\nSTATISTICS\n\t\tN\tMin\tMax\tMean\tMode\tMedian\tSTDDev\n')
outputfile.write('Total '+'\t'+str(len(all_atoms_bfactor))+'\t'+str(numpy.min(all_atoms_bfactor))+'\t'+str(numpy.max(all_atoms_bfactor))+'\t'+str(numpy.mean(all_atoms_bfactor))+'\t'+str(stats.mode(all_atoms_bfactor)[0][0])+'\t'+str(numpy.median(all_atoms_bfactor))+'\t'+str(numpy.std(all_atoms_bfactor))+'\n')
outputfile.write('Hinge '+'\t'+str(len(hinge_atoms_bfactor))+'\t'+str(numpy.min(hinge_atoms_bfactor))+'\t'+str(numpy.max(hinge_atoms_bfactor))+'\t'+str(numpy.mean(hinge_atoms_bfactor))+'\t'+str(stats.mode(hinge_atoms_bfactor)[0][0])+'\t'+str(numpy.median(hinge_atoms_bfactor))+'\t'+str(numpy.std(hinge_atoms_bfactor))+'\n')
outputfile.write('NonHinge'+'\t'+str(len(non_hinge_atoms_bfactor))+'\t'+str(numpy.min(non_hinge_atoms_bfactor))+'\t'+str(numpy.max(non_hinge_atoms_bfactor))+'\t'+str(numpy.mean(non_hinge_atoms_bfactor))+'\t'+str(stats.mode(non_hinge_atoms_bfactor)[0][0])+'\t'+str(numpy.median(non_hinge_atoms_bfactor))+'\t'+str(numpy.std(non_hinge_atoms_bfactor))+'\n')

p_value = permutation_test(hinge_atoms_bfactor, non_hinge_atoms_bfactor,method='approximate',num_rounds=10000,seed=0)
sys.stdout.write('\np-value:\t'+str(p_value)+'\n')
outputfile.write('\np-value:\t'+str(p_value)+'\n')
return p_value


Expand Down Expand Up @@ -166,12 +167,12 @@ def cross(a, b):
# This evaluates a * x3 + b * y3 + c * z3 which equals d
d = numpy.dot(cp, p3)
a,b,c,d=a/d,b/d,c/d,d/d
#print('The equation is {0}x + {1}y + {2}z = {3}'.format(a, b, c, d))
#outputfile.write('The equation is {0}x + {1}y + {2}z = {3}'.format(a, b, c, d))

#Plane in PyMol
sys.stdout.write('import plane\n')
sys.stdout.write('plane.make_plane_points(name=\'HingePlane'+ str(HingePlane) +'\', l1='+str(list(p4))+', l2='+str(list(p2))+', l3='+str(list(p3))+', center=False, makepseudo=False)'+'\n')
sys.stdout.write('set cgo_transparency, 0.35, HingePlane'+str(HingePlane)+'\n')
outputfile.write('import plane\n')
outputfile.write('plane.make_plane_points(name=\'HingePlane'+ str(HingePlane) +'\', l1='+str(list(p4))+', l2='+str(list(p2))+', l3='+str(list(p3))+', center=False, makepseudo=False)'+'\n')
outputfile.write('set cgo_transparency, 0.35, HingePlane'+str(HingePlane)+'\n')
return a,b,c,d

a,b,c,d=FitPlane(hinge_points)
Expand Down Expand Up @@ -235,16 +236,16 @@ def cross(a, b):
PredictedHinges.append(SortedHingeResidues[HingeResiduesID.index(Hinge[0]):HingeResiduesID.index(Hinge[-1])+1])

#Print part
sys.stdout.write('Filename= '+str(filename)+'\t| AlphaValue= '+str(Alpha)+'\t| MinimumHingeLength= '+str(MinimumHingeLength)+'\t| EccentricityClusters= '+str(nclusters)+ '\n')
sys.stdout.write('Hindge Residues(Predicted):\n')
outputfile.write('Filename= '+str(filename)+'\t| AlphaValue= '+str(Alpha)+'\t| MinimumHingeLength= '+str(MinimumHingeLength)+'\t| EccentricityClusters= '+str(nclusters)+ '\n')
outputfile.write('Hindge Residues(Predicted):\n')
for numi,i in enumerate(PredictedHinges):
#sys.stdout.write('\nHinge #'+str(numi+1)+'\nResidues: '+','.join([j.get_name()+'-'+str(j.get_id()) for j in i])+'\n')
sys.stdout.write('\nHinge #'+str(numi+1)+'\nResidues: '+i[0].get_name()+'-'+str(i[0].get_id()) +' to '+i[-1].get_name()+'-'+str(i[-1].get_id())+'\n')
#outputfile.write('\nHinge #'+str(numi+1)+'\nResidues: '+','.join([j.get_name()+'-'+str(j.get_id()) for j in i])+'\n')
outputfile.write('\nHinge #'+str(numi+1)+'\nResidues: '+i[0].get_name()+'-'+str(i[0].get_id()) +' to '+i[-1].get_name()+'-'+str(i[-1].get_id())+'\n')
GetStats(atoms,i,filename=filename)
#sys.stdout.write('\nPymol Terminal Commands for Visualizing:\ncolor blue, resi '+'+'.join(str(j.get_id()) for j in i)+'\n')
sys.stdout.write('\nPymol Terminal Commands for Visualizing:\ncolor blue, resi '+str(i[0].get_id())+':'+str(i[-1].get_id())+'\n')
#outputfile.write('\nPymol Terminal Commands for Visualizing:\ncolor blue, resi '+'+'.join(str(j.get_id()) for j in i)+'\n')
outputfile.write('\nPymol Terminal Commands for Visualizing:\ncolor blue, resi '+str(i[0].get_id())+':'+str(i[-1].get_id())+'\n')
GetLeastSquarePlane(atoms,i,numi+1)
sys.stdout.write("#--------------------------------------------------#\n")
outputfile.write("#--------------------------------------------------#\n")
#RotateHingeBonds(atoms,HingeResidues)

if(GenerateKirchoff):
Expand All @@ -259,13 +260,10 @@ def cross(a, b):
##################################################################################################
'''

def WriteOBJ(atoms,faces,filename='Output.obj'):
def WriteOBJ(atoms,faces, fh):
"""
"""
filename='AlphaShape-'+filename.replace('pdb','obj')
NewIDs={i.get_id():numi+1 for numi,i in enumerate(atoms)}
open(filename,'w').write('')
fh=open(filename,'a')
fh.write('mtllib master.mtl\ng\n')
fh.write('usemtl atoms\n')
for i in atoms:
Expand Down Expand Up @@ -411,15 +409,23 @@ def IO():
"""
parser=argparse.ArgumentParser(description='PACKMAN: PACKing and Motion ANalysis. (https://github.com/Pranavkhade/PACKMAN)')

required = parser.add_mutually_exclusive_group(required=True)
required.add_argument('-pdbid','--pdbid',nargs=2,metavar='PDB_ID', type=str, help='(1) PDB ID of the input file (2) Location and Name by which you wish to save the downloaded file')
required.add_argument('-filename','--filename',nargs=1,metavar='FILENAME', type=str, help='Path and filename of the PDB file')
parser.add_argument('-pdbid','--pdbid', metavar='PDB_ID', type=str, help='If provided, the PBD with this ID will be downloaded and saved to FILENAME.')

parser.add_argument('alpha', metavar='AlphaValue', help='Recommended: 2.8 for closed; 4.5 for open form, Please refer to the paper for more details')
parser.add_argument('filename', metavar='FILENAME', help='Path and filename of the PDB file.')

parser.add_argument('alpha',metavar='AlphaValue',help='Recommended: Start from 2 and keep increasing the parameter value till the hinges become redundant compared to the previous alpha values (Typically around 5), Please refer to the paper for more details')
parser.add_argument('--e_clusters',metavar='NumberOfEccentricityClusters',type=int,default=4,help='Recommended: 4, Please refer to the paper for more details')
parser.add_argument('--minhnglen',metavar='MinimumHingeLength',type=int,default=5,help='Recommended: 5, Please refer to the paper for more details')
parser.add_argument("--chain", help='Enter The Chain ID')
parser.add_argument('--generateobj',choices=['yes', 'no'], default='no', help='Select yes if you wish to generate the .obj file')
parser.add_argument('--generateobj', type=argparse.FileType('wb', 0), help='Path and filename to save the .obj file at. Ignored unless --chain is provided.')

# web server parameters
web_server_group = parser.add_argument_group('Web server parameters', 'Used by the web form')
web_server_group.add_argument('--outputfile', type=argparse.FileType('wb', 0), default=sys.stdout, help='Path and filename write output to')
web_server_group.add_argument('--logfile', type=argparse.FileType('wb', 0), default=sys.stderr, help='Path and filename write log messages to')
web_server_group.add_argument('--callbackurl', type=str, help='Optional callback url if this script was called from Drupal.')
web_server_group.add_argument('--nodeid', type=int, help='Optional node id if this script was called from Drupal.')

args=parser.parse_args()
return args

Expand All @@ -434,36 +440,50 @@ def main():
"""
args=IO()


#Mutually Exclusive Opetion to load the file
if(args.pdbid is not None):
Molecule.DownloadPDB(args.pdbid[0],args.pdbid[1])
mol=Molecule.LoadPDB(args.pdbid[1])
elif(args.filename is not None):
mol=Molecule.LoadPDB(args.filename[0])

if(args.chain):
Backbone=[item for sublist in mol[0][args.chain].get_backbone() for item in sublist]
SelectedTesselations,PredictedHinges=HingePredict(Backbone,Alpha=float(args.alpha),filename=args.filename,nclusters=args.e_clusters,MinimumHingeLength=args.minhnglen)
if(args.generateobj=='yes'):WriteOBJ(Backbone,SelectedTesselations,'CHAIN-'+args.chain+'-'+args.filename[0])
else:
for i in mol[0].get_chains():
Backbone=[item for sublist in mol[0].get_backbone() for item in sublist]
SelectedTesselations,PredictedHinges=HingePredict(Backbone,Alpha=float(args.alpha),filename=args.filename,nclusters=args.e_clusters,MinimumHingeLength=args.minhnglen)
if(args.generateobj=='yes'):WriteOBJ(Backbone,SelectedTesselations,'CHAIN-'+i.get_id()+'-'+args.filename)
Molecule.DownloadPDB(args.pdbid, args.filename)

mol = Molecule.LoadPDB(args.filename)

try:

if(args.chain):
Backbone = [item for sublist in mol[0][args.chain].get_backbone() for item in sublist]
SelectedTesselations, PredictedHinges = HingePredict(Backbone, args.outputfile, Alpha=float(args.alpha), filename=args.filename,nclusters=args.e_clusters,MinimumHingeLength=args.minhnglen)
if(args.generateobj is not None):
WriteOBJ(Backbone, SelectedTesselations, args.generateobj)
else:
for i in mol[0].get_chains():
Backbone = [item for sublist in mol[0].get_backbone() for item in sublist]
SelectedTesselations, PredictedHinges = HingePredict(Backbone, args.outputfile, Alpha=float(args.alpha), filename=args.filename,nclusters=args.e_clusters,MinimumHingeLength=args.minhnglen)

if args.nodeid is not None:
urllib.urlopen(args.callbackurl + '/' + str(args.nodeid) + "/0")

except Exception:

if args.nodeid is not None:
urllib.urlopen(args.callbackurl + '/' + str(args.nodeid) + "/1")

print_footnotes()
sys.stdout.flush()
finally:

print_footnotes(args.outputfile)
args.outputfile.flush()
args.logfile.flush()

if(args.generateobj is not None):
args.generateobj.flush()

return True

'''
##################################################################################################
# End #
##################################################################################################
'''
def print_footnotes():
sys.stdout.write('Footnotes:\n\nSTATISTICS Section Legend:\nN: Number of residues\nMin: Minimum B-factor value\nMax: Maximum B-factor value\nMean: Mean B-factor value\nMode: Mode B-factor value\nMedian: Median B-factor value\nSTDDev: Standard Deviation of the B-factor values\n')
sys.stdout.write('\nRMSF Plane Visualization:\nDownload plane.py file from https://pymolwiki.org/index.php/Plane_Wizard and place it in the PyMol working directory if the RMSF plane needs to be visualized.\n')
def print_footnotes(outputfile):
outputfile.write('Footnotes:\n\nSTATISTICS Section Legend:\nN: Number of residues\nMin: Minimum B-factor value\nMax: Maximum B-factor value\nMean: Mean B-factor value\nMode: Mode B-factor value\nMedian: Median B-factor value\nSTDDev: Standard Deviation of the B-factor values\n')
outputfile.write('\nRMSF Plane Visualization:\nDownload plane.py file from https://pymolwiki.org/index.php/Plane_Wizard and place it in the PyMol working directory if the RMSF plane needs to be visualized.\n')
return True


Expand Down
49 changes: 31 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,42 +47,55 @@ pip install git+git://github.com/Pranavkhade/PACKMAN
Description

```
usage: PACKMAN.py [-h] (-pdbid PDB_ID PDB_ID | -filename FILENAME)
usage: PACKMAN.py [-h] [-pdbid PDB_ID]
[--e_clusters NumberOfEccentricityClusters]
[--minhnglen MinimumHingeLength] [--chain CHAIN]
[--generateobj {yes,no}]
AlphaValue
[--generateobj GENERATEOBJ] [--outputfile OUTPUTFILE]
[--logfile LOGFILE] [--callbackurl CALLBACKURL]
[--nodeid NODEID]
AlphaValue FILENAME
PACKMAN: PACKing and Motion ANalysis. (https://github.com/Pranavkhade/PACKMAN)
positional arguments:
AlphaValue Recommended: Start from 2 and keep increasing the
parameter value till the hinges become redundant
compared to the previous alpha values (Typically
around 5), Please refer to the paper for more details
AlphaValue Recommended: 2.8 for closed; 4.5 for open form, Please
refer to the paper for more details
FILENAME Path and filename of the PDB file.
optional arguments:
-h, --help show this help message and exit
-pdbid PDB_ID PDB_ID, --pdbid PDB_ID PDB_ID
(1) PDB ID of the input file (2) Location and Name by
which you wish to save the downloaded file
-filename FILENAME, --filename FILENAME
Path and filename of the PDB file
-pdbid PDB_ID, --pdbid PDB_ID
If provided, the PBD with this ID will be downloaded
and saved to FILENAME.
--e_clusters NumberOfEccentricityClusters
Recommended: 4, Please refer to the paper for more
details
--minhnglen MinimumHingeLength
Recommended: 5, Please refer to the paper for more
details
--chain CHAIN Enter The Chain ID
--generateobj {yes,no}
Select yes if you wish to generate the .obj file
--generateobj GENERATEOBJ
Path and filename to save the .obj file at. Ignored
unless --chain is provided.
Web server parameters:
Used by the web form
--outputfile OUTPUTFILE
Path and filename write output to
--logfile LOGFILE Path and filename write log messages to
--callbackurl CALLBACKURL
Optional callback url if this script was called from
Drupal.
--nodeid NODEID Optional node id if this script was called from
Drupal.
```
### Examples

1. `python PACKMAN.py 2.8 --pdbid 1prw 1prw.pdb`
First parameter 2.8 is the alpha value parameter which can be changed. for --pdbid, the first parameter is the PDB ID the user submits to download a corresponding PDB file and second is the name of the file you wish to save the downloaded PDB file.
1. `python PPACKMAN.py --pdbid 1prw 2.8 1prw.pdb`
for --pdbid, the parameter is the PDB ID the user submits to download a corresponding PDB file. First positional parameter 2.8 is the alpha value parameter which can be changed. and second is the name of the file you wish to save the downloaded PDB file.


2. `python PACKMAN.py 2.8 --filename 1prw.pdb`
First parameter 2.8 is the alpha value parameter which can be changed. for --filename, the parameter is location and name of the PDB file.
2. `python PPACKMAN.py 2.8 1prw.pdb`
First parameter 2.8 is the alpha value parameter which can be changed. second parameter is the parameter is location and name of the PDB file.
27 changes: 27 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
astroid==1.6.6
backports.functools-lru-cache==1.5
configparser==3.7.4
cycler==0.10.0
decorator==4.4.0
enum34==1.1.6
futures==3.2.0
isort==4.3.18
kiwisolver==1.1.0
lazy-object-proxy==1.3.1
matplotlib==2.2.4
mccabe==0.6.1
mlxtend==0.15.0.0
networkx==2.2
numpy==1.16.3
pandas==0.24.2
pylint==1.9.4
pyparsing==2.4.0
python-dateutil==2.8.0
pytz==2019.1
scikit-learn==0.20.3
scipy==1.2.1
singledispatch==3.4.0.3
six==1.12.0
sklearn==0.0
subprocess32==3.5.3
wrapt==1.11.1

0 comments on commit 167f0f6

Please sign in to comment.