1 """@namespace IMP.pmi.restraints.stereochemistry
2 Restraints for keeping correct stereochemistry.
5 from __future__
import print_function
29 all leaves of the input hierarchies will be input in the
30 restraint. If other_hierarchies is defined, then a Bipartite container
31 between "hierarchies" and "other_hierarchies" leaves is initialized
34 def __init__(self, representation,
36 other_hierarchies=
None,
37 resolution=
None, kappa=1.0):
39 self.m = representation.prot.get_model()
52 resolution=resolution,
53 hierarchies=hierarchies)
55 lsa.add_particles(particles)
57 if other_hierarchies
is None:
66 resolution=resolution,
67 hierarchies=other_hierarchies)
68 other_lsa.add_particles(particles)
76 self.rs.add_restraint(evr)
78 def add_excluded_particle_pairs(self, excluded_particle_pairs):
81 lpc.add_particle_pairs(excluded_particle_pairs)
83 self.cpc.add_pair_filter(icpf)
85 def set_label(self, label):
88 def add_to_model(self):
89 self.m.add_restraint(self.rs)
91 def get_restraint(self):
94 def set_weight(self, weight):
96 self.rs.set_weight(weight)
101 score = self.weight * self.rs.unprotected_evaluate(
None)
102 output[
"_TotalScore"] = str(score)
103 output[
"ExcludedVolumeSphere_" + self.label] = str(score)
110 add bond restraint between pair of consecutive
111 residues/beads to enforce the stereochemistry.
114 from math
import pi
as pi
124 jitter: defines the +- added to the optimal distance in the harmonic well restraint
125 used to increase the tolerance
127 self.m = representation.prot.get_model()
133 particles = IMP.pmi.tools.select_by_tuple(
142 (distance - jitter, distance + jitter), strength)
147 raise ValueError(
"wrong length of pair")
150 raise TypeError(
"not a residue")
153 print(
"ResidueBondRestraint: adding a restraint between %s %s" % (pair[0].get_name(), pair[1].get_name()))
154 self.rs.add_restraint(
159 def set_label(self, label):
161 self.rs.set_name(label)
162 for r
in self.rs.get_restraints():
165 def add_to_model(self):
166 self.m.add_restraint(self.rs)
168 def get_restraint(self):
171 def set_weight(self, weight):
173 self.rs.set_weight(weight)
175 def get_excluded_pairs(self):
176 return self.pairslist
178 def get_output(self):
181 score = self.weight * self.rs.unprotected_evaluate(
None)
182 output[
"_TotalScore"] = str(score)
183 output[
"ResidueBondRestraint_" + self.label] = str(score)
190 add angular restraint between triplets of consecutive
191 residues/beads to enforce the stereochemistry.
194 from math
import pi
as pi
203 self.m = representation.prot.get_model()
209 particles = IMP.pmi.tools.select_by_tuple(
215 (self.pi * anglemin / 180.0,
216 self.pi * anglemax / 180.0),
222 raise ValueError(
"wrong length of triplet")
225 raise TypeError(
"not a residue")
228 print(
"ResidueAngleRestraint: adding a restraint between %s %s %s" % (triplet[0].get_name(), triplet[1].get_name(), triplet[2].get_name()))
229 self.rs.add_restraint(
237 def set_label(self, label):
239 self.rs.set_name(label)
240 for r
in self.rs.get_restraints():
243 def add_to_model(self):
244 self.m.add_restraint(self.rs)
246 def get_restraint(self):
249 def set_weight(self, weight):
251 self.rs.set_weight(weight)
253 def get_excluded_pairs(self):
254 return self.pairslist
256 def get_output(self):
259 score = self.weight * self.rs.unprotected_evaluate(
None)
260 output[
"_TotalScore"] = str(score)
261 output[
"ResidueAngleRestraint_" + self.label] = str(score)
268 add dihedral restraints between quatruplet of consecutive
269 residues/beads to enforce the stereochemistry.
270 Give as input a string of "C" and "T", meaning cys (0+-40) or trans (180+-40)
271 dihedral. The length of the string mush be #residue-3.
272 Without the string, the dihedral will be assumed trans.
275 from math
import pi
as pi
283 self.m = representation.prot.get_model()
289 particles = IMP.pmi.tools.select_by_tuple(
294 if stringsequence
is None:
295 stringsequence =
"T" * (len(particles) - 3)
300 raise ValueError(
"wrong length of quadruplet")
303 raise TypeError(
"not a residue")
306 dihedraltype = stringsequence[n]
307 if dihedraltype ==
"C":
311 (self.pi * anglemin / 180.0,
312 self.pi * anglemax / 180.0),
314 print(
"ResidueDihedralRestraint: adding a CYS restraint between %s %s %s %s" % (quadruplet[0].get_name(), quadruplet[1].get_name(),
315 quadruplet[2].get_name(), quadruplet[3].get_name()))
316 if dihedraltype ==
"T":
317 anglemin = 180 - 70.0
318 anglemax = 180 + 70.0
320 (self.pi * anglemin / 180.0,
321 self.pi * anglemax / 180.0),
323 print(
"ResidueDihedralRestraint: adding a TRANS restraint between %s %s %s %s" % (quadruplet[0].get_name(), quadruplet[1].get_name(),
324 quadruplet[2].get_name(), quadruplet[3].get_name()))
325 self.rs.add_restraint(
331 self.pairslist.append(
333 self.pairslist.append(
336 def set_label(self, label):
338 self.rs.set_name(label)
339 for r
in self.rs.get_restraints():
342 def add_to_model(self):
343 self.m.add_restraint(self.rs)
345 def get_restraint(self):
348 def set_weight(self, weight):
350 self.rs.set_weight(weight)
352 def get_excluded_pairs(self):
353 return self.pairslist
355 def get_output(self):
358 score = self.weight * self.rs.unprotected_evaluate(
None)
359 output[
"_TotalScore"] = str(score)
360 output[
"ResidueDihedralRestraint_" + self.label] = str(score)
365 class SecondaryStructure(object):
380 raise ValueError(
"IMP.isd_emxl is needed")
385 self.particles = IMP.pmi.tools.select_by_tuple(
389 self.m = representation.prot.get_model()
393 self.anglfilename = IMP.isd_emxl.get_data_path(
"CAAngleRestraint.dat")
394 self.dihefilename = IMP.isd_emxl.get_data_path(
395 "CADihedralRestraint.dat")
396 self.nativeness = nativeness
397 self.kt_caff = kt_caff
403 if len(self.particles) != len(ssstring):
404 print(len(self.particles), len(ssstring))
405 print(
"SecondaryStructure: residue range and SS string incompatible")
406 self.ssstring = ssstring
408 (bondrslist, anglrslist, diherslist,
409 pairslist) = self.get_CA_force_field()
410 self.pairslist = pairslist
413 self.anglrs.add_restraints(anglrslist)
414 self.dihers.add_restraints(diherslist)
415 self.bondrs.add_restraints(bondrslist)
417 def set_label(self, label):
420 def add_to_model(self):
421 self.m.add_restraint(self.anglrs)
422 self.m.add_restraint(self.dihers)
423 self.m.add_restraint(self.bondrs)
425 def get_CA_force_field(self):
431 for res
in range(0, len(self.particles) - 1):
433 ps = self.particles[res:res + 2]
436 br = self.get_distance_restraint(ps[0], ps[1], 3.78, 416.0)
437 br.set_name(
'Bond_restraint')
438 bondrslist.append(br)
440 for res
in range(0, len(self.particles) - 4):
445 ps = self.particles[res:res + 5]
448 score_dih] = self.read_potential_dihedral(
449 self.ssstring[res:res + 4],
455 dr = IMP.isd_emxl.CADihedralRestraint(
464 dr.set_name(
'Dihedral restraint')
465 diherslist.append(dr)
467 for res
in range(0, len(self.particles) - 2):
468 ps = self.particles[res:res + 3]
469 [psi, score_ang] = self.read_potential_angle(
470 self.ssstring[res:res + 2],
True)
473 dr = IMP.isd_emxl.CAAngleRestraint(
479 dr.set_name(
'Angle restraint')
480 anglrslist.append(dr)
481 return (bondrslist, anglrslist, diherslist, pairslist)
483 def read_potential_dihedral(self, string, mix=False):
488 for i
in range(0, 36):
489 phi0.append(i * 10.0 / 180.0 * self.pi)
490 phi1.append(i * 10.0 / 180.0 * self.pi)
491 for j
in range(0, 36):
492 score_dih.append(0.0)
495 f = open(self.dihefilename,
'r')
496 for line
in f.readlines():
497 riga = (line.strip()).split()
498 if (len(riga) == 4
and riga[0] == string):
499 ii = int(float(riga[1]) / 10.0)
500 jj = int(float(riga[2]) / 10.0)
501 score_dih[ii * len(phi0) + jj] = - \
502 self.kt_caff * self.log(float(riga[3]))
507 for i
in range(0, 36):
508 for j
in range(0, 36):
510 f = open(self.dihefilename,
'r')
511 for line
in f.readlines():
512 riga = (line.strip()).split()
513 if (len(riga) == 4
and riga[0] == string):
514 ii = int(float(riga[1]) / 10.0)
515 jj = int(float(riga[2]) / 10.0)
516 counts[ii * len(phi0) + jj] += self.nativeness * \
518 if (len(riga) == 4
and riga[0] ==
"-----"):
519 ii = int(float(riga[1]) / 10.0)
520 jj = int(float(riga[2]) / 10.0)
521 counts[ii * len(phi0) + jj] += (1.0 - self.nativeness) * \
524 for i
in range(len(counts)):
525 score_dih[i] = -self.kt_caff * self.log(counts[i])
526 return [phi0, phi1, score_dih]
528 def read_potential_angle(self, string, mix=False):
532 for i
in range(0, 180):
533 psi.append(i / 180.0 * self.pi)
534 score_ang.append(0.0)
537 f = open(self.anglfilename,
'r')
538 for line
in f.readlines():
539 riga = (line.strip()).split()
540 if (len(riga) == 3
and riga[0] == string):
542 score_ang[ii] = -self.kt_caff * self.log(float(riga[2]))
547 for i
in range(0, 180):
550 f = open(self.anglfilename,
'r')
551 for line
in f.readlines():
552 riga = (line.strip()).split()
553 if (len(riga) == 3
and riga[0] == string):
555 counts[ii] += self.nativeness * float(riga[2])
556 if (len(riga) == 3
and riga[0] ==
"---"):
558 counts[ii] += (1.0 - self.nativeness) * float(riga[2])
560 for i
in range(0, 180):
561 score_ang[i] = -self.kt_caff * self.log(counts[i])
562 return [psi, score_ang]
564 def get_excluded_pairs(self):
565 return self.pairslist
567 def get_restraint(self):
569 tmprs.add_restraint(self.anglrs)
570 tmprs.add_restraint(self.dihers)
571 tmprs.add_restraint(self.bondrs)
574 def get_distance_restraint(self, p0, p1, d0, kappa):
580 def get_output(self):
583 score_angle = self.anglrs.unprotected_evaluate(
None)
584 score_dihers = self.dihers.unprotected_evaluate(
None)
585 score_bondrs = self.bondrs.unprotected_evaluate(
None)
586 output[
"_TotalScore"] = str(score_angle + score_dihers + score_bondrs)
588 output[
"SecondaryStructure_Angles_" + self.label] = str(score_angle)
589 output[
"SecondaryStructure_Dihedrals_" +
590 self.label] = str(score_dihers)
591 output[
"SecondaryStructure_Bonds_" + self.label] = str(score_bondrs)
598 add harmonic restraints between all pairs
601 from math
import pi
as pi
610 ca_only: only applies for resolution 0
612 self.m = representation.prot.get_model()
619 for st
in selection_tuples:
620 print(
'selecting with',st)
621 for p
in IMP.pmi.tools.select_by_tuple(representation,st,resolution=resolution):
625 particles.append(p.get_particle())
629 gcpf.set_distance(dist_cutoff)
630 particleindexes=IMP.get_indexes(particles)
631 pairs=gcpf.get_close_pairs( self.m,
636 p1=self.m.get_particle(pair[0])
637 p2=self.m.get_particle(pair[1])
639 print(
"%s and %s are the same particle" % (p1.get_name(),p2.get_name()))
645 print(
"%s and %s are in the same rigid body" % (p1.get_name(),p2.get_name()))
652 print(
"ElasticNetworkConstraint: adding a restraint between %s and %s with distance %.3f" % (p1.get_name(),p2.get_name(),distance))
656 print(
'created',self.rs.get_number_of_restraints(),
'restraints')
658 def set_label(self, label):
660 self.rs.set_name(label)
661 for r
in self.rs.get_restraints():
664 def add_to_model(self):
665 self.m.add_restraint(self.rs)
667 def get_restraint(self):
670 def set_weight(self, weight):
672 self.rs.set_weight(weight)
674 def get_excluded_pairs(self):
675 return self.pairslist
677 def get_output(self):
680 score = self.weight * self.rs.unprotected_evaluate(
None)
681 output[
"_TotalScore"] = str(score)
682 output[
"ElasticNetworkRestraint_" + self.label] = str(score)
689 add charmm force field
692 from math
import pi
as pi
695 def __init__(self,representation,ff_temp=300.0):
697 kB = (1.381 * 6.02214) / 4184.0
699 self.m=representation.prot.get_model()
701 self.nonbonded_rs =
IMP.RestraintSet(self.m, 1.0 / (kB * ff_temp),
'NONBONDED')
707 root=representation.prot
711 topology = ff.create_topology(root)
712 topology.apply_default_patches()
713 topology.setup_hierarchy(root)
715 self.bonds_rs.add_restraint(r)
717 ff.add_well_depths(root)
723 self.nbl.add_pair_filter(r.get_pair_filter())
728 self.nonbonded_rs.add_restraint(pr)
732 print(
'CHARMM is set up')
734 def set_label(self, label):
736 self.rs.set_name(label)
737 for r
in self.rs.get_restraints():
740 def add_to_model(self):
741 self.m.add_restraint(self.bonds_rs)
742 self.m.add_restraint(self.nonbonded_rs)
744 def get_restraint(self):
747 def get_close_pair_container(self):
750 def set_weight(self, weight):
752 self.rs.set_weight(weight)
754 def get_output(self):
757 bonds_score = self.weight * self.bonds_rs.unprotected_evaluate(
None)
758 nonbonded_score = self.weight * self.nonbonded_rs.unprotected_evaluate(
None)
759 score=bonds_score+nonbonded_score
760 output[
"_TotalScore"] = str(score)
761 output[
"CHARMM_BONDS"] = str(bonds_score)
762 output[
"CHARMM_NONBONDED"] = str(nonbonded_score)
769 add bonds and improper dihedral restraints for the CBs
772 from math
import pi
as pi
775 self, rnums, representation, selection_tuple, strength=10.0, kappa=1.0,
776 jitter_angle=0.0, jitter_improper=0.0):
780 ca-cb is a constraint, no restraint needed
785 self.m = representation.prot.get_model()
795 ca, cb = self.get_ca_cb(
796 IMP.pmi.tools.select_by_tuple(representation,
797 (rnum, rnum,
'chainA'), resolution=0))
801 ca_prev, cb_prev = self.get_ca_cb(
802 IMP.pmi.tools.select_by_tuple(representation,
803 (rnum - 1, rnum - 1,
'chainA'), resolution=0))
804 ca_next, cb_next = self.get_ca_cb(
805 IMP.pmi.tools.select_by_tuple(representation,
806 (rnum + 1, rnum + 1,
'chainA'), resolution=0))
840 self.rset_angles.add_restraint(ar13u)
841 self.rset_angles.add_restraint(ar13l)
847 self.rset_angles.add_restraint(ar23u)
848 self.rset_angles.add_restraint(ar23l)
849 if not nter
and not cter:
873 self.rset_angles.add_restraint(idru)
874 self.rset_angles.add_restraint(idrl)
875 self.rs.add_restraint(self.rset_bonds)
876 self.rs.add_restraint(self.rset_angles)
878 def get_ca_cb(self, atoms):
883 ca = a.get_particle()
885 cb = a.get_particle()
888 def set_label(self, label):
890 self.rs.set_name(label)
891 for r
in self.rs.get_restraints():
894 def add_to_model(self):
895 self.m.add_restraint(self.rs)
897 def get_restraint(self):
900 def set_weight(self, weight):
902 self.rs.set_weight(weight)
904 def get_excluded_pairs(self):
905 return self.pairslist
907 def get_output(self):
910 score = self.weight * self.rs.unprotected_evaluate(
None)
911 output[
"_TotalScore"] = str(score)
912 output[
"PseudoAtomicRestraint_" + self.label] = str(score)
A filter which returns true if a container containers the Pair.
add dihedral restraints between quatruplet of consecutive residues/beads to enforce the stereochemist...
CHARMMParameters * get_heavy_atom_CHARMM_parameters()
Lower bound harmonic function (non-zero when feature < mean)
Enforce CHARMM stereochemistry on the given Hierarchy.
Various classes to hold sets of particles.
Upper bound harmonic function (non-zero when feature > mean)
Object used to hold a set of restraints.
add harmonic restraints between all pairs
Low level functionality (logging, error handling, profiling, command line flags etc) that is used by ...
Dihedral restraint between four particles.
Return all close unordered pairs of particles taken from the SingletonContainer.
Return all close ordered pairs of particles taken from the two SingletonContainers.
Distance restraint between two particles.
A class to store an fixed array of same-typed values.
def __init__
ca_only: only applies for resolution 0
Store a kernel::ParticleIndexPairs.
A well with harmonic barriers.
Angle restraint between three particles.
add bond restraint between pair of consecutive residues/beads to enforce the stereochemistry.
add bonds and improper dihedral restraints for the CBs
Store a kernel::ParticleIndexes.
A decorator for a particle representing an atom.
A decorator for a particle with x,y,z coordinates.
add angular restraint between triplets of consecutive residues/beads to enforce the stereochemistry...
Find all nearby pairs by testing all pairs.
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...
static bool get_is_setup(const IMP::kernel::ParticleAdaptor &p)
all leaves of the input hierarchies will be input in the restraint.
static bool get_is_setup(const IMP::kernel::ParticleAdaptor &p)
def __init__
need to add: ca-ca bond ca-cb is a constraint, no restraint needed ca-ca-ca cb-ca-ca-cb ...
double get_distance(const VectorD< D > &v1, const VectorD< D > &v2)
Compute the distance between two vectors.
Applies a PairScore to a Pair.
Functionality for loading, creating, manipulating and scoring atomic structures.
Hierarchies get_leaves(const Selection &h)
def __init__
jitter: defines the +- added to the optimal distance in the harmonic well restraint used to increase ...
Applies a PairScore to each Pair in a list.
A repulsive potential on the distance between two atoms.
Perform more efficient close pair finding when rigid bodies are involved.
Inferential scoring building on methods developed as part of the Inferential Structure Determination ...
Harmonic function (symmetric about the mean)