Skip to content

Commit

Permalink
Merge pull request #40 from Electrostatics/nathan/delint
Browse files Browse the repository at this point in the history
De-lint PROPKA
  • Loading branch information
sobolevnrm committed May 30, 2020
2 parents 5916a80 + d714779 commit dde0d67
Show file tree
Hide file tree
Showing 26 changed files with 5,277 additions and 4,366 deletions.
2 changes: 2 additions & 0 deletions .pylintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[MESSAGES CONTROL]
disable = no-else-return
126 changes: 72 additions & 54 deletions propka/atom.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,35 @@
from . import hybrid36


# Format strings that get used in multiple places (or are very complex)
PKA_FMT = "{:6.2f}"
INPUT_LINE_FMT = (
"{type:6s}{r.numb:>5d} {atom_label} {r.res_name}{r.chain_id:>2s}"
"{r.res_num:>4d}{r.x:>12.3f}{r.y:>8.3f}{r.z:>8.3f}{group:>6s}{pka:>6s} \n")
PDB_LINE_FMT1 = (
"{type:6s}{r.numb:>5d} {atom_label} {r.res_name}{r.chain_id:>2s}"
"{r.res_num:>4d}{r.x:>12.3f}{r.y:>8.3f}{r.z:>8.3f}{r.occ:>6s}"
"{r.beta:>6s}\n")
MOL2_LINE_FMT = (
"{id:<4d} {atom_label:4s} "
"{r.x:>10.4f} {r.y:>10.4f} {r.z:>10.4f} "
"{r.sybyl_type:>6s} {r.res_num:>6d} {r.res_name:>10s} 0.0000\n")
PDB_LINE_FMT2 = (
"ATOM {numb:>6d} {atom_label} {res_name}{chain_id:>2s}{res_num:>4d}"
"{x:>12.3f}{y:>8.3f}{z:>8.3f}{occ:>6.2f}{beta:>6.2f}\n")
STR_FMT = (
"{r.numb:>5d}-{r.name:>4s} {r.res_num:>5d}-{r.res_name:>3s} "
"({r.chain_id:1s}) [{r.x:>8.3f} {r.y:>8.3f} {r.z:>8.3f}] {r.element:s}")


class Atom(object):
"""Atom class - contains all atom information found in the PDB file"""

def __init__(self, line=None, verbose=False):
def __init__(self, line=None):
"""Initialize Atom object.
Args:
line: Line from a PDB file to set properties of atom.
verbose: TODO - this does not appear to be used. Can we remove it?
"""
self.occ = None
self.numb = None
Expand Down Expand Up @@ -48,7 +68,8 @@ def __init__(self, line=None, verbose=False):
self.num_pi_elec_conj_2_3_bonds = 0
self.groups_extracted = 0
self.set_properties(line)
self.residue_label = "%-3s%4d%2s" % (self.name, self.res_num, self.chain_id)
fmt = "{r.name:3s}{r.res_num:>4d}{r.chain_id:>2s}"
self.residue_label = fmt.format(r=self)

# ligand atom types
self.sybyl_type = ''
Expand Down Expand Up @@ -82,13 +103,14 @@ def set_properties(self, line):
self.y = float(line[38:46].strip())
self.z = float(line[46:54].strip())
self.res_num = int(line[22:26].strip())
self.res_name = "%-3s" % (line[17:20].strip())
self.res_name = "{0:<3s}".format(line[17:20].strip())
self.chain_id = line[21]
# Set chain id to "_" if it is just white space.
if not self.chain_id.strip():
self.chain_id = '_'
self.type = line[:6].strip().lower()

# TODO - define nucleic acid residue names elsewhere
if self.res_name in ['DA ', 'DC ', 'DG ', 'DT ']:
self.type = 'hetatm'

Expand All @@ -101,7 +123,8 @@ def set_properties(self, line):
if len(self.name) == 4:
self.element = self.element[0]
if len(self.element) == 2:
self.element = '%1s%1s' % (self.element[0], self.element[1].lower())
self.element = '{0:1s}{1:1s}'.format(
self.element[0], self.element[1].lower())

def set_group_type(self, type_):
"""Set group type of atom.
Expand Down Expand Up @@ -130,9 +153,9 @@ def get_bonded_elements(self, element):
array of bonded atoms.
"""
res = []
for ba in self.bonded_atoms:
if ba.element == element:
res.append(ba)
for bond_atom in self.bonded_atoms:
if bond_atom.element == element:
res.append(bond_atom)
return res

def get_bonded_heavy_atoms(self):
Expand All @@ -156,12 +179,14 @@ def is_atom_within_bond_distance(self, other_atom, max_bonds, cur_bond):
if ba == other_atom:
return True
if max_bonds > cur_bond:
if ba.is_atom_within_bond_distance(other_atom, max_bonds, cur_bond+1):
if ba.is_atom_within_bond_distance(other_atom, max_bonds,
cur_bond+1):
return True
return False

def set_property(self, numb=None, name=None, res_name=None, chain_id=None,
res_num=None, x=None, y=None, z=None, occ=None, beta=None):
res_num=None, x=None, y=None, z=None, occ=None,
beta=None):
"""Set properties of the atom object.
Args:
Expand Down Expand Up @@ -225,7 +250,8 @@ def make_input_line(self):
"""PDB line for this atom.
TODO - Could be @property method/attribute
TODO - figure out difference between make_pdb_line, make_input_line, and make_pdb_line2
TODO - figure out difference between make_pdb_line, make_input_line,
and make_pdb_line2
Returns:
String with PDB-format line.
Expand All @@ -238,12 +264,11 @@ def make_input_line(self):
group = 'C-' ## circumventing C-/COO parameter unification

