IMP logo
IMP Reference Guide  2.5.0
The Integrative Modeling Platform
crosslinking_new.py
1 """@namespace IMP.pmi.restraints.crosslinking_new
2 Restraints for handling crosslinking data.
3 """
4 
5 from __future__ import print_function
6 import IMP
7 import IMP.core
8 import IMP.algebra
9 import IMP.atom
10 import IMP.container
11 import IMP.pmi.tools
12 import pdb
13 
14 class DisulfideCrossLinkRestraint(object):
15  def __init__(self, representation,
16  selection_tuple1,
17  selection_tuple2,
18  length=6.5,
19  resolution=1,
20  slope=0.01,
21  label="None"):
22 
23  self.m = representation.prot.get_model()
24  self.rs = IMP.RestraintSet(self.m, 'likelihood')
25  self.rslin = IMP.RestraintSet(self.m, 'linear_dummy_restraints')
26 
27  # dummy linear restraint used for Chimera display
28  self.linear = IMP.core.Linear(0, 0.0)
29  self.linear.set_slope(0.0)
30  dps2 = IMP.core.DistancePairScore(self.linear)
31 
32  self.label = label
33  self.psi_dictionary={}
34  self.sigma_dictionary={}
35  self.psi_is_sampled = False
36  self.sigma_is_sampled = False
37  self.xl={}
38 
39  ps1 = IMP.pmi.tools.select_by_tuple(
40  representation,
41  selection_tuple1,
42  resolution=resolution)
43 
44  ps2 = IMP.pmi.tools.select_by_tuple(
45  representation,
46  selection_tuple2,
47  resolution=resolution)
48 
49  if len(ps1) > 1 or len(ps1) == 0:
50  raise ValueError("DisulfideBondRestraint: ERROR> first selection pattern selects multiple particles or sero particles")
51 
52  if len(ps2) > 1 or len(ps2) == 0:
53  raise ValueError("DisulfideBondRestraint: ERROR> second selection pattern selects multiple particles or sero particles")
54 
55  p1 = ps1[0]
56  p2 = ps2[0]
57 
58 
59 
60  sigma=self.create_sigma("SIGMA_DISULFIDE_BOND")
61  psi=self.create_psi("PSI_DISULFIDE_BOND")
62 
63  p1i = p1.get_particle_index()
64  p2i = p2.get_particle_index()
65  si = sigma.get_particle().get_index()
66  psii = psi.get_particle().get_index()
67 
69  self.m,
70  length,
71  slope)
72 
73  dr.add_contribution((p1i, p2i), (si, si), psii)
74 
75  if p1i != p2i:
76  pr = IMP.core.PairRestraint(self.m, dps2, (p1i, p2i))
77  pr.set_name("DISULFIDE_BOND_"+self.label)
78  self.rslin.add_restraint(pr)
79 
80  lw = IMP.isd.LogWrapper([dr],1.0)
81  self.rs.add_restraint(lw)
82 
83  self.xl["Particle1"]=p1
84  self.xl["Particle2"]=p2
85  self.xl["Sigma"]=sigma
86  self.xl["Psi"]=psi
87 
88  def add_to_model(self):
90  IMP.pmi.tools.add_restraint_to_model(self.m, self.rslin)
91 
92  def get_hierarchies(self):
93  return self.prot
94 
95  def get_restraint_sets(self):
96  return self.rs
97 
98  def get_restraint(self):
99  return self.rs
100 
101  def get_restraint_for_rmf(self):
102  return self.rslin
103 
104  def get_restraints(self):
105  rlist = []
106  for r in self.rs.get_restraints():
107  rlist.append(IMP.core.PairRestraint.get_from(r))
108  return rlist
109 
110  def set_psi_is_sampled(self, is_sampled=True):
111  self.psi_is_sampled = is_sampled
112 
113  def set_sigma_is_sampled(self, is_sampled=True):
114  self.sigma_is_sampled = is_sampled
115 
116 
117  def create_sigma(self, name):
118  ''' a nuisance on the structural uncertainty '''
119  if name in self.sigma_dictionary:
120  return self.sigma_dictionary[name][0]
121 
122  sigmainit = 1.0
123  sigmaminnuis = 0.0000001
124  sigmamaxnuis = 1000.0
125  sigmamin = 0.01
126  sigmamax = 100.0
127  sigmatrans = 0.5
128  sigma = IMP.pmi.tools.SetupNuisance(self.m, sigmainit,
129  sigmaminnuis, sigmamaxnuis, self.sigma_is_sampled).get_particle()
130  self.sigma_dictionary[name] = (
131  sigma,
132  sigmatrans,
133  self.sigma_is_sampled)
134 
135  return sigma
136 
137  def create_psi(self, name):
138  ''' a nuisance on the inconsistency '''
139  if name in self.psi_dictionary:
140  return self.psi_dictionary[name][0]
141 
142  psiinit=0.001
143  psiminnuis = 0.0000001
144  psimaxnuis = 0.4999999
145  psimin = 0.01
146  psimax = 0.49
147  psitrans = 0.1
148  psi = IMP.pmi.tools.SetupNuisance(self.m, psiinit,
149  psiminnuis, psimaxnuis,
150  self.psi_is_sampled).get_particle()
151  self.psi_dictionary[name] = (
152  psi,
153  psitrans,
154  self.psi_is_sampled)
155 
156  return psi
157 
158 
159  def get_output(self):
160  self.m.update()
161 
162  output = {}
163  score = self.rs.unprotected_evaluate(None)
164  output["_TotalScore"] = str(score)
165  output["DisulfideBondRestraint_Data_Score_" + self.label] = str(score)
166  output["DisulfideBondRestraint_Linear_Score_" +
167  self.label] = self.rslin.unprotected_evaluate(None)
168  return output
169 
170  def get_particles_to_sample(self):
171  raise NotImplementedError(" ")
172 
173 
174 class CrossLinkingMassSpectrometryRestraint(object):
175  import IMP.isd
176  import IMP.pmi.tools
177  from math import log
178 
179  def __init__(self, representation,
180  CrossLinkDataBase,
181  length,
182  resolution=None,
183  slope=0.0,
184  label="None",
185  filelabel="None",
186  attributes_for_label=None):
187 
188  if type(representation) != list:
189  representations = [representation]
190  else:
191  representations = representation
192 
193  if not isinstance(CrossLinkDataBase,IMP.pmi.io.crosslink.CrossLinkDataBase):
194  raise TypeError("CrossLinkingMassSpectrometryRestraint: CrossLinkDataBase should be an IMP.pmi.io.crosslink.CrossLinkDataBase object")
195 
196  self.CrossLinkDataBase=CrossLinkDataBase
197 
198  indb = open("included." + filelabel + ".xl.db", "w")
199  exdb = open("excluded." + filelabel + ".xl.db", "w")
200  midb = open("missing." + filelabel + ".xl.db", "w")
201 
202  self.m = representations[0].prot.get_model()
203  self.rs = IMP.RestraintSet(self.m, 'likelihood')
204  self.rspsi = IMP.RestraintSet(self.m, 'prior_psi')
205  self.rssig = IMP.RestraintSet(self.m, 'prior_sigmas')
206  self.rslin = IMP.RestraintSet(self.m, 'linear_dummy_restraints')
207 
208  # dummy linear restraint used for Chimera display
209  self.linear = IMP.core.Linear(0, 0.0)
210  self.linear.set_slope(0.0)
211  dps2 = IMP.core.DistancePairScore(self.linear)
212 
213  self.label = label
214  self.psi_is_sampled = True
215  self.sigma_is_sampled = True
216  self.psi_dictionary={}
217  self.sigma_dictionary={}
218  self.xl_list=[]
219  self.outputlevel = "low"
220 
221  restraints = []
222 
223  for xlid in self.CrossLinkDataBase.xlid_iterator():
224  new_contribution=True
225  for xl in self.CrossLinkDataBase[xlid]:
226 
227  r1 = xl[self.CrossLinkDataBase.residue1_key]
228  c1 = xl[self.CrossLinkDataBase.protein1_key]
229  r2 = xl[self.CrossLinkDataBase.residue2_key]
230  c2 = xl[self.CrossLinkDataBase.protein2_key]
231 
232  for nstate, r in enumerate(representations):
233  # loop over every state
234  xl[self.CrossLinkDataBase.state_key]=nstate
235  xl[self.CrossLinkDataBase.data_set_name_key]=self.label
236 
237  ps1 = IMP.pmi.tools.select(
238  r,
239  resolution=resolution,
240  name=c1,
241  name_is_ambiguous=False,
242  residue=r1)
243  ps2 = IMP.pmi.tools.select(
244  r,
245  resolution=resolution,
246  name=c2,
247  name_is_ambiguous=False,
248  residue=r2)
249 
250  if len(ps1) > 1:
251  raise ValueError("residue %d of chain %s selects multiple particles %s" % (r1, c1, str(ps1)))
252  elif len(ps1) == 0:
253  print("CrossLinkingMassSpectrometryRestraint: WARNING> residue %d of chain %s is not there" % (r1, c1))
254  midb.write(str(xl) + "\n")
255  continue
256 
257  if len(ps2) > 1:
258  raise ValueError("residue %d of chain %s selects multiple particles %s" % (r2, c2, str(ps2)))
259  elif len(ps2) == 0:
260  print("CrossLinkingMassSpectrometryRestraint: WARNING> residue %d of chain %s is not there" % (r2, c2))
261  midb.write(str(xl) + "\n")
262  continue
263 
264  p1 = ps1[0]
265  p2 = ps2[0]
266 
267  if p1 == p2 and r1 == r2:
268  print("CrossLinkingMassSpectrometryRestraint: WARNING> same particle and same residue, skippin cross-link")
269  continue
270 
271  if new_contribution:
272  print("generating a new crosslink restraint")
273  new_contribution=False
275  self.m,
276  length,
277  slope)
278  restraints.append(dr)
279 
280 
281  if self.CrossLinkDataBase.sigma1_key not in xl.keys():
282  sigma1name="SIGMA"
283  xl[self.CrossLinkDataBase.sigma1_key]=sigma1name
284  else:
285  sigma1name=xl[self.CrossLinkDataBase.sigma1_key]
286  sigma1=self.create_sigma(sigma1name)
287 
288  if self.CrossLinkDataBase.sigma2_key not in xl.keys():
289  sigma2name="SIGMA"
290  xl[self.CrossLinkDataBase.sigma2_key]=sigma2name
291  else:
292  sigma2name=xl[self.CrossLinkDataBase.sigma2_key]
293  sigma2=self.create_sigma(sigma2name)
294 
295  if self.CrossLinkDataBase.psi_key not in xl.keys():
296  psiname="PSI"
297  xl[self.CrossLinkDataBase.psi_key]=psiname
298  else:
299  psiname=xl[self.CrossLinkDataBase.psi_key]
300  psi=self.create_psi(psiname)
301 
302 
303  p1i = p1.get_particle_index()
304  xl["Particle1"]=p1
305  p2i = p2.get_particle_index()
306  xl["Particle2"]=p2
307  s1i = sigma1.get_particle().get_index()
308  xl["Particle_sigma1"]=sigma1
309  s2i = sigma2.get_particle().get_index()
310  xl["Particle_sigma2"]=sigma2
311  psii = psi.get_particle().get_index()
312  xl["Particle_psi"]=psi
313 
314  print("B",(p1i, p2i), (s1i, s2i), psii,dr)
315 
316  dr.add_contribution((p1i, p2i), (s1i, s2i), psii)
317  xl["Restraint"]=dr
318 
319  print("--------------")
320  print("CrossLinkingMassSpectrometryRestraint: generating cross-link restraint between")
321  print("CrossLinkingMassSpectrometryRestraint: residue %d of chain %s and residue %d of chain %s" % (r1, c1, r2, c2))
322  print("CrossLinkingMassSpectrometryRestraint: with sigma1 %s sigma2 %s psi %s" % (sigma1name, sigma2name, psiname))
323  print("CrossLinkingMassSpectrometryRestraint: between particles %s and %s" % (p1.get_name(), p2.get_name()))
324  print("==========================================\n")
325 
326  # check if the two residues belong to the same rigid body
329  IMP.core.RigidMember(p1).get_rigid_body() ==
330  IMP.core.RigidMember(p2).get_rigid_body()):
331  xl["IntraRigidBody"]=True
332  else:
333  xl["IntraRigidBody"]=False
334 
335  xl_label=self.CrossLinkDataBase.get_short_cross_link_string(xl)
336  xl["ShortLabel"]=xl_label
337  dr.set_name(xl_label)
338 
339  if p1i != p2i:
340  pr = IMP.core.PairRestraint(self.m, dps2, (p1i, p2i))
341  pr.set_name(xl_label)
342  self.rslin.add_restraint(pr)
343 
344  self.xl_list.append(xl)
345 
346  indb.write(str(xl) + "\n")
347 
348  if len(self.xl_list) == 0:
349  raise SystemError("CrossLinkingMassSpectrometryRestraint: no crosslink was constructed")
350 
351  lw = IMP.isd.LogWrapper(restraints,1.0)
352  self.rs.add_restraint(lw)
353 
354  def add_to_model(self):
355  IMP.pmi.tools.add_restraint_to_model(self.m, self.rs)
356  IMP.pmi.tools.add_restraint_to_model(self.m, self.rspsi)
357  IMP.pmi.tools.add_restraint_to_model(self.m, self.rssig)
358  IMP.pmi.tools.add_restraint_to_model(self.m, self.rslin)
359 
360  def get_hierarchies(self):
361  return self.prot
362 
363  def get_restraint_sets(self):
364  return self.rs
365 
366  def get_restraint(self):
367  return self.rs
368 
369  def get_restraint_for_rmf(self):
370  return self.rslin
371 
372  def get_restraints(self):
373  rlist = []
374  for r in self.rs.get_restraints():
375  rlist.append(IMP.core.PairRestraint.get_from(r))
376  return rlist
377 
378  def get_particle_pairs(self):
379  ppairs = []
380  for i in range(len(self.pairs)):
381  p0 = self.pairs[i][0]
382  p1 = self.pairs[i][1]
383  ppairs.append((p0, p1))
384  return ppairs
385 
386  def set_output_level(self, level="low"):
387  # this might be "low" or "high"
388  self.outputlevel = level
389 
390  def set_psi_is_sampled(self, is_sampled=True):
391  self.psi_is_sampled = is_sampled
392 
393  def set_sigma_is_sampled(self, is_sampled=True):
394  self.sigma_is_sampled = is_sampled
395 
396 
397  def create_sigma(self, name):
398  ''' a nuisance on the structural uncertainty '''
399  if name in self.sigma_dictionary:
400  return self.sigma_dictionary[name][0]
401 
402  sigmainit = 2.0
403  sigmaminnuis = 0.0000001
404  sigmamaxnuis = 1000.0
405  sigmamin = 0.01
406  sigmamax = 100.0
407  sigmatrans = 0.5
408  sigma = IMP.pmi.tools.SetupNuisance(self.m, sigmainit,
409  sigmaminnuis, sigmamaxnuis, self.sigma_is_sampled).get_particle()
410  self.sigma_dictionary[name] = (
411  sigma,
412  sigmatrans,
413  self.sigma_is_sampled)
414  self.rssig.add_restraint(
416  self.m,
417  sigma,
418  1000000000.0,
419  sigmamax,
420  sigmamin))
421  return sigma
422 
423  def create_psi(self, name):
424  ''' a nuisance on the inconsistency '''
425  if name in self.psi_dictionary:
426  return self.psi_dictionary[name][0]
427 
428  psiinit=0.25
429  psiminnuis = 0.0000001
430  psimaxnuis = 0.4999999
431  psimin = 0.01
432  psimax = 0.49
433  psitrans = 0.1
434  psi = IMP.pmi.tools.SetupNuisance(self.m, psiinit,
435  psiminnuis, psimaxnuis,
436  self.psi_is_sampled).get_particle()
437  self.psi_dictionary[name] = (
438  psi,
439  psitrans,
440  self.psi_is_sampled)
441 
442  self.rspsi.add_restraint(
444  self.m,
445  psi,
446  1000000000.0,
447  psimax,
448  psimin))
449 
450  self.rspsi.add_restraint(IMP.isd.JeffreysRestraint(self.m, psi))
451 
452  return psi
453 
454 
455  def get_output(self):
456  self.m.update()
457 
458  output = {}
459  score = self.rs.unprotected_evaluate(None)
460  output["_TotalScore"] = str(score)
461  output["CrossLinkingMassSpectrometryRestraint_Data_Score_" + self.label] = str(score)
462  output["CrossLinkingMassSpectrometryRestraint_PriorSig_Score_" +
463  self.label] = self.rssig.unprotected_evaluate(None)
464  output["CrossLinkingMassSpectrometryRestraint_PriorPsi_Score_" +
465  self.label] = self.rspsi.unprotected_evaluate(None)
466  output["CrossLinkingMassSpectrometryRestraint_Linear_Score_" +
467  self.label] = self.rslin.unprotected_evaluate(None)
468  for xl in self.xl_list:
469 
470  xl_label=xl["ShortLabel"]
471  ln = xl["Restraint"]
472  p0 = xl["Particle1"]
473  p1 = xl["Particle2"]
474  output["CrossLinkingMassSpectrometryRestraint_Score_" +
475  xl_label] = str(-self.log(ln.unprotected_evaluate(None)))
476 
477  d0 = IMP.core.XYZ(p0)
478  d1 = IMP.core.XYZ(p1)
479  output["CrossLinkingMassSpectrometryRestraint_Distance_" +
480  xl_label] = str(IMP.core.get_distance(d0, d1))
481 
482 
483  for psiname in self.psi_dictionary:
484  output["CrossLinkingMassSpectrometryRestraint_Psi_" +
485  str(psiname) + "_" + self.label] = str(self.psi_dictionary[psiname][0].get_scale())
486 
487  for sigmaname in self.sigma_dictionary:
488  output["CrossLinkingMassSpectrometryRestraint_Sigma_" +
489  str(sigmaname) + "_" + self.label] = str(self.sigma_dictionary[sigmaname][0].get_scale())
490 
491 
492  return output
493 
494  def get_particles_to_sample(self):
495  ps = {}
496  if self.sigma_is_sampled:
497  for sigmaname in self.sigma_dictionary:
498  ps["Nuisances_ISDCrossLinkMS_Sigma_" + str(sigmaname) + "_" + self.label] =\
499  ([self.sigma_dictionary[sigmaname][0]],
500  self.sigma_dictionary[sigmaname][1])
501 
502  if self.psi_is_sampled:
503  for psiname in self.psi_dictionary:
504  ps["Nuisances_ISDCrossLinkMS_Psi_" +
505  str(psiname) + "_" + self.label] =\
506  ([self.psi_dictionary[psiname][0]], self.psi_dictionary[psiname][1])
507 
508  return ps
A restraint for ambiguous cross-linking MS data and multiple state approach.
Various classes to hold sets of particles.
Miscellaneous utilities.
Definition: tools.py:1
static bool get_is_setup(const IMP::ParticleAdaptor &p)
Definition: rigid_bodies.h:469
double get_distance(XYZR a, XYZR b)
Compute the sphere distance between a and b.
Definition: XYZR.h:87
Uniform distribution with harmonic boundaries.
Definition: UniformPrior.h:20
Object used to hold a set of restraints.
Definition: RestraintSet.h:36
Ints get_index(const ParticlesTemp &particles, const Subset &subset, const Subsets &excluded)
def add_restraint_to_model
Add a PMI restraint to the model.
Definition: tools.py:22
A decorator for a particle with x,y,z coordinates.
Definition: XYZ.h:30
Linear function
Definition: Linear.h:19
Basic functionality that is expected to be used by a wide variety of IMP users.
General purpose algebraic and geometric methods that are expected to be used by a wide variety of IMP...
Calculate the -Log of a list of restraints.
Definition: LogWrapper.h:19
Applies a PairScore to a Pair.
Definition: PairRestraint.h:29
def select
this function uses representation=SimplifiedModel it returns the corresponding selected particles rep...
Definition: tools.py:662
Functionality for loading, creating, manipulating and scoring atomic structures.
Inferential scoring building on methods developed as part of the Inferential Structure Determination ...