Rosetta 3.5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
StrandPairing.cc
Go to the documentation of this file.
1 // -*- mode:c++;tab-width:2;indent-tabs-mode:t;show-trailing-whitespace:t;rm-trailing-spaces:t -*-
2 // vi: set ts=2 noet:
3 //
4 // (c) Copyright Rosetta Commons Member Institutions.
5 // (c) This file is part of the Rosetta software suite and is made available under license.
6 // (c) The Rosetta software is developed by the contributing members of the Rosetta Commons.
7 // (c) For more information, see http://www.rosettacommons.org. Questions about this can be
8 // (c) addressed to University of Washington UW TechTransfer, email: license@u.washington.edu.
9 
10 /// @brief
11 /// @detailed
12 ///
13 /// @author Oliver Lange, ported from dssp.cc in rosetta++ authored by Ben Blum (bblum)
14 /// @author Christopher Miles (cmiles@uw.edu)
15 
16 // Unit Headers
18 
19 // Package Headers
22 
23 // Project Headers
24 #include <core/types.hh>
25 #include <core/pose/Pose.hh>
26 
27 // ObjexxFCL Headers
28 #include "ObjexxFCL/FArray1D.hh"
29 #include "ObjexxFCL/FArray2D.hh"
30 
31 // Utility headers
32 #include <utility/vector1.fwd.hh>
33 #include <utility/exit.hh>
34 #include <basic/Tracer.hh>
35 
36 // C++ headers
37 #include <cstdlib>
38 #include <string>
39 #include <list>
40 #include <vector>
41 #include <iostream>
42 
43 // Options
44 #include <basic/options/option.hh> // for quick-test from run:dry_run
45 #include <basic/options/keys/jumps.OptionKeys.gen.hh>
46 
48 #include <utility/vector1.hh>
49 #include <boost/functional/hash.hpp>
50 
51 static basic::Tracer tr("core.scoring.dssp");
52 
53 using core::Real;
54 using namespace core;
55 using namespace basic;
56 using namespace ObjexxFCL;
57 
58 namespace core {
59 namespace scoring {
60 namespace dssp {
61 
62 ///////////////////////////////////////////////////////////////
63 /// @begin StrandPairingSet::StrandPairingSet
64 ///
65 /// @brief Constructor for set of StrandPairing objects
66 ///
67 /// @detailed
68 /// The incoming hbonds matrix is indexed by (acceptor residue,
69 /// donor residue). Residues with energy less than threshold are
70 /// considered paired, unless they are disallowed by the array
71 /// called allowed (this was included to prevent helical
72 /// residues from being considered paired, a problem which
73 /// occasionally arose).
74 ///
75 /// @param
76 ///
77 /// @global_read
78 ///
79 /// @global_write
80 ///
81 /// @remarks
82 ///
83 /// @references
84 ///
85 /// @authors bblum
86 ///
87 /// @last_modified
88 ///////////////////////////////////////////////////////////////
89 
90 StrandPairingSet::StrandPairingSet( pose::Pose const& pose, Real threshold ) {
91  ObjexxFCL::FArray2D_float hbond_bb_pair_score;
92  core::scoring::dssp::fill_hbond_bb_pair_score_dssp( pose, hbond_bb_pair_score );
93  compute( hbond_bb_pair_score, threshold, pose );
94 }
95 
96 StrandPairingSet::StrandPairingSet( FArray2_float const &hbonds,
97  float threshold, pose::Pose const& pose ) {
98  compute( hbonds, threshold, pose);
99 }
100 
101 StrandPairingSet::StrandPairingSet( core::scoring::dssp::PairingList const& in_pairings ) {
102  for ( core::scoring::dssp::PairingList::const_iterator it = in_pairings.begin(), eit = in_pairings.end();
103  it != eit; ++it ) {
104  add_pairing( *it );
105  }
106 }
107 
108 void StrandPairingSet::add_pairing( core::scoring::dssp::Pairing const& p ) {
109  add_pairing( p.Pos1(), p.Pos2(), p.is_anti(), p.Pleating() );
110 }
111 
112 void StrandPairingSet::compute( FArray2_float const &hbonds,
113  float threshold, pose::Pose const& pose ) {
114 
115  Size const nres( pose.total_residue() );
116 
117  for ( Size i = 2; i <= nres - 1; i++ ) {
118  for ( Size j = i + 1; j <= nres - 1; j++ ) {
119  if ( // antiparallel bridge
120  ( hbonds(i,j) < threshold
121  && hbonds(j,i) < threshold )
122  || ( hbonds(i-1,j+1) < threshold
123  && hbonds(j-1,i+1) < threshold ) ) {
124  Size orientation, pleating;
125  get_pleating(pose, i, j, orientation, pleating);
126  // tr.Debug << "found antiparallel pair at (" << i << "," << j << ") "<<std::endl;
127  add_pairing(i, j, true , pleating );
128  } else if ( // parallel bridge
129  ( hbonds(i-1,j) < threshold
130  && hbonds(j,i+1) < threshold )
131  || ( hbonds(j-1,i) < threshold
132  && hbonds(i,j+1) < threshold ) ) {
133  Size orientation, pleating;
134  get_pleating(pose, i, j, orientation, pleating);
135  // tr.Debug << "found parallel pair at (" << i << "," << j << ") "<<std::endl;
136  // tr.Trace << "ben: para phil: " << orientation << std::endl;
137  add_pairing(i,j, false, pleating );
138  }
139  }
140  }
141 }
142 
143 std::istream & operator>>( std::istream &is, StrandPairingSet &set ) {
144  std::string tag;
145  Size nstrand;
146  is >> tag >> nstrand;
147  if ( tag != "STRAND_TOPOLOGY" ) {
148  tr.Trace << "failed reading STRAND_TOPOLOGY --- found instead: " << tag << std::endl;
149  is.setstate( std::ios_base::failbit );
150  return is;
151  }
152  for ( Size ct = 1; ct <= nstrand && is.good(); ct++ ) {
153  StrandPairing sp;
154  is >> sp;
155  if ( is.good() ) {
156  set.pairings_.push_back( sp );
157  }
158  }
159  return is;
160 }
161 
162 std::ostream & operator<<(std::ostream & out, const StrandPairingSet &sp) {
163  out << "STRAND_TOPOLGY " << sp.pairings_.size() << std::endl;
164  for ( StrandPairingSet::const_iterator it = sp.pairings_.begin();
165  it != sp.pairings_.end(); it++ )
166  out << *it << std::endl;
167  return out;
168 }
169 
170 ///////////////////////////////////////////////////////////////
171 /// @begin StrandPairingSet::add_pairing
172 ///
173 /// @brief Add a new pair of bonded residues to the set
174 ///
175 /// @detailed
176 /// Look for a strand pairing to extend with the given pair of
177 /// residues; if none exists, create a new one.
178 ///
179 /// @param
180 ///
181 /// @global_read
182 ///
183 /// @global_write
184 ///
185 /// @remarks
186 ///
187 /// @references
188 ///
189 /// @authors bblum
190 ///
191 /// @last_modified
192 ///////////////////////////////////////////////////////////////
193 void StrandPairingSet::add_pairing( Size res1, Size res2, bool antiparallel, Size pleating) {
194  bool addnew = true;
195  // tr.Trace << "add pairing " << res1 << " " << res2 << (antiparallel ? " anti " : " para ") << std::endl;
196  for ( iterator it = pairings_.begin();
197  it != pairings_.end();
198  it++) {
199  if ( it->extend(res1,res2,antiparallel,pleating) ) {
200  addnew = false;
201  if ( !it->range_check() ) {
202  tr.Error << "[ERROR] just inconsistently added " << res1 << "-" << res2 << " to pairing " << *it << std::endl;
203  runtime_assert( false );
204  }
205  break;
206  }
207  }
208  bool added = false;
209  if( addnew ) {
210  StrandPairing add(res1,res2, antiparallel, pleating);
211  runtime_assert( add.range_check() );
212  for ( iterator it = pairings_.begin();
213  it != pairings_.end();
214  it++)
215  if( add < *it ) {
216  added = true;
217  pairings_.insert(it, add);
218  break;
219  }
220  if(!added)
221  pairings_.push_back(add);
222  }
223 }
224 
225 bool StrandPairingSet::merge(const StrandPairingSet &other, bool domerge) {
226  StrandPairings::iterator it = pairings_.begin();
227  StrandPairings::const_iterator oit = other.pairings_.begin();
228  while( it != pairings_.end() ) {
229  Size count = 0;
230  while( oit != other.pairings_.end() && it->merge(*oit, domerge) ) {
231  oit++;
232  count++;
233  }
234  if(count == 0)
235  return false;
236  it++;
237  }
238  if(oit != other.pairings_.end())
239  return false;
240  if ( domerge ) selfmerge();
241  return true;
242 }
243 
244 void StrandPairingSet::selfmerge() {
245  StrandPairings goodpairings(pairings_);
246  for(StrandPairings::iterator it = pairings_.begin();
247  it != pairings_.end();
248  it++)
249  for(StrandPairings::iterator oit = pairings_.begin();
250  oit != it;
251  oit++)
252  while(oit != it && it->merge(*oit, true))
253  oit = pairings_.erase(oit);
254 }
255 
256 bool StrandPairingSet::check_pleat() const {
257  for(StrandPairings::const_iterator it = pairings_.begin();
258  it != pairings_.end();
259  it++) {
260  if(!it->check_pleat())
261  return false;
262  }
263  return true;
264 }
265 
266 bool StrandPairing::check_pleat() const {
267  for(Size i = 1; i < (Size)pleating1.size(); i++) {
268  if(pleating1[i] == pleating1[i-1] && pleating1[i] != 0)
269  return false;
270  }
271  return true;
272 }
273 
274 core::Size StrandPairing::contact_order() const {
275  if ( antiparallel() ) {
276  return end2_-begin1_;
277  } else {
278  return begin2_-begin1_;
279  }
280  return 0;
281 }
282 
283 ///////////////////////////////////////////////////////////////
284 /// @begin StrandPairing::extend
285 ///
286 /// @brief If possible, extend this pairing by the given residues.
287 ///
288 /// @detailed
289 /// If one of res1 or res2 is within 2 residues of the beginning
290 /// or end of one of the strands of the pairing, and the other
291 /// is within 5 residues, extend the pairing. This is the dssp
292 /// definition of allowable beta bulges. Return true if the
293 /// pairing was extended.
294 // Assumes we are running through res1 and res2 in an ordered
295 // way, so we extend at the beginning or end of the strand.
296 ///
297 /// @param
298 ///
299 /// @global_read
300 ///
301 /// @global_write
302 ///
303 /// @remarks
304 ///
305 /// @references
306 ///
307 /// @authors bblum
308 ///
309 /// @last_modified
310 ///////////////////////////////////////////////////////////////
311 bool StrandPairing::extend( Size res1, Size res2, bool antiparallel, Size pleating ) {
312  StrandPairing old_copy( *this );
313  // Make sure res1 < res2
314  Size temp = std::min(res1, res2);
315  res2 = std::max(res1, res2);
316  res1 = temp;
317  if(begin1_ == 0) { // uninitialized
318  begin1_ = end1_ = res1;
319  begin2_ = end2_ = res2;
320  antipar = antiparallel;
321  pairing1.push_back( antipar ? end2_ : begin2_);
322  pairing2.push_back( antipar ? end1_ : begin1_ );
323  pleating1.push_back(pleating);
324  }
325 
326  const Size SMALL_BULGE_LIMIT( basic::options::option[ basic::options::OptionKeys::jumps::max_strand_gap_allowed] );
327  const Size BIG_BULGE_LIMIT( SMALL_BULGE_LIMIT + 3 );
328 
329  bool cando = false;
330  if(res1 >= begin1_ && res1 <= end1_) { // trivial--already in our strand
331  tr.Trace <<"trivial case " << std::endl;
332  cando = (pairing1[res1 - begin1_] == res2);
333  } else if(res1 > end1_ && res1 <= end1_ + BIG_BULGE_LIMIT) {
334  tr.Trace << "case1 " << std::endl;
335  if(antiparallel) {
336  if(res1 > end1_ + SMALL_BULGE_LIMIT)
337  cando = (res2 < begin2_ && res2 + SMALL_BULGE_LIMIT >= begin2_ );
338  else
339  cando = (res2 < begin2_ && res2 + BIG_BULGE_LIMIT >= begin2_ );
340  } else {
341  if(res1 > end1_ + SMALL_BULGE_LIMIT) //bulge of size > 1
342  cando = (res2 > end2_ && res2 <= end2_ + SMALL_BULGE_LIMIT);
343  else
344  cando = (res2 > end2_ && res2 <= end2_ + BIG_BULGE_LIMIT);
345  }
346  } else if(res1 < begin1_ && res1 + BIG_BULGE_LIMIT >= begin1_ ) {
347  tr.Trace << "case2 "<< std::endl;
348  if(antiparallel) {
349  if( res1 + SMALL_BULGE_LIMIT < begin1_ )
350  cando = (res2 > end2_ && res2 <= end2_ + SMALL_BULGE_LIMIT);
351  else
352  cando = (res2 > end2_ && res2 <= end2_ + BIG_BULGE_LIMIT);
353  } else {
354  if(res1 + SMALL_BULGE_LIMIT < begin1_) //bulge of size > 1
355  cando = (res2 < begin2_ && res2 + SMALL_BULGE_LIMIT >= begin2_);
356  else
357  cando = (res2 < begin2_ && res2 + BIG_BULGE_LIMIT >= begin2_ );
358  }
359  }
360  runtime_assert( begin1_ <= end1_ );
361  runtime_assert( begin2_ <= end2_ );
362 
363  // if extendable, insert this pairing in, adjust begins and ends
364  if(cando) {
365  tr.Trace << "extend " << *this << " to residues " << res1 << " " << res2 << std::endl;
366  if(res1 < begin1_) {
367  if(res1 + 1 < begin1_) {
368  pairing1.insert(pairing1.begin(),begin1_ - res1 - 1, 0);
369  pleating1.insert(pleating1.begin(),begin1_ - res1 - 1, 0);
370  }
371  pairing1.insert(pairing1.begin(), res2);
372  pleating1.insert(pleating1.begin(), pleating);
373  begin1_ = res1;
374  } else if(res1 > end1_) {
375  if(res1 > end1_ + 1) {
376  //add res1-end1_-1 0 to vector
377  pairing1.insert(pairing1.end(), res1 - end1_ - 1, 0);
378  pleating1.insert(pleating1.end(), res1 - end1_ - 1, 0);
379  }
380  pairing1.push_back( res2 );
381  pleating1.push_back( pleating );
382  end1_ = res1;
383  }
384 
385  if(res2 < begin2_) {
386  if(res2 + 1 < begin2_ )
387  pairing2.insert(pairing2.begin(),begin2_ - res2 - 1, 0);
388  pairing2.insert(pairing2.begin(), res1);
389  begin2_ = res2;
390  } else if(res2 > end2_) {
391  if(res2 > end2_ + 1)
392  pairing2.insert(pairing2.end(), res2 - end2_ - 1, 0);
393  pairing2.insert(pairing2.end(), res1);
394  end2_ = res2;
395  }
396  } else {
397  tr.Trace << " cannot extend "<< *this << " to residues " << res1 << " " << res2 << std::endl;
398  }
399 
400  show_internals(tr.Trace );
401  if ( !valid_ends() ) {
402  *this = old_copy;
403  return false;
404  }
405  return cando;
406 }
407 
408 void StrandPairing::extend_to(Size res) {
409  Size res1, res2, pleat, diff = (antipar ? -1 : 1);
410  if(res < begin1_) {
411  res1 = begin1_ - 1;
412  res2 = pairing1[0] - diff;
413  pleat = 3 - pleating1[0];
414  while(res1 >= res) {
415  extend(res1, res2, antipar, pleat);
416  res1 = res1 - 1;
417  res2 = res2 - diff;
418  pleat = 3 - pleat;
419  }
420  } else if(res > end1_) {
421  res1 = end1_ + 1;
422  res2 = pairing1[end1_ - begin1_] + diff;
423  pleat = 3 - pleating1[end1_ - begin1_];
424  while(res1 <= res) {
425  extend(res1, res2, antipar, pleat);
426  res1 += 1;
427  res2 += diff;
428  pleat = 3 - pleat;
429  }
430  }
431 }
432 
433 void StrandPairing::show_internals( std::ostream& out ) const {
434  out << "pairing1: ";
435  for ( Size i=0; i < pairing1.size(); i++) {
436  out << pairing1[ i ] << " ";
437  }
438  out <<"\npairing2: ";
439  for ( Size i=0; i < pairing2.size(); i++) {
440  out << pairing2[ i ] << " ";
441  }
442  out <<"\npairing2: ";
443  for ( Size i=0; i < pleating1.size(); i++) {
444  out << pleating1[ i ] << " ";
445  }
446  out << std::endl;
447 }
448 
449 std::size_t StrandPairing::hash_value() const {
450  std::ostringstream str;
451  str << (antipar ? 'A' : 'P') << '_';
452  core::Size regA, regE;
453  if (antipar) {
454  regA=begin1_ + end2_;
455  regE=end1_ + begin2_;
456  } else {
457  regA=begin2_-begin1_;
458  regE=end2_-end1_;
459  }
460  str << regA << '_' << regE;
461  return boost::hash_value(str.str());
462 }
463 
464 bool StrandPairing::mergeable( const StrandPairing &other ) const {
465  tr.Trace << "compare " << *this << " to " << other << std::endl;
466  if ( antipar != other.antipar) {
467  tr.Trace << " not the same directionality " << std::endl;
468  return false;
469  }
470 
471  // Make sure both strands overlap (or at least almost overlap)
472  const Size MARGIN( basic::options::option[ basic::options::OptionKeys::jumps::max_strand_gap_allowed] - 1 );
473  if ( begin1_ > other.end1_ + MARGIN || begin2_ > other.end2_ + MARGIN
474  || other.begin1_ > end1_ + MARGIN || other.begin2_ > end2_ + MARGIN ) {
475  tr.Trace << " no overlap between strands " << std::endl;
476  tr.Trace << "begin1_ end1 begin2 end2 (repeat with other ) " <<
477  begin1_ << " " << end1_ << " " << begin2_ << " " << end2_ << " " <<
478  other.begin1_ << " " << other.end1_ << " " << other.begin2_ << " " << other.end2_ << " " << std::endl;
479  return false;
480  }
481 
482  // Make sure the merged strands won't overlap
483  if ( end1_ >= other.begin2_ || other.end1_ >= begin2_ ) {
484  tr.Trace << "merged strands will overlap " << std::endl;
485  return false;
486  }
487  tr.Trace << "passed presecreen" << std::endl;
488  // Make sure starting and ending registers match up
489  // (redundant with later, rigorous test, but quick and easy
490  // and gets rid of most pairs of unmergeable topologies)
491  if(antipar) {
492  if((begin1_ + end2_ != other.begin1_ + other.end2_) ||
493  (end1_ + begin2_ != other.end1_ + other.begin2_)) {
494  tr.Trace << "register mismatch " << std::endl;
495  return false;
496  }
497  } else {
498  if((begin1_ + other.begin2_ != other.begin1_ + begin2_) ||
499  (end1_ + other.end2_ != other.end1_ + end2_ )) {
500  tr.Trace << "register mismatch " << std::endl;
501  return false;
502  }
503  }
504 
505  runtime_assert( end1_ - begin1_ < pleating1.size() );
506  runtime_assert( end2_ - begin2_ < pairing2.size() );
507  StrandPairing myex(*this);
508  myex.extend_to(other.begin1_);
509  myex.extend_to(other.end1_);
510 
511  StrandPairing otherex(other);
512  otherex.extend_to(begin1_);
513  otherex.extend_to(end1_);
514 
515  if (myex.end2_ != otherex.end2_ || myex.begin2_ != otherex.begin2_) {
516  tr.Debug << "SURPRISE!\n" << myex << "\n" << otherex << "\n" << *this << "\n" << other << "\n" << std::endl;
517  return false;
518  }
519 
520  // Make sure pairings, bulges, and pleats match up.
521  for(Size i = 0; i <= myex.end1_ - myex.begin1_; i++) {
522  runtime_assert( i < myex.pleating1.size() && i < otherex.pleating1.size() );
523  if(myex.pleating1[i] != otherex.pleating1[i] && myex.pleating1[i] > 0 && otherex.pleating1[i] > 0) {
524  tr.Trace << " wrong pleating " << std::endl;
525  return false;
526  }
527  runtime_assert( i < myex.pairing1.size() && i < otherex.pairing1.size() );
528  if(myex.pairing1[i] != otherex.pairing1[i] && myex.pairing1[i] > 0 && otherex.pairing1[i] > 0) {
529  tr.Trace << "wrong pairing1 " << std::endl;
530  return false;
531  }
532  }
533  for(Size i = 0; i <= myex.end2_ - myex.begin2_; i++) {
534  runtime_assert( i < myex.pairing2.size() && i < otherex.pairing2.size() );
535  if(myex.pairing2[i] != otherex.pairing2[i] && myex.pairing2[i] > 0 && otherex.pairing2[i] > 0) {
536  tr.Trace << "wrong pairing2 :" << myex.pairing2[i] << " " << otherex.pairing2[i] << std::endl;
537  return false;
538  }
539  }
540  tr.Trace << "EQUAL" << std::endl;
541  return true;
542 }
543 
544 bool StrandPairing::merge(const StrandPairing &other, bool domerge) {
545  bool possible ( mergeable( other ) );
546  if( domerge && possible ) {
547  StrandPairing myex(*this);
548  myex.extend_to(other.begin1_);
549  myex.extend_to(other.end1_);
550 
551  StrandPairing otherex(other);
552  otherex.extend_to(begin1_);
553  otherex.extend_to(end1_);
554 
555  //bool changed = other.begin1_ < begin1_ || other.end1_ > end1_;
556  // Now do actual merge
557  // Add in holes in myex extension that are present in otherex
558  for(Size res = myex.begin1_; res <= myex.end1_; res++) {
559  Size i = res - myex.begin1_;
560  if((res < begin1_ || res > end1_) && otherex.pairing1[i] == 0) {
561  if(myex.pairing1[i] == 0 || otherex.pairing2[myex.pairing1[i] - otherex.begin2_] > 0)
562  std::cout << "SERIOUS PROBLEM.\n";
563  myex.pairing2[myex.pairing1[i] - myex.begin2_] = 0;
564  myex.pairing1[i] = myex.pleating1[i] = 0;
565  }
566  // Fill in holes in myex overlap with values from otherex
567  if(res >= std::max(begin1_,other.begin1_) && res <= std::min(end1_,other.end1_) && myex.pairing1[i] == 0 && otherex.pairing1[i] > 0) {
568  if(myex.pairing2[otherex.pairing1[i]-myex.begin2_] > 0)
569  std::cout << "ANOTHER SERIOUS PROBLEM.\n";
570  myex.pairing1[i] = otherex.pairing1[i];
571  myex.pleating1[i] = otherex.pleating1[i];
572  myex.pairing2[otherex.pairing1[i] - myex.begin2_] = res;
573  //changed = true; // set but never used ~Labonte
574  }
575  }
576  if ( !myex.valid_ends() ) return false;
577  *this = myex;
578  }
579  return possible;
580 }
581 
583  if ( res >= begin1_ && res <= end1_ ) {
584  return pleating1[res - begin1_];
585  } else if ( res >= begin2_ && res <= end2_ ) {
586  if ( pairing2[res - begin2_] != 0 )
587  return pleating1[pairing2[res-begin2_]];
588  else
589  return 0;
590  } else
591  return 0;
592 }
593 
594 // Returns the DSSP designation of the given residue (' ' if
595 // unpaired)
596 char StrandPairingSet::dssp_state( Size res ) const {
597  char state = ' ';
598  for(StrandPairings::const_iterator it = pairings_.begin();
599  it != pairings_.end();
600  it++)
601  if(it->contains(res)) {
602  if(it->is_ladder())
603  state = 'E';
604  else if(state == ' ')
605  state = 'B';
606  }
607  return state;
608 }
609 
610 char StrandPairingSet::featurizer_state(Size res) const {
611  char state = 'L';
612  for(StrandPairings::const_iterator it = pairings_.begin();
613  it != pairings_.end();
614  it++)
615  if(it->contains(res)) {
616  if(it->is_bulge(res)) {
617  if(state == 'e')
618  state = 'B';
619  else if(state == 'b')
620  state = 'X';
621  else
622  state = 'b';
623  } else {
624  if(state == 'e')
625  state = 'E';
626  else if(state == 'b')
627  state = 'B';
628  else
629  state = 'e';
630  }
631  }
632  return state;
633 }
634 
635 bool StrandPairingSet::has_pairing( core::scoring::dssp::Pairing const& p ) const {
636  return paired( p.Pos1(), p.Pos2(), p.is_anti() );
637 }
638 
639 bool StrandPairingSet::has_pairing( StrandPairing const& p ) const {
640  bool found ( false );
641  for ( StrandPairings::const_iterator it = pairings_.begin();
642  it != pairings_.end() && !found; it++) {
643  found = p.mergeable( *it );
644  }
645  return found;
646 }
647 
648 bool StrandPairing::has_pairing( core::scoring::dssp::Pairing const& p ) const {
649  return paired( p.Pos1(), p.Pos2(), p.is_anti() );
650 }
651 
652 bool StrandPairing::paired( Size res1, Size res2, bool antipar ) const {
653  return ( antiparallel() == antipar && contains( res1 ) && get_pair( res1 ) == res2 );
654 }
655 
656 bool StrandPairingSet::paired(Size res1, Size res2, bool antiparallel) const {
657  for ( StrandPairings::const_iterator it = pairings_.begin();
658  it != pairings_.end(); it++) {
659  if ( it->paired( res1, res2, antiparallel ) ) {
660  return true;
661  }
662  }
663  return false;
664 }
665 
666 //////////////////////////////////////////////////////////////////////////
667 // Handy function for getting out a list of easy-to-read beta pairings.
668 //////////////////////////////////////////////////////////////////////////
669 void StrandPairingSet::get_beta_pairs( core::scoring::dssp::PairingList & beta_pairs ) const {
670  for( StrandPairings::const_iterator it = pairings_.begin(),
671  eit = pairings_.end(); it!=eit; it++) {
672  it->get_beta_pairs( beta_pairs );
673  }
674 }
675 
676 StrandPairingSet::~StrandPairingSet() {
677 }
678 
679 StrandPairing::StrandPairing(Size res1, Size res2, bool antiparallel, Size pleating) :
680  begin1_( std::min( res1, res2 ) ), end1_(begin1_),
681  begin2_( std::max( res1, res2 ) ), end2_(begin2_),
682  antipar(antiparallel)
683 {
684  pairing1.push_back( antipar ? end2_ : begin2_ );
685  pairing2.push_back( antipar ? begin1_ : end1_ );
686  pleating1.push_back(pleating);
687 }
688 
689 StrandPairing::StrandPairing() : begin1_(0),end1_(0), begin2_(0), end2_(0), antipar(true) {
690 }
691 
693 }
694 
696  if ( antipar ) {
697  return begin1_ + pairing1[0];
698  } else {
699  return pairing1[0] - begin1_;
700  }
701 }
702 
704  if ( antipar ) {
705  Size reg = begin1_ + pairing1[0];
706  regs.push_back( reg );
707  for ( Size i = 1; ( Size)i < pairing1.size(); i++) {
708  if( pairing1[i] != 0 && begin1_ + i + pairing1[i] != reg ) {
709  reg = begin1_ + i + pairing1[i];
710  regs.push_back( reg );
711  bulges.push_back( begin1_ + i - 1 );
712  }
713  }
714  } else {
715  Size reg = pairing1[0] - begin1_;
716  regs.push_back( reg );
717  for ( Size i = 1; ( Size)i < pairing1.size(); i++ ) {
718  if ( pairing1[i] != 0 && pairing1[i] - begin1_ - i != reg ) {
719  reg = pairing1[i] - begin1_ - i;
720  regs.push_back( reg );
721  bulges.push_back( begin1_ + i - 1 );
722  }
723  }
724  }
725 }
726 
728  return (end1_-begin1_ + 1 == pairing1.size() ) && ( end2_-begin2_ + 1 == pairing2.size() );
729 }
730 
731 std::istream & operator>>( std::istream &is, StrandPairing &sp ) {
732  using namespace std;
733  char direction;
734  is >> direction;
735  if ( direction == 'A' ) {
736  sp.antipar = true;
737  } else if ( direction == 'P' ) {
738  sp.antipar = false;
739  } else {
740  tr.Trace << "failed reading A/P info --- found instead: " << direction << std::endl;
741  is.setstate( std::ios_base::failbit );
742  return is;
743  }
744 
745  char minus;
746  string to;
747  if ( sp.antipar ) {
748  is >> sp.begin1_ >> minus >> sp.end2_ >> to >> sp.end1_ >> minus >> sp.begin2_;
749  tr.Trace << "read " << sp.begin1_ << "-" << sp.end2_ << " to " << sp.end1_ << "-" << sp.begin2_ << std::endl;
750  } else {
751  is >> sp.begin1_ >> minus >> sp.begin2_ >> to >> sp.end1_ >> minus >> sp.end2_;
752  tr.Trace << "read " << sp.begin1_ << "-" << sp.begin2_ << " to " << sp.end1_ << "-" << sp.end2_ << std::endl;
753  }
754  if ( minus != '-' ) {
755  tr.Trace << "failed reading start pairing --- found instead: " << sp.begin1_ << minus << sp.end2_ << std::endl;
756  is.setstate( std::ios_base::failbit );
757  return is;
758  }
759 
760  string regstr;
761  is >> regstr;
762  if ( regstr != "reg:" ) {
763  tr.Trace << "failed reading register tag --- found instead: " << regstr << std::endl;
764  is.setstate( std::ios_base::failbit );
765  return is;
766  }
767 
768  runtime_assert( !is.fail() );
769 
771  Size reg1;
772  string comma (",");
773  while ( comma == "," && is >> reg1 >> comma ) {
774  regs.push_back( reg1 );
775  }
776 
777  if ( comma != "bulges:" && comma != "pleating:" ) {
778  tr.Trace << "failed reading bulges tag --- found instead: " << comma << std::endl;
779  is.setstate( std::ios_base::failbit );
780  return is;
781  }
782 
783  if ( tr.Trace.visible() ) {
784  tr.Trace << " regs: ";
785  for ( utility::vector1< Size >::iterator it = regs.begin(), eit = regs.end();
786  it != eit; ++it ) {
787  tr.Trace << *it << " ";
788  }
789  }
790 
792  if ( comma == "bulges:" ) {
793  comma = ",";
794  Size bulge;
795  while ( comma == "," && is >> bulge >> comma ) {
796  bulges.push_back( bulge );
797  }
798  }
799 
800  if ( tr.Trace.visible() ) {
801  tr.Trace << " bulges: ";
802  for ( utility::vector1< Size >::iterator it = bulges.begin(), eit = bulges.end();
803  it != eit; ++it ) {
804  tr.Trace << *it << " ";
805  }
806  }
807 
808  if ( comma != "pleating:" ) {
809  tr.Trace << "failed reading pleating tag --- found instead: " << comma << std::endl;
810  is.setstate( std::ios_base::failbit );
811  return is;
812  }
813 
814  // work out how many pairings we have.. then read pleatings
815  utility::vector1< Size >::iterator regit = regs.begin(), eregit = regs.end();
816  utility::vector1< Size >::iterator bulgeit = bulges.begin(), ebulgeit = bulges.end();
817  Size reg = *regit;
818  int dir = sp.antipar ? -1 : 1;
819  Size bulge = 0;
820  for ( Size pos1 = sp.begin1_,
821  pos2 = sp.antipar ? sp.end2_ : sp.begin2_; pos1 <= sp.end1_; pos1++ ) {
822  Size pleat;
823  is >> pleat;
824  runtime_assert( ( sp.antipar ? sp.end2_ - pos2 : pos2 - sp.begin2_ ) == sp.pairing2.size() );
825  reg = *regit;
826  if ( bulgeit != ebulgeit ) bulge = *bulgeit;
827  else bulge = 0;
828  tr.Trace << " pos1 " << pos1 << " next bulge " << bulge << " pos2 " << pos2 << std::endl;
829 
830  if ( pleat == 0 ) { //unsatisfied residue is in strand 1
831  sp.pairing1.push_back( 0 );
832  sp.pleating1.push_back( 0 );
833  //work out if we have a bulge on strand1, ie. their is no corresponding pairing on strand2
834  bool bulge2( false );
835  {
836  utility::vector1< Size >::iterator next_regit = regit;
837  if ( next_regit != eregit ) ++next_regit;
838  if ( next_regit != eregit ) {
839  Size nex_reg = *next_regit;
840  bulge2 = sp.antipar ? nex_reg > reg : nex_reg < reg;
841  }
842  }
843  if ( !bulge2 && !bulge ) {
844  sp.pairing2.insert( sp.antipar ? sp.pairing2.begin() : sp.pairing2.end(), 0 );
845  pos2+=dir;
846  }
847  } else { //
848  sp.pairing1.push_back( pos2 );
849  sp.pleating1.push_back( pleat );
850  sp.pairing2.insert( sp.antipar ? sp.pairing2.begin() : sp.pairing2.end(), pos1 );
851  pos2+=dir;
852  }
853 
854  if ( pos1 == bulge ) {
855  if ( regit == eregit ) {
856  tr.Error << "read bulge at " << bulge << " but no new register in list " << std::endl;
857  is.setstate( std::ios_base::failbit );
858  return is;
859  }
860  ++regit;++bulgeit;
861 
862  Size new_pos2 = sp.antipar ? ( *regit - pos1 - 1 ) : ( *regit + pos1 + 1);
863  tr.Trace << "jump to " << new_pos2 << " in strand2 due to new register " << *regit << " after bulge at " << bulge << std::endl;
864  if ( sp.antipar && new_pos2 < pos2 ) {
865  sp.pairing2.insert( sp.pairing2.begin(), pos2 - new_pos2, 0 );
866  } else if ( !sp.antipar && new_pos2 > pos2 ) {
867  sp.pairing2.insert( sp.pairing2.end(), new_pos2 - pos2, 0 );
868  }
869  pos2 = new_pos2;
870  }
871  } //for ... pos1 = begin1 .. end1
872 
873  if ( sp.begin1_ > sp.end1_ || sp.begin2_ > sp.end2_ ) {
874  tr.Error << "begin1 end1 begin2 end2 " << sp.begin1_ << " " << sp.end1_ << " " << sp.begin2_ << " " << sp.end2_ << std::endl;
875  utility_exit_with_message( "error reading pairing from stream " );
876  }
877 
878  tr.Trace << std::endl;
879  runtime_assert( !is.fail() );
880  sp.show_internals( tr.Trace );
881  return is;
882 }
883 
884 std::ostream & operator<<(std::ostream & out, const StrandPairing &sp) {
885  runtime_assert( sp.begin1_ <= sp.end1_ );
886  runtime_assert( sp.begin2_ <= sp.end2_ );
887  out << (sp.antipar ? 'A' : 'P') << ' ' << sp.begin1_ << '-' << sp.pairing1[0] << " to " << sp.end1_ << '-' << sp.pairing1[sp.pairing1.size()-1] << " reg: ";
888 
889  StrandPairing::SizeList regs,bulges;
890  sp.get_all_register_and_bulges( regs, bulges );
891  bool first( true );
892  for ( StrandPairing::SizeList::const_iterator it = regs.begin(), eit = regs.end(); it != eit; ++it ) {
893  if ( !first ) {
894  out << ", ";
895  }
896  out << *it;
897  first = false;
898  }
899  first = true;
900  if ( bulges.size() ) {
901  out << " bulges: ";
902  for ( StrandPairing::SizeList::const_iterator it = bulges.begin(), eit = bulges.end(); it != eit; ++it ) {
903  if ( !first ) {
904  out << ", ";
905  }
906  out << *it;
907  first = false;
908  }
909  out << " ";
910  }
911  out << " pleating: ";
912  for( Size i = 0; i < sp.pleating1.size(); i++)
913  out << sp.pleating1[i] << ' ';
914  return out;
915 }
916 
918  if( antipar != other.antipar )
919  return antipar;
920 
921  Size reg = antipar ? pairing1[0] + begin1_ : pairing1[0] - begin1_;
922  Size otherreg = antipar ? other.pairing1[0] + other.begin1_ : other.pairing1[0] - other.begin1_;
923  if(reg == otherreg) {
924  if(end1_ <= other.begin1_)
925  return true;
926  else if(begin1_ >= other.end1_)
927  return false;
928  else {
929  std::cout << "DSSP error: strange strand pairing\n";
930  std::cout << begin1_ << ' ' << end1_ << ' ' << begin2_ << ' ' << end2_ <<' ' << std::endl;
931  std::cout << other.begin1_ << ' ' << other.end1_ << ' ' << other.begin2_ << ' ' << other.end2_ <<' ' << std::endl;
932  return begin1_ < other.begin1_;
933  }
934  } else
935  return reg < otherreg;
936 }
937 
939  for ( Size i = begin1_; i <= end1_; i++) {
940  if ( pairing1[ i - begin1_ ] != 0) {
941  Pairing pair;
942  pair.Pos1(i);
943  pair.Pos2(pairing1[ i - begin1_ ]);
944  pair.Orientation(antipar ? 1 : 2);
945  pair.Pleating(pleating1[ i - begin1_ ]);
946  if ( other.has_pairing( pair ) ) return true;
947  }
948  }
949  return false;
950 }
951 
953  return (begin1_ == other.begin1_ && begin2_ == other.begin2_ &&
954  end1_ == other.end1_ && end2_ == other.end2_ &&
955  pairing1 == other.pairing1 && pairing2 == other.pairing2 &&
956  pleating1 == other.pleating1);
957 }
958 
959 // Return true if the given residue is part of a beta bulge
960 bool StrandPairing::is_bulge(Size res) const {
961  if (! contains(res) ) return false;
962  if (get_pair(res) != 0 ) return false;
963  return true;
964 }
965 
966 // Return true if the given residue is part of this pairing
967 // (includes bulges)
968 bool StrandPairing::contains(Size res) const {
969  return (res >= begin1_ && res <= end1_) || (res >= begin2_ && res <= end2_);
970 }
971 
972 // Return the residue to which the given residue is paired
973 // (0 if the residue is unpaired, i.e. a bulge residue, or
974 // is not contained in the pairing at all)
976  if(res >= begin1_ && res <= end1_)
977  return pairing1[res-begin1_];
978  else if(res >= begin2_ && res <= end2_)
979  return pairing2[res-begin2_];
980  else
981  return 0;
982 }
983 
984 // Return true if this pairing is of length greater than 1.
986  return end1_-begin1_ > 0 && end2_-begin2_ > 0;
987 }
988 
990  return antipar;
991 }
992 
994  for ( Size i = begin1_; i <= end1_; i++) {
995  if ( pairing1[ i - begin1_ ] != 0) {
997  pair.Pos1(i);
998  pair.Pos2(pairing1[ i - begin1_ ]);
999  pair.Orientation(antipar ? 1 : 2);
1000  pair.Pleating(pleating1[ i - begin1_ ]);
1001  beta_pairs.push_back( pair );
1002  }
1003  }
1004 }
1005 
1007  if ( antipar ) { ///bad pairing don't write
1008  Size end2( pairing1[ 0 ] );
1009  Size begin2( pairing1[ pairing1.size()-1 ] );
1010  if ( begin2 > end2 ) return false;
1011  } else {
1012  Size begin2( pairing1[ 0 ] );
1013  Size end2( pairing1[ pairing1.size()-1 ] );
1014  if ( begin2 > end2 ) return false;
1015  }
1016  return true;
1017 }
1018 
1019 }
1020 }
1021 }