if self.group.titratable:
model_pka = '%6.2f'%self.group.model_pka
str_ = "%-6s%5d %s " % (self.type.upper(), self.numb,
propka.lib.makeTidyAtomLabel(self.name, self.element))
str_ += "%s%2s%4d%12.3lf%8.3lf%8.3lf%6s%6s \n" % (self.res_name, self.chain_id,
self.res_num, self.x, self.y,
self.z, group, model_pka)
model_pka = PKA_FMT.format(self.group.model_pka)
str_ = INPUT_LINE_FMT.format(
type=self.type.upper(), r=self,
atom_label=propka.lib.make_tidy_atom_label(self.name, self.element),
group=group, pka=model_pka)
return str_

def make_conect_line(self):
Expand All @@ -252,15 +277,15 @@ def make_conect_line(self):
Returns:
String with PDB line.
"""
res = 'CONECT%5d' % self.numb
res = 'CONECT{0:5d}'.format(self.numb)

bonded = []
for atom in self.bonded_atoms:
bonded.append(atom.numb)
bonded.sort()

for b in bonded:
res += '%5d'%b
for bond in bonded:
res += '{0:5d}'.format(bond)
res += '\n'
return res

Expand Down Expand Up @@ -290,10 +315,15 @@ def get_input_parameters(self):
self.occ = self.occ.replace('LG', 'non_titratable_ligand')
# try to initialise the group
try:
# TODO - get rid of this exec() statement for security reasons
exec('self.group = propka.group.%s_group(self)' % self.occ)
group_attr = "{0:s}_group".format(self.occ)
group_attr = getattr(propka.group, group_attr)
self.group = group_attr(self)
except:
raise Exception('%s in input_file is not recognized as a group' % self.occ)
# TODO - be more specific with expection handling here
str_ = (
'{0:s} in input_file is not recognized as a group'.format(
self.occ))
raise Exception(str_)
# set the model pKa value
if self.beta != '-':
self.group.model_pka = float(self.beta)
Expand All @@ -306,17 +336,15 @@ def make_pdb_line(self):
"""Create PDB line.
TODO - this could/should be a @property method/attribute
TODO - figure out difference between make_pdb_line, make_input_line, and make_pdb_line2
TODO - figure out difference between make_pdb_line, make_input_line,
and make_pdb_line2
Returns:
String with PDB line.
"""
str_ = "%-6s%5d " % (self.type.upper(), self.numb)
str_ += "%s %s" % (propka.lib.makeTidyAtomLabel(self.name, self.element),
self.res_name)
str_ += "%2s%4d%12.3lf%8.3lf%8.3lf%6s%6s\n" % (self.chain_id, self.res_num,
self.x, self.y, self.z,
self.occ, self.beta)
str_ = PDB_LINE_FMT1.format(
type=self.type.upper(), r=self,
atom_label=propka.lib.make_tidy_atom_label(self.name, self.element))
return str_

def make_mol2_line(self, id_):
Expand All @@ -329,19 +357,19 @@ def make_mol2_line(self, id_):
Returns:
String with MOL2 line.
"""
str_ = "%-4d %-4s " % (id_, propka.lib.makeTidyAtomLabel(self.name,
self.element))
str_ += "%10.4f %10.4f %10.4f " % (self.x, self.y, self.z)
str_ += "%6s %6d %10s %10.4f\n" % (self.sybyl_type.replace('-', ''),
self.res_num, self.res_name, 0.0)
str_ = MOL2_LINE_FMT.format(
id=id_, r=self,
atom_label=propka.lib.make_tidy_atom_label(self.name, self.element))
return str_

def make_pdb_line2(self, numb=None, name=None, res_name=None, chain_id=None,
res_num=None, x=None, y=None, z=None, occ=None, beta=None):
res_num=None, x=None, y=None, z=None, occ=None,
beta=None):
"""Create a PDB line.
TODO - this could/should be a @property method/attribute
TODO - figure out difference between make_pdb_line, make_input_line, and make_pdb_line2
TODO - figure out difference between make_pdb_line, make_input_line,
and make_pdb_line2
Returns:
String with PDB line.
Expand All @@ -366,18 +394,11 @@ def make_pdb_line2(self, numb=None, name=None, res_name=None, chain_id=None,
occ = self.occ
if beta is None:
beta = self.beta
str_ = "ATOM "
str_ += "%6d" % (numb)
str_ += " %s" % (propka.lib.makeTidyAtomLabel(name, self.element))
str_ += " %s" % (res_name)
str_ += "%2s" % (chain_id)
str_ += "%4d" % (res_num)
str_ += "%12.3lf" % (x)
str_ += "%8.3lf" % (y)
str_ += "%8.3lf" % (z)
str_ += "%6.2lf" % (occ)
str_ += "%6.2lf" % (beta)
str_ += '\n'
str_ = PDB_LINE_FMT2.format(
numb=numb, res_name=res_name, chain_id=chain_id, res_num=res_num,
x=x, y=y, z=z, occ=occ, beta=beta,
atom_label=propka.lib.make_tidy_atom_label(name, self.element)
)
return str_

def get_tidy_label(self):
Expand All @@ -387,14 +408,11 @@ def get_tidy_label(self):
Returns:
String with label"""
return propka.lib.makeTidyAtomLabel(self.name, self.element)
return propka.lib.make_tidy_atom_label(self.name, self.element)

def __str__(self):
"""Return an undefined-format string version of this atom."""
return '%5d-%4s %5d-%3s (%1s) [%8.3f %8.3f %8.3f] %s' % (self.numb, self.name,
self.res_num, self.res_name,
self.chain_id, self.x, self.y,
self.z, self.element)
return STR_FMT.format(r=self)

def set_residue(self, residue):
""" Makes a reference to the parent residue
Expand Down
Loading

0 comments on commit dde0d67

Please sign in to comment.