239 lines
9.4 KiB
Python
239 lines
9.4 KiB
Python
import math, time
|
|
|
|
import Source.iterative, Source.lib, Source.vector_algebra
|
|
import Source.calculations
|
|
from Source.determinant import Determinant
|
|
|
|
|
|
def setDeterminants(propka_groups, version=None, options=None):
|
|
"""
|
|
adding side-chain and coulomb determinants/perturbations to all residues - note, backbone determinants are set separately
|
|
"""
|
|
|
|
iterative_interactions = []
|
|
# --- NonIterative section ---#
|
|
for group1 in propka_groups:
|
|
for group2 in propka_groups:
|
|
if group1 == group2:
|
|
break
|
|
# do not calculate interactions for coupled groups
|
|
if group2 in group1.covalently_coupled_groups:
|
|
break
|
|
|
|
distance = Source.calculations.distance(group1, group2)
|
|
|
|
if distance < version.parameters.coulomb_cutoff2:
|
|
interaction_type = version.parameters.interaction_matrix.get_value(group1.type,group2.type)
|
|
if interaction_type == 'I':
|
|
Source.iterative.addtoDeterminantList(group1, group2, distance, iterative_interactions, version=version)
|
|
elif interaction_type == 'N':
|
|
addDeterminants(group1, group2, distance, version)
|
|
|
|
|
|
# --- Iterative section ---#
|
|
Source.iterative.addDeterminants(iterative_interactions, version, options=options)
|
|
|
|
|
|
def addDeterminants(group1, group2, distance, version):
|
|
"""
|
|
adding determinants/perturbations, distance(R1, R2) < coulomb_cutoff always
|
|
"""
|
|
|
|
# side-chain determinant
|
|
addSidechainDeterminants(group1, group2, version)
|
|
|
|
# Coulomb determinant
|
|
addCoulombDeterminants(group1, group2, distance, version)
|
|
|
|
return
|
|
|
|
def addSidechainDeterminants(group1, group2, version=None):
|
|
"""
|
|
adding side-chain determinants/perturbations
|
|
Note, resNumb1 > resNumb2
|
|
"""
|
|
|
|
hbond_interaction = version.hydrogen_bond_interaction(group1, group2)
|
|
|
|
if hbond_interaction:
|
|
|
|
if group1.charge == group2.charge:
|
|
# acid pair or base pair
|
|
if group1.model_pka < group2.model_pka:
|
|
newDeterminant1 = Determinant(group2, -hbond_interaction)
|
|
newDeterminant2 = Determinant(group1, hbond_interaction)
|
|
else:
|
|
newDeterminant1 = Determinant(group2, hbond_interaction)
|
|
newDeterminant2 = Determinant(group1, -hbond_interaction)
|
|
else:
|
|
newDeterminant1 = Determinant(group2, hbond_interaction*group1.charge)
|
|
newDeterminant2 = Determinant(group1, hbond_interaction*group2.charge)
|
|
|
|
group1.determinants['sidechain'].append(newDeterminant1)
|
|
group2.determinants['sidechain'].append(newDeterminant2)
|
|
|
|
return
|
|
|
|
def addCoulombDeterminants(group1, group2, distance, version):
|
|
"""
|
|
adding NonIterative Coulomb determinants/perturbations
|
|
"""
|
|
|
|
coulomb_interaction = version.electrostatic_interaction(group1, group2, distance)
|
|
|
|
if coulomb_interaction:
|
|
Q1 = group1.charge
|
|
Q2 = group2.charge
|
|
|
|
# assigning the Coulombic interaction
|
|
if Q1 < 0.0 and Q2 < 0.0:
|
|
""" both are acids """
|
|
addCoulombAcidPair(group1, group2, coulomb_interaction)
|
|
elif Q1 > 0.0 and Q2 > 0.0:
|
|
""" both are bases """
|
|
addCoulombBasePair(group1, group2, coulomb_interaction)
|
|
else:
|
|
""" one of each """
|
|
addCoulombIonPair(group1, group2, coulomb_interaction)
|
|
|
|
return
|
|
|
|
|
|
def addCoulombAcidPair(object1, object2, value):
|
|
"""
|
|
Adding the Coulomb interaction (an acid pair):
|
|
the higher pKa is raised
|
|
"""
|
|
|
|
if object1.model_pka > object2.model_pka:
|
|
newDeterminant = Determinant(object2, value)
|
|
object1.determinants['coulomb'].append(newDeterminant)
|
|
else:
|
|
newDeterminant = Determinant(object1, value)
|
|
object2.determinants['coulomb'].append(newDeterminant)
|
|
|
|
|
|
def addCoulombBasePair(object1, object2, value):
|
|
"""
|
|
Adding the Coulomb interaction (a base pair):
|
|
the lower pKa is lowered
|
|
"""
|
|
if object1.model_pka < object2.model_pka:
|
|
newDeterminant = Determinant(object2, -value)
|
|
object1.determinants['coulomb'].append(newDeterminant)
|
|
else:
|
|
newDeterminant = Determinant(object1, -value)
|
|
object2.determinants['coulomb'].append(newDeterminant)
|
|
|
|
|
|
def addCoulombIonPair(object1, object2, value):
|
|
"""
|
|
Adding the Coulomb interaction (an acid-base pair):
|
|
the pKa of the acid is lowered & the pKa of the base is raised
|
|
"""
|
|
|
|
# residue1
|
|
Q1 = object1.charge
|
|
newDeterminant = Determinant(object2, Q1*value)
|
|
object1.determinants['coulomb'].append(newDeterminant)
|
|
|
|
# residue2
|
|
Q2 = object2.charge
|
|
newDeterminant = Determinant(object1, Q2*value)
|
|
object2.determinants['coulomb'].append(newDeterminant)
|
|
|
|
|
|
|
|
|
|
def setIonDeterminants(conformation_container, version):
|
|
"""
|
|
adding ion determinants/perturbations
|
|
"""
|
|
for titratable_group in conformation_container.get_titratable_groups():
|
|
for ion_group in conformation_container.get_ions():
|
|
squared_distance = Source.calculations.squared_distance(titratable_group, ion_group)
|
|
if squared_distance < version.parameters.coulomb_cutoff2_squared:
|
|
weight = version.calculatePairWeight(titratable_group.Nmass, ion_group.Nmass)
|
|
# the pKa of both acids and bases are shifted up by negative ions (and vice versa)
|
|
value = (-ion_group.charge) * version.calculateCoulombEnergy(math.sqrt(squared_distance), weight)
|
|
newDeterminant = Determinant(ion_group, value)
|
|
titratable_group.determinants['coulomb'].append(newDeterminant)
|
|
|
|
return
|
|
|
|
def setBackBoneDeterminants(titratable_groups, backbone_groups, version):
|
|
|
|
for titratable_group in titratable_groups:
|
|
# find out which backbone groups this titratable is interacting with
|
|
for backbone_group in backbone_groups:
|
|
# find the interacting atoms
|
|
backbone_interaction_atoms = backbone_group.get_interaction_atoms(titratable_group)
|
|
titratable_group_interaction_atoms = titratable_group.interaction_atoms_for_acids
|
|
|
|
# find the smallest distance
|
|
[backbone_atom, distance, titratable_atom] = Source.calculations.get_smallest_distance(backbone_interaction_atoms,
|
|
titratable_group_interaction_atoms)
|
|
# get the parameters
|
|
parameters = version.get_backbone_hydrogen_bond_parameters(backbone_atom, titratable_atom)
|
|
if not parameters:
|
|
continue
|
|
[dpKa_max, [cutoff1, cutoff2]] = parameters
|
|
|
|
|
|
if distance < cutoff2:
|
|
# calculate angle factor
|
|
f_angle = 1.0
|
|
# for BBC groups, the hydrogen is on the titratable group
|
|
#
|
|
# Titra.
|
|
# /
|
|
# H
|
|
# .
|
|
# O
|
|
# ||
|
|
# C
|
|
if backbone_group.type == 'BBC':
|
|
if titratable_group.type in version.parameters.angular_dependent_sidechain_interactions:
|
|
if titratable_atom.element == 'H':
|
|
heavy_atom = titratable_atom.bonded_atoms[0]
|
|
hydrogen_atom = titratable_atom
|
|
[d1, f_angle, d2] = Source.calculations.AngleFactorX(atom1=heavy_atom,
|
|
atom2=hydrogen_atom,
|
|
atom3=backbone_atom)
|
|
else:
|
|
# Either the structure is corrupt (no hydrogen), or the heavy atom is closer to
|
|
# the titratable atom than the hydrogen. In either case we set the angle factor
|
|
# to 0
|
|
f_angle = 0.0
|
|
|
|
# for BBN groups, the hydrogen is on the backbone group
|
|
#
|
|
# Titra.
|
|
# .
|
|
# H
|
|
# |
|
|
# N
|
|
# / \
|
|
if backbone_group.type == 'BBN':
|
|
if backbone_atom.element == 'H':
|
|
backbone_N = backbone_atom.bonded_atoms[0]
|
|
backbone_H = backbone_atom
|
|
[d1, f_angle, d2] = Source.calculations.AngleFactorX(atom1=titratable_atom,
|
|
atom2=backbone_H,
|
|
atom3=backbone_N)
|
|
else:
|
|
# Either the structure is corrupt (no hydrogen), or the heavy atom is closer to
|
|
# the titratable atom than the hydrogen. In either case we set the angle factor
|
|
# to 0
|
|
f_angle = 0.0
|
|
|
|
|
|
if f_angle > 0.001:
|
|
value = titratable_group.charge * Source.calculations.HydrogenBondEnergy(distance, dpKa_max, [cutoff1,cutoff2], f_angle)
|
|
|
|
newDeterminant = Determinant(backbone_group, value)
|
|
titratable_group.determinants['backbone'].append(newDeterminant)
|
|
|
|
|
|
return
|