diff --git a/propka/calculations.py b/propka/calculations.py index 144755e..711cd60 100644 --- a/propka/calculations.py +++ b/propka/calculations.py @@ -647,7 +647,7 @@ def hydrogen_bond_interaction(group1, group2, version): # Do nothing, value should have been assigned. pass else: - value = version.calculateSideChainEnergy(dist, dpka_max, cutoff, weight, + value = version.calculate_side_chain_energy(dist, dpka_max, cutoff, weight, f_angle) return value diff --git a/propka/conformation_container.py b/propka/conformation_container.py index 107a0a8..bc0698c 100644 --- a/propka/conformation_container.py +++ b/propka/conformation_container.py @@ -195,7 +195,7 @@ class ConformationContainer: # setting ion determinants set_ion_determinants(self, version) # calculating the back-bone reorganization/desolvation term - version.calculatebackbone_reorganization(self) + version.calculate_backbone_reorganization(self) # setting remaining non-iterative and iterative side-chain & Coulomb # interaction determinants set_determinants(self.get_sidechain_groups(), version=version, diff --git a/propka/molecular_container.py b/propka/molecular_container.py index 76768c0..3ef1478 100644 --- a/propka/molecular_container.py +++ b/propka/molecular_container.py @@ -48,7 +48,8 @@ class Molecular_container: try: version_class = getattr(propka.version, parameters.version) self.version = version_class(parameters) - except: + except AttributeError as err: + print(err) errstr = 'Error: Version %s does not exist' % parameters.version raise Exception(errstr) # read the input file diff --git a/propka/propka.cfg b/propka/propka.cfg index 58b1aec..c78ea43 100644 --- a/propka/propka.cfg +++ b/propka/propka.cfg @@ -1,6 +1,6 @@ # PropKa configuration file -version version_A +version VersionA # Model pKa values model_pkas C- 3.20 diff --git a/propka/version.py b/propka/version.py index 86c4268..b994cbc 100644 --- a/propka/version.py +++ b/propka/version.py @@ -1,216 +1,281 @@ -from __future__ import division -from __future__ import print_function -import math -import sys, os +"""Contains version-specific methods and parameters. -import propka.lib as lib -from propka.lib import info, warning -import propka.calculations as calculations -import propka.parameters +TODO - this module unnecessarily confuses the code. Can we eliminate it? +""" +from propka.lib import info +import propka.calculations as calcs -class version: - def __init__(self,parameters): +class Version: + """Store version-specific methods and parameters.""" + def __init__(self, parameters): self.parameters = parameters - return + self.desolvation_model = self.empty_function + self.weight_pair_method = self.empty_function + self.hydrogen_bond_interaction_model = self.empty_function + self.sidechain_interaction_model = self.empty_function + self.electrostatic_interaction_model = self.empty_function + self.coulomb_interaction_model = self.empty_function + self.check_coulomb_pair_method = self.empty_function + self.backbone_reorganisation_method = self.empty_function + self.exception_check_method = self.empty_function + self.molecular_preparation_method = self.empty_function + self.prepare_bonds = self.empty_function + + @staticmethod + def empty_function(*args): + """Placeholder function so we don't use uninitialized variables. + + Args: + args: whatever arguments would have been passed to the function + Raises: + NotImplementedError + """ + err = "Called an empty Version function with args %s" % args + raise NotImplementedError(err) - # desolvation def calculate_desolvation(self, group): + """Calculate desolvation energy using assigned model.""" return self.desolvation_model(self.parameters, group) def calculate_pair_weight(self, num_volume1, num_volume2): + """Calculate pair weight using assigned model.""" return self.weight_pair_method(self.parameters, num_volume1, num_volume2) - # side chains def hydrogen_bond_interaction(self, group1, group2): + """Calculate H-bond energy using assigned model.""" return self.hydrogen_bond_interaction_model(group1, group2, self) - def calculateSideChainEnergy(self, distance, dpka_max, cutoff, weight, f_angle): - return self.sidechain_interaction_model(distance, dpka_max, cutoff, f_angle) # weight is ignored in 3.0 Sep07 + def calculate_side_chain_energy(self, distance, dpka_max, cutoff, _, f_angle): + """Calculate sidechain energy using assigned model.""" + return self.sidechain_interaction_model(distance, dpka_max, cutoff, f_angle) - # coulomb def electrostatic_interaction(self, group1, group2, distance): + """Calculate electrostatic energy using assigned model.""" return self.electrostatic_interaction_model(group1, group2, distance, self) def calculate_coulomb_energy(self, distance, weight): + """Calculate Coulomb energy using assigned model.""" return self.coulomb_interaction_model(distance, weight, self.parameters) def check_coulomb_pair(self, group1, group2, distance): + """Check Coulomb pair using assigned model.""" return self.check_coulomb_pair_method(self.parameters, group1, group2, distance) - # backbone re-organisation - def calculatebackbone_reorganization(self, conformation): + def calculate_backbone_reorganization(self, conformation): + """Calculate backbone reorganization using assigned model.""" return self.backbone_reorganisation_method(self.parameters, conformation) - # exceptions def check_exceptions(self, group1, group2): + """Calculate exceptions using assigned model.""" return self.exception_check_method(self, group1, group2) def setup_bonding_and_protonation(self, molecular_container): + """Setup bonding and protonation using assigned model.""" return self.molecular_preparation_method(self.parameters, molecular_container) def setup_bonding(self, molecular_container): + """Setup bonding using assigned model.""" return self.prepare_bonds(self.parameters, molecular_container) +class VersionA(Version): + """TODO - figure out what this is.""" -class version_A(version): def __init__(self, parameters): + """Initialize object with parameters.""" # set the calculation rutines used in this version - version.__init__(self, parameters) - - # atom naming, bonding, and protonation - self.molecular_preparation_method = propka.calculations.setup_bonding_and_protonation - self.prepare_bonds = propka.calculations.setup_bonding - - - # desolvation related methods - self.desolvation_model = calculations.radial_volume_desolvation - self.weight_pair_method = calculations.calculate_pair_weight - - # side chain methods - self.sidechain_interaction_model = propka.calculations.hydrogen_bond_energy - self.hydrogen_bond_interaction_model = propka.calculations.hydrogen_bond_interaction - - # colomb methods - self.electrostatic_interaction_model = propka.calculations.electrostatic_interaction - self.check_coulomb_pair_method = propka.calculations.check_coulomb_pair - self.coulomb_interaction_model = propka.calculations.coulomb_energy - - #backbone - self.backbone_interaction_model = propka.calculations.hydrogen_bond_energy - self.backbone_reorganisation_method = propka.calculations.backbone_reorganization - - # exception methods - self.exception_check_method = propka.calculations.check_exceptions - return + super().__init__(parameters) + self.molecular_preparation_method = calcs.setup_bonding_and_protonation + self.prepare_bonds = calcs.setup_bonding + self.desolvation_model = calcs.radial_volume_desolvation + self.weight_pair_method = calcs.calculate_pair_weight + self.sidechain_interaction_model = calcs.hydrogen_bond_energy + self.hydrogen_bond_interaction_model = calcs.hydrogen_bond_interaction + self.electrostatic_interaction_model = calcs.electrostatic_interaction + self.check_coulomb_pair_method = calcs.check_coulomb_pair + self.coulomb_interaction_model = calcs.coulomb_energy + self.backbone_interaction_model = calcs.hydrogen_bond_energy + self.backbone_reorganisation_method = calcs.backbone_reorganization + self.exception_check_method = calcs.check_exceptions def get_hydrogen_bond_parameters(self, atom1, atom2): + """Get hydrogen bond parameters for two atoms. + + Args: + atom1: first atom + atom2: second atom + Returns: + [dpka_max, cutoff] + """ dpka_max = self.parameters.sidechain_interaction - cutoff = self.parameters.sidechain_cutoffs.get_value(atom1.group_type, atom2.group_type) + cutoff = self.parameters.sidechain_cutoffs.get_value( + atom1.group_type, atom2.group_type) return [dpka_max, cutoff] def get_backbone_hydrogen_bond_parameters(self, backbone_atom, atom): + """Get hydrogen bond parameters between backbone atom and other atom. + + Args: + backbone_atom: backbone atom + atom: other atom + Returns + [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(): - [v,c1,c2] = self.parameters.backbone_CO_hydrogen_bond[atom.group_type] - return [v,[c1,c2]] - + [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(): - [v,c1,c2] = self.parameters.backbone_NH_hydrogen_bond[atom.group_type] - return [v,[c1,c2]] - + [v, c1, c2] = self.parameters.backbone_NH_hydrogen_bond[ + atom.group_type] + return [v, [c1, c2]] return None +class SimpleHB(VersionA): + """A simple hydrogen bond version.""" - -class simple_hb(version_A): def __init__(self, parameters): + """Initialize object with parameters.""" # set the calculation rutines used in this version - version_A.__init__(self, parameters) + super().__init__(parameters) info('Using simple hb model') - return def get_hydrogen_bond_parameters(self, atom1, atom2): - return self.parameters.hydrogen_bonds.get_value(atom1.element, atom2.element) + """Get hydrogen bond parameters for two atoms. + Args: + atom1: first atom + atom2: second atom + Returns: + [dpka_max, cutoff] + """ + return self.parameters.hydrogen_bonds.get_value( + atom1.element, atom2.element) def get_backbone_hydrogen_bond_parameters(self, backbone_atom, atom): - return self.parameters.hydrogen_bonds.get_value(backbone_atom.element, atom.element) + """Get hydrogen bond parameters between backbone atom and other atom. + + Args: + backbone_atom: backbone atom + atom: other atom + Returns + [v, [c1, c3]] TODO - figure out what this is + """ + return self.parameters.hydrogen_bonds.get_value( + backbone_atom.element, atom.element) +class ElementBasedLigandInteractions(VersionA): + """TODO - figure out what this is.""" - -class element_based_ligand_interactions(version_A): def __init__(self, parameters): + """Initialize object with parameters.""" # set the calculation rutines used in this version - version_A.__init__(self, parameters) + super().__init__(parameters) info('Using detailed SC model!') return def get_hydrogen_bond_parameters(self, atom1, atom2): - if not 'hetatm' in [atom1.type, atom2.type]: - # this is a protein-protein interaction - dpka_max = self.parameters.sidechain_interaction.get_value(atom1.group_type, atom2.group_type) - cutoff = self.parameters.sidechain_cutoffs.get_value(atom1.group_type, atom2.group_type) - return [dpka_max, cutoff] + """Get hydrogen bond parameters for two atoms. + Args: + atom1: first atom + atom2: second atom + Returns: + [dpka_max, cutoff] + """ + if 'hetatm' not in [atom1.type, atom2.type]: + # this is a protein-protein interaction + dpka_max = self.parameters.sidechain_interaction.get_value( + atom1.group_type, atom2.group_type) + cutoff = self.parameters.sidechain_cutoffs.get_value( + atom1.group_type, atom2.group_type) + return [dpka_max, cutoff] # at least one ligand atom is involved in this interaction # make sure that we are using the heavy atoms for finding paramters elements = [] - for a in [atom1, atom2]: - if a.element == 'H': elements.append(a.bonded_atoms[0].element) - else: elements.append(a.element) - - return self.parameters.hydrogen_bonds.get_value(elements[0], elements[1]) - + for atom in [atom1, atom2]: + if atom.element == 'H': + elements.append(atom.bonded_atoms[0].element) + else: + elements.append(atom.element) + return self.parameters.hydrogen_bonds.get_value( + elements[0], elements[1]) def get_backbone_hydrogen_bond_parameters(self, backbone_atom, atom): + """Get hydrogen bond parameters between backbone atom and other atom. + + Args: + backbone_atom: backbone atom + atom: other atom + Returns + [v, [c1, c3]] TODO - figure out what this is + """ if atom.type == 'atom': # this is a backbone-protein interaction - if backbone_atom.group_type == 'BBC' and\ - 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 == 'BBC' + and 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' and\ - 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]] + if (backbone_atom.group_type == 'BBN' + and 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]] else: # this is a backbone-ligand interaction # make sure that we are using the heavy atoms for finding paramters elements = [] - for a in [backbone_atom, atom]: - if a.element == 'H': elements.append(a.bonded_atoms[0].element) - else: elements.append(a.element) - - res = self.parameters.hydrogen_bonds.get_value(elements[0], elements[1]) + for atom2 in [backbone_atom, atom]: + if atom2.element == 'H': + elements.append(atom2.bonded_atoms[0].element) + else: + elements.append(atom2.element) + res = self.parameters.hydrogen_bonds.get_value( + elements[0], elements[1]) if not res: info('Could not determine backbone interaction parameters for:', backbone_atom, atom) - - return - + return None return None +class Propka30(Version): + """Version class for PROPKA 3.0.""" -class propka30(version): def __init__(self, parameters): - # set the calculation rutines used in this version - version.__init__(self, parameters) - - # atom naming, bonding, and protonation - self.molecular_preparation_method = propka.calculations.setup_bonding_and_protonation_30_style - - # desolvation related methods - self.desolvation_model = calculations.radial_volume_desolvation - self.weight_pair_method = calculations.calculate_pair_weight - - # side chain methods - self.sidechain_interaction_model = propka.calculations.hydrogen_bond_energy - - # colomb methods - self.check_coulomb_pair_method = propka.calculations.check_coulomb_pair - self.coulomb_interaction_model = propka.calculations.coulomb_energy - - #backbone - self.backbone_reorganisation_method = propka.calculations.backbone_reorganization - - # exception methods - self.exception_check_method = propka.calculations.check_exceptions - - - return + """Initialize object with parameters.""" + # set the calculation routines used in this version + super().__init__(parameters) + self.molecular_preparation_method = ( + calcs.setup_bonding_and_protonation_30_style) + self.desolvation_model = calcs.radial_volume_desolvation + self.weight_pair_method = calcs.calculate_pair_weight + self.sidechain_interaction_model = calcs.hydrogen_bond_energy + self.check_coulomb_pair_method = calcs.check_coulomb_pair + self.coulomb_interaction_model = calcs.coulomb_energy + self.backbone_reorganisation_method = calcs.backbone_reorganization + self.exception_check_method = calcs.check_exceptions def get_hydrogen_bond_parameters(self, atom1, atom2): - dpka_max = self.parameters.sidechain_interaction.get_value(atom1.group_type, atom2.group_type) - cutoff = self.parameters.sidechain_cutoffs.get_value(atom1.group_type, atom2.group_type) + """Get hydrogen bond parameters for two atoms. + + Args: + atom1: first atom + atom2: second atom + Returns: + [dpka_max, cutoff] + """ + dpka_max = self.parameters.sidechain_interaction.get_value( + atom1.group_type, atom2.group_type) + cutoff = self.parameters.sidechain_cutoffs.get_value( + atom1.group_type, atom2.group_type) return [dpka_max, cutoff] - - - -