5 Module written by Niklaus Johner (niklaus.johner@a3.epfl.ch) 2012
7 This module is a flexible rewrite of HBPlus, allowing to calculate hbond
8 conservation between different structures or over a trajectory.
9 It uses customizable dictionaries to define donors and acceptors and can
10 account for equivalent HBonds such as involving for example either oxygen atom
13 __all__=(
'HBondDonor',
'HBondAcceptor',
'BuildCHARMMHBondDonorAcceptorDict',
'AreHBonded',
'GetHbondDonorAcceptorList',\
14 'GetHbondListFromDonorAcceptorLists',
'GetHbondListFromView',
'GetHbondListFromTraj',
'GetHbondListBetweenViews'\
15 'CalculateHBondScore',
'AnalyzeHBondScore')
25 bb_donors=[[
'N',
'HN']]
26 bb_acceptors=[[
'O',[
'C']]]
41 cz=[[
'NH1',
'HH11'],[
'NH1',
'HH12'],[
'NH2',
'HH21'],[
'NH2',
'HH22']]
43 nz=[[
'NZ',
'HZ1'],[
'NZ',
'HZ2'],[
'NZ',
'HZ3']]
51 od12=[[
'OD1',[
'CG']],[
'OD2',[
'CG']]]
53 oe12=[[
'OE1',[
'CD']],[
'OE2',[
'CD']]]
58 nd2=[[
'ND2',
'HD21'],[
'ND2',
'HD22']]
60 ne2=[[
'NE2',
'HE21'],[
'NE2',
'HE22']]
67 og1_a=[[
'OG1',[
'CB']]]
68 hb_da_dict[
'THR']=
HBondableAtoms(bb_donors+og1_d,bb_acceptors+og1_a)
74 ne2_a=[[
'NE2',[
'CD2',
'CE1']]]
75 hb_da_dict[
'HSD']=
HBondableAtoms(bb_donors+nd1_d,bb_acceptors+ne2_a)
77 nd1_a=[[
'ND1',[
'CG',
'CE1']]]
78 hb_da_dict[
'HSE']=
HBondableAtoms(bb_donors+ne2_d,bb_acceptors+nd1_a)
79 hb_da_dict[
'HSP']=
HBondableAtoms(bb_donors+nd1_d+ne2_d,bb_acceptors)
81 oe12=[[
'OE1',[
'CD']],[
'OE2',[
'CD']]]
84 od12=[[
'OD1',[
'CG']],[
'OD2',[
'CG']]]
91 donor_swap_dict[
'ARG']=[[[
'NH1',
'HH11'],[
'NH1',
'HH12'],[
'NH2',
'HH21'],[
'NH2',
'HH22']]]
92 donor_swap_dict[
'ASN']=[[[
'ND2',
'HD21'],[
'ND2',
'HD22']]]
93 donor_swap_dict[
'GLN']=[[[
'NE2',
'HE21'],[
'NE2',
'HE22']]]
94 donor_swap_dict[
'LYS']=[[[
'NZ',
'HZ1'],[
'NZ',
'HZ2'],[
'NZ',
'HZ3']]]
95 return donor_swap_dict
99 acceptor_swap_dict[
'ASP']=[[[
'OD1',[
'CG']],[
'OD2',[
'CG']]]]
100 acceptor_swap_dict[
'GLU']=[[[
'OE1',[
'CD']],[
'OE2',[
'CD']]]]
101 return acceptor_swap_dict
104 if not donor.heavy_atom.residue.name
in donor_swap_dict:
return [donor]
106 donor_atom_names=[donor.heavy_atom.name,donor.hydrogen.name]
107 res=donor.heavy_atom.residue
108 for equivalence_list
in donor_swap_dict[donor.heavy_atom.residue.name]:
109 if not donor_atom_names
in equivalence_list:
continue
110 for atom_names
in equivalence_list:
111 if atom_names==donor_atom_names:
continue
112 else:donor_list.append(HBondDonor.FromResidue(res,atom_names[0],atom_names[1]))
116 if not acceptor.atom.residue.name
in acceptor_swap_dict:
return [acceptor]
117 acceptor_list=[acceptor]
118 acceptor_atom_names=[acceptor.atom.name,[a.name
for a
in acceptor.antecedent_list]]
119 res=acceptor.atom.residue
120 for equivalence_list
in acceptor_swap_dict[acceptor.atom.residue.name]:
121 if not acceptor_atom_names
in equivalence_list:
continue
122 for atom_names
in equivalence_list:
123 if atom_names==acceptor_atom_names:
continue
124 else:acceptor_list.append(HBondAcceptor.FromResidue(res,atom_names[0],atom_names[1]))
133 if not isinstance(hbd,HBondDonor):
return False
134 else:
return self.
heavy_atomheavy_atom==hbd.heavy_atom
and self.
hydrogenhydrogen==hbd.hydrogen
139 _donor=res.FindAtom(donor_name).handle
140 _hydrogen=res.FindAtom(hydrogen_name).handle
141 if not _donor.IsValid():
142 if verbose:print(
'Could not find '+donor_name+
' in residue '+str(res))
144 if not _hydrogen.IsValid():
145 if verbose:print(
'Could not find '+hydrogen_name+
' in residue '+str(res))
147 return cls(_donor,_hydrogen)
158 if not isinstance(hba,HBondAcceptor):
return False
159 else:
return self.
atomatom==hba.atom
161 return hash(self.
atomatom)
163 def FromResidue(cls,res,acceptor_name,antecedent_name_list,verbose=True):
164 _acceptor=res.FindAtom(acceptor_name).handle
165 _antecedent_list=_ost.mol.AtomHandleList([res.FindAtom(name).handle
for name
in antecedent_name_list])
166 if not _acceptor.IsValid():
167 if verbose:print(
'Could not find '+acceptor_name+
' in residue '+str(res))
169 for i,a
in enumerate(_antecedent_list):
171 if verbose:print(
'Could not find '+antecedent_name_list[i]+
' in residue '+str(res))
173 return cls(_acceptor,_antecedent_list)
183 if not isinstance(hb,HBond):
return False
184 else:
return self.
acceptoracceptor==hb.acceptor
and self.
donordonor==hb.donor
191 dp=self.
donordonor.heavy_atom.pos;ap=self.
acceptoracceptor.atom.pos;hp=self.
donordonor.hydrogen.pos
192 return _geom.Angle(dp-hp,ap-hp)
194 dp=self.
donordonor.heavy_atom.pos;ap=self.
acceptoracceptor.atom.pos
195 a=min([_geom.Angle(aa.pos-ap,dp-ap)
for aa
in self.
acceptoracceptor.antecedent_list])
198 hp=self.
donordonor.hydrogen.pos;ap=self.
acceptoracceptor.atom.pos
199 a=min([_geom.Angle(aa.pos-ap,hp-ap)
for aa
in acceptor.antecedent_list])
203 def AreHBonded(donor,acceptor,da_dist=3.9,ha_dist=2.5,dha_angle=1.57,daaa_angle=1.57,haaa_angle=1.57):
205 determines if a donor/acceptor pair is hydrogen bonded or not
207 dp=donor.heavy_atom.pos
209 if _geom.Distance(dp,ap)>da_dist:
return False
210 hp=donor.hydrogen.pos
211 if _geom.Distance(hp,ap)>ha_dist:
return False
212 if _geom.Angle(dp-hp,ap-hp)<dha_angle:
return False
213 a=min([_geom.Angle(aa.pos-ap,dp-ap)
for aa
in acceptor.antecedent_list])
214 if a<daaa_angle:
return False
215 a=min([_geom.Angle(aa.pos-ap,hp-ap)
for aa
in acceptor.antecedent_list])
216 if a<haaa_angle:
return False
221 returns a list of hydrogen-bond donors and acceptors from an Entity or EntityView.
222 It relies on atom names to determine the list of H-bond donors and acceptors.
223 These names are given in a dictionary, which defaults to CHARMM.
225 if not hbond_donor_acceptor_dict:
226 print(
'Using default CHARMM atom namings')
230 for r
in eh.residues:
231 if not r.name
in hbond_donor_acceptor_dict:
232 print(
'donors and acceptors for',r,
'are not defined in the dictionary and will not be included')
234 res_da_dict=hbond_donor_acceptor_dict[r.name]
235 for acceptor
in res_da_dict.acceptors:
236 a=HBondAcceptor.FromResidue(r,acceptor[0],acceptor[1],verbose)
237 if not a==
None:acceptor_list.append(a)
238 for donor
in res_da_dict.donors:
239 d=HBondDonor.FromResidue(r,donor[0],donor[1],verbose)
240 if not d==
None:donor_list.append(d)
241 return [donor_list,acceptor_list]
246 return a list of hydrogen bonds between donors and acceptors from
247 a list of donors and a list of acceptors.
250 for donor
in donor_list:
251 for acceptor
in acceptor_list:
257 return a list of hydrogen bonds from an Entity or EntityView.
258 if no dictionary for the hbond donors and acceptors is specified
259 it will use the standard CHARMM names to determine them
263 for donor
in donor_list:
264 for acceptor
in acceptor_list:
268 def GetHbondListFromTraj(t,eh,cutoff=0.7,stride=1,swap=False,donor_swap_dict={},acceptor_swap_dict={},hbond_donor_acceptor_dict={},verbose=True):
270 return a list of hydrogen bonds from an Entity or EntityView that are
271 present in a fraction of the frames larger than *cutoff*.
272 if no dictionary for the hbond donors and acceptors is specified
273 it will use the standard CHARMM names to determine them
276 if not donor_swap_dict:
277 print(
'use of standard CHARMM HBond donor swap dictionary')
279 if not acceptor_swap_dict:
280 print(
'use of standard CHARMM HBond acceptor swap dictionary')
286 for i
in range(0,t.GetFrameCount(),stride):
291 hbond_list=
GetEquivalentHBonds(hbond_list,eh,swap,donor_swap_dict,acceptor_swap_dict,verbose)
292 for hb
in hbond_list:
293 if hb
in hbond_list[hbond_list.index(hb)+1:]:hbond_list.pop(hbond_list.index(hb))
294 for hb
in hbond_list:
295 if hb
in hb_list:hb_score[hb_list.index(hb)]+=1
301 for hb,s
in zip(hb_list,hb_score):
302 if s/float(nframes)>=cutoff:
303 if swap:hbond_list.append(list(hb)[0])
304 else:hbond_list.append(hb)
305 hbond_score.append(s/float(nframes))
306 return (hbond_list,hbond_score)
310 return the list of hydrogen bonds formed between two Entity or EntityView.
311 if no dictionary for the hbond donors and acceptors is specified
312 it will use the standard CHARMM names to determine them
317 for donor
in donor_list1:
318 for acceptor
in acceptor_list2:
320 hb=
HBond(donor,acceptor)
321 if hb
in hbond_list:
continue
322 hbond_list.append(hb)
323 for donor
in donor_list2:
324 for acceptor
in acceptor_list1:
326 hb=
HBond(donor,acceptor)
327 if hb
in hbond_list:
continue
328 hbond_list.append(hb)
331 def GetEquivalentHBonds(ref_hbond_list,eh,swap=False,donor_swap_dict={},acceptor_swap_dict={},verbose=True):
334 for hbond
in ref_hbond_list:
335 res1=eh.FindResidue(hbond.donor.heavy_atom.chain.name,hbond.donor.heavy_atom.residue.number.num)
336 res2=eh.FindResidue(hbond.acceptor.atom.chain.name,hbond.acceptor.atom.residue.number.num)
337 donor=HBondDonor.FromResidue(res1,hbond.donor.heavy_atom.name,hbond.donor.hydrogen.name,verbose)
338 acceptor=HBondAcceptor.FromResidue(res2,hbond.acceptor.atom.name,[a.name
for a
in hbond.acceptor.antecedent_list],verbose)
339 hbond_list.append(set([
HBond(donor,acceptor)]))
341 if not donor_swap_dict:
342 print(
'use of standard CHARMM HBond donor swap dictionary')
344 if not acceptor_swap_dict:
345 print(
'use of standard CHARMM HBond acceptor swap dictionary')
347 for hbond
in ref_hbond_list:
348 res1=eh.FindResidue(hbond.donor.heavy_atom.chain.name,hbond.donor.heavy_atom.residue.number.num)
349 res2=eh.FindResidue(hbond.acceptor.atom.chain.name,hbond.acceptor.atom.residue.number.num)
350 donor=HBondDonor.FromResidue(res1,hbond.donor.heavy_atom.name,hbond.donor.hydrogen.name,verbose)
351 acceptor=HBondAcceptor.FromResidue(res2,hbond.acceptor.atom.name,[a.name
for a
in hbond.acceptor.antecedent_list],verbose)
354 hbond_list.append(set([
HBond(d,a)
for d
in donor_list
for a
in acceptor_list]))
358 def CalculateHBondScore(ref_eh,eh2,ref_eh2=None,hbond_donor_acceptor_dict={},swap=False,donor_swap_dict={},acceptor_swap_dict={},verbose=True):
360 Returns the fraction of H-bonds from ref_eh that are also present in eh2.
361 If ref_eh2 is specified, it uses as reference the Hbonds between ref_eh and ref_eh2.
362 This allows to look at H-bonds between specific parts of proteins or so.
363 Alternatively ref_eh can be a list of H-bonds.
364 This function relies on atom names to determine the list of H-bond donors and acceptors.
365 These names are given in a dictionary, which defaults to CHARMM.
366 If swap is set to True, a dictionary for equivalent donors and one for equivalent acceptors
367 (defaults to CHARMM) is used to check for equivalent HBonds in eh2.
368 If swap is set to True, if two equivalent hydrogen bonds are present in the reference entity
369 (for example both oxygens of ASP H-bonding the same atom), it suffices that on of these bonds is
370 present in eh2 for both of them to be counted as present in eh2.
373 elif type(ref_eh)==list:hbond_list1=ref_eh
375 nbonds=float(len(hbond_list1))
377 print(
'No HBonds in reference view')
379 hbond_list2=
GetEquivalentHBonds(hbond_list1,eh2,swap,donor_swap_dict,acceptor_swap_dict,verbose)
381 for hl
in hbond_list2:
383 if HBond(hbond.donor,hbond.acceptor).IsFormed():
386 return c/float(len(hbond_list1))
389 def AnalyzeHBondScore(ref_eh,t,eh2,ref_eh2=None,hbond_donor_acceptor_dict={},swap=False,donor_swap_dict={},acceptor_swap_dict={},first=0,last=-1,stride=1,verbose=True):
391 Returns the same score as CalculateHBondScore, but for a trajectory.
394 if not donor_swap_dict:
395 print(
'use of standard CHARMM HBond donor swap dictionary')
397 if not acceptor_swap_dict:
398 print(
'use of standard CHARMM HBond acceptor swap dictionary')
401 elif type(ref_eh)==list:hbond_list1=ref_eh
403 nbonds=float(len(hbond_list1))
405 print(
'No HBonds in reference view')
407 print(
'number of hbonds in ref_eh:',nbonds)
408 hbond_list2=
GetEquivalentHBonds(hbond_list1,eh2,swap,donor_swap_dict,acceptor_swap_dict,verbose)
409 if last==-1:last=t.GetFrameCount()
411 for f
in range(first,last,stride):
414 for hl
in hbond_list2:
419 score.append(c/nbonds)
425 if not donor_swap_dict:
426 print(
'use of standard CHARMM HBond donor swap dictionary')
428 if not acceptor_swap_dict:
429 print(
'use of standard CHARMM HBond acceptor swap dictionary')
432 ref_hbond_list=
GetEquivalentHBonds(ref_hbond_list,ref_eh,swap,donor_swap_dict,acceptor_swap_dict)
434 for hb
in ref_hbond_list:
436 out_hbond_list.append(hb)
437 return out_hbond_list
def __init__(self, acceptor, antecedent_list)
def IsHBondedTo(self, donor)
def FromResidue(cls, res, acceptor_name, antecedent_name_list, verbose=True)
def __init__(self, donor, hydrogen)
def IsHBondedTo(self, acceptor)
def FromResidue(cls, res, donor_name, hydrogen_name, verbose=True)
def __init__(self, donor, acceptor)
def DonorAcceptorDistance(self)
def DonorAcceptorAcceptorAntecedentAngle(self)
def HydrogenAcceptorAcceptorAntecedentAngle(self)
def DonorHydrogenAcceptorAngle(self)
def HydrogenAcceptorDistance(self)
def __init__(self, donors=[], acceptors=[])
Real DLLEXPORT_OST_GEOM Distance(const Line2 &l, const Vec2 &v)
def AreHBonded(donor, acceptor, da_dist=3.9, ha_dist=2.5, dha_angle=1.57, daaa_angle=1.57, haaa_angle=1.57)
def BuildCHARMMHBondDonorEquivalenceDict()
def ListEquivalentAcceptors(acceptor, acceptor_swap_dict)
def GetHbondDonorAcceptorList(eh, hbond_donor_acceptor_dict={}, verbose=True)
def GetEquivalentHBonds(ref_hbond_list, eh, swap=False, donor_swap_dict={}, acceptor_swap_dict={}, verbose=True)
def CalculateHBondScore(ref_eh, eh2, ref_eh2=None, hbond_donor_acceptor_dict={}, swap=False, donor_swap_dict={}, acceptor_swap_dict={}, verbose=True)
def GetHbondListBetweenViews(eh1, eh2, hbond_donor_acceptor_dict={}, verbose=True)
def ListEquivalentDonors(donor, donor_swap_dict)
def GetHBondListIntersection(ref_hbond_list, ref_eh, hbond_list, swap=False, donor_swap_dict={}, acceptor_swap_dict={})
def BuildCHARMMHBondAcceptorEquivalenceDict()
def GetHbondListFromView(eh, hbond_donor_acceptor_dict={}, verbose=True)
def GetHbondListFromDonorAcceptorLists(donor_list, acceptor_list)
def AnalyzeHBondScore(ref_eh, t, eh2, ref_eh2=None, hbond_donor_acceptor_dict={}, swap=False, donor_swap_dict={}, acceptor_swap_dict={}, first=0, last=-1, stride=1, verbose=True)
def GetHbondListFromTraj(t, eh, cutoff=0.7, stride=1, swap=False, donor_swap_dict={}, acceptor_swap_dict={}, hbond_donor_acceptor_dict={}, verbose=True)
def BuildCHARMMHBondDonorAcceptorDict()