Skip to content
This repository has been archived by the owner on Jun 19, 2020. It is now read-only.

Commit

Permalink
Remove cyclic import based on atom.py
Browse files Browse the repository at this point in the history
Partially addresses jensengroup#49
  • Loading branch information
sobolevnrm committed May 30, 2020
1 parent 461edda commit 397d5e1
Show file tree
Hide file tree
Showing 7 changed files with 155 additions and 153 deletions.
32 changes: 12 additions & 20 deletions propka/atom.py
@@ -1,8 +1,7 @@
"""Atom class - contains all atom information found in the PDB file"""
import string
import propka.lib
import propka.group
from . import hybrid36
from propka.lib import make_tidy_atom_label


# Format strings that get used in multiple places (or are very complex)
Expand Down Expand Up @@ -50,6 +49,9 @@ def __init__(self, line=None):
self.z = None
self.group = None
self.group_type = None
self.group_label = None
self.group_model_pka = None
self.group_model_pka_set = None
self.number_of_bonded_elements = {}
self.cysteine_bridge = False
self.bonded_atoms = []
Expand Down Expand Up @@ -267,7 +269,7 @@ def make_input_line(self):
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),
atom_label=make_tidy_atom_label(self.name, self.element),
group=group, pka=model_pka)
return str_

Expand Down Expand Up @@ -313,21 +315,11 @@ def get_input_parameters(self):
self.occ = self.occ.replace('ALG', 'titratable_ligand')
self.occ = self.occ.replace('BLG', 'titratable_ligand')
self.occ = self.occ.replace('LG', 'non_titratable_ligand')
# try to initialise the group
try:
group_attr = "{0:s}_group".format(self.occ)
group_attr = getattr(propka.group, group_attr)
self.group = group_attr(self)
except:
# 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_)
self.group_label = "{0:s}_group".format(self.occ)
# set the model pKa value
if self.beta != '-':
self.group.model_pka = float(self.beta)
self.group.model_pka_set = True
self.group_model_pka = float(self.beta)
self.group_model_pka_set = True
# set occ and beta to standard values
self.occ = '1.00'
self.beta = '0.00'
Expand All @@ -344,7 +336,7 @@ def make_pdb_line(self):
"""
str_ = PDB_LINE_FMT1.format(
type=self.type.upper(), r=self,
atom_label=propka.lib.make_tidy_atom_label(self.name, self.element))
atom_label=make_tidy_atom_label(self.name, self.element))
return str_

def make_mol2_line(self, id_):
Expand All @@ -359,7 +351,7 @@ def make_mol2_line(self, id_):
"""
str_ = MOL2_LINE_FMT.format(
id=id_, r=self,
atom_label=propka.lib.make_tidy_atom_label(self.name, self.element))
atom_label=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,
Expand Down Expand Up @@ -397,7 +389,7 @@ def make_pdb_line2(self, numb=None, name=None, res_name=None, chain_id=None,
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)
atom_label=make_tidy_atom_label(name, self.element)
)
return str_

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

def __str__(self):
"""Return an undefined-format string version of this atom."""
Expand Down
3 changes: 0 additions & 3 deletions propka/calculations.py
@@ -1,8 +1,5 @@
"""PROPKA calculations."""
import math
import propka.protonate
import propka.bonds
from propka.lib import warning, info


# TODO - this file should be broken into three separate files:
Expand Down
13 changes: 13 additions & 0 deletions propka/group.py
Expand Up @@ -6,6 +6,7 @@
from propka.determinant import Determinant
from propka.lib import info, warning


# Constants that start with "UNK_" are a mystery to me
UNK_PKA_SCALING = -1.36
PROTONATOR = propka.protonate.Protonate(verbose=False)
Expand Down Expand Up @@ -1417,3 +1418,15 @@ def is_ion_group(parameters, atom):
if atom.res_name.strip() in parameters.ions.keys():
return IonGroup(atom)
return None

def initialize_atom_group(atom):
"""Initialize an atom group.
Args:
atom: atom to initialize
"""
# try to initialise the group
group_attr = globals()[atom.group_label]
atom.group = group_attr(atom)
atom.group.model_pka = atom.group_model_pka
atom.group.model_pka_set = atom.group_model_pka_set
7 changes: 4 additions & 3 deletions propka/ligand_pka_values.py
Expand Up @@ -6,7 +6,7 @@
import propka.calculations
import propka.parameters
import propka.pdb
import propka.lib
from propka.output import write_mol2_for_atoms
from propka.lib import info, warning


