Remove logging abstraction to facilitate debugging and reduce bloat.
Also performed minor delinting. Fixes #108
This commit is contained in:
@@ -5,12 +5,14 @@ Bonds
|
||||
PROPKA representation of bonds.
|
||||
|
||||
"""
|
||||
import logging
|
||||
import math
|
||||
import json
|
||||
import pkg_resources
|
||||
import propka.calculations
|
||||
# TODO - replace the info/warning imports with logging functionality
|
||||
from propka.lib import info
|
||||
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
# TODO - should these constants be defined higher up in the module?
|
||||
@@ -30,8 +32,8 @@ class BondMaker:
|
||||
"""
|
||||
def __init__(self):
|
||||
# predefined bonding distances
|
||||
self.distances = {'S-S' : DISULFIDE_DISTANCE,
|
||||
'F-F' : FLUORIDE_DISTANCE}
|
||||
self.distances = {'S-S': DISULFIDE_DISTANCE,
|
||||
'F-F': FLUORIDE_DISTANCE}
|
||||
self.distances_squared = {}
|
||||
for key in self.distances:
|
||||
self.distances_squared[key] = (
|
||||
@@ -53,22 +55,22 @@ class BondMaker:
|
||||
'C': ['CA', 'O'], 'O': ['C']}
|
||||
self.num_pi_elec_bonds_backbone = {'C': 1, 'O': 1}
|
||||
self.num_pi_elec_conj_bonds_backbone = {'N': 1}
|
||||
self.num_pi_elec_bonds_sidechains = {'ARG-CZ' : 1, 'ARG-NH1': 1,
|
||||
'ASN-OD1': 1, 'ASN-CG' : 1,
|
||||
'ASP-OD1': 1, 'ASP-CG' : 1,
|
||||
'GLU-OE1': 1, 'GLU-CD' : 1,
|
||||
'GLN-OE1': 1, 'GLN-CD' : 1,
|
||||
'HIS-CG' : 1, 'HIS-CD2': 1,
|
||||
self.num_pi_elec_bonds_sidechains = {'ARG-CZ': 1, 'ARG-NH1': 1,
|
||||
'ASN-OD1': 1, 'ASN-CG': 1,
|
||||
'ASP-OD1': 1, 'ASP-CG': 1,
|
||||
'GLU-OE1': 1, 'GLU-CD': 1,
|
||||
'GLN-OE1': 1, 'GLN-CD': 1,
|
||||
'HIS-CG': 1, 'HIS-CD2': 1,
|
||||
'HIS-ND1': 1, 'HIS-CE1': 1,
|
||||
'PHE-CG' : 1, 'PHE-CD1': 1,
|
||||
'PHE-CE1': 1, 'PHE-CZ' : 1,
|
||||
'PHE-CG': 1, 'PHE-CD1': 1,
|
||||
'PHE-CE1': 1, 'PHE-CZ': 1,
|
||||
'PHE-CE2': 1, 'PHE-CD2': 1,
|
||||
'TRP-CG' : 1, 'TRP-CD1': 1,
|
||||
'TRP-CG': 1, 'TRP-CD1': 1,
|
||||
'TRP-CE2': 1, 'TRP-CD2': 1,
|
||||
'TRP-CE3': 1, 'TRP-CZ3': 1,
|
||||
'TRP-CH2': 1, 'TRP-CZ2': 1,
|
||||
'TYR-CG' : 1, 'TYR-CD1': 1,
|
||||
'TYR-CE1': 1, 'TYR-CZ' : 1,
|
||||
'TYR-CG': 1, 'TYR-CD1': 1,
|
||||
'TYR-CE1': 1, 'TYR-CZ': 1,
|
||||
'TYR-CE2': 1, 'TYR-CD2': 1}
|
||||
self.num_pi_elec_conj_bonds_sidechains = {'ARG-NE': 1, 'ARG-NH2': 1,
|
||||
'ASN-ND2': 1, 'GLN-NE2': 1,
|
||||
@@ -90,13 +92,13 @@ class BondMaker:
|
||||
Args:
|
||||
protein: the protein to search for bonds
|
||||
"""
|
||||
info('++++ Side chains ++++')
|
||||
_LOGGER.info('++++ Side chains ++++')
|
||||
# side chains
|
||||
for chain in protein.chains:
|
||||
for residue in chain.residues:
|
||||
if residue.res_name.replace(' ', '') not in ['N+', 'C-']:
|
||||
self.find_bonds_for_side_chain(residue.atoms)
|
||||
info('++++ Backbones ++++')
|
||||
_LOGGER.info('++++ Backbones ++++')
|
||||
# backbone
|
||||
last_residues = []
|
||||
for chain in protein.chains:
|
||||
@@ -108,11 +110,11 @@ class BondMaker:
|
||||
self.connect_backbone(chain.residues[i-1],
|
||||
chain.residues[i])
|
||||
last_residues.append(chain.residues[i])
|
||||
info('++++ terminal oxygen ++++')
|
||||
_LOGGER.info('++++ terminal oxygen ++++')
|
||||
# terminal OXT
|
||||
for last_residue in last_residues:
|
||||
self.find_bonds_for_terminal_oxygen(last_residue)
|
||||
info('++++ cysteines ++++')
|
||||
_LOGGER.info('++++ cysteines ++++')
|
||||
# Cysteines
|
||||
for chain in protein.chains:
|
||||
for i in range(0, len(chain.residues)):
|
||||
@@ -180,7 +182,7 @@ class BondMaker:
|
||||
self.num_pi_elec_bonds_backbone[atom1.name])
|
||||
if atom1.name in (
|
||||
list(self.num_pi_elec_conj_bonds_backbone.keys())
|
||||
and len(atom1.bonded_atoms) > 1): # avoid N-term
|
||||
and len(atom1.bonded_atoms) > 1): # avoid N-term
|
||||
atom1.num_pi_elec_conj_2_3_bonds = (
|
||||
self.num_pi_elec_conj_bonds_backbone[atom1.name])
|
||||
|
||||
@@ -204,8 +206,8 @@ class BondMaker:
|
||||
if key in list(self.num_pi_elec_conj_bonds_sidechains.keys()):
|
||||
atom1.num_pi_elec_conj_2_3_bonds = (
|
||||
self.num_pi_elec_conj_bonds_sidechains[key])
|
||||
if not atom1.name in self.backbone_atoms:
|
||||
if not atom1.name in self.terminal_oxygen_names:
|
||||
if atom1.name not in self.backbone_atoms:
|
||||
if atom1.name not in self.terminal_oxygen_names:
|
||||
for atom2 in atoms:
|
||||
if atom2.name in (
|
||||
self
|
||||
@@ -266,7 +268,6 @@ class BondMaker:
|
||||
Returns:
|
||||
list of atoms
|
||||
"""
|
||||
#self.find_bonds_for_protein(molecule)
|
||||
atoms = []
|
||||
for chain in molecule.chains:
|
||||
for residue in chain.residues:
|
||||
@@ -424,9 +425,9 @@ class BondMaker:
|
||||
"""
|
||||
if atom1 == atom2:
|
||||
return
|
||||
if not atom1 in atom2.bonded_atoms:
|
||||
if atom1 not in atom2.bonded_atoms:
|
||||
atom2.bonded_atoms.append(atom1)
|
||||
if not atom2 in atom1.bonded_atoms:
|
||||
if atom2 not in atom1.bonded_atoms:
|
||||
atom1.bonded_atoms.append(atom2)
|
||||
|
||||
def generate_protein_bond_dictionary(self, atoms):
|
||||
@@ -441,21 +442,21 @@ class BondMaker:
|
||||
name_i = atom.name
|
||||
resi_j = bonded_atom.res_name
|
||||
name_j = bonded_atom.name
|
||||
if not name_i in (
|
||||
if name_i not in (
|
||||
self.backbone_atoms
|
||||
or not name_j in self.backbone_atoms):
|
||||
if not name_i in (
|
||||
or name_j not in self.backbone_atoms):
|
||||
if name_i not in (
|
||||
self.terminal_oxygen_names
|
||||
and not name_j in self.terminal_oxygen_names):
|
||||
if not resi_i in list(self.protein_bonds.keys()):
|
||||
and name_j not in self.terminal_oxygen_names):
|
||||
if resi_i not in list(self.protein_bonds.keys()):
|
||||
self.protein_bonds[resi_i] = {}
|
||||
if not name_i in self.protein_bonds[resi_i]:
|
||||
if name_i not in self.protein_bonds[resi_i]:
|
||||
self.protein_bonds[resi_i][name_i] = []
|
||||
if not name_j in self.protein_bonds[resi_i][name_i]:
|
||||
if name_j not in self.protein_bonds[resi_i][name_i]:
|
||||
self.protein_bonds[resi_i][name_i].append(name_j)
|
||||
if not resi_j in list(self.protein_bonds.keys()):
|
||||
if resi_j not in list(self.protein_bonds.keys()):
|
||||
self.protein_bonds[resi_j] = {}
|
||||
if not name_j in self.protein_bonds[resi_j]:
|
||||
if name_j not in self.protein_bonds[resi_j]:
|
||||
self.protein_bonds[resi_j][name_j] = []
|
||||
if not name_i in self.protein_bonds[resi_j][name_j]:
|
||||
if name_i not in self.protein_bonds[resi_j][name_j]:
|
||||
self.protein_bonds[resi_j][name_j].append(name_i)
|
||||
|
||||
@@ -4,6 +4,7 @@ Molecular data structures
|
||||
|
||||
Container data structure for molecular conformations.
|
||||
"""
|
||||
import logging
|
||||
import functools
|
||||
import propka.ligand
|
||||
from propka.output import make_interaction_map
|
||||
@@ -12,11 +13,14 @@ from propka.coupled_groups import NCCG
|
||||
from propka.determinants import set_backbone_determinants, set_ion_determinants
|
||||
from propka.determinants import set_determinants
|
||||
from propka.group import Group, is_group
|
||||
from propka.lib import info
|
||||
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
#: A large number that gets multipled with the integer obtained from applying
|
||||
#: :func:`ord` to the atom chain ID. Used in calculating atom keys for sorting.
|
||||
#: :func:`ord` to the atom chain ID. Used in calculating atom keys for
|
||||
#: sorting.
|
||||
UNICODE_MULTIPLIER = 1e7
|
||||
|
||||
#: A number that gets mutiplied with an atom's residue number. Used in
|
||||
@@ -54,7 +58,8 @@ class ConformationContainer:
|
||||
else:
|
||||
group = atom.group
|
||||
# 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
|
||||
# if it has a group that should be used in this conformation
|
||||
# as well
|
||||
if group:
|
||||
self.setup_and_add_group(group)
|
||||
|
||||
@@ -66,7 +71,7 @@ class ConformationContainer:
|
||||
'Covalent coupling map for {0:s}'.format(str(self)),
|
||||
self.get_covalently_coupled_groups(),
|
||||
lambda g1, g2: g1 in g2.covalently_coupled_groups)
|
||||
info(map_)
|
||||
_LOGGER.info(map_)
|
||||
# check if we should set a common charge centre as well
|
||||
if self.parameters.common_charge_centre:
|
||||
self.set_common_charge_centres()
|
||||
@@ -108,7 +113,7 @@ class ConformationContainer:
|
||||
'Covalent coupling map for {0:s}'.format(str(self)),
|
||||
self.get_covalently_coupled_groups(),
|
||||
lambda g1, g2: g1 in g2.covalently_coupled_groups)
|
||||
info(map_)
|
||||
_LOGGER.info("Coupling map:\n%s", map_)
|
||||
|
||||
def find_non_covalently_coupled_groups(self, verbose=False):
|
||||
"""Find non-covalently coupled groups and set common charge centres.
|
||||
@@ -116,7 +121,8 @@ class ConformationContainer:
|
||||
Args:
|
||||
verbose: verbose output
|
||||
"""
|
||||
# check if non-covalent coupling has already been set up in an input file
|
||||
# check if non-covalent coupling has already been set up in an input
|
||||
# file
|
||||
if len(list(filter(lambda g: len(g.non_covalently_coupled_groups) > 0,
|
||||
self.get_titratable_groups()))) > 0:
|
||||
self.non_covalently_coupled_groups = True
|
||||
@@ -193,7 +199,7 @@ class ConformationContainer:
|
||||
version: version object
|
||||
options: option object
|
||||
"""
|
||||
info('\nCalculating pKas for', self)
|
||||
_LOGGER.info('Calculating pKas for %s', self)
|
||||
# calculate desolvation
|
||||
for group in self.get_titratable_groups() + self.get_ions():
|
||||
version.calculate_desolvation(group)
|
||||
@@ -215,7 +221,7 @@ class ConformationContainer:
|
||||
penalised_labels = self.coupling_effects()
|
||||
if (self.parameters.remove_penalised_group
|
||||
and len(penalised_labels) > 0):
|
||||
info('Removing penalised groups!!!')
|
||||
_LOGGER.info('Removing penalised groups!!!')
|
||||
for group in self.get_titratable_groups():
|
||||
group.remove_determinants(penalised_labels)
|
||||
# re-calculating the total pKa values
|
||||
@@ -257,7 +263,7 @@ class ConformationContainer:
|
||||
# group with the highest pKa is allowed to titrate...
|
||||
continue
|
||||
group.coupled_titrating_group = first_group
|
||||
#... and the rest are penalised
|
||||
# ... and the rest are penalised
|
||||
penalised_labels.append(group.label)
|
||||
return penalised_labels
|
||||
|
||||
@@ -282,7 +288,7 @@ class ConformationContainer:
|
||||
max_dets[det.group] = max(det.value,
|
||||
max_dets[det.group],
|
||||
key=lambda v: abs(v))
|
||||
# overwrite/add maximum value for each determinant
|
||||
# overwrite/add maximum value for each determinant
|
||||
for det_group in max_dets:
|
||||
new_determinant = Determinant(det_group, max_dets[det_group])
|
||||
for group in groups:
|
||||
@@ -433,9 +439,9 @@ class ConformationContainer:
|
||||
def get_groups_for_calculations(self):
|
||||
"""Get a list of groups that should be included in results report.
|
||||
|
||||
If --titrate_only option is specified, only residues that are titratable
|
||||
and are in that list are included; otherwise all titratable residues
|
||||
and CYS residues are included.
|
||||
If --titrate_only option is specified, only residues that are
|
||||
titratable and are in that list are included; otherwise all titratable
|
||||
residues and CYS residues are included.
|
||||
|
||||
Returns:
|
||||
list of groups
|
||||
@@ -525,7 +531,7 @@ class ConformationContainer:
|
||||
if not atom.molecular_container:
|
||||
atom.molecular_container = self.molecular_container
|
||||
# store chain id for bookkeeping
|
||||
if not atom.chain_id in self.chains:
|
||||
if atom.chain_id not in self.chains:
|
||||
self.chains.append(atom.chain_id)
|
||||
|
||||
def copy_atom(self, atom):
|
||||
@@ -556,7 +562,7 @@ class ConformationContainer:
|
||||
"""
|
||||
my_residue_labels = {a.residue_label for a in self.atoms}
|
||||
for atom in other.atoms:
|
||||
if not atom.residue_label in my_residue_labels:
|
||||
if atom.residue_label not in my_residue_labels:
|
||||
self.copy_atom(atom)
|
||||
|
||||
def find_group(self, group):
|
||||
|
||||
@@ -4,12 +4,14 @@ Coupling between groups
|
||||
|
||||
Describe and analyze energetic coupling between groups.
|
||||
"""
|
||||
|
||||
import logging
|
||||
import itertools
|
||||
import propka.lib
|
||||
from propka.group import Group
|
||||
from propka.output import make_interaction_map
|
||||
from propka.lib import info
|
||||
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class NonCovalentlyCoupledGroups:
|
||||
@@ -37,7 +39,7 @@ class NonCovalentlyCoupledGroups:
|
||||
if (interaction_energy <= self.parameters.min_interaction_energy
|
||||
and return_on_fail):
|
||||
return {'coupling_factor': -1.0}
|
||||
# calculate intrinsic pKa's, if not already done
|
||||
# calculate intrinsic pKa's, if not already done
|
||||
for group in [group1, group2]:
|
||||
if group.intrinsic_pka is None:
|
||||
group.calculate_intrinsic_pka()
|
||||
@@ -80,7 +82,8 @@ class NonCovalentlyCoupledGroups:
|
||||
if (abs(group1.intrinsic_pka - group2.intrinsic_pka)
|
||||
> self.parameters.max_intrinsic_pka_diff and return_on_fail):
|
||||
return {'coupling_factor': -1.0}
|
||||
# if everything is OK, calculate the coupling factor and return all info
|
||||
# if everything is OK, calculate the coupling factor and return all
|
||||
# info
|
||||
factor = (
|
||||
self.get_free_energy_diff_factor(default_energy, swapped_energy)
|
||||
* self.get_pka_diff_factor(group1.intrinsic_pka,
|
||||
@@ -107,7 +110,7 @@ class NonCovalentlyCoupledGroups:
|
||||
if intrinsic_pka_diff <= self.parameters.max_intrinsic_pka_diff:
|
||||
res = (
|
||||
1-(intrinsic_pka_diff
|
||||
/self.parameters.max_intrinsic_pka_diff)**2)
|
||||
/ self.parameters.max_intrinsic_pka_diff)**2)
|
||||
return res
|
||||
|
||||
def get_free_energy_diff_factor(self, energy1, energy2):
|
||||
@@ -139,7 +142,7 @@ class NonCovalentlyCoupledGroups:
|
||||
res = (
|
||||
(interaction_energy-self.parameters.min_interaction_energy)
|
||||
/ (1.0+interaction_energy
|
||||
-self.parameters.min_interaction_energy))
|
||||
- self.parameters.min_interaction_energy))
|
||||
return res
|
||||
|
||||
def identify_non_covalently_coupled_groups(self, conformation,
|
||||
@@ -162,17 +165,25 @@ class NonCovalentlyCoupledGroups:
|
||||
'\n'
|
||||
' Detecting non-covalently coupled residues\n'
|
||||
'{sep}\n'
|
||||
' Maximum pKa difference: {c.max_intrinsic_pka_diff:>4.2f} pKa units\n'
|
||||
' Minimum interaction energy: {c.min_interaction_energy:>4.2f} pKa units\n'
|
||||
' Maximum free energy diff.: {c.max_free_energy_diff:>4.2f} pKa units\n'
|
||||
' Minimum swap pKa shift: {c.min_swap_pka_shift:>4.2f} pKa units\n'
|
||||
' pH: {c.pH:>6} \n'
|
||||
' Reference: {c.reference}\n'
|
||||
' Min pKa: {c.min_pka:>4.2f}\n'
|
||||
' Max pKa: {c.max_pka:>4.2f}\n'
|
||||
' Maximum pKa difference: '
|
||||
'{c.max_intrinsic_pka_diff:>4.2f} pKa units\n'
|
||||
' Minimum interaction energy: '
|
||||
'{c.min_interaction_energy:>4.2f} pKa units\n'
|
||||
' Maximum free energy diff.: '
|
||||
'{c.max_free_energy_diff:>4.2f} pKa units\n'
|
||||
' Minimum swap pKa shift: '
|
||||
'{c.min_swap_pka_shift:>4.2f} pKa units\n'
|
||||
' pH: '
|
||||
'{c.pH:>6} \n'
|
||||
' Reference: '
|
||||
'{c.reference}\n'
|
||||
' Min pKa: '
|
||||
'{c.min_pka:>4.2f}\n'
|
||||
' Max pKa: '
|
||||
'{c.max_pka:>4.2f}\n'
|
||||
'\n')
|
||||
sep = "-" * 103
|
||||
info(info_fmt.format(sep=sep, c=self))
|
||||
_LOGGER.info(info_fmt.format(sep=sep, c=self))
|
||||
# find coupled residues
|
||||
titratable_groups = conformation.get_titratable_groups()
|
||||
if not conformation.non_covalently_coupled_groups:
|
||||
@@ -202,7 +213,7 @@ class NonCovalentlyCoupledGroups:
|
||||
'Non-covalent coupling map for {0:s}'.format(str(conformation)),
|
||||
conformation.get_non_covalently_coupled_groups(),
|
||||
lambda g1, g2: g1 in g2.non_covalently_coupled_groups)
|
||||
info(map_)
|
||||
_LOGGER.info(map_)
|
||||
for system in conformation.get_coupled_systems(
|
||||
conformation.get_non_covalently_coupled_groups(),
|
||||
Group.get_non_covalently_coupled_groups):
|
||||
@@ -215,7 +226,7 @@ class NonCovalentlyCoupledGroups:
|
||||
conformation: conformation to print
|
||||
system: system to print
|
||||
"""
|
||||
info(
|
||||
_LOGGER.info(
|
||||
'System containing {0:d} groups:'.format(len(system)))
|
||||
# make list of interactions within this system
|
||||
interactions = list(itertools.combinations(system, 2))
|
||||
@@ -230,7 +241,7 @@ class NonCovalentlyCoupledGroups:
|
||||
coup_info += (
|
||||
self.make_data_to_string(data, interaction[0], interaction[1])
|
||||
+ '\n\n')
|
||||
info(coup_info)
|
||||
_LOGGER.info(coup_info)
|
||||
# make list of possible combinations of swap to try out
|
||||
combinations = propka.lib.generate_combinations(interactions)
|
||||
# Make possible swap combinations
|
||||
@@ -246,7 +257,7 @@ class NonCovalentlyCoupledGroups:
|
||||
for interaction in combination:
|
||||
self.swap_interactions([interaction[0]], [interaction[1]])
|
||||
swap_info += self.print_determinants_section(system, 'Swapped')
|
||||
info(swap_info)
|
||||
_LOGGER.info(swap_info)
|
||||
|
||||
@staticmethod
|
||||
def get_interaction(group1, group2, include_side_chain_hbs=True):
|
||||
|
||||
108
propka/energy.py
108
propka/energy.py
@@ -6,10 +6,13 @@ Energy calculations.
|
||||
|
||||
"""
|
||||
import math
|
||||
from propka.lib import warning
|
||||
import logging
|
||||
from propka.calculations import squared_distance, get_smallest_distance
|
||||
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
# TODO - I have no idea what these constants mean so I labeled them "UNK_"
|
||||
UNK_MIN_DISTANCE = 2.75
|
||||
MIN_DISTANCE_4TH = math.pow(UNK_MIN_DISTANCE, 4)
|
||||
@@ -72,7 +75,10 @@ def calculate_scale_factor(parameters, weight):
|
||||
Returns:
|
||||
scaling factor
|
||||
"""
|
||||
scale_factor = 1.0 - (1.0 - parameters.desolvationSurfaceScalingFactor)*(1.0 - weight)
|
||||
scale_factor = (
|
||||
1.0 - (1.0 - parameters.desolvationSurfaceScalingFactor)
|
||||
* (1.0 - weight)
|
||||
)
|
||||
return scale_factor
|
||||
|
||||
|
||||
@@ -83,7 +89,8 @@ def calculate_weight(parameters, num_volume):
|
||||
|
||||
Args:
|
||||
parameters: parameters for desolvation calculation
|
||||
num_volume: number of heavy atoms within desolvation calculation volume
|
||||
num_volume: number of heavy atoms within desolvation calculation
|
||||
volume
|
||||
Returns:
|
||||
desolvation weight
|
||||
"""
|
||||
@@ -135,12 +142,14 @@ def hydrogen_bond_energy(dist, dpka_max, cutoffs, f_angle=1.0):
|
||||
|
||||
|
||||
def angle_distance_factors(atom1=None, atom2=None, atom3=None, center=None):
|
||||
"""Calculate distance and angle factors for three atoms for backbone interactions.
|
||||
"""Calculate distance and angle factors for three atoms for backbone
|
||||
interactions.
|
||||
|
||||
NOTE - you need to use atom1 to be the e.g. ASP atom if distance is reset at
|
||||
return: [O1 -- H2-N3].
|
||||
NOTE - you need to use atom1 to be the e.g. ASP atom if distance is reset
|
||||
at return: [O1 -- H2-N3].
|
||||
|
||||
Also generalized to be able to be used for residue 'centers' for C=O COO interactions.
|
||||
Also generalized to be able to be used for residue 'centers' for C=O COO
|
||||
interactions.
|
||||
|
||||
Args:
|
||||
atom1: first atom for calculation (could be None)
|
||||
@@ -194,9 +203,11 @@ def hydrogen_bond_interaction(group1, group2, version):
|
||||
# find the smallest distance between interacting atoms
|
||||
atoms1 = group1.get_interaction_atoms(group2)
|
||||
atoms2 = group2.get_interaction_atoms(group1)
|
||||
[closest_atom1, dist, closest_atom2] = get_smallest_distance(atoms1, atoms2)
|
||||
[closest_atom1, dist, closest_atom2] = get_smallest_distance(
|
||||
atoms1, atoms2
|
||||
)
|
||||
if None in [closest_atom1, closest_atom2]:
|
||||
warning(
|
||||
_LOGGER.warning(
|
||||
'Side chain interaction failed for {0:s} and {1:s}'.format(
|
||||
group1.label, group2.label))
|
||||
return None
|
||||
@@ -210,11 +221,16 @@ def hydrogen_bond_interaction(group1, group2, version):
|
||||
return None
|
||||
# check that bond distance criteria is met
|
||||
min_hbond_dist = version.parameters.min_bond_distance_for_hydrogen_bonds
|
||||
if group1.atom.is_atom_within_bond_distance(group2.atom, min_hbond_dist, 1):
|
||||
if group1.atom.is_atom_within_bond_distance(
|
||||
group2.atom, min_hbond_dist, 1
|
||||
):
|
||||
return None
|
||||
# set angle factor
|
||||
f_angle = 1.0
|
||||
if group2.type in version.parameters.angular_dependent_sidechain_interactions:
|
||||
if (
|
||||
group2.type in
|
||||
version.parameters.angular_dependent_sidechain_interactions
|
||||
):
|
||||
if closest_atom2.element == 'H':
|
||||
heavy_atom = closest_atom2.bonded_atoms[0]
|
||||
hydrogen = closest_atom2
|
||||
@@ -225,7 +241,10 @@ def hydrogen_bond_interaction(group1, group2, version):
|
||||
# is closer to the titratable atom than the hydrogen. In either
|
||||
# case, we set the angle factor to 0
|
||||
f_angle = 0.0
|
||||
elif group1.type in version.parameters.angular_dependent_sidechain_interactions:
|
||||
elif (
|
||||
group1.type in
|
||||
version.parameters.angular_dependent_sidechain_interactions
|
||||
):
|
||||
if closest_atom1.element == 'H':
|
||||
heavy_atom = closest_atom1.bonded_atoms[0]
|
||||
hydrogen = closest_atom1
|
||||
@@ -236,7 +255,9 @@ def hydrogen_bond_interaction(group1, group2, version):
|
||||
# is closer to the titratable atom than the hydrogen. In either
|
||||
# case, we set the angle factor to 0
|
||||
f_angle = 0.0
|
||||
weight = version.calculate_pair_weight(group1.num_volume, group2.num_volume)
|
||||
weight = version.calculate_pair_weight(
|
||||
group1.num_volume, group2.num_volume
|
||||
)
|
||||
exception, value = version.check_exceptions(group1, group2)
|
||||
if exception:
|
||||
# Do nothing, value should have been assigned.
|
||||
@@ -256,12 +277,15 @@ def electrostatic_interaction(group1, group2, dist, version):
|
||||
dist: distance between groups
|
||||
version: version-specific object with parameters and functions
|
||||
Returns:
|
||||
electrostatic interaction energy or None (if no interaction is appropriate)
|
||||
electrostatic interaction energy or None (if no interaction is
|
||||
appropriate)
|
||||
"""
|
||||
# check if we should do coulomb interaction at all
|
||||
if not version.check_coulomb_pair(group1, group2, dist):
|
||||
return None
|
||||
weight = version.calculate_pair_weight(group1.num_volume, group2.num_volume)
|
||||
weight = version.calculate_pair_weight(
|
||||
group1.num_volume, group2.num_volume
|
||||
)
|
||||
value = version.calculate_coulomb_energy(dist, weight)
|
||||
return value
|
||||
|
||||
@@ -334,7 +358,9 @@ def backbone_reorganization(_, conformation):
|
||||
weight = titratable_group.buried
|
||||
dpka = 0.00
|
||||
for bbc_group in bbc_groups:
|
||||
center = [titratable_group.x, titratable_group.y, titratable_group.z]
|
||||
center = [
|
||||
titratable_group.x, titratable_group.y, titratable_group.z
|
||||
]
|
||||
atom2 = bbc_group.get_interaction_atoms(titratable_group)[0]
|
||||
dist, f_angle, _ = angle_distance_factors(atom2=atom2,
|
||||
atom3=bbc_group.atom,
|
||||
@@ -359,7 +385,8 @@ def check_exceptions(version, group1, group2):
|
||||
group2: second group for check
|
||||
Returns:
|
||||
1. Boolean indicating atypical behavior,
|
||||
2. value associated with atypical interaction (None if Boolean is False)
|
||||
2. value associated with atypical interaction (None if Boolean is
|
||||
False)
|
||||
"""
|
||||
res_type1 = group1.type
|
||||
res_type2 = group2.type
|
||||
@@ -398,7 +425,8 @@ def check_coo_arg_exception(group_coo, group_arg, version):
|
||||
version: version object
|
||||
Returns:
|
||||
1. Boolean indicating atypical behavior,
|
||||
2. value associated with atypical interaction (None if Boolean is False)
|
||||
2. value associated with atypical interaction (None if Boolean is
|
||||
False)
|
||||
"""
|
||||
exception = True
|
||||
value_tot = 0.00
|
||||
@@ -409,13 +437,18 @@ def check_coo_arg_exception(group_coo, group_arg, version):
|
||||
atoms_arg.extend(group_arg.get_interaction_atoms(group_coo))
|
||||
for _ in ["shortest", "runner-up"]:
|
||||
# find the closest interaction pair
|
||||
[closest_coo_atom, dist, closest_arg_atom] = get_smallest_distance(atoms_coo,
|
||||
atoms_arg)
|
||||
[dpka_max, cutoff] = version.get_hydrogen_bond_parameters(closest_coo_atom,
|
||||
closest_arg_atom)
|
||||
[closest_coo_atom, dist, closest_arg_atom] = get_smallest_distance(
|
||||
atoms_coo, atoms_arg
|
||||
)
|
||||
[dpka_max, cutoff] = version.get_hydrogen_bond_parameters(
|
||||
closest_coo_atom, closest_arg_atom
|
||||
)
|
||||
# calculate and sum up interaction energy
|
||||
f_angle = 1.00
|
||||
if group_arg.type in version.parameters.angular_dependent_sidechain_interactions:
|
||||
if (
|
||||
group_arg.type in
|
||||
version.parameters.angular_dependent_sidechain_interactions
|
||||
):
|
||||
atom3 = closest_arg_atom.bonded_atoms[0]
|
||||
dist, f_angle, _ = angle_distance_factors(closest_coo_atom,
|
||||
closest_arg_atom,
|
||||
@@ -437,18 +470,23 @@ def check_coo_coo_exception(group1, group2, version):
|
||||
version: version object
|
||||
Returns:
|
||||
1. Boolean indicating atypical behavior,
|
||||
2. value associated with atypical interaction (None if Boolean is False)
|
||||
2. value associated with atypical interaction (None if Boolean is
|
||||
False)
|
||||
"""
|
||||
exception = True
|
||||
interact_groups12 = group1.get_interaction_atoms(group2)
|
||||
interact_groups21 = group2.get_interaction_atoms(group1)
|
||||
[closest_atom1, dist, closest_atom2] = get_smallest_distance(interact_groups12,
|
||||
interact_groups21)
|
||||
[dpka_max, cutoff] = version.get_hydrogen_bond_parameters(closest_atom1,
|
||||
closest_atom2)
|
||||
[closest_atom1, dist, closest_atom2] = get_smallest_distance(
|
||||
interact_groups12, interact_groups21
|
||||
)
|
||||
[dpka_max, cutoff] = version.get_hydrogen_bond_parameters(
|
||||
closest_atom1, closest_atom2
|
||||
)
|
||||
f_angle = 1.00
|
||||
value = hydrogen_bond_energy(dist, dpka_max, cutoff, f_angle)
|
||||
weight = calculate_pair_weight(version.parameters, group1.num_volume, group2.num_volume)
|
||||
weight = calculate_pair_weight(
|
||||
version.parameters, group1.num_volume, group2.num_volume
|
||||
)
|
||||
value = value * (1.0 + weight)
|
||||
return exception, value
|
||||
|
||||
@@ -462,7 +500,8 @@ def check_coo_his_exception(group1, group2, version):
|
||||
version: version object
|
||||
Returns:
|
||||
1. Boolean indicating atypical behavior,
|
||||
2. value associated with atypical interaction (None if Boolean is False)
|
||||
2. value associated with atypical interaction (None if Boolean is
|
||||
False)
|
||||
"""
|
||||
exception = False
|
||||
if check_buried(group1.num_volume, group2.num_volume):
|
||||
@@ -479,7 +518,8 @@ def check_oco_his_exception(group1, group2, version):
|
||||
version: version object
|
||||
Returns:
|
||||
1. Boolean indicating atypical behavior,
|
||||
2. value associated with atypical interaction (None if Boolean is False)
|
||||
2. value associated with atypical interaction (None if Boolean is
|
||||
False)
|
||||
"""
|
||||
exception = False
|
||||
if check_buried(group1.num_volume, group2.num_volume):
|
||||
@@ -496,7 +536,8 @@ def check_cys_his_exception(group1, group2, version):
|
||||
version: version object
|
||||
Returns:
|
||||
1. Boolean indicating atypical behavior,
|
||||
2. value associated with atypical interaction (None if Boolean is False)
|
||||
2. value associated with atypical interaction (None if Boolean is
|
||||
False)
|
||||
"""
|
||||
exception = False
|
||||
if check_buried(group1.num_volume, group2.num_volume):
|
||||
@@ -513,7 +554,8 @@ def check_cys_cys_exception(group1, group2, version):
|
||||
version: version object
|
||||
Returns:
|
||||
1. Boolean indicating atypical behavior,
|
||||
2. value associated with atypical interaction (None if Boolean is False)
|
||||
2. value associated with atypical interaction (None if Boolean is
|
||||
False)
|
||||
"""
|
||||
exception = False
|
||||
if check_buried(group1.num_volume, group2.num_volume):
|
||||
|
||||
@@ -4,12 +4,15 @@ Data structures for groups
|
||||
|
||||
Routines and classes for storing groups important to PROPKA calculations.
|
||||
"""
|
||||
import logging
|
||||
import math
|
||||
import propka.ligand
|
||||
import propka.protonate
|
||||
from propka.ligand_pka_values import LigandPkaValues
|
||||
from propka.determinant import Determinant
|
||||
from propka.lib import info, warning
|
||||
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
# Constants that start with "UNK_" are a mystery to me
|
||||
@@ -20,7 +23,7 @@ EXPECTED_ATOMS_ACID_INTERACTIONS = {
|
||||
'COO': {'O': 2}, 'HIS': {'H': 2, 'N': 2}, 'CYS': {'S': 1}, 'TYR': {'O': 1},
|
||||
'LYS': {'N': 1}, 'ARG': {'H': 5, 'N': 3}, 'ROH': {'O': 1},
|
||||
'AMD': {'H': 2, 'N': 1}, 'TRP': {'H': 1, 'N': 1}, 'N+': {'N': 1},
|
||||
'C-': {'O': 2}, 'BBN': {'H': 1, 'N': 1,}, 'BBC': {'O': 1},
|
||||
'C-': {'O': 2}, 'BBN': {'H': 1, 'N': 1}, 'BBC': {'O': 1},
|
||||
'NAR': {'H': 1, 'N': 1}, 'NAM': {'H': 1, 'N': 1}, 'F': {'F': 1},
|
||||
'Cl': {'Cl': 1}, 'OH': {'H': 1, 'O': 1}, 'OP': {'O': 1}, 'O3': {'O': 1},
|
||||
'O2': {'O': 1}, 'SH': {'S': 1}, 'CG': {'H': 5, 'N': 3},
|
||||
@@ -106,9 +109,9 @@ class Group:
|
||||
other: other group for coupling
|
||||
"""
|
||||
# do the coupling
|
||||
if not other in self.covalently_coupled_groups:
|
||||
if other not in self.covalently_coupled_groups:
|
||||
self.covalently_coupled_groups.append(other)
|
||||
if not self in other.covalently_coupled_groups:
|
||||
if self not in other.covalently_coupled_groups:
|
||||
other.covalently_coupled_groups.append(self)
|
||||
|
||||
def couple_non_covalently(self, other):
|
||||
@@ -118,9 +121,9 @@ class Group:
|
||||
other: other group for coupling
|
||||
"""
|
||||
# do the coupling
|
||||
if not other in self.non_covalently_coupled_groups:
|
||||
if other not in self.non_covalently_coupled_groups:
|
||||
self.non_covalently_coupled_groups.append(other)
|
||||
if not self in other.non_covalently_coupled_groups:
|
||||
if self not in other.non_covalently_coupled_groups:
|
||||
other.non_covalently_coupled_groups.append(self)
|
||||
|
||||
def get_covalently_coupled_groups(self):
|
||||
@@ -399,26 +402,26 @@ class Group:
|
||||
str_ = 'Missing atoms or failed protonation for '
|
||||
str_ += '{0:s} ({1:s}) -- please check the structure'.format(
|
||||
self.label, self.type)
|
||||
warning(str_)
|
||||
warning('{0:s}'.format(str(self)))
|
||||
_LOGGER.warning(str_)
|
||||
_LOGGER.warning('{0:s}'.format(str(self)))
|
||||
num_acid = sum(
|
||||
[EXPECTED_ATOMS_ACID_INTERACTIONS[self.type][e]
|
||||
for e in EXPECTED_ATOMS_ACID_INTERACTIONS[self.type].keys()])
|
||||
num_base = sum(
|
||||
[EXPECTED_ATOMS_BASE_INTERACTIONS[self.type][e]
|
||||
for e in EXPECTED_ATOMS_BASE_INTERACTIONS[self.type].keys()])
|
||||
warning(
|
||||
_LOGGER.warning(
|
||||
'Expected {0:d} interaction atoms for acids, found:'.format(
|
||||
num_acid))
|
||||
for i in range(len(self.interaction_atoms_for_acids)):
|
||||
warning(
|
||||
_LOGGER.warning(
|
||||
' {0:s}'.format(
|
||||
str(self.interaction_atoms_for_acids[i])))
|
||||
warning(
|
||||
_LOGGER.warning(
|
||||
'Expected {0:d} interaction atoms for bases, found:'.format(
|
||||
num_base))
|
||||
for i in range(len(self.interaction_atoms_for_bases)):
|
||||
warning(
|
||||
_LOGGER.warning(
|
||||
' {0:s}'.format(
|
||||
str(self.interaction_atoms_for_bases[i])))
|
||||
|
||||
@@ -672,7 +675,9 @@ class HISGroup(Group):
|
||||
# Find the atoms in the histidine ring
|
||||
ring_atoms = propka.ligand.is_ring_member(self.atom)
|
||||
if len(ring_atoms) != 5:
|
||||
warning('His group does not seem to contain a ring', self)
|
||||
_LOGGER.warning(
|
||||
'His group does not seem to contain a ring %s', self
|
||||
)
|
||||
# protonate ring
|
||||
for ring_atom in ring_atoms:
|
||||
PROTONATOR.protonate_atom(ring_atom)
|
||||
@@ -682,7 +687,8 @@ class HISGroup(Group):
|
||||
else:
|
||||
# Missing side-chain atoms
|
||||
self.set_center([self.atom])
|
||||
# TODO - perhaps it would be better to ignore this group completely?
|
||||
# TODO - perhaps it would be better to ignore this group
|
||||
# completely?
|
||||
# find the hydrogens on the ring-nitrogens
|
||||
hydrogens = []
|
||||
nitrogens = [ra for ra in ring_atoms if ra.element == 'N']
|
||||
@@ -815,7 +821,7 @@ class CtermGroup(Group):
|
||||
the_other_oxygen = the_carbons[0].get_bonded_elements('O')
|
||||
the_other_oxygen.remove(self.atom)
|
||||
# set the center and interaction atoms
|
||||
the_oxygens = [self.atom]+ the_other_oxygen
|
||||
the_oxygens = [self.atom] + the_other_oxygen
|
||||
self.set_center(the_oxygens)
|
||||
self.set_interaction_atoms(the_oxygens, the_oxygens)
|
||||
|
||||
@@ -866,7 +872,7 @@ class NARGroup(Group):
|
||||
Group.__init__(self, atom)
|
||||
self.type = 'NAR'
|
||||
self.residue_type = 'NAR'
|
||||
info('Found NAR group:', atom)
|
||||
_LOGGER.info('Found NAR group: %s', atom)
|
||||
|
||||
def setup_atoms(self):
|
||||
"""Set up atoms in group."""
|
||||
@@ -889,7 +895,7 @@ class NAMGroup(Group):
|
||||
Group.__init__(self, atom)
|
||||
self.type = 'NAM'
|
||||
self.residue_type = 'NAM'
|
||||
info('Found NAM group:', atom)
|
||||
_LOGGER.info('Found NAM group: %s', atom)
|
||||
|
||||
def setup_atoms(self):
|
||||
"""Set up atoms in this group."""
|
||||
@@ -909,7 +915,7 @@ class FGroup(Group):
|
||||
Group.__init__(self, atom)
|
||||
self.type = 'F'
|
||||
self.residue_type = 'F'
|
||||
info('Found F group:', atom)
|
||||
_LOGGER.info('Found F group: %s', atom)
|
||||
|
||||
|
||||
class ClGroup(Group):
|
||||
@@ -919,7 +925,7 @@ class ClGroup(Group):
|
||||
Group.__init__(self, atom)
|
||||
self.type = 'Cl'
|
||||
self.residue_type = 'Cl'
|
||||
info('Found Cl group:', atom)
|
||||
_LOGGER.info('Found Cl group: %s', atom)
|
||||
|
||||
|
||||
class OHGroup(Group):
|
||||
@@ -929,7 +935,7 @@ class OHGroup(Group):
|
||||
Group.__init__(self, atom)
|
||||
self.type = 'OH'
|
||||
self.residue_type = 'OH'
|
||||
info('Found OH group:', atom)
|
||||
_LOGGER.info('Found OH group: %s', atom)
|
||||
|
||||
def setup_atoms(self):
|
||||
"""Set up atoms in this group."""
|
||||
@@ -949,7 +955,7 @@ class OPGroup(Group):
|
||||
Group.__init__(self, atom)
|
||||
self.type = 'OP'
|
||||
self.residue_type = 'OP'
|
||||
info('Found OP group:', atom)
|
||||
_LOGGER.info('Found OP group: %s', atom)
|
||||
|
||||
def setup_atoms(self):
|
||||
"""Set up atoms in this group."""
|
||||
@@ -970,7 +976,7 @@ class O3Group(Group):
|
||||
Group.__init__(self, atom)
|
||||
self.type = 'O3'
|
||||
self.residue_type = 'O3'
|
||||
info('Found O3 group:', atom)
|
||||
_LOGGER.info('Found O3 group: %s', atom)
|
||||
|
||||
|
||||
class O2Group(Group):
|
||||
@@ -983,7 +989,7 @@ class O2Group(Group):
|
||||
Group.__init__(self, atom)
|
||||
self.type = 'O2'
|
||||
self.residue_type = 'O2'
|
||||
info('Found O2 group:', atom)
|
||||
_LOGGER.info('Found O2 group: %s', atom)
|
||||
|
||||
|
||||
class SHGroup(Group):
|
||||
@@ -993,7 +999,7 @@ class SHGroup(Group):
|
||||
Group.__init__(self, atom)
|
||||
self.type = 'SH'
|
||||
self.residue_type = 'SH'
|
||||
info('Found SH group:', atom)
|
||||
_LOGGER.info('Found SH group: %s', atom)
|
||||
|
||||
|
||||
class CGGroup(Group):
|
||||
@@ -1003,7 +1009,7 @@ class CGGroup(Group):
|
||||
Group.__init__(self, atom)
|
||||
self.type = 'CG'
|
||||
self.residue_type = 'CG'
|
||||
info('Found CG group:', atom)
|
||||
_LOGGER.info('Found CG group: %s', atom)
|
||||
|
||||
def setup_atoms(self):
|
||||
"""Set up atoms in this group."""
|
||||
@@ -1026,7 +1032,7 @@ class C2NGroup(Group):
|
||||
Group.__init__(self, atom)
|
||||
self.type = 'C2N'
|
||||
self.residue_type = 'C2N'
|
||||
info('Found C2N group:', atom)
|
||||
_LOGGER.info('Found C2N group: %s', atom)
|
||||
|
||||
def setup_atoms(self):
|
||||
"""Set up atoms in this group."""
|
||||
@@ -1050,7 +1056,7 @@ class OCOGroup(Group):
|
||||
Group.__init__(self, atom)
|
||||
self.type = 'OCO'
|
||||
self.residue_type = 'OCO'
|
||||
info('Found OCO group:', atom)
|
||||
_LOGGER.info('Found OCO group: %s', atom)
|
||||
|
||||
def setup_atoms(self):
|
||||
"""Set up atoms in group."""
|
||||
@@ -1071,7 +1077,7 @@ class N30Group(Group):
|
||||
Group.__init__(self, atom)
|
||||
self.type = 'N30'
|
||||
self.residue_type = 'N30'
|
||||
info('Found N30 group:', atom)
|
||||
_LOGGER.info('Found N30 group: %s', atom)
|
||||
|
||||
def setup_atoms(self):
|
||||
"""Set up atoms in this group."""
|
||||
@@ -1093,7 +1099,7 @@ class N31Group(Group):
|
||||
Group.__init__(self, atom)
|
||||
self.type = 'N31'
|
||||
self.residue_type = 'N31'
|
||||
info('Found N31 group:', atom)
|
||||
_LOGGER.info('Found N31 group: %s', atom)
|
||||
|
||||
def setup_atoms(self):
|
||||
"""Set up atoms in this group."""
|
||||
@@ -1115,7 +1121,7 @@ class N32Group(Group):
|
||||
Group.__init__(self, atom)
|
||||
self.type = 'N32'
|
||||
self.residue_type = 'N32'
|
||||
info('Found N32 group:', atom)
|
||||
_LOGGER.info('Found N32 group: %s', atom)
|
||||
|
||||
def setup_atoms(self):
|
||||
"""Set up atoms in this group."""
|
||||
@@ -1137,7 +1143,7 @@ class N33Group(Group):
|
||||
Group.__init__(self, atom)
|
||||
self.type = 'N33'
|
||||
self.residue_type = 'N33'
|
||||
info('Found N33 group:', atom)
|
||||
_LOGGER.info('Found N33 group: %s', atom)
|
||||
|
||||
def setup_atoms(self):
|
||||
"""Set up atoms in this group."""
|
||||
@@ -1159,7 +1165,7 @@ class NP1Group(Group):
|
||||
Group.__init__(self, atom)
|
||||
self.type = 'NP1'
|
||||
self.residue_type = 'NP1'
|
||||
info('Found NP1 group:', atom)
|
||||
_LOGGER.info('Found NP1 group: %s', atom)
|
||||
|
||||
def setup_atoms(self):
|
||||
"""Set up atoms in group."""
|
||||
@@ -1181,7 +1187,7 @@ class N1Group(Group):
|
||||
Group.__init__(self, atom)
|
||||
self.type = 'N1'
|
||||
self.residue_type = 'N1'
|
||||
info('Found N1 group:', atom)
|
||||
_LOGGER.info('Found N1 group: %s', atom)
|
||||
|
||||
|
||||
class IonGroup(Group):
|
||||
@@ -1191,7 +1197,7 @@ class IonGroup(Group):
|
||||
Group.__init__(self, atom)
|
||||
self.type = 'ION'
|
||||
self.residue_type = atom.res_name.strip()
|
||||
info('Found ion group:', atom)
|
||||
_LOGGER.info('Found ion group: %s', atom)
|
||||
|
||||
|
||||
class NonTitratableLigandGroup(Group):
|
||||
@@ -1223,8 +1229,10 @@ class TitratableLigandGroup(Group):
|
||||
# this is not true if we are reading an input file
|
||||
if atom.marvin_pka:
|
||||
self.model_pka = atom.marvin_pka
|
||||
info('Titratable ligand group ',
|
||||
atom, self.model_pka, self.charge)
|
||||
_LOGGER.info(
|
||||
'Titratable ligand group %s %s %s',
|
||||
atom, self.model_pka, self.charge
|
||||
)
|
||||
self.model_pka_set = True
|
||||
|
||||
|
||||
@@ -1273,12 +1281,12 @@ def is_protein_group(parameters, atom):
|
||||
"""
|
||||
if atom.type != 'atom':
|
||||
return None
|
||||
### Check for termial groups
|
||||
# Check for termial groups
|
||||
if atom.terminal == 'N+':
|
||||
return NtermGroup(atom)
|
||||
elif atom.terminal == 'C-':
|
||||
return CtermGroup(atom)
|
||||
### Backbone
|
||||
# Backbone
|
||||
if atom.type == 'atom' and atom.name == 'N':
|
||||
# ignore proline backbone nitrogens
|
||||
if atom.res_name != 'PRO':
|
||||
@@ -1287,7 +1295,7 @@ def is_protein_group(parameters, atom):
|
||||
# ignore C- carboxyl
|
||||
if atom.count_bonded_elements('O') == 1:
|
||||
return BBCGroup(atom)
|
||||
### Filters for side chains based on PDB protein atom names
|
||||
# Filters for side chains based on PDB protein atom names
|
||||
key = '{0:s}-{1:s}'.format(atom.res_name, atom.name)
|
||||
if key in parameters.protein_group_mapping.keys():
|
||||
class_str = "{0:s}Group".format(parameters.protein_group_mapping[key])
|
||||
@@ -1305,7 +1313,7 @@ def is_ligand_group_by_groups(_, atom):
|
||||
Returns:
|
||||
group for atom or None
|
||||
"""
|
||||
### Ligand group filters
|
||||
# Ligand group filters
|
||||
if atom.type != 'hetatm':
|
||||
return None
|
||||
PROTONATOR.protonate_atom(atom)
|
||||
@@ -1327,7 +1335,8 @@ def is_ligand_group_by_groups(_, atom):
|
||||
if atom.sybyl_type == 'N.1':
|
||||
return N1Group(atom)
|
||||
if atom.sybyl_type == 'N.pl3':
|
||||
# make sure that this atom is not part of a guadinium or amidinium group
|
||||
# make sure that this atom is not part of a guadinium or amidinium
|
||||
# group
|
||||
bonded_carbons = atom.get_bonded_elements('C')
|
||||
if len(bonded_carbons) == 1:
|
||||
bonded_nitrogens = bonded_carbons[0].get_bonded_elements('N')
|
||||
@@ -1426,13 +1435,14 @@ def is_ion_group(parameters, atom):
|
||||
return IonGroup(atom)
|
||||
return None
|
||||
|
||||
|
||||
def initialize_atom_group(atom):
|
||||
"""Initialize an atom group.
|
||||
|
||||
Args:
|
||||
atom: atom to initialize
|
||||
"""
|
||||
# try to initialise the group
|
||||
# try to initialise the group
|
||||
group_attr = globals()[atom.group_label]
|
||||
atom.group = group_attr(atom)
|
||||
atom.group.model_pka = atom.group_model_pka
|
||||
|
||||
@@ -6,12 +6,14 @@ Calculations related to hydrogen placement.
|
||||
|
||||
"""
|
||||
import math
|
||||
from propka.lib import info
|
||||
import logging
|
||||
from propka.protonate import Protonate
|
||||
from propka.bonds import BondMaker
|
||||
from propka.atom import Atom
|
||||
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def setup_bonding_and_protonation(molecular_container):
|
||||
"""Set up bonding and protonation for a molecule.
|
||||
@@ -68,7 +70,7 @@ def protonate_30_style(molecular_container):
|
||||
molecular_container: molecule
|
||||
"""
|
||||
for name in molecular_container.conformation_names:
|
||||
info('Now protonating', name)
|
||||
_LOGGER.info('Now protonating %s', name)
|
||||
# split atom into residues
|
||||
curres = -1000000
|
||||
residue = []
|
||||
@@ -78,19 +80,19 @@ def protonate_30_style(molecular_container):
|
||||
if atom.res_num != curres:
|
||||
curres = atom.res_num
|
||||
if len(residue) > 0:
|
||||
#backbone
|
||||
# backbone
|
||||
[o_atom, c_atom] = add_backbone_hydrogen(
|
||||
residue, o_atom, c_atom)
|
||||
#arginine
|
||||
# arginine
|
||||
if residue[0].res_name == 'ARG':
|
||||
add_arg_hydrogen(residue)
|
||||
#histidine
|
||||
# histidine
|
||||
if residue[0].res_name == 'HIS':
|
||||
add_his_hydrogen(residue)
|
||||
#tryptophan
|
||||
# tryptophan
|
||||
if residue[0].res_name == 'TRP':
|
||||
add_trp_hydrogen(residue)
|
||||
#amides
|
||||
# amides
|
||||
if residue[0].res_name in ['GLN', 'ASN']:
|
||||
add_amd_hydrogen(residue)
|
||||
residue = []
|
||||
@@ -116,7 +118,6 @@ def add_arg_hydrogen(residue):
|
||||
Returns:
|
||||
list of hydrogen atoms
|
||||
"""
|
||||
#info('Adding arg H',residue)
|
||||
for atom in residue:
|
||||
if atom.name == "CD":
|
||||
cd_atom = atom
|
||||
@@ -348,5 +349,3 @@ def make_new_h(atom, x, y, z):
|
||||
atom.bonded_atoms.append(new_h)
|
||||
atom.conformation_container.add_atom(new_h)
|
||||
return new_h
|
||||
|
||||
|
||||
|
||||
@@ -6,8 +6,11 @@ Iterative functions for pKa calculations. These appear to mostly
|
||||
involve :class:`propka.determinant.Determinant` instances.
|
||||
|
||||
"""
|
||||
import logging
|
||||
from propka.determinant import Determinant
|
||||
from propka.lib import info, debug
|
||||
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
# TODO - these are undocumented constants
|
||||
@@ -215,9 +218,12 @@ def add_determinants(iterative_interactions, version, _=None):
|
||||
iteratives.append(new_iterative)
|
||||
done_group.append(group)
|
||||
# Initialize iterative scheme
|
||||
debug(
|
||||
"\n --- pKa iterations ({0:d} groups, {1:d} interactions) ---".format(
|
||||
len(iteratives), len(iterative_interactions)))
|
||||
_LOGGER.debug(
|
||||
"\n --- pKa iterations ({0:d} groups, {1:d} interactions) "
|
||||
"---".format(
|
||||
len(iteratives), len(iterative_interactions)
|
||||
)
|
||||
)
|
||||
converged = False
|
||||
iteration = 0
|
||||
# set non-iterative pka values as first step
|
||||
@@ -237,7 +243,7 @@ def add_determinants(iterative_interactions, version, _=None):
|
||||
object1, object2 = find_iterative(pair, iteratives)
|
||||
q1 = object1.q
|
||||
q2 = object2.q
|
||||
if q1 < 0.0 and q2 < 0.0:
|
||||
if q1 < 0.0 and q2 < 0.0:
|
||||
# both are acids
|
||||
add_iterative_acid_pair(object1, object2, interaction)
|
||||
elif q1 > 0.0 and q2 > 0.0:
|
||||
@@ -267,26 +273,27 @@ def add_determinants(iterative_interactions, version, _=None):
|
||||
itres.pka_iter.append(itres.pka_new)
|
||||
|
||||
if iteration == 10:
|
||||
info("did not converge in {0:d} iterations".format(iteration))
|
||||
_LOGGER.info(
|
||||
"did not converge in {0:d} iterations".format(iteration)
|
||||
)
|
||||
break
|
||||
# printing pKa iterations
|
||||
# formerly was conditioned on if options.verbosity >= 2 - now unnecessary
|
||||
str_ = ' '
|
||||
for index in range(iteration+1):
|
||||
str_ += "{0:>8d}".format(index)
|
||||
debug(str_)
|
||||
_LOGGER.debug(str_)
|
||||
for itres in iteratives:
|
||||
str_ = "{0:s} ".format(itres.label)
|
||||
for pka in itres.pka_iter:
|
||||
str_ += "{0:>8.2f}".format(pka)
|
||||
if not itres.converged:
|
||||
str_ += " *"
|
||||
debug(str_)
|
||||
_LOGGER.debug(str_)
|
||||
# creating real determinants and adding them to group object
|
||||
for itres in iteratives:
|
||||
for type_ in ['sidechain', 'backbone', 'coulomb']:
|
||||
for interaction in itres.determinants[type_]:
|
||||
#info('done',itres.group.label,interaction[0],interaction[1])
|
||||
value = interaction[1]
|
||||
if value > UNK_MIN_VALUE or value < -UNK_MIN_VALUE:
|
||||
group = interaction[0]
|
||||
|
||||
@@ -11,10 +11,7 @@ import argparse
|
||||
import pkg_resources
|
||||
|
||||
|
||||
_LOGGER = logging.getLogger("propka")
|
||||
_STDOUT_HANDLER = logging.StreamHandler(sys.stdout)
|
||||
_STDOUT_HANDLER.setFormatter(logging.Formatter("%(message)s"))
|
||||
_LOGGER.addHandler(_STDOUT_HANDLER)
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
EXPECTED_ATOM_NUMBERS = {'ALA': 5, 'ARG': 11, 'ASN': 8, 'ASP': 8, 'CYS': 6,
|
||||
@@ -53,7 +50,7 @@ def protein_precheck(conformations, names):
|
||||
"{res:s} in conformation {conf:s}".format(
|
||||
num=len(res_atoms), res=residue_label,
|
||||
conf=name))
|
||||
warning(str_)
|
||||
_LOGGER.warning(str_)
|
||||
continue
|
||||
# check number of atoms in residue
|
||||
if len(res_atoms) != EXPECTED_ATOM_NUMBERS[res_name]:
|
||||
@@ -61,7 +58,7 @@ def protein_precheck(conformations, names):
|
||||
"{res:s} in conformation {conf:s}".format(
|
||||
num=len(res_atoms), res=residue_label,
|
||||
conf=name))
|
||||
warning(str_)
|
||||
_LOGGER.warning(str_)
|
||||
|
||||
|
||||
def resid_from_atom(atom):
|
||||
@@ -101,7 +98,7 @@ def make_molecule(atom, atoms):
|
||||
list of 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:
|
||||
if bond_atom in atoms:
|
||||
atoms.remove(bond_atom)
|
||||
@@ -190,9 +187,9 @@ def build_parser(parser=None):
|
||||
"""Build an argument parser for PROPKA.
|
||||
|
||||
Args:
|
||||
parser: existing parser. If this is not None, then the PROPKA parser will
|
||||
be created as a subparser to this existing parser. Otherwise, a
|
||||
new parser will be created.
|
||||
parser: existing parser. If this is not None, then the PROPKA parser
|
||||
will be created as a subparser to this existing parser.
|
||||
Otherwise, a new parser will be created.
|
||||
Returns:
|
||||
ArgumentParser object.
|
||||
"""
|
||||
@@ -209,7 +206,10 @@ def build_parser(parser=None):
|
||||
group.add_argument("input_pdb", help="read data from <filename>")
|
||||
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",
|
||||
help=("setting which reference to use for stability calculations "
|
||||
@@ -221,8 +221,8 @@ def build_parser(parser=None):
|
||||
group.add_argument(
|
||||
"-i", "--titrate_only", dest="titrate_only",
|
||||
help=('Treat only the specified residues as titratable. Value should '
|
||||
'be a comma-separated list of "chain:resnum" values; for example: '
|
||||
'-i "A:10,A:11"'))
|
||||
'be a comma-separated list of "chain:resnum" values; for '
|
||||
'example: -i "A:10,A:11"'))
|
||||
group.add_argument(
|
||||
"-t", "--thermophile", action="append", dest="thermophiles",
|
||||
help=("defining a thermophile filename; usually used in "
|
||||
@@ -265,7 +265,11 @@ def build_parser(parser=None):
|
||||
"related properties [0.0, 14.0, 0.1]"))
|
||||
group.add_argument(
|
||||
"--mutator", dest="mutator",
|
||||
help="setting approach for mutating <filename> [alignment/scwrl/jackal]")
|
||||
help=(
|
||||
"setting approach for mutating <filename> "
|
||||
"[alignment/scwrl/jackal]"
|
||||
)
|
||||
)
|
||||
group.add_argument(
|
||||
"--mutator-option", dest="mutator_options", action="append",
|
||||
help="setting property for mutator [e.g. type=\"side-chain\"]")
|
||||
@@ -340,14 +344,14 @@ def make_tidy_atom_label(name, element):
|
||||
Returns:
|
||||
string
|
||||
"""
|
||||
if len(name) > 4: # if longer than 4, just truncate the name
|
||||
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
|
||||
elif len(name) == 4: # if length is 4, otherwise use the name as it is
|
||||
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:
|
||||
label = ' {0:<3s}'.format(name)
|
||||
else: # The element should occupy the two first chars
|
||||
else: # The element should occupy the two first chars
|
||||
label = '{0:<4s}'.format(name)
|
||||
return label
|
||||
|
||||
@@ -368,47 +372,3 @@ def get_sorted_configurations(configuration_keys):
|
||||
def configuration_compare(conf):
|
||||
"""TODO - figure out what this function does."""
|
||||
return 100*int(conf[1:-2]) + ord(conf[-1])
|
||||
|
||||
|
||||
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))
|
||||
|
||||
|
||||
def info(*args):
|
||||
"""Log a message to info.
|
||||
|
||||
Level defaults to INFO unless overridden.
|
||||
|
||||
Args:
|
||||
args: argument list
|
||||
"""
|
||||
_LOGGER.info(_args_to_str(args))
|
||||
|
||||
|
||||
def debug(*args):
|
||||
"""Log a message to debug.
|
||||
|
||||
Level defaults to DEBUG unless overridden.
|
||||
|
||||
Args:
|
||||
args: argument list
|
||||
"""
|
||||
_LOGGER.debug(_args_to_str(args))
|
||||
|
||||
|
||||
def warning(*args):
|
||||
"""Log a message to warning.
|
||||
|
||||
Level defaults to WARNING unless overridden.
|
||||
|
||||
Args:
|
||||
args: argument list
|
||||
"""
|
||||
_LOGGER.warning(_args_to_str(args))
|
||||
|
||||
@@ -9,11 +9,15 @@ programs are required).
|
||||
.. _Marvin: https://chemaxon.com/products/marvin
|
||||
|
||||
"""
|
||||
import logging
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
from propka.output import write_mol2_for_atoms
|
||||
from propka.lib import info, warning, split_atoms_into_molecules
|
||||
from propka.lib import split_atoms_into_molecules
|
||||
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class LigandPkaValues:
|
||||
@@ -29,9 +33,9 @@ class LigandPkaValues:
|
||||
# attempt to find Marvin executables in the path
|
||||
self.molconvert = self.find_in_path('molconvert')
|
||||
self.cxcalc = self.find_in_path('cxcalc')
|
||||
info('Found Marvin executables:')
|
||||
info(self.cxcalc)
|
||||
info(self.molconvert)
|
||||
_LOGGER.info('Found Marvin executables:')
|
||||
_LOGGER.info(self.cxcalc)
|
||||
_LOGGER.info(self.molconvert)
|
||||
|
||||
@staticmethod
|
||||
def find_in_path(program):
|
||||
@@ -50,7 +54,7 @@ class LigandPkaValues:
|
||||
if len(locs) == 0:
|
||||
str_ = "'Error: Could not find {0:s}.".format(program)
|
||||
str_ += ' Please make sure that it is found in the path.'
|
||||
info(str_)
|
||||
_LOGGER.info(str_)
|
||||
sys.exit(-1)
|
||||
return locs[0]
|
||||
|
||||
@@ -146,7 +150,7 @@ class LigandPkaValues:
|
||||
"Didn't find a user-modified file '{0:s}' "
|
||||
"- generating one".format(
|
||||
filename))
|
||||
warning(errstr)
|
||||
_LOGGER.warning(errstr)
|
||||
write_mol2_for_atoms(atoms, filename)
|
||||
# Marvin calculate pKa values
|
||||
fmt = (
|
||||
@@ -159,17 +163,22 @@ class LigandPkaValues:
|
||||
[self.cxcalc, filename]+options.split(), stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE).communicate()
|
||||
if len(errors) > 0:
|
||||
info('***********************************************************'
|
||||
'*********************************************')
|
||||
info('* Warning: Marvin execution failed: '
|
||||
' *')
|
||||
info('* {0:<100s} *'.format(errors))
|
||||
info('* '
|
||||
' *')
|
||||
info('* Please edit the ligand mol2 file and re-run PropKa with '
|
||||
'the -l option: {0:>29s} *'.format(filename))
|
||||
info('***********************************************************'
|
||||
'*********************************************')
|
||||
_LOGGER.info(
|
||||
'***********************************************************'
|
||||
'*********************************************')
|
||||
_LOGGER.info(
|
||||
'* Warning: Marvin execution failed: '
|
||||
' *')
|
||||
_LOGGER.info('* {0:<100s} *'.format(errors))
|
||||
_LOGGER.info(
|
||||
'* '
|
||||
' *')
|
||||
_LOGGER.info(
|
||||
'* Please edit the ligand mol2 file and re-run PropKa with '
|
||||
'the -l option: {0:>29s} *'.format(filename))
|
||||
_LOGGER.info(
|
||||
'***********************************************************'
|
||||
'*********************************************')
|
||||
sys.exit(-1)
|
||||
# extract calculated pkas
|
||||
indices, pkas, types = self.extract_pkas(output)
|
||||
@@ -177,7 +186,9 @@ class LigandPkaValues:
|
||||
for i, index in enumerate(indices):
|
||||
atoms[index].marvin_pka = pkas[i]
|
||||
atoms[index].charge = {'a': -1, 'b': 1}[types[i]]
|
||||
info('{0:s} model pKa: {1:<.2f}'.format(atoms[index], pkas[i]))
|
||||
_LOGGER.info(
|
||||
'{0:s} model pKa: {1:<.2f}'.format(atoms[index], pkas[i])
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def extract_pkas(output):
|
||||
|
||||
@@ -4,11 +4,15 @@ PDB molecular container
|
||||
|
||||
Molecular container for storing all contents of PDB files.
|
||||
"""
|
||||
import logging
|
||||
import os
|
||||
import propka.version
|
||||
from propka.output import write_propka, write_pka, print_header, print_result
|
||||
from propka.conformation_container import ConformationContainer
|
||||
from propka.lib import info, warning, make_grid
|
||||
from propka.lib import make_grid
|
||||
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
# TODO - these are constants whose origins are a little murky
|
||||
@@ -55,13 +59,11 @@ class MolecularContainer:
|
||||
|
||||
def find_covalently_coupled_groups(self):
|
||||
"""Find covalently coupled groups."""
|
||||
info('-' * 103)
|
||||
for name in self.conformation_names:
|
||||
self.conformations[name].find_covalently_coupled_groups()
|
||||
|
||||
def find_non_covalently_coupled_groups(self):
|
||||
"""Find non-covalently coupled groups."""
|
||||
info('-' * 103)
|
||||
verbose = self.options.display_coupled_residues
|
||||
for name in self.conformation_names:
|
||||
self.conformations[name].find_non_covalently_coupled_groups(
|
||||
@@ -110,7 +112,7 @@ class MolecularContainer:
|
||||
'Group {0:s} could not be found in '
|
||||
'conformation {1:s}.'.format(
|
||||
group.atom.residue_label, name))
|
||||
warning(str_)
|
||||
_LOGGER.warning(str_)
|
||||
# ... and store the average value
|
||||
avr_group = avr_group / len(self.conformation_names)
|
||||
avr_conformation.groups.append(avr_group)
|
||||
|
||||
@@ -4,11 +4,14 @@ Output
|
||||
|
||||
Output routines.
|
||||
"""
|
||||
import logging
|
||||
from datetime import date
|
||||
from propka.lib import info
|
||||
from . import __version__
|
||||
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def open_file_for_writing(input_file):
|
||||
"""Open file or file-like stream for writing.
|
||||
|
||||
@@ -49,7 +52,7 @@ def print_header():
|
||||
str_ = "{0:s}\n".format(get_propka_header())
|
||||
str_ += "{0:s}\n".format(get_references_header())
|
||||
str_ += "{0:s}\n".format(get_warning_header())
|
||||
info(str_)
|
||||
_LOGGER.info("\n%s", str_)
|
||||
|
||||
|
||||
def write_pdb_for_protein(
|
||||
@@ -69,7 +72,7 @@ def write_pdb_for_protein(
|
||||
filename = "{0:s}.pdb".format(protein.name)
|
||||
# TODO - this would be better as a context manager
|
||||
pdbfile = open(filename, 'w')
|
||||
info("writing pdbfile {0:s}".format(filename))
|
||||
_LOGGER.info("writing pdbfile {0:s}".format(filename))
|
||||
close_file = True
|
||||
else:
|
||||
# don't close the file, it was opened in a different place
|
||||
@@ -122,7 +125,7 @@ def write_pka(protein, parameters, filename=None, conformation='1A',
|
||||
# TODO - this would be much better with a context manager
|
||||
file_ = open(filename, 'w')
|
||||
if verbose:
|
||||
info("Writing {0:s}".format(filename))
|
||||
_LOGGER.info("Writing {0:s}".format(filename))
|
||||
# writing propka header
|
||||
str_ = "{0:s}\n".format(get_propka_header())
|
||||
str_ += "{0:s}\n".format(get_references_header())
|
||||
@@ -172,7 +175,7 @@ def print_tm_profile(protein, reference="neutral", window=[0., 14., 1.],
|
||||
and (ph % window[2] < 0.01
|
||||
or ph % window[2] > 0.99*window[2])):
|
||||
str_ += "{0:>6.2f}{1:>10.2f}\n".format(ph, tm_)
|
||||
info(str_)
|
||||
_LOGGER.info(str_)
|
||||
|
||||
|
||||
def print_result(protein, conformation, parameters):
|
||||
@@ -196,9 +199,9 @@ def print_pka_section(protein, conformation, parameters):
|
||||
"""
|
||||
# geting the determinants section
|
||||
str_ = get_determinant_section(protein, conformation, parameters)
|
||||
info(str_)
|
||||
_LOGGER.info("pKa determinants:\n%s", str_)
|
||||
str_ = get_summary_section(protein, conformation, parameters)
|
||||
info(str_)
|
||||
_LOGGER.info("pKa summary:\n%s", str_)
|
||||
|
||||
|
||||
def get_determinant_section(protein, conformation, parameters):
|
||||
@@ -291,8 +294,9 @@ def get_folding_profile_section(
|
||||
else:
|
||||
str_ += "The pH of optimum stability is {0:>4.1f}".format(ph_opt)
|
||||
str_ += (
|
||||
" for which the free energy is {0:>6.1f} kcal/mol at 298K\n".format(
|
||||
dg_opt))
|
||||
" for which the free energy is {0:>6.1f} kcal/mol at "
|
||||
"298K\n".format(dg_opt)
|
||||
)
|
||||
if dg_min is None or dg_max is None:
|
||||
str_ += "Could not determine pH values where the free energy"
|
||||
str_ += " is within 80 % of minimum\n"
|
||||
@@ -332,7 +336,10 @@ def get_charge_profile_section(protein, conformation='AVR', _=None):
|
||||
if pi_pro is None or pi_mod is None:
|
||||
str_ += "Could not determine the pI\n\n"
|
||||
else:
|
||||
str_ += f"The pI is {pi_pro:>5.2f} (folded) and {pi_mod:>5.2f} (unfolded)\n"
|
||||
str_ += (
|
||||
f"The pI is {pi_pro:>5.2f} (folded) and {pi_mod:>5.2f} "
|
||||
f"(unfolded)\n"
|
||||
)
|
||||
return str_
|
||||
|
||||
|
||||
@@ -590,6 +597,7 @@ def write_mol2_for_atoms(atoms, filename):
|
||||
out.write(substructure_section)
|
||||
out.close()
|
||||
|
||||
|
||||
def write_propka(molecular_container, filename):
|
||||
"""Write PROPKA input file for molecular container.
|
||||
|
||||
|
||||
@@ -2,13 +2,18 @@
|
||||
Configuration file parameters
|
||||
=============================
|
||||
|
||||
Holds parameters and settings that can be set in :file:`propka.cfg`. The file format consists of lines of ``keyword value [value ...]``, blank lines, and comment lines (introduced with ``#``).
|
||||
Holds parameters and settings that can be set in :file:`propka.cfg`. The file
|
||||
format consists of lines of ``keyword value [value ...]``, blank lines, and
|
||||
comment lines (introduced with ``#``).
|
||||
|
||||
The module attributes below list the names and types of all key words
|
||||
in configuration file.
|
||||
|
||||
"""
|
||||
from propka.lib import info, warning
|
||||
import logging
|
||||
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
#: matrices
|
||||
@@ -126,7 +131,7 @@ class Parameters:
|
||||
"""
|
||||
dict_ = getattr(self, words[0])
|
||||
key = words[1]
|
||||
if not key in dict_:
|
||||
if key not in dict_:
|
||||
dict_[key] = []
|
||||
for value in words[2:]:
|
||||
if isinstance(value, list):
|
||||
@@ -204,12 +209,12 @@ class Parameters:
|
||||
|
||||
def print_interaction_parameters(self):
|
||||
"""Print interaction parameters."""
|
||||
info('--------------- Model pKa values ----------------------')
|
||||
_LOGGER.info('--------------- Model pKa values ----------------------')
|
||||
for k in self.model_pkas:
|
||||
info('{0:>3s} {1:8.2f}'.format(k, self.model_pkas[k]))
|
||||
_LOGGER.info('{0:>3s} {1:8.2f}'.format(k, self.model_pkas[k]))
|
||||
|
||||
info('')
|
||||
info('--------------- Interactions --------------------------')
|
||||
_LOGGER.info('')
|
||||
_LOGGER.info('--------------- Interactions --------------------------')
|
||||
agroups = [
|
||||
'COO', 'HIS', 'CYS', 'TYR', 'SER', 'N+', 'LYS', 'AMD', 'ARG',
|
||||
'TRP', 'ROH', 'CG', 'C2N', 'N30', 'N31', 'N32', 'N33', 'NAR',
|
||||
@@ -234,7 +239,9 @@ class Parameters:
|
||||
map_interaction = ''
|
||||
if group2 in map_:
|
||||
for val in map_[group2]:
|
||||
fmt = "|{grp1:>3s} {grp2:>3s} {mat:1s} {val1:4} {val2:4}"
|
||||
fmt = (
|
||||
"|{grp1:>3s} {grp2:>3s} {mat:1s} {val1:4} {val2:4}"
|
||||
)
|
||||
map_interaction += fmt.format(
|
||||
group1, val, self.interaction_matrix[group1][val],
|
||||
self.sidechain_cutoffs.get_value(group1, val)[0],
|
||||
@@ -260,18 +267,18 @@ class Parameters:
|
||||
group1, group2)[1]
|
||||
!= 4)):
|
||||
map_interaction += '? '
|
||||
info(interaction, map_interaction)
|
||||
_LOGGER.info("%s %s", interaction, map_interaction)
|
||||
if group1 == group2:
|
||||
break
|
||||
info('-')
|
||||
info('--------------- Exceptions ----------------------------')
|
||||
info('COO-HIS', self.COO_HIS_exception)
|
||||
info('OCO-HIS', self.OCO_HIS_exception)
|
||||
info('CYS-HIS', self.CYS_HIS_exception)
|
||||
info('CYS-CYS', self.CYS_CYS_exception)
|
||||
_LOGGER.info('-')
|
||||
_LOGGER.info('--------------- Exceptions ----------------------------')
|
||||
_LOGGER.info('COO-HIS %s', self.COO_HIS_exception)
|
||||
_LOGGER.info('OCO-HIS %s', self.OCO_HIS_exception)
|
||||
_LOGGER.info('CYS-HIS %s', self.CYS_HIS_exception)
|
||||
_LOGGER.info('CYS-CYS %s', self.CYS_CYS_exception)
|
||||
|
||||
info('--------------- Mapping -------------------------------')
|
||||
info("""
|
||||
_LOGGER.info('--------------- Mapping -------------------------------')
|
||||
_LOGGER.info("""
|
||||
Titratable:
|
||||
CG ARG
|
||||
C2N ARG
|
||||
@@ -318,14 +325,16 @@ O2
|
||||
"\\midrule",
|
||||
"\\endfirsthead",
|
||||
"",
|
||||
"\\multicolumn{{5}}{{l}}{\\emph{{continued from the previous page}}}\\\\",
|
||||
"\\multicolumn{{5}}{{l}}{\\emph{{continued from the previous "
|
||||
"page}}}\\\\",
|
||||
"\\toprule",
|
||||
"Group1 & Group2 & Interaction & c1 &c2 \\\\",
|
||||
"\\midrule",
|
||||
"\\endhead",
|
||||
"",
|
||||
"\\midrule",
|
||||
"\\multicolumn{{5}}{{r}}{\\emph{{continued on the next page}}}\\\\",
|
||||
"\\multicolumn{{5}}{{r}}{\\emph{{continued on the next "
|
||||
"page}}}\\\\",
|
||||
"\\endfoot",
|
||||
"",
|
||||
"\\bottomrule",
|
||||
@@ -350,11 +359,12 @@ O2
|
||||
if group1 == group2:
|
||||
break
|
||||
str_ += ' \\end{{longtable}}\n'
|
||||
info(str_)
|
||||
_LOGGER.info(str_)
|
||||
|
||||
def print_interactions_latex(self):
|
||||
"""Print interactions in LaTeX."""
|
||||
# TODO - are these the same lists as above? Convert to module constants.
|
||||
# TODO - are these the same lists as above? Convert to module
|
||||
# constants.
|
||||
agroups = ['COO', 'HIS', 'CYS', 'TYR', 'SER', 'N+', 'LYS', 'AMD',
|
||||
'ARG', 'TRP', 'ROH', 'CG', 'C2N', 'N30', 'N31', 'N32',
|
||||
'N33', 'NAR', 'OCO', 'NP1', 'OH', 'O3', 'CL', 'F', 'NAM',
|
||||
@@ -371,14 +381,16 @@ O2
|
||||
"\\midrule",
|
||||
"\\endfirsthead",
|
||||
"",
|
||||
"\\multicolumn{{5}}{{l}}{\\emph{{continued from the previous page}}}\\\\",
|
||||
"\\multicolumn{{5}}{{l}}{\\emph{{continued from the previous "
|
||||
"page}}}\\\\",
|
||||
"\\toprule",
|
||||
"Group1 & Group2 & Interaction & c1 &c2 \\\\",
|
||||
"\\midrule",
|
||||
"\\endhead",
|
||||
"",
|
||||
"\\midrule",
|
||||
"\\multicolumn{{5}}{{r}}{\\emph{{continued on the next page}}}\\\\",
|
||||
"\\multicolumn{{5}}{{r}}{\\emph{{continued on the next "
|
||||
"page}}}\\\\",
|
||||
"\\endfoot",
|
||||
"",
|
||||
"\\bottomrule",
|
||||
@@ -388,7 +400,10 @@ O2
|
||||
str_ = "\n".join(lines)
|
||||
for group1 in agroups:
|
||||
for group2 in agroups:
|
||||
fmt = '{g1:>3s} & {g2:>3s} & {mat:1s} & {val1:>4s} & {val2:>4s}\\\\ \n'
|
||||
fmt = (
|
||||
'{g1:>3s} & {g2:>3s} & {mat:1s} & {val1:>4s} & '
|
||||
'{val2:>4s}\\\\ \n'
|
||||
)
|
||||
str_ += fmt.format(
|
||||
group1, group2, self.interaction_matrix[group1][group2],
|
||||
str(self.sidechain_cutoffs.get_value(group1, group2)[0]),
|
||||
@@ -396,7 +411,7 @@ O2
|
||||
if group1 == group2:
|
||||
break
|
||||
str_ += ' \\end{{longtable}}\n'
|
||||
info(str_)
|
||||
_LOGGER.info(str_)
|
||||
|
||||
|
||||
class InteractionMatrix:
|
||||
@@ -421,7 +436,7 @@ class InteractionMatrix:
|
||||
"""
|
||||
new_group = words[0]
|
||||
self.ordered_keys.append(new_group)
|
||||
if not new_group in self.dictionary.keys():
|
||||
if new_group not in self.dictionary.keys():
|
||||
self.dictionary[new_group] = {}
|
||||
for i, group in enumerate(self.ordered_keys):
|
||||
if len(words) > i+1:
|
||||
@@ -524,8 +539,8 @@ class PairwiseMatrix:
|
||||
str_ = (
|
||||
'Parameter value for {0:s}, {1:s} defined more '
|
||||
'than once'.format(key1, key2))
|
||||
warning(str_)
|
||||
if not key1 in self.dictionary:
|
||||
_LOGGER.warning(str_)
|
||||
if key1 not in self.dictionary:
|
||||
self.dictionary[key1] = {}
|
||||
self.dictionary[key1][key2] = value
|
||||
|
||||
|
||||
@@ -7,11 +7,14 @@ The :class:`Protonate` processes a
|
||||
protons.
|
||||
|
||||
"""
|
||||
import logging
|
||||
import math
|
||||
import propka.bonds
|
||||
import propka.atom
|
||||
from propka.vector_algebra import rotate_vector_around_an_axis, Vector
|
||||
from propka.lib import warning, debug
|
||||
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class Protonate:
|
||||
@@ -49,7 +52,7 @@ class Protonate:
|
||||
Args:
|
||||
molecules: molecular containers
|
||||
"""
|
||||
debug('----- Protonation started -----')
|
||||
_LOGGER.debug('----- Protonation started -----')
|
||||
# Remove all currently present hydrogen atoms
|
||||
self.remove_all_hydrogen_atoms(molecules)
|
||||
# protonate all atoms
|
||||
@@ -81,11 +84,11 @@ class Protonate:
|
||||
if atom.type == 'atom':
|
||||
key = '{0:3s}-{1:s}'.format(atom.res_name, atom.name)
|
||||
if atom.terminal:
|
||||
debug(atom.terminal)
|
||||
_LOGGER.debug("%s", atom.terminal)
|
||||
key = atom.terminal
|
||||
if key in self.standard_charges:
|
||||
atom.charge = self.standard_charges[key]
|
||||
debug('Charge', atom, atom.charge)
|
||||
_LOGGER.debug('Charge %s %s', atom, atom.charge)
|
||||
atom.charge_set = True
|
||||
# atom is a ligand atom
|
||||
elif atom.type == 'hetatm':
|
||||
@@ -130,21 +133,25 @@ class Protonate:
|
||||
Args:
|
||||
atom: atom for calculation
|
||||
"""
|
||||
debug('*'*10)
|
||||
debug('Setting number of protons to add for', atom)
|
||||
_LOGGER.debug('*'*10)
|
||||
_LOGGER.debug('Setting number of protons to add for %s', atom)
|
||||
atom.number_of_protons_to_add = 8
|
||||
debug(" 8")
|
||||
_LOGGER.debug(" 8")
|
||||
atom.number_of_protons_to_add -= self.valence_electrons[atom.element]
|
||||
debug('Valence electrons: {0:>4d}'.format(
|
||||
_LOGGER.debug('Valence electrons: {0:>4d}'.format(
|
||||
-self.valence_electrons[atom.element]))
|
||||
atom.number_of_protons_to_add -= len(atom.bonded_atoms)
|
||||
debug('Number of bonds: {0:>4d}'.format(-len(atom.bonded_atoms)))
|
||||
_LOGGER.debug(
|
||||
'Number of bonds: {0:>4d}'.format(-len(atom.bonded_atoms))
|
||||
)
|
||||
atom.number_of_protons_to_add -= atom.num_pi_elec_2_3_bonds
|
||||
debug('Pi electrons: {0:>4d}'.format(-atom.num_pi_elec_2_3_bonds))
|
||||
_LOGGER.debug(
|
||||
'Pi electrons: {0:>4d}'.format(-atom.num_pi_elec_2_3_bonds)
|
||||
)
|
||||
atom.number_of_protons_to_add += int(atom.charge)
|
||||
debug('Charge: {0:>4.1f}'.format(atom.charge))
|
||||
debug('-'*10)
|
||||
debug(atom.number_of_protons_to_add)
|
||||
_LOGGER.debug('Charge: {0:>4.1f}'.format(atom.charge))
|
||||
_LOGGER.debug('-'*10)
|
||||
_LOGGER.debug(atom.number_of_protons_to_add)
|
||||
|
||||
def set_steric_number_and_lone_pairs(self, atom):
|
||||
"""Set steric number and lone pairs for atom.
|
||||
@@ -155,39 +162,41 @@ class Protonate:
|
||||
# If we already did this, there is no reason to do it again
|
||||
if atom.steric_num_lone_pairs_set:
|
||||
return
|
||||
debug('='*10)
|
||||
debug('Setting steric number and lone pairs for', atom)
|
||||
_LOGGER.debug('='*10)
|
||||
_LOGGER.debug('Setting steric number and lone pairs for %s', atom)
|
||||
atom.steric_number = 0
|
||||
debug('{0:>65s}: {1:>4d}'.format(
|
||||
_LOGGER.debug('{0:>65s}: {1:>4d}'.format(
|
||||
'Valence electrons', self.valence_electrons[atom.element]))
|
||||
atom.steric_number += self.valence_electrons[atom.element]
|
||||
debug('{0:>65s}: {1:>4d}'.format(
|
||||
_LOGGER.debug('{0:>65s}: {1:>4d}'.format(
|
||||
'Number of bonds', len(atom.bonded_atoms)))
|
||||
atom.steric_number += len(atom.bonded_atoms)
|
||||
debug('{0:>65s}: {1:>4d}'.format(
|
||||
_LOGGER.debug('{0:>65s}: {1:>4d}'.format(
|
||||
'Number of hydrogen atoms to add', atom.number_of_protons_to_add))
|
||||
atom.steric_number += atom.number_of_protons_to_add
|
||||
debug('{0:>65s}: {1:>4d}'.format(
|
||||
_LOGGER.debug('{0:>65s}: {1:>4d}'.format(
|
||||
'Number of pi-electrons in double and triple bonds(-)',
|
||||
atom.num_pi_elec_2_3_bonds))
|
||||
atom.steric_number -= atom.num_pi_elec_2_3_bonds
|
||||
debug('{0:>65s}: {1:>4d}'.format(
|
||||
_LOGGER.debug('{0:>65s}: {1:>4d}'.format(
|
||||
'Number of pi-electrons in conjugated double and triple bonds(-)',
|
||||
atom.num_pi_elec_conj_2_3_bonds))
|
||||
atom.steric_number -= atom.num_pi_elec_conj_2_3_bonds
|
||||
debug('{0:>65s}: {1:>4d}'.format(
|
||||
_LOGGER.debug('{0:>65s}: {1:>4d}'.format(
|
||||
'Number of donated co-ordinated bonds', 0))
|
||||
atom.steric_number += 0
|
||||
debug('{0:>65s}: {1:>4.1f}'.format(
|
||||
_LOGGER.debug('{0:>65s}: {1:>4.1f}'.format(
|
||||
'Charge(-)', atom.charge))
|
||||
atom.steric_number -= atom.charge
|
||||
atom.steric_number = math.floor(atom.steric_number/2.0)
|
||||
atom.number_of_lone_pairs = (
|
||||
atom.steric_number-len(atom.bonded_atoms)-atom.number_of_protons_to_add)
|
||||
debug('-'*70)
|
||||
debug('{0:>65s}: {1:>4d}'.format(
|
||||
atom.steric_number - len(atom.bonded_atoms)
|
||||
- atom.number_of_protons_to_add
|
||||
)
|
||||
_LOGGER.debug('-'*70)
|
||||
_LOGGER.debug('{0:>65s}: {1:>4d}'.format(
|
||||
'Steric number', atom.steric_number))
|
||||
debug('{0:>65s}: {1:>4d}'.format(
|
||||
_LOGGER.debug('{0:>65s}: {1:>4d}'.format(
|
||||
'Number of lone pairs', atom.number_of_lone_pairs))
|
||||
atom.steric_num_lone_pairs_set = True
|
||||
|
||||
@@ -198,12 +207,14 @@ class Protonate:
|
||||
atom: atom for calculation
|
||||
"""
|
||||
# decide which method to use
|
||||
debug('PROTONATING', atom)
|
||||
_LOGGER.debug('PROTONATING %s', atom)
|
||||
if atom.steric_number in list(self.protonation_methods.keys()):
|
||||
self.protonation_methods[atom.steric_number](atom)
|
||||
else:
|
||||
warning('Do not have a method for protonating', atom,
|
||||
'(steric number: {0:d})'.format(atom.steric_number))
|
||||
_LOGGER.warning(
|
||||
'Do not have a method for protonating %s %s', atom,
|
||||
'(steric number: {0:d})'.format(atom.steric_number)
|
||||
)
|
||||
|
||||
def trigonal(self, atom):
|
||||
"""Add hydrogens in trigonal geometry.
|
||||
@@ -211,7 +222,9 @@ class Protonate:
|
||||
Args:
|
||||
atom: atom to protonate
|
||||
"""
|
||||
debug('TRIGONAL - {0:d} bonded atoms'.format(len(atom.bonded_atoms)))
|
||||
_LOGGER.debug(
|
||||
'TRIGONAL - {0:d} bonded atoms'.format(len(atom.bonded_atoms))
|
||||
)
|
||||
rot_angle = math.radians(120.0)
|
||||
cvec = Vector(atom1=atom)
|
||||
# 0 bonds
|
||||
@@ -269,7 +282,7 @@ class Protonate:
|
||||
Args:
|
||||
atom: atom to protonate.
|
||||
"""
|
||||
debug(
|
||||
_LOGGER.debug(
|
||||
'TETRAHEDRAL - {0:d} bonded atoms'.format(len(atom.bonded_atoms)))
|
||||
# TODO - might be good to move tetrahedral angle to constant
|
||||
rot_angle = math.radians(109.5)
|
||||
@@ -320,8 +333,9 @@ class Protonate:
|
||||
res_name=atom.res_name,
|
||||
chain_id=atom.chain_id,
|
||||
res_num=atom.res_num,
|
||||
x=round(position.x, 3), # round of to three decimal points to
|
||||
# avoid round-off differences in input file
|
||||
x=round(position.x, 3), # round of to three decimal points to
|
||||
# avoid round-off differences in input
|
||||
# file
|
||||
y=round(position.y, 3),
|
||||
z=round(position.z, 3),
|
||||
occ=None,
|
||||
@@ -350,7 +364,7 @@ class Protonate:
|
||||
proton.residue_label = "{0:<3s}{1:>4d}{2:>2s}".format(
|
||||
proton.name, proton.res_num, proton.chain_id)
|
||||
i += 1
|
||||
debug('added', new_h, 'to', atom)
|
||||
_LOGGER.debug('added %s %s %s', new_h, 'to', atom)
|
||||
|
||||
def set_bond_distance(self, bvec, element):
|
||||
"""Set bond distance between atom and element.
|
||||
@@ -368,6 +382,6 @@ class Protonate:
|
||||
str_ = (
|
||||
'Bond length for {0:s} not found, using the standard value '
|
||||
'of {1:f}'.format(element, dist))
|
||||
warning(str_)
|
||||
_LOGGER.warning(str_)
|
||||
bvec = bvec.rescale(dist)
|
||||
return bvec
|
||||
|
||||
@@ -11,18 +11,23 @@ function. If similar functionality is desired from a Python script
|
||||
|
||||
"""
|
||||
import logging
|
||||
import sys
|
||||
from propka.lib import loadOptions
|
||||
from propka.input import read_parameter_file, read_molecule_file
|
||||
from propka.parameters import Parameters
|
||||
from propka.molecular_container import MolecularContainer
|
||||
|
||||
|
||||
_LOGGER = logging.getLogger("PROPKA")
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def main(optargs=None):
|
||||
"""Read in structure files, calculate pKa values, and print pKa files."""
|
||||
# loading options, flags and arguments
|
||||
logger = logging.getLogger("")
|
||||
stdout_handler = logging.StreamHandler(sys.stdout)
|
||||
stdout_handler.setFormatter(logging.Formatter("%(message)s"))
|
||||
logger.addHandler(stdout_handler)
|
||||
optargs = optargs if optargs is not None else []
|
||||
options = loadOptions(*optargs)
|
||||
pdbfiles = options.filenames
|
||||
|
||||
@@ -4,8 +4,12 @@ Vector calculations
|
||||
|
||||
Vector algebra for PROPKA.
|
||||
"""
|
||||
import logging
|
||||
import math
|
||||
from propka.lib import info, get_sorted_configurations
|
||||
from propka.lib import get_sorted_configurations
|
||||
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class Vector:
|
||||
@@ -63,7 +67,7 @@ class Vector:
|
||||
elif type(other) in [int, float]:
|
||||
return Vector(self.x * other, self.y * other, self.z * other)
|
||||
else:
|
||||
info('{0:s} not supported'.format(type(other)))
|
||||
_LOGGER.info('{0:s} not supported'.format(type(other)))
|
||||
raise TypeError
|
||||
|
||||
def __rmul__(self, other):
|
||||
|
||||
@@ -6,7 +6,7 @@ Contains version-specific methods and parameters.
|
||||
|
||||
TODO - this module unnecessarily confuses the code. Can we eliminate it?
|
||||
"""
|
||||
from propka.lib import info
|
||||
import logging
|
||||
from propka.hydrogens import setup_bonding_and_protonation, setup_bonding
|
||||
from propka.hydrogens import setup_bonding_and_protonation_30_style
|
||||
from propka.energy import radial_volume_desolvation, calculate_pair_weight
|
||||
@@ -16,6 +16,9 @@ from propka.energy import coulomb_energy, check_exceptions
|
||||
from propka.energy import backbone_reorganization
|
||||
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class Version:
|
||||
"""Store version-specific methods and parameters."""
|
||||
def __init__(self, parameters):
|
||||
@@ -140,12 +143,18 @@ class VersionA(Version):
|
||||
[v, [c1, c3]] TODO - figure out what this is
|
||||
"""
|
||||
if backbone_atom.group_type == 'BBC':
|
||||
if atom.group_type in self.parameters.backbone_CO_hydrogen_bond.keys():
|
||||
if (
|
||||
atom.group_type in
|
||||
self.parameters.backbone_CO_hydrogen_bond.keys()
|
||||
):
|
||||
[v, c1, c2] = self.parameters.backbone_CO_hydrogen_bond[
|
||||
atom.group_type]
|
||||
return [v, [c1, c2]]
|
||||
if backbone_atom.group_type == 'BBN':
|
||||
if atom.group_type in self.parameters.backbone_NH_hydrogen_bond.keys():
|
||||
if (
|
||||
atom.group_type in
|
||||
self.parameters.backbone_NH_hydrogen_bond.keys()
|
||||
):
|
||||
[v, c1, c2] = self.parameters.backbone_NH_hydrogen_bond[
|
||||
atom.group_type]
|
||||
return [v, [c1, c2]]
|
||||
@@ -159,7 +168,7 @@ class SimpleHB(VersionA):
|
||||
"""Initialize object with parameters."""
|
||||
# set the calculation rutines used in this version
|
||||
super().__init__(parameters)
|
||||
info('Using simple hb model')
|
||||
_LOGGER.info('Using simple hb model')
|
||||
|
||||
def get_hydrogen_bond_parameters(self, atom1, atom2):
|
||||
"""Get hydrogen bond parameters for two atoms.
|
||||
@@ -193,7 +202,7 @@ class ElementBasedLigandInteractions(VersionA):
|
||||
"""Initialize object with parameters."""
|
||||
# set the calculation rutines used in this version
|
||||
super().__init__(parameters)
|
||||
info('Using detailed SC model!')
|
||||
_LOGGER.info('Using detailed SC model!')
|
||||
return
|
||||
|
||||
def get_hydrogen_bond_parameters(self, atom1, atom2):
|
||||
@@ -259,8 +268,9 @@ class ElementBasedLigandInteractions(VersionA):
|
||||
res = self.parameters.hydrogen_bonds.get_value(
|
||||
elements[0], elements[1])
|
||||
if not res:
|
||||
info(
|
||||
'Could not determine backbone interaction parameters for:',
|
||||
_LOGGER.info(
|
||||
'Could not determine backbone interaction parameters '
|
||||
'for: %s %s',
|
||||
backbone_atom, atom)
|
||||
return None
|
||||
return None
|
||||
|
||||
Reference in New Issue
Block a user