Merge pull request #2 from orbeckst/master

packaged for standalone installation (Python 3 and Python 2)
This commit is contained in:
Jimmy Charnley Kromann
2013-08-10 03:51:24 -07:00
31 changed files with 1465 additions and 610 deletions

19
INSTALL Normal file
View File

@@ -0,0 +1,19 @@
## Installation
Clone repository or unpack the tar ball and install with
[setuptools](http://pythonhosted.org/setuptools/index.html) (note: if
you don't have setuptools installed you will need an internet
connection so that the installation procedure can sownload the
required files):
cd propka-3.1
python setup.py install --user
This will install the `propka31` script in your executable directory,
as configured for setuptools, for instance `~/.local/bin`. You can
change the bin directory with the `--install-scripts` option. For
example, in order to install in my `bin` directory in my home
directory:
python setup.py install --user --install-scripts ~/bin

4
MANIFEST.in Normal file
View File

@@ -0,0 +1,4 @@
include README.md INSTALL
include ez_setup.py setup.py
include propka.cfg

View File

@@ -1,45 +1,69 @@
# PROPKA 3.1 # PROPKA 3.1
PROPKA predicts the pKa values of ionizable groups in PROPKA predicts the pKa values of ionizable groups in proteins
proteins (version 3.0) and (version 3.0) and protein-ligand complexes (version 3.1)
protein-ligand complexes (version 3.1) based on the 3D structure.
based in the 3D structure.
For proteins without ligands both version should produce the same result. For proteins without ligands both version should produce the same result.
The method is described in the following papers, which you should cite The method is described in the following papers, which you should cite
in publications: in publications:
* Søndergaard, Chresten R., Mats HM Olsson, Michal Rostkowski, and Jan H. Jensen. "Improved Treatment of Ligands and Coupling Effects in Empirical Calculation and Rationalization of pKa Values." Journal of Chemical Theory and Computation 7, no. 7 (2011): 2284-2295. * Sondergaard, Chresten R., Mats HM Olsson, Michal Rostkowski, and Jan H. Jensen. "Improved Treatment of Ligands and Coupling Effects in Empirical Calculation and Rationalization of pKa Values." Journal of Chemical Theory and Computation 7, no. 7 (2011): 2284-2295.
* Olsson, Mats HM, Chresten R. Søndergaard, Michal Rostkowski, and Jan H. Jensen. "PROPKA3: consistent treatment of internal and surface residues in empirical pKa predictions." Journal of Chemical Theory and Computation 7, no. 2 (2011): 525-537. * Olsson, Mats HM, Chresten R. Sondergaard, Michal Rostkowski, and Jan H. Jensen. "PROPKA3: consistent treatment of internal and surface residues in empirical pKa predictions." Journal of Chemical Theory and Computation 7, no. 2 (2011): 525-537.
See [propka.ki.ku.dk](http://propka.ki.ku.dk/) for the PROPKA web server, See [propka.ki.ku.dk](http://propka.ki.ku.dk/) for the PROPKA web server,
using the [tutorial](http://propka.ki.ku.dk/~luca/wiki/index.php/PROPKA_3.1_Tutorial). using the [tutorial](http://propka.ki.ku.dk/~luca/wiki/index.php/PROPKA_3.1_Tutorial).
## Modifications
This release of PROPKA 3.1 was modified by Oliver Beckstein
<oliver.beckstein@asu.edu> from the released version.
* Included patches from
https://github.com/schrodinger/propka-3.1/tree/python27-compat to
make it compatible with Python 2.7
* Packaged for installation with setuptools.
## Installation ## Installation
No installation needed. Just clone and run. Clone repository or unpack the tar ball and install with
[setuptools](http://pythonhosted.org/setuptools/index.html) (note: if
you don't have setuptools installed you will need an internet
connection so that the installation procedure can download the
required files):
cd propka-3.1
python setup.py install --user
This will install the `propka31` script in your executable directory,
as configured for setuptools, for instance `~/.local/bin`. You can
change the bin directory with the `--install-scripts` option. For
example, in order to install in my `bin` directory in my home
directory:
python setup.py install --user --install-scripts ~/bin
## Requirements ## Requirements
* Python 3.1 or higher * Python 2.7 or higher or Python 3.1 or higher
## Getting started ## Getting started
1. Clone the code from GitHub 1. Clone the code from GitHub
2. Run 'propka.py' with a .pdb file (see Examples) 2. `python setup.py install --user`
2. Run `propka31` with a .pdb file (see Examples)
## Examples ## Examples
Calculate using pdb file Calculate using pdb file
./propka.py 1hpx.pdb propka31 1hpx.pdb
If for some reason your setup with python3.1+ is
not located in '/usr/bin/python3', run the script
python3.2 propka.py 1hpx.pdb
## Testing (for developers) ## Testing (for developers)
@@ -49,9 +73,9 @@ Please run `Tests/runtest.py/` after changes before pushing commits.
Please cite these references in publications: Please cite these references in publications:
* Søndergaard, Chresten R., Mats HM Olsson, Michal Rostkowski, and Jan H. Jensen. "Improved Treatment of Ligands and Coupling Effects in Empirical Calculation and Rationalization of pKa Values." Journal of Chemical Theory and Computation 7, no. 7 (2011): 2284-2295. * Sondergaard, Chresten R., Mats HM Olsson, Michal Rostkowski, and Jan H. Jensen. "Improved Treatment of Ligands and Coupling Effects in Empirical Calculation and Rationalization of pKa Values." Journal of Chemical Theory and Computation 7, no. 7 (2011): 2284-2295.
* Olsson, Mats HM, Chresten R. Søndergaard, Michal Rostkowski, and Jan H. Jensen. "PROPKA3: consistent treatment of internal and surface residues in empirical pKa predictions." Journal of Chemical Theory and Computation 7, no. 2 (2011): 525-537. * Olsson, Mats HM, Chresten R. Sondergaard, Michal Rostkowski, and Jan H. Jensen. "PROPKA3: consistent treatment of internal and surface residues in empirical pKa predictions." Journal of Chemical Theory and Computation 7, no. 2 (2011): 525-537.

View File

@@ -1,9 +1,13 @@
#!/usr/bin/python3 #!/usr/bin/env python
""" Run test for test pdbs """ """ Run test for test pdbs """
from __future__ import division
from __future__ import print_function
from subprocess import call from subprocess import call
import os, re import os, re
import sys
pdbs = ['1FTJ-Chain-A', pdbs = ['1FTJ-Chain-A',
'1HPX', '1HPX',
@@ -14,7 +18,7 @@ for pdb in pdbs:
print('RUNNING '+pdb) print('RUNNING '+pdb)
# Run pka calculation # Run pka calculation
call(['../propka.py','pdb/'+pdb+'.pdb'], stdout = open(pdb+'.out', 'w+')) call([sys.executable, '../scripts/propka31.py','pdb/'+pdb+'.pdb'], stdout = open(pdb+'.out', 'w+'))
# Test pka predictiona # Test pka predictiona
result = open('results/'+pdb+'.dat','r') result = open('results/'+pdb+'.dat','r')

258
ez_setup.py Normal file
View File

@@ -0,0 +1,258 @@
#!python
"""Bootstrap setuptools installation
If you want to use setuptools in your package's setup.py, just include this
file in the same directory with it, and add this to the top of your setup.py::
from ez_setup import use_setuptools
use_setuptools()
If you want to require a specific version of setuptools, set a download
mirror, or use an alternate download directory, you can do so by supplying
the appropriate options to ``use_setuptools()``.
This file can also be run as a script to install or upgrade setuptools.
"""
import os
import shutil
import sys
import tempfile
import tarfile
import optparse
import subprocess
from distutils import log
try:
from site import USER_SITE
except ImportError:
USER_SITE = None
DEFAULT_VERSION = "0.9.6"
DEFAULT_URL = "https://pypi.python.org/packages/source/s/setuptools/"
def _python_cmd(*args):
args = (sys.executable,) + args
return subprocess.call(args) == 0
def _install(tarball, install_args=()):
# extracting the tarball
tmpdir = tempfile.mkdtemp()
log.warn('Extracting in %s', tmpdir)
old_wd = os.getcwd()
try:
os.chdir(tmpdir)
tar = tarfile.open(tarball)
_extractall(tar)
tar.close()
# going in the directory
subdir = os.path.join(tmpdir, os.listdir(tmpdir)[0])
os.chdir(subdir)
log.warn('Now working in %s', subdir)
# installing
log.warn('Installing Setuptools')
if not _python_cmd('setup.py', 'install', *install_args):
log.warn('Something went wrong during the installation.')
log.warn('See the error message above.')
# exitcode will be 2
return 2
finally:
os.chdir(old_wd)
shutil.rmtree(tmpdir)
def _build_egg(egg, tarball, to_dir):
# extracting the tarball
tmpdir = tempfile.mkdtemp()
log.warn('Extracting in %s', tmpdir)
old_wd = os.getcwd()
try:
os.chdir(tmpdir)
tar = tarfile.open(tarball)
_extractall(tar)
tar.close()
# going in the directory
subdir = os.path.join(tmpdir, os.listdir(tmpdir)[0])
os.chdir(subdir)
log.warn('Now working in %s', subdir)
# building an egg
log.warn('Building a Setuptools egg in %s', to_dir)
_python_cmd('setup.py', '-q', 'bdist_egg', '--dist-dir', to_dir)
finally:
os.chdir(old_wd)
shutil.rmtree(tmpdir)
# returning the result
log.warn(egg)
if not os.path.exists(egg):
raise IOError('Could not build the egg.')
def _do_download(version, download_base, to_dir, download_delay):
egg = os.path.join(to_dir, 'setuptools-%s-py%d.%d.egg'
% (version, sys.version_info[0], sys.version_info[1]))
if not os.path.exists(egg):
tarball = download_setuptools(version, download_base,
to_dir, download_delay)
_build_egg(egg, tarball, to_dir)
sys.path.insert(0, egg)
import setuptools
setuptools.bootstrap_install_from = egg
def use_setuptools(version=DEFAULT_VERSION, download_base=DEFAULT_URL,
to_dir=os.curdir, download_delay=15):
# making sure we use the absolute path
to_dir = os.path.abspath(to_dir)
was_imported = 'pkg_resources' in sys.modules or \
'setuptools' in sys.modules
try:
import pkg_resources
except ImportError:
return _do_download(version, download_base, to_dir, download_delay)
try:
pkg_resources.require("setuptools>=" + version)
return
except pkg_resources.VersionConflict:
e = sys.exc_info()[1]
if was_imported:
sys.stderr.write(
"The required version of setuptools (>=%s) is not available,\n"
"and can't be installed while this script is running. Please\n"
"install a more recent version first, using\n"
"'easy_install -U setuptools'."
"\n\n(Currently using %r)\n" % (version, e.args[0]))
sys.exit(2)
else:
del pkg_resources, sys.modules['pkg_resources'] # reload ok
return _do_download(version, download_base, to_dir,
download_delay)
except pkg_resources.DistributionNotFound:
return _do_download(version, download_base, to_dir,
download_delay)
def download_setuptools(version=DEFAULT_VERSION, download_base=DEFAULT_URL,
to_dir=os.curdir, delay=15):
"""Download setuptools from a specified location and return its filename
`version` should be a valid setuptools version number that is available
as an egg for download under the `download_base` URL (which should end
with a '/'). `to_dir` is the directory where the egg will be downloaded.
`delay` is the number of seconds to pause before an actual download
attempt.
"""
# making sure we use the absolute path
to_dir = os.path.abspath(to_dir)
try:
from urllib.request import urlopen
except ImportError:
from urllib2 import urlopen
tgz_name = "setuptools-%s.tar.gz" % version
url = download_base + tgz_name
saveto = os.path.join(to_dir, tgz_name)
src = dst = None
if not os.path.exists(saveto): # Avoid repeated downloads
try:
log.warn("Downloading %s", url)
src = urlopen(url)
# Read/write all in one block, so we don't create a corrupt file
# if the download is interrupted.
data = src.read()
dst = open(saveto, "wb")
dst.write(data)
finally:
if src:
src.close()
if dst:
dst.close()
return os.path.realpath(saveto)
def _extractall(self, path=".", members=None):
"""Extract all members from the archive to the current working
directory and set owner, modification time and permissions on
directories afterwards. `path' specifies a different directory
to extract to. `members' is optional and must be a subset of the
list returned by getmembers().
"""
import copy
import operator
from tarfile import ExtractError
directories = []
if members is None:
members = self
for tarinfo in members:
if tarinfo.isdir():
# Extract directories with a safe mode.
directories.append(tarinfo)
tarinfo = copy.copy(tarinfo)
tarinfo.mode = 448 # decimal for oct 0700
self.extract(tarinfo, path)
# Reverse sort directories.
if sys.version_info < (2, 4):
def sorter(dir1, dir2):
return cmp(dir1.name, dir2.name)
directories.sort(sorter)
directories.reverse()
else:
directories.sort(key=operator.attrgetter('name'), reverse=True)
# Set correct owner, mtime and filemode on directories.
for tarinfo in directories:
dirpath = os.path.join(path, tarinfo.name)
try:
self.chown(tarinfo, dirpath)
self.utime(tarinfo, dirpath)
self.chmod(tarinfo, dirpath)
except ExtractError:
e = sys.exc_info()[1]
if self.errorlevel > 1:
raise
else:
self._dbg(1, "tarfile: %s" % e)
def _build_install_args(options):
"""
Build the arguments to 'python setup.py install' on the setuptools package
"""
install_args = []
if options.user_install:
if sys.version_info < (2, 6):
log.warn("--user requires Python 2.6 or later")
raise SystemExit(1)
install_args.append('--user')
return install_args
def _parse_args():
"""
Parse the command line for options
"""
parser = optparse.OptionParser()
parser.add_option(
'--user', dest='user_install', action='store_true', default=False,
help='install in user site package (requires Python 2.6 or later)')
parser.add_option(
'--download-base', dest='download_base', metavar="URL",
default=DEFAULT_URL,
help='alternative URL from where to download the setuptools package')
options, args = parser.parse_args()
# positional arguments are ignored
return options
def main(version=DEFAULT_VERSION):
"""Install or upgrade setuptools and EasyInstall"""
options = _parse_args()
tarball = download_setuptools(download_base=options.download_base)
return _install(tarball, _build_install_args(options))
if __name__ == '__main__':
sys.exit(main())

View File

@@ -1,23 +0,0 @@
#!/usr/bin/python3
import string,re,sys,os,math
import Source.lib, Source.molecular_container
def main():
"""
Reads in structure files, calculates pKa values, and prints pKa files
"""
# loading options, flaggs and arguments
options, pdbfiles = Source.lib.loadOptions()
for pdbfile in pdbfiles:
my_molecule = Source.molecular_container.Molecular_container(pdbfile, options)
my_molecule.calculate_pka()
my_molecule.write_pka()
if __name__ == '__main__':
#import cProfile
#cProfile.run('main()',sort=1)
main()

View File

@@ -1,3 +1,5 @@
# # propka 3.1
# (Module renamed from original Source to propka to facilitate setuptools installation)
__all__ = ['coupled_residues', 'lib', 'parameters', 'residue', 'bonds', 'debug', 'ligand', 'pdb', 'calculator', 'determinants', 'mutate', 'protein', 'chain', 'iterative', 'output', 'protonate'] __all__ = ['coupled_residues', 'lib', 'parameters', 'residue', 'bonds', 'debug', 'ligand', 'pdb', 'calculator', 'determinants', 'mutate', 'protein', 'chain', 'iterative', 'output', 'protonate']

View File

@@ -1,4 +1,8 @@
import string, Source.lib, Source.group
from __future__ import division
from __future__ import print_function
import string, propka.lib, propka.group
class Atom: class Atom:
@@ -195,7 +199,7 @@ class Atom:
str = "%-6s%5d %s %s%2s%4d%12.3lf%8.3lf%8.3lf%6s%6s \n" % (self.type.upper(), str = "%-6s%5d %s %s%2s%4d%12.3lf%8.3lf%8.3lf%6s%6s \n" % (self.type.upper(),
self.numb, self.numb,
Source.lib.makeTidyAtomLabel(self.name, propka.lib.makeTidyAtomLabel(self.name,
self.element), self.element),
self.resName, self.resName,
self.chainID, self.chainID,
@@ -258,7 +262,7 @@ class Atom:
# try to initialise the group # try to initialise the group
try: try:
exec('self.group = Source.group.%s_group(self)'%self.occ) exec('self.group = propka.group.%s_group(self)'%self.occ)
except: except:
raise Exception('%s in input_file is not recognized as a group'%self.occ) raise Exception('%s in input_file is not recognized as a group'%self.occ)
@@ -282,7 +286,7 @@ class Atom:
# making string # making string
str = "%-6s%5d %s %s%2s%4d%12.3lf%8.3lf%8.3lf%6s%6s\n" % (self.type.upper(), str = "%-6s%5d %s %s%2s%4d%12.3lf%8.3lf%8.3lf%6s%6s\n" % (self.type.upper(),
self.numb, self.numb,
Source.lib.makeTidyAtomLabel(self.name, propka.lib.makeTidyAtomLabel(self.name,
self.element), self.element),
self.resName, self.resName,
self.chainID, self.chainID,
@@ -299,10 +303,10 @@ class Atom:
def make_mol2_line(self,id): def make_mol2_line(self,id):
#1 S1 3.6147 2.0531 1.4795 S.3 1 noname -0.1785 #1 S1 3.6147 2.0531 1.4795 S.3 1 noname -0.1785
# making string # making string
str = "%-4d %-4s %10.4f %10.4f %10.4f %6s %6d %10s %10.4f\n" % (id, str = "%-4d %-4s %10.4f %10.4f %10.4f %6s %6d %10s %10.4f\n" % (id,
Source.lib.makeTidyAtomLabel(self.name, propka.lib.makeTidyAtomLabel(self.name,
self.element), self.element),
self.x, self.x,
self.y, self.y,
@@ -346,7 +350,7 @@ class Atom:
# making string # making string
str = "ATOM " str = "ATOM "
str += "%6d" % (numb) str += "%6d" % (numb)
str += " %s" % (Source.lib.makeTidyAtomLabel(name,self.element)) str += " %s" % (propka.lib.makeTidyAtomLabel(name,self.element))
str += " %s" % (resName) str += " %s" % (resName)
str += "%2s" % (chainID) str += "%2s" % (chainID)
str += "%4d" % (resNumb) str += "%4d" % (resNumb)
@@ -363,7 +367,7 @@ class Atom:
""" """
Returns a 'tidier' atom label for printing the new pdbfile Returns a 'tidier' atom label for printing the new pdbfile
""" """
return Source.lib.makeTidyAtomLabel(self.name,self.element) return propka.lib.makeTidyAtomLabel(self.name,self.element)
def __str__(self): def __str__(self):

View File

@@ -1,5 +1,10 @@
import pickle,sys,os,math,Source.calculations
from __future__ import division
from __future__ import print_function
import pickle,sys,os,math,propka.calculations
import pkg_resources
class bondmaker: class bondmaker:
def __init__(self): def __init__(self):
@@ -22,8 +27,7 @@ class bondmaker:
self.max_sq_distance = max(list(self.distances_squared.values())+[self.default_dist_squared]) self.max_sq_distance = max(list(self.distances_squared.values())+[self.default_dist_squared])
# protein bonding data # protein bonding data
path = os.path.split(__file__)[0] self.data_file_name = pkg_resources.resource_filename(__name__, 'protein_bonds.dat')
self.data_file_name = os.path.join(path,'protein_bonds.dat')
data = open(self.data_file_name,'rb') data = open(self.data_file_name,'rb')
self.protein_bonds = pickle.load(data) self.protein_bonds = pickle.load(data)
@@ -145,7 +149,7 @@ class bondmaker:
if atom1.name == 'SG': if atom1.name == 'SG':
for atom2 in cys2.atoms: for atom2 in cys2.atoms:
if atom2.name == 'SG': if atom2.name == 'SG':
if Source.calculations.squared_distance(atom1,atom2) < self.SS_dist_squared: if propka.calculations.squared_distance(atom1,atom2) < self.SS_dist_squared:
self.make_bond(atom1, atom2) self.make_bond(atom1, atom2)
@@ -174,7 +178,7 @@ class bondmaker:
if atom1.name == 'C': if atom1.name == 'C':
for atom2 in residue2.atoms: for atom2 in residue2.atoms:
if atom2.name == 'N': if atom2.name == 'N':
if Source.calculations.squared_distance(atom1,atom2) < self.default_dist_squared: if propka.calculations.squared_distance(atom1,atom2) < self.default_dist_squared:
self.make_bond(atom1, atom2) self.make_bond(atom1, atom2)
return return
@@ -283,7 +287,7 @@ class bondmaker:
def check_distance(self, atom1, atom2): def check_distance(self, atom1, atom2):
sq_dist = Source.calculations.squared_distance(atom1, atom2) sq_dist = propka.calculations.squared_distance(atom1, atom2)
if sq_dist > self.max_sq_distance: if sq_dist > self.max_sq_distance:
return False return False
@@ -350,9 +354,11 @@ class bondmaker:
#print('z range: [%6.2f;%6.2f] %6.2f'%(zmin,zmax,zlen)) #print('z range: [%6.2f;%6.2f] %6.2f'%(zmin,zmax,zlen))
# how many boxes do we need in each dimension? # how many boxes do we need in each dimension?
self.no_box_x = max(1, math.ceil(xlen/box_size)) # NOTE: math.ceil() returns an int in python3 and a float in python2,
self.no_box_y = max(1, math.ceil(ylen/box_size)) # so we need to cast it to int for range() to work.
self.no_box_z = max(1, math.ceil(zlen/box_size)) self.no_box_x = max(1, int(math.ceil(xlen/box_size)))
self.no_box_y = max(1, int(math.ceil(ylen/box_size)))
self.no_box_z = max(1, int(math.ceil(zlen/box_size)))
#print('No. box x: %6.2f'%self.no_box_x) #print('No. box x: %6.2f'%self.no_box_x)
#print('No. box y: %6.2f'%self.no_box_y) #print('No. box y: %6.2f'%self.no_box_y)

View File

@@ -1,6 +1,8 @@
from __future__ import division
from __future__ import print_function
import math, Source.protonate, Source.bonds,copy, sys import math, propka.protonate, propka.bonds,copy, sys
# #
@@ -19,7 +21,7 @@ def setup_bonding_and_protonation(parameters, molecular_container):
# Protonate atoms # Protonate atoms
if molecular_container.options.protonate_all: if molecular_container.options.protonate_all:
my_protonator = Source.protonate.Protonate(verbose=False) my_protonator = propka.protonate.Protonate(verbose=False)
my_protonator.protonate(molecular_container) my_protonator.protonate(molecular_container)
@@ -29,7 +31,7 @@ def setup_bonding_and_protonation(parameters, molecular_container):
def setup_bonding(parameters, molecular_container): def setup_bonding(parameters, molecular_container):
# make bonds # make bonds
my_bond_maker = Source.bonds.bondmaker() my_bond_maker = propka.bonds.bondmaker()
my_bond_maker.find_bonds_for_molecules_using_boxes(molecular_container) my_bond_maker.find_bonds_for_molecules_using_boxes(molecular_container)
return my_bond_maker return my_bond_maker
@@ -50,7 +52,7 @@ def setup_bonding_and_protonation_30_style(parameters, molecular_container):
protonate_30_style(molecular_container) protonate_30_style(molecular_container)
# make bonds # make bonds
my_bond_maker = Source.bonds.bondmaker() my_bond_maker = propka.bonds.bondmaker()
my_bond_maker.find_bonds_for_molecules_using_boxes(molecular_container) my_bond_maker.find_bonds_for_molecules_using_boxes(molecular_container)
return return
@@ -307,7 +309,7 @@ def protonateSP2(list):
def make_new_H(atom, x,y,z): def make_new_H(atom, x,y,z):
new_H = Source.atom.Atom() new_H = propka.atom.Atom()
new_H.setProperty(numb = None, new_H.setProperty(numb = None,
name = 'H%s'%atom.name[1:], name = 'H%s'%atom.name[1:],
resName = atom.resName, resName = atom.resName,
@@ -569,7 +571,7 @@ def hydrogen_bond_interaction(group1, group2, version):
# find the smallest distance between interacting atoms # find the smallest distance between interacting atoms
atoms1 = group1.get_interaction_atoms(group2) atoms1 = group1.get_interaction_atoms(group2)
atoms2 = group2.get_interaction_atoms(group1) atoms2 = group2.get_interaction_atoms(group1)
[closest_atom1, distance, closest_atom2] = Source.calculations.get_smallest_distance(atoms1, atoms2) [closest_atom1, distance, closest_atom2] = propka.calculations.get_smallest_distance(atoms1, atoms2)
if None in [closest_atom1, closest_atom2]: if None in [closest_atom1, closest_atom2]:
print('Warning: Side chain interaction failed for %s and %s'%(group1.label, group2.label)) print('Warning: Side chain interaction failed for %s and %s'%(group1.label, group2.label))
@@ -602,7 +604,7 @@ def hydrogen_bond_interaction(group1, group2, version):
if closest_atom2.element == 'H': if closest_atom2.element == 'H':
heavy_atom = closest_atom2.bonded_atoms[0] heavy_atom = closest_atom2.bonded_atoms[0]
hydrogen = closest_atom2 hydrogen = closest_atom2
distance, f_angle, nada = Source.calculations.AngleFactorX(closest_atom1, hydrogen, heavy_atom) distance, f_angle, nada = propka.calculations.AngleFactorX(closest_atom1, hydrogen, heavy_atom)
else: else:
# Either the structure is corrupt (no hydrogen), or the heavy atom is closer to # Either the structure is corrupt (no hydrogen), or the heavy atom is closer to
# the titratable atom than the hydrogen. In either case we set the angle factor # the titratable atom than the hydrogen. In either case we set the angle factor
@@ -613,7 +615,7 @@ def hydrogen_bond_interaction(group1, group2, version):
if closest_atom1.element == 'H': if closest_atom1.element == 'H':
heavy_atom = closest_atom1.bonded_atoms[0] heavy_atom = closest_atom1.bonded_atoms[0]
hydrogen = closest_atom1 hydrogen = closest_atom1
distance, f_angle, nada = Source.calculations.AngleFactorX(closest_atom2, hydrogen, heavy_atom) distance, f_angle, nada = propka.calculations.AngleFactorX(closest_atom2, hydrogen, heavy_atom)
else: else:
# Either the structure is corrupt (no hydrogen), or the heavy atom is closer to # Either the structure is corrupt (no hydrogen), or the heavy atom is closer to
# the titratable atom than the hydrogen. In either case we set the angle factor # the titratable atom than the hydrogen. In either case we set the angle factor

View File

@@ -2,7 +2,10 @@
# Container for molecular conformations # Container for molecular conformations
# #
import Source.group, Source.determinants, Source.determinant, Source.ligand, Source.output, Source.coupled_groups, functools from __future__ import division
from __future__ import print_function
import propka.group, propka.determinants, propka.determinant, propka.ligand, propka.output, propka.coupled_groups, functools
class Conformation_container: class Conformation_container:
def __init__(self, name='', parameters=None, molecular_container=None): def __init__(self, name='', parameters=None, molecular_container=None):
@@ -28,7 +31,7 @@ class Conformation_container:
for atom in self.get_non_hydrogen_atoms(): for atom in self.get_non_hydrogen_atoms():
# has this atom been checked for groups? # has this atom been checked for groups?
if atom.groups_extracted == 0: if atom.groups_extracted == 0:
self.validate_group(Source.group.is_group(self.parameters, atom)) self.validate_group(propka.group.is_group(self.parameters, atom))
# if the atom has been checked in a another conformation, check if it has a # if the atom has been checked in a another conformation, check if it has a
# group that should be used in this conformation as well # group that should be used in this conformation as well
elif atom.group: elif atom.group:
@@ -42,7 +45,7 @@ class Conformation_container:
# some more configuration might be needed # some more configuration might be needed
# print coupling map # print coupling map
map = Source.output.make_interaction_map('Covalent coupling map for %s'%self, map = propka.output.make_interaction_map('Covalent coupling map for %s'%self,
self.get_covalently_coupled_groups(), self.get_covalently_coupled_groups(),
lambda g1,g2: g1 in g2.covalently_coupled_groups) lambda g1,g2: g1 in g2.covalently_coupled_groups)
print(map) print(map)
@@ -54,7 +57,7 @@ class Conformation_container:
return return
def set_common_charge_centres(self): def set_common_charge_centres(self):
for system in self.get_coupled_systems(self.get_covalently_coupled_groups(), Source.group.Group.get_covalently_coupled_groups): for system in self.get_coupled_systems(self.get_covalently_coupled_groups(), propka.group.Group.get_covalently_coupled_groups):
# make a list of the charge centre coordinates # make a list of the charge centre coordinates
all_coordinates = list(map(lambda g: [g.x, g.y, g.z], system)) all_coordinates = list(map(lambda g: [g.x, g.y, g.z], system))
# find the common charge center # find the common charge center
@@ -88,7 +91,7 @@ class Conformation_container:
self.set_common_charge_centres() self.set_common_charge_centres()
# print coupling map # print coupling map
map = Source.output.make_interaction_map('Covalent coupling map for %s'%self, map = propka.output.make_interaction_map('Covalent coupling map for %s'%self,
#self.get_titratable_groups(), #self.get_titratable_groups(),
self.get_covalently_coupled_groups(), self.get_covalently_coupled_groups(),
lambda g1,g2: g1 in g2.covalently_coupled_groups) lambda g1,g2: g1 in g2.covalently_coupled_groups)
@@ -103,7 +106,7 @@ class Conformation_container:
if len(list(filter(lambda g: len(g.non_covalently_coupled_groups)>0, self.get_titratable_groups())))>0: if len(list(filter(lambda g: len(g.non_covalently_coupled_groups)>0, self.get_titratable_groups())))>0:
self.non_covalently_coupled_groups = True self.non_covalently_coupled_groups = True
Source.coupled_groups.nccg.identify_non_covalently_coupled_groups(self,verbose=verbose) propka.coupled_groups.nccg.identify_non_covalently_coupled_groups(self,verbose=verbose)
# re-do the check # re-do the check
if len(list(filter(lambda g: len(g.non_covalently_coupled_groups)>0, self.get_titratable_groups())))>0: if len(list(filter(lambda g: len(g.non_covalently_coupled_groups)>0, self.get_titratable_groups())))>0:
@@ -163,16 +166,16 @@ class Conformation_container:
version.calculate_desolvation(group) version.calculate_desolvation(group)
# calculate backbone interactions # calculate backbone interactions
Source.determinants.setBackBoneDeterminants(self.get_titratable_groups(), self.get_backbone_groups(), version) propka.determinants.setBackBoneDeterminants(self.get_titratable_groups(), self.get_backbone_groups(), version)
# setting ion determinants # setting ion determinants
Source.determinants.setIonDeterminants(self, version) propka.determinants.setIonDeterminants(self, version)
# calculating the back-bone reorganization/desolvation term # calculating the back-bone reorganization/desolvation term
version.calculateBackBoneReorganization(self) version.calculateBackBoneReorganization(self)
# setting remaining non-iterative and iterative side-chain & Coulomb interaction determinants # setting remaining non-iterative and iterative side-chain & Coulomb interaction determinants
Source.determinants.setDeterminants(self.get_sidechain_groups(), version=version, options=options) propka.determinants.setDeterminants(self.get_sidechain_groups(), version=version, options=options)
# calculating the total pKa values # calculating the total pKa values
for group in self.groups: group.calculate_total_pka() for group in self.groups: group.calculate_total_pka()
@@ -208,7 +211,7 @@ class Conformation_container:
penalised_labels = [] penalised_labels = []
for all_groups in self.get_coupled_systems(self.get_covalently_coupled_groups(), for all_groups in self.get_coupled_systems(self.get_covalently_coupled_groups(),
Source.group.Group.get_covalently_coupled_groups): propka.group.Group.get_covalently_coupled_groups):
# check if we should share determinants # check if we should share determinants
if self.parameters.shared_determinants: if self.parameters.shared_determinants:
@@ -250,7 +253,7 @@ class Conformation_container:
# overwrite/add maximum value for each determinant # overwrite/add maximum value for each determinant
for det_group in max_dets.keys(): for det_group in max_dets.keys():
new_determinant = Source.determinant.Determinant(det_group, max_dets[det_group]) new_determinant = propka.determinant.Determinant(det_group, max_dets[det_group])
for g in groups: for g in groups:
g.set_determinant(new_determinant,type) g.set_determinant(new_determinant,type)
@@ -410,7 +413,7 @@ class Conformation_container:
def set_ligand_atom_names(self): def set_ligand_atom_names(self):
for atom in self.get_ligand_atoms(): for atom in self.get_ligand_atoms():
Source.ligand.assign_sybyl_type(atom) propka.ligand.assign_sybyl_type(atom)
return return

View File

@@ -1,5 +1,8 @@
import math, Source.output, Source.group, Source.lib, itertools from __future__ import division
from __future__ import print_function
import math, propka.output, propka.group, propka.lib, itertools
class non_covalently_couple_groups: class non_covalently_couple_groups:
@@ -163,12 +166,12 @@ class non_covalently_couple_groups:
return return
def print_out_swaps(self, conformation, verbose=True): def print_out_swaps(self, conformation, verbose=True):
map = Source.output.make_interaction_map('Non-covalent coupling map for %s'%conformation, map = propka.output.make_interaction_map('Non-covalent coupling map for %s'%conformation,
conformation.get_non_covalently_coupled_groups(), conformation.get_non_covalently_coupled_groups(),
lambda g1,g2: g1 in g2.non_covalently_coupled_groups) lambda g1,g2: g1 in g2.non_covalently_coupled_groups)
print(map) print(map)
for system in conformation.get_coupled_systems(conformation.get_non_covalently_coupled_groups(),Source.group.Group.get_non_covalently_coupled_groups): for system in conformation.get_coupled_systems(conformation.get_non_covalently_coupled_groups(),propka.group.Group.get_non_covalently_coupled_groups):
self.print_system(conformation, list(system)) self.print_system(conformation, list(system))
return return
@@ -187,7 +190,7 @@ class non_covalently_couple_groups:
print(coup_info) print(coup_info)
# make list of possible combinations of swap to try out # make list of possible combinations of swap to try out
combinations = Source.lib.generate_combinations(interactions) combinations = propka.lib.generate_combinations(interactions)
# Make possible swap combinations # Make possible swap combinations
swap_info = '' swap_info = ''

View File

@@ -1,4 +1,7 @@
from __future__ import division
from __future__ import print_function
class Determinant: class Determinant:
""" """
Determinant class - set up for later structurization Determinant class - set up for later structurization

View File

@@ -1,8 +1,12 @@
from __future__ import division
from __future__ import print_function
import math, time import math, time
import Source.iterative, Source.lib, Source.vector_algebra import propka.iterative, propka.lib, propka.vector_algebra
import Source.calculations import propka.calculations
from Source.determinant import Determinant from propka.determinant import Determinant
def setDeterminants(propka_groups, version=None, options=None): def setDeterminants(propka_groups, version=None, options=None):
@@ -20,18 +24,18 @@ def setDeterminants(propka_groups, version=None, options=None):
if group2 in group1.covalently_coupled_groups: if group2 in group1.covalently_coupled_groups:
break break
distance = Source.calculations.distance(group1, group2) distance = propka.calculations.distance(group1, group2)
if distance < version.parameters.coulomb_cutoff2: if distance < version.parameters.coulomb_cutoff2:
interaction_type = version.parameters.interaction_matrix.get_value(group1.type,group2.type) interaction_type = version.parameters.interaction_matrix.get_value(group1.type,group2.type)
if interaction_type == 'I': if interaction_type == 'I':
Source.iterative.addtoDeterminantList(group1, group2, distance, iterative_interactions, version=version) propka.iterative.addtoDeterminantList(group1, group2, distance, iterative_interactions, version=version)
elif interaction_type == 'N': elif interaction_type == 'N':
addDeterminants(group1, group2, distance, version) addDeterminants(group1, group2, distance, version)
# --- Iterative section ---# # --- Iterative section ---#
Source.iterative.addDeterminants(iterative_interactions, version, options=options) propka.iterative.addDeterminants(iterative_interactions, version, options=options)
def addDeterminants(group1, group2, distance, version): def addDeterminants(group1, group2, distance, version):
@@ -151,7 +155,7 @@ def setIonDeterminants(conformation_container, version):
""" """
for titratable_group in conformation_container.get_titratable_groups(): for titratable_group in conformation_container.get_titratable_groups():
for ion_group in conformation_container.get_ions(): for ion_group in conformation_container.get_ions():
squared_distance = Source.calculations.squared_distance(titratable_group, ion_group) squared_distance = propka.calculations.squared_distance(titratable_group, ion_group)
if squared_distance < version.parameters.coulomb_cutoff2_squared: if squared_distance < version.parameters.coulomb_cutoff2_squared:
weight = version.calculatePairWeight(titratable_group.Nmass, ion_group.Nmass) weight = version.calculatePairWeight(titratable_group.Nmass, ion_group.Nmass)
# the pKa of both acids and bases are shifted up by negative ions (and vice versa) # the pKa of both acids and bases are shifted up by negative ions (and vice versa)
@@ -171,7 +175,7 @@ def setBackBoneDeterminants(titratable_groups, backbone_groups, version):
titratable_group_interaction_atoms = titratable_group.interaction_atoms_for_acids titratable_group_interaction_atoms = titratable_group.interaction_atoms_for_acids
# find the smallest distance # find the smallest distance
[backbone_atom, distance, titratable_atom] = Source.calculations.get_smallest_distance(backbone_interaction_atoms, [backbone_atom, distance, titratable_atom] = propka.calculations.get_smallest_distance(backbone_interaction_atoms,
titratable_group_interaction_atoms) titratable_group_interaction_atoms)
# get the parameters # get the parameters
parameters = version.get_backbone_hydrogen_bond_parameters(backbone_atom, titratable_atom) parameters = version.get_backbone_hydrogen_bond_parameters(backbone_atom, titratable_atom)
@@ -197,7 +201,7 @@ def setBackBoneDeterminants(titratable_groups, backbone_groups, version):
if titratable_atom.element == 'H': if titratable_atom.element == 'H':
heavy_atom = titratable_atom.bonded_atoms[0] heavy_atom = titratable_atom.bonded_atoms[0]
hydrogen_atom = titratable_atom hydrogen_atom = titratable_atom
[d1, f_angle, d2] = Source.calculations.AngleFactorX(atom1=heavy_atom, [d1, f_angle, d2] = propka.calculations.AngleFactorX(atom1=heavy_atom,
atom2=hydrogen_atom, atom2=hydrogen_atom,
atom3=backbone_atom) atom3=backbone_atom)
else: else:
@@ -218,7 +222,7 @@ def setBackBoneDeterminants(titratable_groups, backbone_groups, version):
if backbone_atom.element == 'H': if backbone_atom.element == 'H':
backbone_N = backbone_atom.bonded_atoms[0] backbone_N = backbone_atom.bonded_atoms[0]
backbone_H = backbone_atom backbone_H = backbone_atom
[d1, f_angle, d2] = Source.calculations.AngleFactorX(atom1=titratable_atom, [d1, f_angle, d2] = propka.calculations.AngleFactorX(atom1=titratable_atom,
atom2=backbone_H, atom2=backbone_H,
atom3=backbone_N) atom3=backbone_N)
else: else:
@@ -229,7 +233,7 @@ def setBackBoneDeterminants(titratable_groups, backbone_groups, version):
if f_angle > 0.001: if f_angle > 0.001:
value = titratable_group.charge * Source.calculations.HydrogenBondEnergy(distance, dpKa_max, [cutoff1,cutoff2], f_angle) value = titratable_group.charge * propka.calculations.HydrogenBondEnergy(distance, dpKa_max, [cutoff1,cutoff2], f_angle)
newDeterminant = Determinant(backbone_group, value) newDeterminant = Determinant(backbone_group, value)
titratable_group.determinants['backbone'].append(newDeterminant) titratable_group.determinants['backbone'].append(newDeterminant)

View File

@@ -2,9 +2,12 @@
# Class for storing groups important for propka calculations # Class for storing groups important for propka calculations
# #
import Source.ligand, Source.determinant, Source.ligand_pka_values, math, Source.protonate from __future__ import division
from __future__ import print_function
my_protonator = Source.protonate.Protonate(verbose=False) import propka.ligand, propka.determinant, propka.ligand_pka_values, math, propka.protonate
my_protonator = propka.protonate.Protonate(verbose=False)
expected_atoms_acid_interactions = { expected_atoms_acid_interactions = {
'COO':{'O':2}, 'COO':{'O':2},
@@ -190,7 +193,7 @@ class Group:
# otherwise we just add the determinant to our list # otherwise we just add the determinant to our list
if not added: if not added:
self.determinants[type].append(Source.determinant.Determinant(new_determinant.group, self.determinants[type].append(propka.determinant.Determinant(new_determinant.group,
new_determinant.value)) new_determinant.value))
return return
@@ -283,7 +286,7 @@ class Group:
return return
# otherwise we just add the determinant to our list # otherwise we just add the determinant to our list
self.determinants[type].append(Source.determinant.Determinant(new_determinant.group, self.determinants[type].append(propka.determinant.Determinant(new_determinant.group,
new_determinant.value)) new_determinant.value))
return return
@@ -298,7 +301,7 @@ class Group:
return return
# otherwise we just add the determinant to our list # otherwise we just add the determinant to our list
self.determinants[type].append(Source.determinant.Determinant(new_determinant.group, self.determinants[type].append(propka.determinant.Determinant(new_determinant.group,
new_determinant.value)) new_determinant.value))
return return
@@ -624,7 +627,7 @@ class HIS_group(Group):
def setup_atoms(self): def setup_atoms(self):
# Find the atoms in the histidine ring # Find the atoms in the histidine ring
ring_atoms = Source.ligand.is_ring_member(self.atom) ring_atoms = propka.ligand.is_ring_member(self.atom)
if len(ring_atoms) != 5: if len(ring_atoms) != 5:
print('Warning: His group does not seem to contain a ring',self) print('Warning: His group does not seem to contain a ring',self)
@@ -1284,7 +1287,7 @@ def is_ligand_group_by_marvin_pkas(parameters, atom):
# calculate Marvin ligand pkas for this conformation container # calculate Marvin ligand pkas for this conformation container
# if not already done # if not already done
if not atom.conformation_container.marvin_pkas_calculated: if not atom.conformation_container.marvin_pkas_calculated:
lpka = Source.ligand_pka_values.ligand_pka_values(parameters) lpka = propka.ligand_pka_values.ligand_pka_values(parameters)
lpka.get_marvin_pkas_for_molecular_container(atom.molecular_container, lpka.get_marvin_pkas_for_molecular_container(atom.molecular_container,
min_pH=parameters.min_ligand_model_pka, min_pH=parameters.min_ligand_model_pka,
max_pH=parameters.max_ligand_model_pka) max_pH=parameters.max_ligand_model_pka)

View File

@@ -1,7 +1,12 @@
from __future__ import division
from __future__ import print_function
import math, time import math, time
import Source.lib as lib
from Source.determinant import Determinant import propka.lib as lib
import Source.calculations from propka.determinant import Determinant
import propka.calculations
# Some library functions for the interative pKa determinants # Some library functions for the interative pKa determinants

20
Source/lib.py → propka/lib.py Executable file → Normal file
View File

@@ -1,20 +1,24 @@
#!/usr/bin/python from __future__ import division
from __future__ import print_function
import string, sys, copy, math, os import string, sys, copy, math, os
import pkg_resources
# #
# file I/O # file I/O
# #
def open_file_for_reading(filename): def open_file_for_reading(filename):
if not os.path.isfile(filename): try:
f = open(filename,'r')
except:
raise Exception('Cannot find file %s' %filename) raise Exception('Cannot find file %s' %filename)
return f
return open(filename,'r')
def open_file_for_writing(filename): def open_file_for_writing(filename):
res = open(filename,'w') try:
if not res: res = open(filename,'w')
except:
raise Exception('Could not open %s'%filename) raise Exception('Could not open %s'%filename)
return res return res
@@ -99,8 +103,8 @@ def loadOptions():
help="specifying mutation labels which is used to modify <filename> according to, e.g. N25R/N181D") help="specifying mutation labels which is used to modify <filename> according to, e.g. N25R/N181D")
parser.add_option("-v", "--version", dest="version_label", default="Jan15", parser.add_option("-v", "--version", dest="version_label", default="Jan15",
help="specifying the sub-version of propka [Jan15/Dec19]") help="specifying the sub-version of propka [Jan15/Dec19]")
parser.add_option("-p", "--parameters",dest="parameters", default="propka.cfg", parser.add_option("-p", "--parameters",dest="parameters", default=pkg_resources.resource_filename(__name__, "propka.cfg"),
help="set the parameter file") help="set the parameter file [%default]")
parser.add_option("-z", "--verbose", dest="verbose", action="store_true", default=True, parser.add_option("-z", "--verbose", dest="verbose", action="store_true", default=True,
help="sleep during calculations") help="sleep during calculations")
parser.add_option("-q", "--quiet", dest="verbose", action="store_false", parser.add_option("-q", "--quiet", dest="verbose", action="store_false",

15
Source/ligand.py → propka/ligand.py Executable file → Normal file
View File

@@ -1,7 +1,12 @@
#!/usr/bin/python #!/usr/bin/python
import sys, Source.calculations from __future__ import division
from Source.vector_algebra import * from __future__ import print_function
import sys
import propka.calculations
from propka.vector_algebra import *
all_sybyl_types = [ all_sybyl_types = [
@@ -217,7 +222,7 @@ def assign_sybyl_type(atom):
# sp carbon # sp carbon
if len(atom.bonded_atoms)<=2: if len(atom.bonded_atoms)<=2:
for b in atom.bonded_atoms: for b in atom.bonded_atoms:
if Source.calculations.squared_distance(atom, b) < max_C_triple_bond_squared: if propka.calculations.squared_distance(atom, b) < max_C_triple_bond_squared:
set_type(atom,'C.1') set_type(atom,'C.1')
set_type(b,b.element+'.1') set_type(b,b.element+'.1')
if atom.sybyl_assigned: if atom.sybyl_assigned:
@@ -270,7 +275,7 @@ def assign_sybyl_type(atom):
return return
# check for X=O # check for X=O
if Source.calculations.squared_distance(atom, atom.bonded_atoms[0]) < max_C_double_bond_squared: if propka.calculations.squared_distance(atom, atom.bonded_atoms[0]) < max_C_double_bond_squared:
set_type(atom,'O.2') set_type(atom,'O.2')
if atom.bonded_atoms[0].element=='C': if atom.bonded_atoms[0].element=='C':
set_type(atom.bonded_atoms[0],'C.2') set_type(atom.bonded_atoms[0],'C.2')
@@ -316,7 +321,7 @@ def assign_sybyl_type(atom):
# bonded_oxygens_1 = [o for o in bonded_oxygens if len(o.get_bonded_heavy_atoms())==1] # bonded_oxygens_1 = [o for o in bonded_oxygens if len(o.get_bonded_heavy_atoms())==1]
# # find the closest oxygen ... # # find the closest oxygen ...
# closest_oxygen = min(bonded_oxygens_1, # closest_oxygen = min(bonded_oxygens_1,
# key= lambda o:Source.calculations.squared_distance(atom,o)) # key= lambda o:propka.calculations.squared_distance(atom,o))
# # ... and set it to O.2 # # ... and set it to O.2
# set_type(closest_oxygen,'O.2') # set_type(closest_oxygen,'O.2')

View File

@@ -1,6 +1,9 @@
#!/usr/bin/env python #!/usr/bin/env python
import Source.molecular_container, Source.calculations, Source.calculations, Source.parameters, Source.pdb, Source.lib, os, subprocess, sys from __future__ import division
from __future__ import print_function
import propka.molecular_container, propka.calculations, propka.calculations, propka.parameters, propka.pdb, propka.lib, os, subprocess, sys
class ligand_pka_values: class ligand_pka_values:
def __init__(self, parameters): def __init__(self, parameters):
@@ -29,7 +32,7 @@ class ligand_pka_values:
return l[0] return l[0]
def get_marvin_pkas_for_pdb_file(self, file, no_pkas=10, min_pH =-10, max_pH=20): def get_marvin_pkas_for_pdb_file(self, file, no_pkas=10, min_pH =-10, max_pH=20):
molecule = Source.molecular_container.Molecular_container(file) molecule = propka.molecular_container.Molecular_container(file)
self.get_marvin_pkas_for_molecular_container(molecule, no_pkas=no_pkas, min_pH =min_pH, max_pH=max_pH) self.get_marvin_pkas_for_molecular_container(molecule, no_pkas=no_pkas, min_pH =min_pH, max_pH=max_pH)
return return
@@ -50,7 +53,7 @@ class ligand_pka_values:
def get_marvin_pkas_for_atoms(self, atoms, name='temp', reuse=False, no_pkas=10, min_pH =-10, max_pH=20): def get_marvin_pkas_for_atoms(self, atoms, name='temp', reuse=False, no_pkas=10, min_pH =-10, max_pH=20):
# do one molecule at the time so we don't confuse marvin # do one molecule at the time so we don't confuse marvin
molecules = Source.lib.split_atoms_into_molecules(atoms) molecules = propka.lib.split_atoms_into_molecules(atoms)
for i in range(len(molecules)): for i in range(len(molecules)):
filename = '%s_%d.mol2'%(name, i+1) filename = '%s_%d.mol2'%(name, i+1)
self.get_marvin_pkas_for_molecule(molecules[i], filename=filename, reuse=reuse, no_pkas=no_pkas, min_pH =min_pH, max_pH=max_pH) self.get_marvin_pkas_for_molecule(molecules[i], filename=filename, reuse=reuse, no_pkas=no_pkas, min_pH =min_pH, max_pH=max_pH)
@@ -61,11 +64,11 @@ class ligand_pka_values:
def get_marvin_pkas_for_molecule(self, atoms, filename='__tmp_ligand.mol2', reuse=False, no_pkas=10, min_pH =-10, max_pH=20): def get_marvin_pkas_for_molecule(self, atoms, filename='__tmp_ligand.mol2', reuse=False, no_pkas=10, min_pH =-10, max_pH=20):
# print out structure unless we are using user-modified structure # print out structure unless we are using user-modified structure
if not reuse: if not reuse:
Source.pdb.write_mol2_for_atoms(atoms, filename) propka.pdb.write_mol2_for_atoms(atoms, filename)
# check that we actually have a file to work with # check that we actually have a file to work with
if not os.path.isfile(filename): if not os.path.isfile(filename):
print('Warning: Didn\'t find a user-modified file \'%s\' - generating one'%filename) print('Warning: Didn\'t find a user-modified file \'%s\' - generating one'%filename)
Source.pdb.write_mol2_for_atoms(atoms, filename) propka.pdb.write_mol2_for_atoms(atoms, filename)

View File

@@ -3,13 +3,17 @@
# Molecular container for storing all contents of pdb files # Molecular container for storing all contents of pdb files
# #
# #
from __future__ import division
from __future__ import print_function
import os, Source.pdb, sys, Source.version, Source.output, Source.conformation_container, Source.group, Source.lib import os, sys
import propka.pdb, propka.version, propka.output, propka.conformation_container, propka.group, propka.lib
class Molecular_container: class Molecular_container:
def __init__(self, input_file, options=None): def __init__(self, input_file, options=None):
# printing out header before parsing input # printing out header before parsing input
Source.output.printHeader() propka.output.printHeader()
# set up some values # set up some values
self.options = options self.options = options
@@ -21,11 +25,11 @@ class Molecular_container:
# set the version # set the version
if options: if options:
parameters = Source.parameters.Parameters(self.options.parameters) parameters = propka.parameters.Parameters(self.options.parameters)
else: else:
parameters = Source.parameters.Parameters('propka.cfg') parameters = propka.parameters.Parameters('propka.cfg')
try: try:
exec('self.version = Source.version.%s(parameters)'%parameters.version) exec('self.version = propka.version.%s(parameters)'%parameters.version)
except: except:
raise Exception('Error: Version %s does not exist'%parameters.version) raise Exception('Error: Version %s does not exist'%parameters.version)
@@ -33,7 +37,7 @@ class Molecular_container:
if input_file_extension[0:4] == '.pdb': if input_file_extension[0:4] == '.pdb':
# input is a pdb file # input is a pdb file
# read in atoms and top up containers to make sure that all atoms are present in all conformations # read in atoms and top up containers to make sure that all atoms are present in all conformations
[self.conformations, self.conformation_names] = Source.pdb.read_pdb(input_file, self.version.parameters,self) [self.conformations, self.conformation_names] = propka.pdb.read_pdb(input_file, self.version.parameters,self)
if len(self.conformations)==0: if len(self.conformations)==0:
print('Error: The pdb file does not seems to contain any molecular conformations') print('Error: The pdb file does not seems to contain any molecular conformations')
sys.exit(-1) sys.exit(-1)
@@ -41,7 +45,7 @@ class Molecular_container:
self.top_up_conformations() self.top_up_conformations()
# make a structure precheck # make a structure precheck
Source.pdb.protein_precheck(self.conformations, self.conformation_names) propka.pdb.protein_precheck(self.conformations, self.conformation_names)
# set up atom bonding and protonation # set up atom bonding and protonation
self.version.setup_bonding_and_protonation(self) self.version.setup_bonding_and_protonation(self)
@@ -58,12 +62,12 @@ class Molecular_container:
# write out the input file # write out the input file
filename = self.file.replace(input_file_extension,'.propka_input') filename = self.file.replace(input_file_extension,'.propka_input')
Source.pdb.write_input(self, filename) propka.pdb.write_input(self, filename)
elif input_file_extension == '.propka_input': elif input_file_extension == '.propka_input':
#input is a propka_input file #input is a propka_input file
[self.conformations, self.conformation_names] = Source.pdb.read_input(input_file, self.version.parameters, self) [self.conformations, self.conformation_names] = propka.pdb.read_input(input_file, self.version.parameters, self)
# Extract groups - this merely sets up the groups found in the input file # Extract groups - this merely sets up the groups found in the input file
self.extract_groups() self.extract_groups()
@@ -125,13 +129,13 @@ class Molecular_container:
self.average_of_conformations() self.average_of_conformations()
# print out the conformation-average results # print out the conformation-average results
Source.output.printResult(self, 'AVR', self.version.parameters) propka.output.printResult(self, 'AVR', self.version.parameters)
return return
def average_of_conformations(self): def average_of_conformations(self):
# make a new configuration to hold the average values # make a new configuration to hold the average values
avr_conformation = Source.conformation_container.Conformation_container(name='average', avr_conformation = propka.conformation_container.Conformation_container(name='average',
parameters=self.conformations[self.conformation_names[0]].parameters, parameters=self.conformations[self.conformation_names[0]].parameters,
molecular_container=self) molecular_container=self)
@@ -161,7 +165,7 @@ class Molecular_container:
def write_pka(self, filename=None, reference="neutral", direction="folding", options=None): def write_pka(self, filename=None, reference="neutral", direction="folding", options=None):
#for name in self.conformation_names: #for name in self.conformation_names:
# Source.output.writePKA(self, self.version.parameters, filename='%s_3.1_%s.pka'%(self.name, name), # propka.output.writePKA(self, self.version.parameters, filename='%s_3.1_%s.pka'%(self.name, name),
# conformation=name,reference=reference, # conformation=name,reference=reference,
# direction=direction, options=options) # direction=direction, options=options)
@@ -176,7 +180,7 @@ class Molecular_container:
if hasattr(self.version.parameters, 'output_file_tag') and len(self.version.parameters.output_file_tag)>0: if hasattr(self.version.parameters, 'output_file_tag') and len(self.version.parameters.output_file_tag)>0:
filename=os.path.join('%s_%s.pka'%(self.name,self.version.parameters.output_file_tag)) filename=os.path.join('%s_%s.pka'%(self.name,self.version.parameters.output_file_tag))
Source.output.writePKA(self, self.version.parameters, filename=filename, propka.output.writePKA(self, self.version.parameters, filename=filename,
conformation='AVR',reference=reference, conformation='AVR',reference=reference,
direction=direction, options=options) direction=direction, options=options)
@@ -185,7 +189,7 @@ class Molecular_container:
def getFoldingProfile(self, conformation='AVR',reference="neutral", direction="folding", grid=[0., 14., 0.1], options=None): def getFoldingProfile(self, conformation='AVR',reference="neutral", direction="folding", grid=[0., 14., 0.1], options=None):
# calculate stability profile # calculate stability profile
profile = [] profile = []
for ph in Source.lib.make_grid(*grid): for ph in propka.lib.make_grid(*grid):
ddg = self.conformations[conformation].calculate_folding_energy( pH=ph, reference=reference) ddg = self.conformations[conformation].calculate_folding_energy( pH=ph, reference=reference)
#print(ph,ddg) #print(ph,ddg)
profile.append([ph, ddg]) profile.append([ph, ddg])
@@ -213,7 +217,7 @@ class Molecular_container:
def getChargeProfile(self, conformation='AVR', grid=[0., 14., .1]): def getChargeProfile(self, conformation='AVR', grid=[0., 14., .1]):
charge_profile = [] charge_profile = []
for ph in Source.lib.make_grid(*grid): for ph in propka.lib.make_grid(*grid):
q_unfolded, q_folded = self.conformations[conformation].calculate_charge(self.version.parameters, pH=ph) q_unfolded, q_folded = self.conformations[conformation].calculate_charge(self.version.parameters, pH=ph)
charge_profile.append([ph, q_unfolded, q_folded]) charge_profile.append([ph, q_unfolded, q_folded])

View File

@@ -1,5 +1,10 @@
from __future__ import division
from __future__ import print_function
import sys import sys
import Source.lib
import propka.lib
def printHeader(): def printHeader():

View File

@@ -1,7 +1,12 @@
from __future__ import division
from __future__ import print_function
import math import math
import Source.lib as lib import propka.lib as lib
import sys, os import sys, os
import pkg_resources
# names and types of all key words in configuration file # names and types of all key words in configuration file
matrices = ['interaction_matrix'] matrices = ['interaction_matrix']
@@ -53,8 +58,7 @@ class Parameters:
def read_parameters(self, file): def read_parameters(self, file):
# try to locate the parameters file # try to locate the parameters file
try: try:
path = os.path.dirname(__file__) ifile = pkg_resources.resource_filename(__name__, file)
ifile = os.path.join(path,'../'+file)
input = lib.open_file_for_reading(ifile) input = lib.open_file_for_reading(ifile)
except: except:
input = lib.open_file_for_reading(file) input = lib.open_file_for_reading(file)

View File

@@ -1,6 +1,12 @@
import string, sys, copy, Source.lib
from Source.atom import Atom from __future__ import division
from Source.conformation_container import Conformation_container from __future__ import print_function
import string, sys, copy
import propka.lib
from propka.atom import Atom
from propka.conformation_container import Conformation_container
expected_atom_numbers = {'ALA':5, expected_atom_numbers = {'ALA':5,
'ARG':11, 'ARG':11,
@@ -35,7 +41,7 @@ def read_pdb(pdb_file, parameters, molecule):
conformations[name].add_atom(atom) conformations[name].add_atom(atom)
# make a sorted list of conformation names # make a sorted list of conformation names
names = sorted(conformations.keys(), key=Source.lib.conformation_sorter) names = sorted(conformations.keys(), key=propka.lib.conformation_sorter)
return [conformations, names] return [conformations, names]
@@ -74,7 +80,7 @@ def resid_from_atom(a):
def get_atom_lines_from_pdb(pdb_file, ignore_residues = [], keep_protons=False, tags = ['ATOM ', 'HETATM'], chains=None): def get_atom_lines_from_pdb(pdb_file, ignore_residues = [], keep_protons=False, tags = ['ATOM ', 'HETATM'], chains=None):
lines = Source.lib.open_file_for_reading(pdb_file).readlines() lines = propka.lib.open_file_for_reading(pdb_file).readlines()
nterm_residue = 'next_residue' nterm_residue = 'next_residue'
old_residue = None old_residue = None
terminal = None terminal = None
@@ -147,7 +153,7 @@ def write_pdb(conformation, filename):
return return
def write_pdb_for_atoms(atoms, filename, make_conect_section=False): def write_pdb_for_atoms(atoms, filename, make_conect_section=False):
out = Source.lib.open_file_for_writing(filename) out = propka.lib.open_file_for_writing(filename)
for atom in atoms: for atom in atoms:
out.write(atom.make_pdb_line()) out.write(atom.make_pdb_line())
@@ -185,7 +191,7 @@ def write_mol2_for_atoms(atoms, filename):
if len(atoms)>0: if len(atoms)>0:
substructure_section = '@<TRIPOS>SUBSTRUCTURE\n%-7d %10s %7d\n'%(atoms[0].resNumb,atoms[0].resName,atoms[0].numb) substructure_section = '@<TRIPOS>SUBSTRUCTURE\n%-7d %10s %7d\n'%(atoms[0].resNumb,atoms[0].resName,atoms[0].numb)
out = Source.lib.open_file_for_writing(filename) out = propka.lib.open_file_for_writing(filename)
out.write(header%(len(atoms),id-1)) out.write(header%(len(atoms),id-1))
out.write(atoms_section) out.write(atoms_section)
out.write(bonds_section) out.write(bonds_section)
@@ -216,7 +222,7 @@ def get_bond_order(atom1, atom2):
def write_input(molecular_container, filename): def write_input(molecular_container, filename):
out = Source.lib.open_file_for_writing(filename) out = propka.lib.open_file_for_writing(filename)
for conformation_name in molecular_container.conformation_names: for conformation_name in molecular_container.conformation_names:
out.write('MODEL %s\n'%conformation_name) out.write('MODEL %s\n'%conformation_name)
@@ -250,14 +256,14 @@ def read_input(input_file, parameters,molecule):
conformations[name].add_atom(atom) conformations[name].add_atom(atom)
# make a sorted list of conformation names # make a sorted list of conformation names
names = sorted(conformations.keys(), key=Source.lib.conformation_sorter) names = sorted(conformations.keys(), key=propka.lib.conformation_sorter)
return [conformations, names] return [conformations, names]
def get_atom_lines_from_input(input_file, tags = ['ATOM ','HETATM']): def get_atom_lines_from_input(input_file, tags = ['ATOM ','HETATM']):
lines = Source.lib.open_file_for_reading(input_file).readlines() lines = propka.lib.open_file_for_reading(input_file).readlines()
conformation = '' conformation = ''
atoms = {} atoms = {}

398
propka/propka.cfg Normal file
View File

@@ -0,0 +1,398 @@
# PropKa configuration file
version version_A
# Model pKa values
model_pkas C- 3.20
model_pkas ASP 3.80
model_pkas GLU 4.50
model_pkas HIS 6.50
model_pkas CYS 9.00
model_pkas TYR 10.00
model_pkas LYS 10.50
model_pkas ARG 12.50
#model_pkas SER 14.20 Jack Kyte: Structure in Protein Chemistry, 1995, Garland Publishing, Inc New York and London
model_pkas N+ 8.00
model_pkas CG 11.50
model_pkas C2N 11.50
model_pkas N30 10.00
model_pkas N31 10.00
model_pkas N32 10.00
model_pkas N33 10.00
model_pkas NAR 5.00
model_pkas OCO 4.50
model_pkas SH 10.00
model_pkas OP 6.00
# Custom ligand pKa values
# P. Acharya, P. Cheruku, S. Chatterjee, S. Acharya, and, J. Chattopadhyaya:
# Measurement of Nucleobase pKa Values in Model Mononucleotides
# Shows RNA-RNA Duplexes To Be More Stable than DNA-DNA Duplexes
# Journal of the American Chemical Society 2004 126 (9), 2862-2869
#
custom_model_pkas DA-N1 3.82
custom_model_pkas DA-N3 3.82
custom_model_pkas DA-N7 3.82
custom_model_pkas DA-OP1 1.00
custom_model_pkas DA-OP2 1.00
custom_model_pkas DG-N1 9.59
custom_model_pkas DG-N3 9.59
custom_model_pkas DG-N7 9.59
custom_model_pkas DG-OP1 1.00
custom_model_pkas DG-OP2 1.00
custom_model_pkas DC-N3 4.34
custom_model_pkas DC-OP1 1.00
custom_model_pkas DC-OP2 1.00
custom_model_pkas DT-N3 10.12
custom_model_pkas DT-OP1 1.00
custom_model_pkas DT-OP2 1.00
# protein group mapping
protein_group_mapping ASP-CG COO
protein_group_mapping GLU-CD COO
protein_group_mapping HIS-CG HIS
protein_group_mapping CYS-SG CYS
protein_group_mapping TYR-OH TYR
protein_group_mapping LYS-NZ LYS
protein_group_mapping ARG-CZ ARG
#protein_group_mapping SER-OG SER
protein_group_mapping THR-OG1 ROH
protein_group_mapping SER-OG ROH#
protein_group_mapping ASN-CG AMD
protein_group_mapping GLN-CD AMD
protein_group_mapping TRP-NE1 TRP
# matrix for propka interactions
# 'N' non-iterative interaction
# 'I' iterative interaction
# '-' no interaction
#CYS
interaction_matrix CYS I#N+
interaction_matrix N+ N I#HIS
interaction_matrix HIS I N I#LYS
interaction_matrix LYS N N N I#AMD
interaction_matrix AMD N - N - -#COO
interaction_matrix COO I N I N N I#ARG
interaction_matrix ARG N N N N - N I#TRP
interaction_matrix TRP N - - - - N - -#ROH
interaction_matrix ROH N - - - - N - - -#TYR
interaction_matrix TYR N I I I N N N N N I#SER
interaction_matrix SER N N N N N N I N N N I #CG
interaction_matrix CG N N N N - N I - - N I I#C2N
interaction_matrix C2N N N N N - N I - - N I I I#N30
interaction_matrix N30 N I N N - N N - - I N I I I#N31
interaction_matrix N31 N I N N - N N - - I N I I I I#N32
interaction_matrix N32 N I N N - N N - - I N I I I I I#N33
interaction_matrix N33 N I N N - N N - - I N I I I I I I#NAR
interaction_matrix NAR I N I I N I N - - I N N N N N N N I#OCO
interaction_matrix OCO I N I N N I N N N N N N N N N N N I I#NP1
interaction_matrix NP1 N - N - - N - - - N N - - - - - - N N -#OH
interaction_matrix OH N - - - - N - - - N N - - - - - - - N - -#O3
interaction_matrix O3 N - N - - N - - - N N - - - - - - N N - - -#CL
interaction_matrix CL N - N - - N - - - N N - - - - - - N N - - - -#F
interaction_matrix F N - N - - N - - - N N - - - - - - N N - - - - -#NAM
interaction_matrix NAM N - N - - N - - - N N - - - - - - N N - - - - - -#N1
interaction_matrix N1 N - N - - N - - - N N - - - - - - N N - - - - - - -#O2
interaction_matrix O2 N - N - - N - - - N N - - - - - - N N - - - - - - - -#OP
interaction_matrix OP I N I N N I N N N N N N N N N N N I I N N N N N N N N I#SH
interaction_matrix SH I N N N N N N N N N N I I I I I I N N N N N N N N N N N I
# Cutoff values for side chain interactions
# default value
sidechain_cutoffs default 3.0 4.0
# COO
sidechain_cutoffs COO COO 2.5 3.5
Sidechain_cutoffs COO SER 2.65 3.65
sidechain_cutoffs COO ARG 1.85 2.85
sidechain_cutoffs COO LYS 2.85 3.85
sidechain_cutoffs COO HIS 2.0 3.0
sidechain_cutoffs COO AMD 2.0 3.0
sidechain_cutoffs COO TRP 2.0 3.0
sidechain_cutoffs COO ROH 2.65 3.65
sidechain_cutoffs COO TYR 2.65 3.65
sidechain_cutoffs COO N+ 2.85 3.85
sidechain_cutoffs COO CG 1.85 2.85
sidechain_cutoffs COO C2N 1.85 2.85
sidechain_cutoffs COO N30 2.85 3.85
sidechain_cutoffs COO N31 2.85 3.85
sidechain_cutoffs COO N32 2.85 3.85
sidechain_cutoffs COO N33 2.85 3.85
sidechain_cutoffs COO NAR 2.0 3.0
sidechain_cutoffs COO OCO 2.5 3.5
sidechain_cutoffs COO OH 2.65 3.65
sidechain_cutoffs COO NAM 2.0 3.0
# SER
sidechain_cutoffs SER SER 3.5 4.5
sidechain_cutoffs SER ARG 2.5 4.0
sidechain_cutoffs SER HIS 2.0 3.0
sidechain_cutoffs SER AMD 2.5 3.5
sidechain_cutoffs SER CYS 3.5 4.5
sidechain_cutoffs SER TRP 2.5 3.5
sidechain_cutoffs SER ROH 3.5 4.5
sidechain_cutoffs SER CG 2.5 4.0
sidechain_cutoffs SER C2N 2.5 4.0
sidechain_cutoffs SER NAR 2.0 3.0
sidechain_cutoffs SER OH 3.5 4.5
sidechain_cutoffs SER SH 3.5 4.5
sidechain_cutoffs SER TYR 3.5 4.5
sidechain_cutoffs SER N+ 3.0 4.5
sidechain_cutoffs SER NAM 2.5 3.5
# ARG
sidechain_cutoffs ARG CYS 2.5 4.0
sidechain_cutoffs ARG TYR 2.5 4.0
sidechain_cutoffs ARG OCO 1.85 2.85
sidechain_cutoffs ARG SH 2.5 4.0
# HIS
sidechain_cutoffs HIS AMD 2.0 3.0
sidechain_cutoffs HIS TYR 2.0 3.0
sidechain_cutoffs HIS OCO 2.0 3.0
# CYS
sidechain_cutoffs CYS CYS 3.0 5.0
sidechain_cutoffs CYS TRP 2.5 3.5
sidechain_cutoffs CYS ROH 3.5 4.5
sidechain_cutoffs CYS AMD 2.5 3.5
sidechain_cutoffs CYS TYR 3.5 4.5
sidechain_cutoffs CYS N+ 3.0 4.5
sidechain_cutoffs CYS CG 2.5 4.0
sidechain_cutoffs CYS C2N 2.5 4.0
sidechain_cutoffs CYS N30 3.0 4.5
sidechain_cutoffs CYS N31 3.0 4.5
sidechain_cutoffs CYS N32 3.0 4.5
sidechain_cutoffs CYS N33 3.0 4.5
sidechain_cutoffs CYS OH 3.5 4.5
sidechain_cutoffs CYS NAM 2.5 3.5
sidechain_cutoffs CYS SH 3.0 5.0
# TYR
sidechain_cutoffs TYR TYR 3.5 4.5
sidechain_cutoffs TYR N+ 3.0 4.5
sidechain_cutoffs TYR AMD 2.5 3.5
sidechain_cutoffs TYR TRP 2.5 3.5
sidechain_cutoffs TYR ROH 3.5 4.5
sidechain_cutoffs TYR CG 2.5 4.0
sidechain_cutoffs TYR C2N 2.5 4.0
sidechain_cutoffs TYR OCO 2.65 3.65
sidechain_cutoffs TYR NAR 2.0 3.0
sidechain_cutoffs TYR OH 3.5 4.5
sidechain_cutoffs TYR NAM 2.5 3.5
sidechain_cutoffs TYR SH 3.5 4.5
# N+
sidechain_cutoffs N+ OCO 2.85 3.85
sidechain_cutoffs N+ SH 3.0 4.5
# LYS
sidechain_cutoffs LYS OCO 2.85 3.85
# OCO
sidechain_cutoffs OCO OCO 2.5 3.5
sidechain_cutoffs OCO TRP 2.0 3.0
sidechain_cutoffs OCO ROH 2.65 3.65
sidechain_cutoffs OCO AMD 2.0 3.0
sidechain_cutoffs OCO CG 1.85 2.85
sidechain_cutoffs OCO C2N 1.85 2.85
sidechain_cutoffs OCO N30 2.85 3.85
sidechain_cutoffs OCO N31 2.85 3.85
sidechain_cutoffs OCO N32 2.85 3.85
sidechain_cutoffs OCO N33 2.85 3.85
sidechain_cutoffs OCO NAR 2.0 3.0
sidechain_cutoffs OCO OH 2.65 3.65
sidechain_cutoffs OCO NAM 2.0 3.0
# NAR
sidechain_cutoffs NAR AMD 2.0 3.0
# SH
sidechain_cutoffs SH ROH 3.5 4.5
sidechain_cutoffs SH TRP 2.5 3.5
sidechain_cutoffs SH AMD 2.5 3.5
sidechain_cutoffs SH NAM 2.5 3.5
sidechain_cutoffs SH CG 2.5 4.0
sidechain_cutoffs SH C2N 2.5 4.0
sidechain_cutoffs SH OH 3.5 4.5
sidechain_cutoffs SH SH 3.0 5.0
# Maximal interaction energies for side chains
sidechain_interaction 0.85
# Angular dependent sidechain interactions
angular_dependent_sidechain_interactions HIS
angular_dependent_sidechain_interactions ARG
angular_dependent_sidechain_interactions AMD
angular_dependent_sidechain_interactions TRP
# exception interaction values
COO_HIS_exception 1.60
OCO_HIS_exception 1.60
CYS_HIS_exception 1.60
CYS_CYS_exception 3.60
# Coulomb interaction parameters
coulomb_cutoff1 4.0
coulomb_cutoff2 10.0
coulomb_diel 80.0
# Backbone hydrogen bond parameters
backbone_NH_hydrogen_bond COO -0.85 2.00 3.00
#backbone_NH_hydrogen_bond C- -0.85 2.00 3.00
backbone_NH_hydrogen_bond CYS -0.85 3.00 4.00
backbone_NH_hydrogen_bond TYR -0.85 2.20 3.20
backbone_NH_hydrogen_bond OCO -0.85 2.00 3.50
backbone_NH_hydrogen_bond NAR -0.85 2.00 3.50
backbone_CO_hydrogen_bond HIS 0.85 2.00 3.00
backbone_CO_hydrogen_bond OCO 0.85 3.00 4.00
backbone_CO_hydrogen_bond CG 0.85 2.00 4.00
backbone_CO_hydrogen_bond C2N 0.85 2.00 4.00
backbone_CO_hydrogen_bond N30 0.85 2.00 4.00
backbone_CO_hydrogen_bond N31 0.85 2.00 4.00
backbone_CO_hydrogen_bond N32 0.85 2.00 4.00
backbone_CO_hydrogen_bond N33 0.85 2.00 4.00
backbone_CO_hydrogen_bond NAR 0.85 2.00 3.50
# Group charges
charge COO -1
charge HIS +1
charge CYS -1
charge TYR -1
charge LYS +1
charge ARG +1
charge N+ +1
charge C- -1
charge OCO -1
charge SER -1
charge CG +1
charge C2N +1
charge N30 +1
charge N31 +1
charge N32 +1
charge N33 +1
charge NAR +1
charge SH -1
charge OP -1
# list of acids
acid_list ASP
acid_list GLU
acid_list CYS
acid_list TYR
acid_list SER
acid_list C-
acid_list OCO
acid_list OP
acid_list SH
# list of bases
base_list ARG
base_list LYS
base_list HIS
base_list N+
base_list CG
base_list C2N
base_list N30
base_list N31
base_list N32
base_list N33
base_list NAR
# list of groups used in backbone reorganisation calculations
backbone_reorganisation_list ASP
backbone_reorganisation_list GLU
# Residues that should be ignored
ignore_residues HOH
ignore_residues H2O
ignore_residues HOH
ignore_residues SO4
ignore_residues PO4
ignore_residues PEG
ignore_residues EPE
#ignore_residues NAG
ignore_residues TRS
# Relative Van der Waals volume parameters for the radial volume model
# Radii adopted from Bondi, A. (1964). "Van der Waals Volumes and Radii". J. Phys. Chem. 68 (3): 441-51
VanDerWaalsVolume C 1.40 # radius: 1.70, volume: 20.58 all 'C' and 'CA' atoms
VanDerWaalsVolume C4 2.64 # 38.79 hydrodphobic carbon atoms + unidentified atoms
VanDerWaalsVolume N 1.06 # radius: 1.55, volume: 15.60 all nitrogen atoms
VanDerWaalsVolume O 1.00 # radius: 1.52, volume: 14.71 all oxygen atoms
VanDerWaalsVolume S 1.66 # radius: 1.80, volume: 24.43 all sulphur atoms
VanDerWaalsVolume F 0.90 # raidus: 1.47, volume: 13.30 for fluorine
VanDerWaalsVolume Cl 1.53 # radius: 1.75, volume: 22.44 for chlorine
VanDerWaalsVolume P 1.66 # radius: 1.80, volume: 24.42 for phosphorus
# Other desolvation parameters
desolvationSurfaceScalingFactor 0.25
desolvationPrefactor -13.0
desolvationAllowance 0.0
desolv_cutoff 20.0
buried_cutoff 15.0
Nmin 280
Nmax 560
# Ligand groups
ligand_typing groups
min_bond_distance_for_hydrogen_bonds 4
# covalent coupling
coupling_max_number_of_bonds 3
shared_determinants 0
common_charge_centre 0
remove_penalised_group 1
# non-covalent coupling
max_intrinsic_pKa_diff 2.0
min_interaction_energy 0.5
max_free_energy_diff 1.0
min_swap_pka_shift 1.0
min_pka 0.0
max_pka 10.0
pH variable
reference neutral
# ions
ions 1P 1 # generic charged atoms
ions 2P 2
ions 1N -1
ions 2N -2
ions MG 2 #Magnesium Ion
ions CA 2 #Calcium Ion
ions ZN 2 #Zinc Ion
ions NA 1 #Sodium Ion
ions CL -1 #Chloride Ion
ions MN 2 #Manganese (ii) Ion
ions K 1 #Potassium Ion
ions CD 2 #Cadmium Ion
ions FE 3 #Fe (iii) Ion
ions SR 2 #Strontium Ion
ions CU 2 #Copper (ii) Ion
ions IOD -1 #Iodide Ion
ions HG 2 #Mercury (ii) Ion
ions BR -1 #Bromide Ion
ions CO 2 #Cobalt (ii) Ion
ions NI 2 #Nickel (ii) Ion
ions FE2 2 #Fe (ii) Ion
# write out order of residues
write_out_order ASP
write_out_order GLU
write_out_order C-
write_out_order HIS
write_out_order CYS
write_out_order TYR
write_out_order LYS
write_out_order ARG
write_out_order SER
write_out_order N+
write_out_order CG
write_out_order C2N
write_out_order N30
write_out_order N31
write_out_order N32
write_out_order N33
write_out_order NAR
write_out_order OCO
write_out_order SH
write_out_order OP

9
Source/protonate.py → propka/protonate.py Executable file → Normal file
View File

@@ -1,7 +1,10 @@
#!/usr/bin/python #!/usr/bin/python
from Source.vector_algebra import * from __future__ import division
import Source.bonds, Source.pdb, Source.atom from __future__ import print_function
from propka.vector_algebra import *
import propka.bonds, propka.pdb, propka.atom
class Protonate: class Protonate:
""" Protonates atoms using VSEPR theory """ """ Protonates atoms using VSEPR theory """
@@ -357,7 +360,7 @@ class Protonate:
def add_proton(self, atom, position): def add_proton(self, atom, position):
# Create the new proton # Create the new proton
new_H = Source.atom.Atom() new_H = propka.atom.Atom()
new_H.setProperty(numb = None, new_H.setProperty(numb = None,
name = 'H%s'%atom.name[1:], name = 'H%s'%atom.name[1:],
resName = atom.resName, resName = atom.resName,

15
propka/run.py Normal file
View File

@@ -0,0 +1,15 @@
# entry point for propka script
import propka.lib, propka.molecular_container
def main():
"""
Reads in structure files, calculates pKa values, and prints pKa files
"""
# loading options, flaggs and arguments
options, pdbfiles = propka.lib.loadOptions()
for pdbfile in pdbfiles:
my_molecule = propka.molecular_container.Molecular_container(pdbfile, options)
my_molecule.calculate_pka()
my_molecule.write_pka()

View File

@@ -1,3 +1,5 @@
from __future__ import division
from __future__ import print_function
import math import math
class vector: class vector:

View File

@@ -1,8 +1,11 @@
from __future__ import division
from __future__ import print_function
import math import math
import Source.lib as lib
import sys, os import sys, os
import Source.calculations as calculations
import Source.parameters import propka.lib as lib
import propka.calculations as calculations
import propka.parameters
class version: class version:
@@ -56,8 +59,8 @@ class version_A(version):
version.__init__(self, parameters) version.__init__(self, parameters)
# atom naming, bonding, and protonation # atom naming, bonding, and protonation
self.molecular_preparation_method = Source.calculations.setup_bonding_and_protonation self.molecular_preparation_method = propka.calculations.setup_bonding_and_protonation
self.prepare_bonds = Source.calculations.setup_bonding self.prepare_bonds = propka.calculations.setup_bonding
# desolvation related methods # desolvation related methods
@@ -65,20 +68,20 @@ class version_A(version):
self.weight_pair_method = calculations.calculatePairWeight self.weight_pair_method = calculations.calculatePairWeight
# side chain methods # side chain methods
self.sidechain_interaction_model = Source.calculations.HydrogenBondEnergy self.sidechain_interaction_model = propka.calculations.HydrogenBondEnergy
self.hydrogen_bond_interaction_model = Source.calculations.hydrogen_bond_interaction self.hydrogen_bond_interaction_model = propka.calculations.hydrogen_bond_interaction
# colomb methods # colomb methods
self.electrostatic_interaction_model = Source.calculations.electrostatic_interaction self.electrostatic_interaction_model = propka.calculations.electrostatic_interaction
self.check_coulomb_pair_method = Source.calculations.checkCoulombPair self.check_coulomb_pair_method = propka.calculations.checkCoulombPair
self.coulomb_interaction_model = Source.calculations.CoulombEnergy self.coulomb_interaction_model = propka.calculations.CoulombEnergy
#backbone #backbone
self.backbone_interaction_model = Source.calculations.HydrogenBondEnergy self.backbone_interaction_model = propka.calculations.HydrogenBondEnergy
self.backbone_reorganisation_method = Source.calculations.BackBoneReorganization self.backbone_reorganisation_method = propka.calculations.BackBoneReorganization
# exception methods # exception methods
self.exception_check_method = Source.calculations.checkExceptions self.exception_check_method = propka.calculations.checkExceptions
return return
def get_hydrogen_bond_parameters(self, atom1, atom2): def get_hydrogen_bond_parameters(self, atom1, atom2):
@@ -180,24 +183,24 @@ class propka30(version):
version.__init__(self, parameters) version.__init__(self, parameters)
# atom naming, bonding, and protonation # atom naming, bonding, and protonation
self.molecular_preparation_method = Source.calculations.setup_bonding_and_protonation_30_style self.molecular_preparation_method = propka.calculations.setup_bonding_and_protonation_30_style
# desolvation related methods # desolvation related methods
self.desolvation_model = calculations.radial_volume_desolvation self.desolvation_model = calculations.radial_volume_desolvation
self.weight_pair_method = calculations.calculatePairWeight self.weight_pair_method = calculations.calculatePairWeight
# side chain methods # side chain methods
self.sidechain_interaction_model = Source.calculations.HydrogenBondEnergy self.sidechain_interaction_model = propka.calculations.HydrogenBondEnergy
# colomb methods # colomb methods
self.check_coulomb_pair_method = Source.calculations.checkCoulombPair self.check_coulomb_pair_method = propka.calculations.checkCoulombPair
self.coulomb_interaction_model = Source.calculations.CoulombEnergy self.coulomb_interaction_model = propka.calculations.CoulombEnergy
#backbone #backbone
self.backbone_reorganisation_method = Source.calculations.BackBoneReorganization self.backbone_reorganisation_method = propka.calculations.BackBoneReorganization
# exception methods # exception methods
self.exception_check_method = Source.calculations.checkExceptions self.exception_check_method = propka.calculations.checkExceptions
return return

31
scripts/propka31.py Executable file
View File

@@ -0,0 +1,31 @@
#!/usr/bin/env python
# This is the original propka script. However, this distribute-based
# installation moved the main() function into propka.run.main and just
# generates a script called propka31 from the setup.py installation
# script. You should not need to use this script.
#
# (Also note that there can be import problems because the script name
# is the same as the module name; that's why the new script is called
# propka31.)
import propka.lib, propka.molecular_container
def main():
"""
Reads in structure files, calculates pKa values, and prints pKa files
"""
# loading options, flaggs and arguments
options, pdbfiles = propka.lib.loadOptions()
for pdbfile in pdbfiles:
my_molecule = propka.molecular_container.Molecular_container(pdbfile, options)
my_molecule.calculate_pka()
my_molecule.write_pka()
if __name__ == '__main__':
#import cProfile
#cProfile.run('main()',sort=1)
main()

51
setup.py Normal file
View File

@@ -0,0 +1,51 @@
# PROPKA 3.1
#
#
# setuptools installation of PROPKA 3.1
import ez_setup
ez_setup.use_setuptools()
from setuptools import setup, find_packages
VERSION = "3.1"
setup(name="PROPKA",
version=VERSION,
description="Heuristic pKa calculations with ligands",
long_description="""
PROPKA predicts the pKa values of ionizable groups in proteins (version 3.0) and
protein-ligand complexes (version 3.1) based on the 3D structure.
For proteins without ligands both version should produce the same result.
The method is described in the following papers, which you should cite
in publications:
* Sondergaard, Chresten R., Mats HM Olsson, Michal Rostkowski, and Jan
H. Jensen. "Improved Treatment of Ligands and Coupling Effects in
Empirical Calculation and Rationalization of pKa Values." Journal of
Chemical Theory and Computation 7, no. 7 (2011): 2284-2295.
* Olsson, Mats HM, Chresten R. Sondergaard, Michal Rostkowski, and Jan
H. Jensen. "PROPKA3: consistent treatment of internal and surface
residues in empirical pKa predictions." Journal of Chemical Theory
and Computation 7, no. 2 (2011): 525-537.
See http://propka.ki.ku.dk/ for the PROPKA web server,
using the tutorial http://propka.ki.ku.dk/~luca/wiki/index.php/PROPKA_3.1_Tutorial .
""",
author="Jan H. Jensen",
author_email="jhjensen@chem.ku.dk",
license="",
url="http://propka.ki.ku.dk/",
keywords="science",
packages=find_packages(exclude=['scripts']),
package_data = {'propka': ['*.dat', '*.cfg']},
#scripts = ["scripts/propka31.py"], # use entry point below
entry_points = {
'console_scripts': [
'propka31 = propka.run:main',
],
},
zip_safe=True,
)