Expand Down Expand Up @@ -133,15 +133,15 @@ def get_marvin_pkas_for_molecule(self, atoms, filename='__tmp_ligand.mol2',
"""
# print out structure unless we are using user-modified structure
if not reuse:
propka.pdb.write_mol2_for_atoms(atoms, filename)
write_mol2_for_atoms(atoms, filename)
# check that we actually have a file to work with
if not os.path.isfile(filename):
errstr = (
"Didn't find a user-modified file '{0:s}' "
"- generating one".format(
filename))
warning(errstr)
propka.pdb.write_mol2_for_atoms(atoms, filename)
write_mol2_for_atoms(atoms, filename)
# Marvin calculate pKa values
fmt = (
'pka -a {num1} -b {num2} --min {min_ph} '
Expand Down Expand Up @@ -197,3 +197,4 @@ def extract_pkas(output):
if len(indices) != len(values) != len(types):
raise Exception('Lengths of atoms and pka values mismatch')
return indices, values, types

16 changes: 7 additions & 9 deletions propka/molecular_container.py
@@ -1,13 +1,11 @@
"""Molecular container for storing all contents of PDB files."""
import os
import sys
import propka.pdb
import propka.version
import propka.output
import propka.group
import propka.lib
from propka.pdb import read_input
from propka.output import write_input
from propka.conformation_container import ConformationContainer
from propka.lib import info, warning
from propka.lib import info, warning, make_grid


# TODO - these are constants whose origins are a little murky
Expand Down Expand Up @@ -78,7 +76,7 @@ def __init__(self, input_file, options=None):
self.find_covalently_coupled_groups()
# write out the input file
filename = self.file.replace(input_file_extension, '.propka_input')
propka.pdb.write_input(self, filename)
write_input(self, filename)
elif input_file_extension == '.propka_input':
#input is a propka_input file
[self.conformations, self.conformation_names] = (
Expand Down Expand Up @@ -155,7 +153,7 @@ def average_of_conformations(self):
else:
str_ = (
'Group {0:s} could not be found in '
'conformation {0:s}.'.format(
'conformation {1:s}.'.format(
group.atom.residue_label, name))
warning(str_)
# ... and store the average value
Expand Down Expand Up @@ -214,7 +212,7 @@ def get_folding_profile(self, conformation='AVR', reference="neutral",
"""
# calculate stability profile
profile = []
for ph in propka.lib.make_grid(*grid):
for ph in make_grid(*grid):
conf = self.conformations[conformation]
ddg = conf.calculate_folding_energy(ph=ph, reference=reference)
profile.append([ph, ddg])
Expand Down Expand Up @@ -244,7 +242,7 @@ def get_charge_profile(self, conformation='AVR', grid=[0., 14., .1]):
list of charge state values
"""
charge_profile = []
for ph in propka.lib.make_grid(*grid):
for ph in make_grid(*grid):
conf = self.conformations[conformation]
q_unfolded, q_folded = conf.calculate_charge(
self.version.parameters, ph=ph)
Expand Down
121 changes: 116 additions & 5 deletions propka/output.py
@@ -1,6 +1,6 @@
"""Output routines."""
from datetime import date
from propka.lib import info
from propka.lib import info, open_file_for_writing


def print_header():
Expand All @@ -11,8 +11,8 @@ def print_header():
info(str_)


def write_pdb(protein, pdbfile=None, filename=None, include_hydrogens=False,
_=None):
def write_pdb_for_protein(
protein, pdbfile=None, filename=None, include_hydrogens=False, _=None):
"""Write a residue to the new PDB file.
Args:
Expand Down Expand Up @@ -50,6 +50,16 @@ def write_pdb(protein, pdbfile=None, filename=None, include_hydrogens=False,
pdbfile.close()


def write_pdb_for_conformation(conformation, filename):
"""Write PDB conformation to a file.
Args:
conformation: conformation container
filename: filename for output
"""
write_pdb_for_atoms(conformation.atoms, filename)


def write_pka(protein, parameters, filename=None, conformation='1A',
reference="neutral", _="folding", verbose=False,
__=None):
Expand Down Expand Up @@ -204,8 +214,8 @@ def get_summary_section(protein, conformation, parameters):


def get_folding_profile_section(
protein, conformation='AVR', direction="folding", reference="neutral",
window=[0., 14., 1.0], _=False, __=None):
protein, conformation='AVR', direction="folding", reference="neutral",
window=[0., 14., 1.0], _=False, __=None):
"""Returns string with the folding profile section of the results.
Args:
Expand Down Expand Up @@ -461,3 +471,104 @@ def make_interaction_map(name, list_, interaction):
tag = ' X '
res += '{0:>10s}| '.format(tag)
return res


def write_pdb_for_atoms(atoms, filename, make_conect_section=False):
"""Write out PDB file for atoms.
Args:
atoms: list of atoms
filename: name of file
make_conect_section: generate a CONECT PDB section
"""
out = open_file_for_writing(filename)
for atom in atoms:
out.write(atom.make_pdb_line())
if make_conect_section:
for atom in atoms:
out.write(atom.make_conect_line())
out.close()


def get_bond_order(atom1, atom2):
"""Get the order of a bond between two atoms.
Args:
atom1: first atom in bond
atom2: second atom in bond
Returns:
string with bond type
"""
type_ = '1'
pi_electrons1 = atom1.num_pi_elec_2_3_bonds
pi_electrons2 = atom2.num_pi_elec_2_3_bonds
if '.ar' in atom1.sybyl_type:
pi_electrons1 -= 1
if '.ar' in atom2.sybyl_type:
pi_electrons2 -= 1
if pi_electrons1 > 0 and pi_electrons2 > 0:
type_ = '{0:d}'.format(min(pi_electrons1, pi_electrons2)+1)
if '.ar' in atom1.sybyl_type and '.ar' in atom2.sybyl_type:
type_ = 'ar'
return type_


def write_mol2_for_atoms(atoms, filename):
"""Write out MOL2 file for atoms.
Args:
atoms: list of atoms
filename: name of file
"""
# TODO - header needs to be converted to format string
header = '@<TRIPOS>MOLECULE\n\n{natom:d} {id:d}\nSMALL\nUSER_CHARGES\n'
atoms_section = '@<TRIPOS>ATOM\n'
for i, atom in enumerate(atoms):
atoms_section += atom.make_mol2_line(i+1)
bonds_section = '@<TRIPOS>BOND\n'
id_ = 1
for i, atom1 in enumerate(atoms):
for j, atom2 in enumerate(atoms, i+1):
if atom1 in atom2.bonded_atoms:
type_ = get_bond_order(atom1, atom2)
bonds_section += '{0:>7d} {1:>7d} {2:>7d} {3:>7s}\n'.format(
id_, i+1, j+1, type_)
id_ += 1
substructure_section = '@<TRIPOS>SUBSTRUCTURE\n\n'
if len(atoms) > 0:
substructure_section = (
'@<TRIPOS>SUBSTRUCTURE\n{0:<7d} {1:>10s} {2:>7d}\n'.format(
atoms[0].res_num, atoms[0].res_name, atoms[0].numb))
out = open_file_for_writing(filename)
out.write(header.format(natom=len(atoms), id=id_-1))
out.write(atoms_section)
out.write(bonds_section)
out.write(substructure_section)
out.close()

def write_input(molecular_container, filename):
"""Write PROPKA input file for molecular container.
Args:
molecular_container: molecular container
filename: output file name
"""
out = open_file_for_writing(filename)
for conformation_name in molecular_container.conformation_names:
out.write('MODEL {0:s}\n'.format(conformation_name))
# write atoms
for atom in molecular_container.conformations[conformation_name].atoms:
out.write(atom.make_input_line())
# write bonds
for atom in molecular_container.conformations[conformation_name].atoms:
out.write(atom.make_conect_line())
# write covalently coupled groups
for group in (
molecular_container.conformations[conformation_name].groups):
out.write(group.make_covalently_coupled_line())
# write non-covalently coupled groups
for group in (
molecular_container.conformations[conformation_name].groups):
out.write(group.make_non_covalently_coupled_line())
out.write('ENDMDL\n')
out.close()

0 comments on commit 397d5e1

Please sign in to comment.