De-lint lib.py.
This commit is contained in:
@@ -240,7 +240,7 @@ class Atom(object):
|
|||||||
if self.group.titratable:
|
if self.group.titratable:
|
||||||
model_pka = '%6.2f'%self.group.model_pka
|
model_pka = '%6.2f'%self.group.model_pka
|
||||||
str_ = "%-6s%5d %s " % (self.type.upper(), self.numb,
|
str_ = "%-6s%5d %s " % (self.type.upper(), self.numb,
|
||||||
propka.lib.makeTidyAtomLabel(self.name, self.element))
|
propka.lib.make_tidy_atom_label(self.name, self.element))
|
||||||
str_ += "%s%2s%4d%12.3lf%8.3lf%8.3lf%6s%6s \n" % (self.res_name, self.chain_id,
|
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.res_num, self.x, self.y,
|
||||||
self.z, group, model_pka)
|
self.z, group, model_pka)
|
||||||
@@ -313,7 +313,7 @@ class Atom(object):
|
|||||||
String with PDB line.
|
String with PDB line.
|
||||||
"""
|
"""
|
||||||
str_ = "%-6s%5d " % (self.type.upper(), self.numb)
|
str_ = "%-6s%5d " % (self.type.upper(), self.numb)
|
||||||
str_ += "%s %s" % (propka.lib.makeTidyAtomLabel(self.name, self.element),
|
str_ += "%s %s" % (propka.lib.make_tidy_atom_label(self.name, self.element),
|
||||||
self.res_name)
|
self.res_name)
|
||||||
str_ += "%2s%4d%12.3lf%8.3lf%8.3lf%6s%6s\n" % (self.chain_id, self.res_num,
|
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.x, self.y, self.z,
|
||||||
@@ -330,7 +330,7 @@ class Atom(object):
|
|||||||
Returns:
|
Returns:
|
||||||
String with MOL2 line.
|
String with MOL2 line.
|
||||||
"""
|
"""
|
||||||
str_ = "%-4d %-4s " % (id_, propka.lib.makeTidyAtomLabel(self.name,
|
str_ = "%-4d %-4s " % (id_, propka.lib.make_tidy_atom_label(self.name,
|
||||||
self.element))
|
self.element))
|
||||||
str_ += "%10.4f %10.4f %10.4f " % (self.x, self.y, self.z)
|
str_ += "%10.4f %10.4f %10.4f " % (self.x, self.y, self.z)
|
||||||
str_ += "%6s %6d %10s %10.4f\n" % (self.sybyl_type.replace('-', ''),
|
str_ += "%6s %6d %10s %10.4f\n" % (self.sybyl_type.replace('-', ''),
|
||||||
@@ -369,7 +369,7 @@ class Atom(object):
|
|||||||
beta = self.beta
|
beta = self.beta
|
||||||
str_ = "ATOM "
|
str_ = "ATOM "
|
||||||
str_ += "%6d" % (numb)
|
str_ += "%6d" % (numb)
|
||||||
str_ += " %s" % (propka.lib.makeTidyAtomLabel(name, self.element))
|
str_ += " %s" % (propka.lib.make_tidy_atom_label(name, self.element))
|
||||||
str_ += " %s" % (res_name)
|
str_ += " %s" % (res_name)
|
||||||
str_ += "%2s" % (chain_id)
|
str_ += "%2s" % (chain_id)
|
||||||
str_ += "%4d" % (res_num)
|
str_ += "%4d" % (res_num)
|
||||||
@@ -388,7 +388,7 @@ class Atom(object):
|
|||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
String with label"""
|
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):
|
def __str__(self):
|
||||||
"""Return an undefined-format string version of this atom."""
|
"""Return an undefined-format string version of this atom."""
|
||||||
|
|||||||
289
propka/lib.py
289
propka/lib.py
@@ -1,112 +1,142 @@
|
|||||||
from __future__ import division
|
"""Implements many of the main functions used to call PROPKA."""
|
||||||
from __future__ import print_function
|
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
import pkg_resources
|
|
||||||
import logging
|
import logging
|
||||||
import argparse
|
import argparse
|
||||||
|
import pkg_resources
|
||||||
|
|
||||||
|
|
||||||
logger = logging.getLogger("propka")
|
_LOGGER = logging.getLogger("propka")
|
||||||
stdout_handler = logging.StreamHandler(sys.stdout)
|
_STDOUT_HANDLER = logging.StreamHandler(sys.stdout)
|
||||||
stdout_handler.setFormatter(logging.Formatter("%(message)s"))
|
_STDOUT_HANDLER.setFormatter(logging.Formatter("%(message)s"))
|
||||||
logger.addHandler(stdout_handler)
|
_LOGGER.addHandler(_STDOUT_HANDLER)
|
||||||
|
|
||||||
#
|
|
||||||
# file I/O
|
|
||||||
#
|
|
||||||
def open_file_for_reading(filename):
|
|
||||||
"""Open file or file-like stream *filename* for reading.
|
|
||||||
|
|
||||||
*filename* may be a string and then it is opened but if it is a
|
def open_file_for_reading(input_file):
|
||||||
file-like object (such as an open :class:`file` or
|
"""Open file or file-like stream for reading.
|
||||||
:class:`StringIO.StringIO` --- really anything with ``next()``,
|
|
||||||
``read()``, ``readlines()``, ``readline``, ``close`` methods) then
|
TODO - convert this to a context manager
|
||||||
the object is just passed through (the stream is attempted to be
|
|
||||||
reset to the beginning with ``fseek(0)``).
|
Args:
|
||||||
|
input_file: path to file or file-like object. If file-like object,
|
||||||
|
then will attempt fseek(0).
|
||||||
"""
|
"""
|
||||||
if (hasattr(filename, 'next') or hasattr(filename, '__next__')) \
|
try:
|
||||||
and hasattr(filename, 'read') \
|
input_file.fseek(0)
|
||||||
and hasattr(filename, 'readline') and hasattr(filename, 'readlines') \
|
return input_file
|
||||||
and hasattr(filename, 'close'):
|
except AttributeError:
|
||||||
# already a stream
|
pass
|
||||||
try:
|
|
||||||
filename.fseek(0)
|
|
||||||
except AttributeError:
|
|
||||||
pass
|
|
||||||
return filename
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
f = open(filename,'r')
|
file_ = open(input_file, 'rt')
|
||||||
except:
|
except:
|
||||||
raise IOError('Cannot find file %s' %filename)
|
raise IOError('Cannot find file %s' % input_file)
|
||||||
return f
|
return file_
|
||||||
|
|
||||||
def open_file_for_writing(filename):
|
|
||||||
"""Open file or file-like stream for writing"""
|
def open_file_for_writing(input_file):
|
||||||
if hasattr(filename, 'write') and hasattr(filename, 'writeline') and hasattr(filename, 'writelines') \
|
"""Open file or file-like stream for writing.
|
||||||
and hasattr(filename, 'close'):
|
|
||||||
# already a stream
|
TODO - convert this to a context manager.
|
||||||
try:
|
|
||||||
mode = filename.mode
|
Args:
|
||||||
except AttributeError:
|
input_file: path to file or file-like object. If file-like object,
|
||||||
mode = "w"
|
then will attempt to get file mode.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
mode = input_file.mode
|
||||||
if not ("w" in mode or "a" in mode or "+" in mode):
|
if not ("w" in mode or "a" in mode or "+" in mode):
|
||||||
raise IOError("File/stream not open for writing")
|
raise IOError("File/stream not open for writing")
|
||||||
return filename
|
return input_file
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
try:
|
try:
|
||||||
f = open(filename,'w')
|
file_ = open(input_file, 'wt')
|
||||||
except:
|
except FileNotFoundError:
|
||||||
raise Exception('Could not open %s'%filename)
|
raise Exception('Could not open %s' % input_file)
|
||||||
return f
|
return file_
|
||||||
|
|
||||||
|
|
||||||
#
|
|
||||||
# bookkeeping etc.
|
|
||||||
#
|
|
||||||
def conformation_sorter(conf):
|
def conformation_sorter(conf):
|
||||||
|
"""TODO - figure out what this function does."""
|
||||||
model = int(conf[:-1])
|
model = int(conf[:-1])
|
||||||
altloc = conf[-1:]
|
altloc = conf[-1:]
|
||||||
return model*100+ord(altloc)
|
return model*100+ord(altloc)
|
||||||
|
|
||||||
|
|
||||||
def split_atoms_into_molecules(atoms):
|
def split_atoms_into_molecules(atoms):
|
||||||
|
"""Maps atoms into molecules.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
atoms: list of atoms
|
||||||
|
Returns:
|
||||||
|
list of molecules
|
||||||
|
"""
|
||||||
molecules = []
|
molecules = []
|
||||||
|
while len(atoms) > 0:
|
||||||
while len(atoms)>0:
|
|
||||||
initial_atom = atoms.pop()
|
initial_atom = atoms.pop()
|
||||||
molecules.append( make_molecule(initial_atom,atoms))
|
molecules.append(make_molecule(initial_atom, atoms))
|
||||||
|
|
||||||
return molecules
|
return molecules
|
||||||
|
|
||||||
|
|
||||||
def make_molecule(atom, atoms):
|
def make_molecule(atom, atoms):
|
||||||
|
"""Make a molecule from atoms.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
atom: one of the atoms
|
||||||
|
atoms: a list of the remaining atoms
|
||||||
|
Return:
|
||||||
|
list of atoms
|
||||||
|
"""
|
||||||
bonded_atoms = [a for a in atoms if atom in a.bonded_atoms]
|
bonded_atoms = [a for a in atoms if atom in a.bonded_atoms]
|
||||||
res_atoms = [atom,]
|
res_atoms = [atom,]
|
||||||
|
for bond_atom in bonded_atoms:
|
||||||
for ba in bonded_atoms:
|
if bond_atom in atoms:
|
||||||
if ba in atoms:
|
atoms.remove(bond_atom)
|
||||||
atoms.remove(ba)
|
res_atoms.extend(make_molecule(bond_atom, atoms))
|
||||||
res_atoms.extend(make_molecule(ba, atoms))
|
|
||||||
|
|
||||||
return res_atoms
|
return res_atoms
|
||||||
|
|
||||||
|
|
||||||
def make_grid(min,max,step):
|
def make_grid(min_, max_, step):
|
||||||
x = min
|
"""Make a grid across the specified tange.
|
||||||
while x <= max:
|
|
||||||
|
TODO - figure out if this duplicates existing generators like `range` or
|
||||||
|
numpy function.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
min_: minimum value of grid
|
||||||
|
max_: maximum value of grid
|
||||||
|
step: grid step size
|
||||||
|
"""
|
||||||
|
x = min_
|
||||||
|
while x <= max_:
|
||||||
yield x
|
yield x
|
||||||
x += step
|
x += step
|
||||||
return
|
|
||||||
|
|
||||||
def generate_combinations(interactions):
|
def generate_combinations(interactions):
|
||||||
|
"""Generate combinations of interactions.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
interactions: list of interactions
|
||||||
|
Returns:
|
||||||
|
list of combinations
|
||||||
|
"""
|
||||||
res = [[]]
|
res = [[]]
|
||||||
for interaction in interactions:
|
for interaction in interactions:
|
||||||
res = make_combination(res, interaction)
|
res = make_combination(res, interaction)
|
||||||
res.remove([])
|
res.remove([])
|
||||||
|
|
||||||
return res
|
return res
|
||||||
|
|
||||||
|
|
||||||
def make_combination(combis, interaction):
|
def make_combination(combis, interaction):
|
||||||
|
"""Make a specific set of combinations.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
combis: list of combinations
|
||||||
|
interaction: interaction to add to combinations
|
||||||
|
Returns:
|
||||||
|
list of combinations
|
||||||
|
"""
|
||||||
res = []
|
res = []
|
||||||
for combi in combis:
|
for combi in combis:
|
||||||
res.append(combi+[interaction])
|
res.append(combi+[interaction])
|
||||||
@@ -115,10 +145,14 @@ def make_combination(combis, interaction):
|
|||||||
|
|
||||||
|
|
||||||
def parse_res_string(res_str):
|
def parse_res_string(res_str):
|
||||||
"""
|
"""Parse a residue string.
|
||||||
Parse the residue string, in format "chain:resnum[inscode]", and return
|
|
||||||
a tuple of (chain, resnum, inscode). Raises ValueError if the input
|
Args:
|
||||||
string is invalid.
|
res_string: residue string in format "chain:resnum[inscode]"
|
||||||
|
Returns:
|
||||||
|
a tuple of (chain, resnum, inscode).
|
||||||
|
Raises:
|
||||||
|
ValueError if the input string is invalid.
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
chain, resnum_str = res_str.split(":")
|
chain, resnum_str = res_str.split(":")
|
||||||
@@ -142,7 +176,7 @@ def build_parser(parser=None):
|
|||||||
"""Build an argument parser for PROPKA.
|
"""Build an argument parser for PROPKA.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
parser_: existing parser. If this is not None, then the PROPKA parser will
|
parser: existing parser. If this is not None, then the PROPKA parser will
|
||||||
be created as a subparser to this existing parser. Otherwise, a
|
be created as a subparser to this existing parser. Otherwise, a
|
||||||
new parser will be created.
|
new parser will be created.
|
||||||
Returns:
|
Returns:
|
||||||
@@ -158,7 +192,6 @@ def build_parser(parser=None):
|
|||||||
# This is duck-typing at its finest
|
# This is duck-typing at its finest
|
||||||
group = parser
|
group = parser
|
||||||
group.add_argument("input_pdb", help="read data from <filename>")
|
group.add_argument("input_pdb", help="read data from <filename>")
|
||||||
|
|
||||||
group.add_argument("-f", "--file", action="append", dest="filenames", default=[],
|
group.add_argument("-f", "--file", action="append", dest="filenames", default=[],
|
||||||
help="read data from <filename>, i.e. <filename> is added to arguments")
|
help="read data from <filename>, i.e. <filename> is added to arguments")
|
||||||
group.add_argument("-r", "--reference", dest="reference", default="neutral",
|
group.add_argument("-r", "--reference", dest="reference", default="neutral",
|
||||||
@@ -223,31 +256,25 @@ def build_parser(parser=None):
|
|||||||
|
|
||||||
|
|
||||||
def loadOptions(args):
|
def loadOptions(args):
|
||||||
"""
|
"""Load the arguments parser with options.
|
||||||
Load the arguments parser with options. Note that verbosity is set as soon
|
|
||||||
as this function is invoked.
|
NOTE - verbosity is set as soon as this function is invoked.
|
||||||
|
|
||||||
Arguments:
|
Arguments:
|
||||||
args: list of arguments
|
args: list of arguments
|
||||||
Returns:
|
Returns:
|
||||||
argparse namespace
|
argparse namespace
|
||||||
"""
|
"""
|
||||||
# defining a 'usage' message
|
|
||||||
usage = "usage: %prog [options] filename"
|
|
||||||
|
|
||||||
# loading the parser
|
# loading the parser
|
||||||
parser = build_parser()
|
parser = build_parser()
|
||||||
|
|
||||||
# parsing and returning options and arguments
|
# parsing and returning options and arguments
|
||||||
if len(args) == 0:
|
if len(args) == 0:
|
||||||
# command line
|
# command line
|
||||||
options = parser.parse_args()
|
options = parser.parse_args()
|
||||||
else:
|
else:
|
||||||
options = parser.parse_args(args)
|
options = parser.parse_args(args)
|
||||||
|
|
||||||
# adding specified filenames to arguments
|
# adding specified filenames to arguments
|
||||||
options.filenames.append(options.input_pdb)
|
options.filenames.append(options.input_pdb)
|
||||||
|
|
||||||
# Convert titrate_only string to a list of (chain, resnum) items:
|
# Convert titrate_only string to a list of (chain, resnum) items:
|
||||||
if options.titrate_only is not None:
|
if options.titrate_only is not None:
|
||||||
res_list = []
|
res_list = []
|
||||||
@@ -255,76 +282,108 @@ def loadOptions(args):
|
|||||||
try:
|
try:
|
||||||
chain, resnum, inscode = parse_res_string(res_str)
|
chain, resnum, inscode = parse_res_string(res_str)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
logger.critical('Invalid residue string: "%s"' % res_str)
|
_LOGGER.critical('Invalid residue string: "%s"', res_str)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
res_list.append((chain, resnum, inscode))
|
res_list.append((chain, resnum, inscode))
|
||||||
options.titrate_only = res_list
|
options.titrate_only = res_list
|
||||||
|
|
||||||
|
|
||||||
# Set the no-print variable
|
# Set the no-print variable
|
||||||
level = getattr(logging, options.log_level)
|
level = getattr(logging, options.log_level)
|
||||||
logger.setLevel(level)
|
_LOGGER.setLevel(level)
|
||||||
|
|
||||||
# done!
|
# done!
|
||||||
return options
|
return options
|
||||||
|
|
||||||
|
|
||||||
def makeTidyAtomLabel(name,element):
|
def make_tidy_atom_label(name, element):
|
||||||
"""
|
"""Returns a 'tidier' atom label for printing to the new PDB file.
|
||||||
Returns a 'tidier' atom label for printing the new pdbfile
|
|
||||||
"""
|
|
||||||
|
|
||||||
if len(name)>4:# if longer than 4, just truncate the name
|
Args:
|
||||||
label=name[0:4]
|
name: atom name
|
||||||
elif len(name)==4:# if lenght is 4, otherwise use the name as it is
|
element: atom element
|
||||||
|
Returns:
|
||||||
|
string
|
||||||
|
"""
|
||||||
|
if len(name) > 4: # if longer than 4, just truncate the name
|
||||||
|
label = name[0:4]
|
||||||
|
elif len(name) == 4: # if length is 4, otherwise use the name as it is
|
||||||
label = name
|
label = name
|
||||||
else: # if less than 4 characters long, insert white space as needed
|
else: # if less than 4 characters long, insert white space as needed
|
||||||
if len(element)==1:
|
if len(element) == 1:
|
||||||
label = ' %-3s'%name
|
label = ' %-3s' % name
|
||||||
else: # The element shoul occupy the two first chars
|
else: # The element should occupy the two first chars
|
||||||
label = '%-4s'%name
|
label = '%-4s' % name
|
||||||
|
|
||||||
return label
|
return label
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def get_sorted_configurations(configuration_keys):
|
def get_sorted_configurations(configuration_keys):
|
||||||
"""
|
"""Extract and sort configurations.
|
||||||
extract and sort configurations
|
|
||||||
|
Args:
|
||||||
|
configuration_keys: list of configuration keys
|
||||||
|
Returns:
|
||||||
|
list of configurations
|
||||||
"""
|
"""
|
||||||
configurations = list(configuration_keys)
|
configurations = list(configuration_keys)
|
||||||
configurations.sort(key=configuration_compare)
|
configurations.sort(key=configuration_compare)
|
||||||
return configurations
|
return configurations
|
||||||
|
|
||||||
|
|
||||||
def configuration_compare(conf):
|
def configuration_compare(conf):
|
||||||
|
"""TODO - figure out what this function does."""
|
||||||
return 100*int(conf[1:-2]) + ord(conf[-1])
|
return 100*int(conf[1:-2]) + ord(conf[-1])
|
||||||
|
|
||||||
|
|
||||||
|
def write_file(filename, lines):
|
||||||
|
"""Writes a new file.
|
||||||
|
|
||||||
|
Args:
|
||||||
def writeFile(filename, lines):
|
filename: name of file
|
||||||
|
lines: lines to write to file
|
||||||
"""
|
"""
|
||||||
Writes a new file
|
file_ = open_file_for_writing(filename)
|
||||||
"""
|
|
||||||
f = open_file_for_writing(filename)
|
|
||||||
|
|
||||||
for line in lines:
|
for line in lines:
|
||||||
f.write( "%s\n" % (line) )
|
file_.write("%s\n" % (line))
|
||||||
f.close()
|
file_.close()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def _args_to_str(arg_list):
|
def _args_to_str(arg_list):
|
||||||
|
"""Summarize list of arguments in string.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
arg_list: list of arguments
|
||||||
|
Returns:
|
||||||
|
string
|
||||||
|
"""
|
||||||
return " ".join(map(str, arg_list))
|
return " ".join(map(str, arg_list))
|
||||||
|
|
||||||
|
|
||||||
def info(*args):
|
def info(*args):
|
||||||
"""Log a message. Level defaults to INFO unless overridden."""
|
"""Log a message to info.
|
||||||
logger.info(_args_to_str(args))
|
|
||||||
|
Level defaults to INFO unless overridden.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
args: argument list
|
||||||
|
"""
|
||||||
|
_LOGGER.info(_args_to_str(args))
|
||||||
|
|
||||||
|
|
||||||
def debug(*args):
|
def debug(*args):
|
||||||
"""Log a message on the DEBUG level."""
|
"""Log a message to debug.
|
||||||
logger.debug(_args_to_str(args))
|
|
||||||
|
Level defaults to DEBUG unless overridden.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
args: argument list
|
||||||
|
"""
|
||||||
|
_LOGGER.debug(_args_to_str(args))
|
||||||
|
|
||||||
|
|
||||||
def warning(*args):
|
def warning(*args):
|
||||||
"""Log a WARN message"""
|
"""Log a message to warning.
|
||||||
logger.warning(_args_to_str(args))
|
|
||||||
|
Level defaults to WARNING unless overridden.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
args: argument list
|
||||||
|
"""
|
||||||
|
_LOGGER.warning(_args_to_str(args))
|
||||||
|
|||||||
Reference in New Issue
Block a user