Rosetta 3.5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
HybridizeFoldtreeDynamic.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 A mover to dynamically manipulate fold tree during the template hybridization sampling
11 /// @detailed based on Chris Miles's start tree builder
12 /// @file protocols/hybridization/HybridizeFoldtreeDynamic.cc
13 /// @author Yifan Song, David Kim
14 
15 // Unit headers
17 
18 // C/C++ headers
19 #include <string>
20 #include <utility>
21 
22 // Utility headers
23 #include <basic/options/option.hh>
24 #include <basic/options/keys/OptionKeys.hh>
25 #include <basic/options/keys/in.OptionKeys.gen.hh>
26 #include <numeric/util.hh>
27 #include <numeric/xyzVector.hh>
28 #include <numeric/random/DistributionSampler.hh>
29 #include <ObjexxFCL/FArray1D.hh>
30 #include <ObjexxFCL/FArray2D.hh>
31 #include <utility/vector1.hh>
32 
33 // Project headers
34 #include <core/types.hh>
37 #include <core/pose/Pose.hh>
38 #include <core/pose/util.hh>
39 #include <core/scoring/rms_util.hh>
40 #include <protocols/loops/Loop.hh>
41 #include <protocols/loops/Loops.hh>
42 #include <protocols/loops/util.hh>
44 
45 // symmetry
54 
55 #include <basic/Tracer.hh>
56 
57 //Auto Headers
59 
60 static basic::Tracer TR( "protocols.hybridization.HybridizeFoldtreeDynamic" );
61 static numeric::random::RandomGenerator RG(65433);
62 
63 namespace protocols {
64 namespace hybridization {
65 
67 
69  // complete the chunks to cover the whole protein and customize cutpoints
70  // cutpoints in the middle of the loop
71  // cut number is the residue before the cut
72  std::string cut_point_decision = "middle_L";
73 
74  using utility::vector1;
75  vector1<core::Size> cuts_orig;
78 
79  utility::vector1<bool> cut_options(n_residues, true);
80 
81  // not allowing cuts in the core_chunks, currectly is set by the secondary structure of the initial template
82  for (core::Size ichunk = 1; ichunk<=core_chunks_.num_loop(); ++ichunk) {
83  for (core::Size ires = core_chunks_[ichunk].start(); ires <= core_chunks_[ichunk].stop()-1; ++ires) {
84  cut_options[ires] = false;
85  }
86  }
87 
88  utility::vector1 < core::Size > cut_positions;
89  for (core::Size i=2; i<=core_chunks_.num_loop(); ++i) {
90  core::Size loop_start = core_chunks_[i-1].stop();
91  core::Size loop_end = core_chunks_[i].start() - 1;
92  core::Size cut;
93 
94  if (loop_start >= loop_end) {
95  cut = loop_start;
96  }
97  else {
98  // if there is a cut in the original foldtree (in multi-chain cases), use that cut
99  bool cut_found = false;
100  for (core::Size i_cut_old = 1; i_cut_old <= cuts_orig.size(); ++i_cut_old) {
101  if (cuts_orig[i_cut_old] >= loop_start && cuts_orig[i_cut_old] <= loop_end) {
102  cut = cuts_orig[i_cut_old];
103  TR.Debug << "Respect the input cut position: " << cut << std::endl;
104  cut_found = true;
105  break;
106  }
107  }
108  if (! cut_found) {
109  if ( cut_point_decision == "middle") {
110  cut = (loop_start + loop_end ) /2;
111  }
112  else if ( cut_point_decision == "middle_L" ) {
113  cut = (loop_start + loop_end ) /2;
114  if (pose.secstruct(cut) != 'L') {
116  for (core::Size ic = cut-1; ic>=loop_start;--ic) {
117  if (pose.secstruct(ic) == 'L') {
118  candidates.push_back(ic);
119  break;
120  }
121  }
122  for (core::Size ic = cut+1; ic<=loop_end;++ic) {
123  if (pose.secstruct(ic) == 'L') {
124  candidates.push_back(ic);
125  break;
126  }
127  }
128  if (candidates.size())
129  cut = candidates[RG.random_range(1,candidates.size())];
130  }
131  }
132  else if ( cut_point_decision == "combine" ) {
133  utility::vector1 < core::Size > cut_residues;
134  for (core::Size ires = loop_start; ires <= loop_end; ++ires) {
135  if (cut_options[ires]) {
136  cut_residues.push_back(ires);
137  }
138  }
139  if (cut_residues.size() > 0) {
140  using boost::math::normal;
141  using core::Size;
142  using numeric::random::DistributionSampler;
143 
144  double mu = cut_residues.size() / 2.0;
145  double sigma = cut_residues.size() / 5.0;
146  normal distribution(mu, sigma);
147  DistributionSampler<normal> sampler(distribution);
148 
149  // Clamp insertion position to closed interval [start, stop]
150  Size position = static_cast<Size>(sampler.sample());
151  position = numeric::clamp<core::Size>(position, 1, cut_residues.size());;
152 
153  cut = cut_residues[position];
154  }
155  else {
156  cut = (loop_start + loop_end ) /2;
157  }
158  }
159  else {
160  utility_exit_with_message("do not know how to make cut points");
161  }
162  }
163  }
164  cut_positions.push_back(cut);
165  TR << "Cutpoint " << i << " at " << cut << std::endl;
166  TR << " Loop SS: ";
167  std::string jnk;
168  for (core::Size ic = loop_start; ic<=loop_end;++ic) {
169  TR << pose.secstruct(ic);
170  jnk += (ic == cut) ? "*" : "-";
171  }
172  TR << std::endl;
173  TR << " " << jnk << std::endl;
174  }
175  return cut_positions;
176 }
177 
179  utility::vector1 < core::Size > cut_positions,
180  core::Size n_residues
181 )
182 {
183  assert(cut_positions.size() == core_chunks_.size() - 1);
184 
186  for (core::Size i=1; i<=chunks_.num_loop(); ++i) {
187  if (i==1) {
188  chunks_[i].set_start(1);
189  } else {
190  core::Size new_start = cut_positions[i-1] + 1;
191  chunks_[i].set_start( new_start );
192  }
193 
194  if (i==chunks_.num_loop()) {
195  chunks_[i].set_stop(n_residues);
196  } else {
197  core::Size new_stop = cut_positions[i];
198  chunks_[i].set_stop( new_stop );
199  }
200  }
201 }
202 
204  anchor_positions_.clear();
205  for (core::Size i=1; i<=core_chunks_.num_loop(); ++i)
207 }
208 
209 // from cmiles:
210 // mu : midpoint of the chunk
211 // sigma : linear function of chunk length
213  using boost::math::normal;
214  using core::Size;
215  using numeric::random::DistributionSampler;
216 
217  double mu = chunk.start() + chunk.length() / 2.0;
218  double sigma = chunk.length() / 5.0;
219  normal distribution(mu, sigma);
220  DistributionSampler<normal> sampler(distribution);
221 
222  // Clamp insertion position to closed interval [start, stop]
223  Size position = static_cast<Size>(sampler.sample());
224  return numeric::clamp<core::Size>(position, chunk.start(), chunk.stop());
225 }
226 
227 
229  core::pose::Pose & pose,
230  protocols::loops::Loops const & core_chunks, // template chunks (may include single residue strand pairings as chunks)
231  utility::vector1< std::pair< core::Size, core::Size > > const & strand_pairs, // strand pair residue positions
232  std::set<core::Size> const & strand_pair_library_positions // strand pair positions that are from the pairing library (not from a pdb template)
233 ) {
234  using core::Size;
235  using core::Real;
238  using utility::vector1;
239 
243  saved_ft_ = pose.conformation().fold_tree();
244 
247  }
248  else {
250  }
251 
252  // strand pairings
253  // initialize pairings data
254  strand_pairs_ = strand_pairs;
255  strand_pair_library_positions_ = strand_pair_library_positions;
256  // identify core_chunks that are not from the strand pair library (i.e. these should be from a template)
257  std::set<core::Size>::iterator set_iter;
258  for (core::Size i=1; i<=core_chunks.num_loop(); ++i) {
259  bool pair_chunk = false;
260  for (set_iter = strand_pair_library_positions_.begin(); set_iter != strand_pair_library_positions_.end(); ++set_iter) {
261  if (core_chunks[i].start() <= *set_iter && core_chunks[i].stop() >= *set_iter) {
262  pair_chunk = true;
263  break;
264  }
265  }
266  if (!pair_chunk) {
267  TR << "Identified template core chunk with index: " << i << std::endl;
268  TR << core_chunks[i] << std::endl;
270  }
271  } // strand pairings
272 
273  //symmetry
277  dynamic_cast<core::conformation::symmetry::SymmetricConformation &> ( pose.conformation()) );
278  symm_info = SymmConf.Symmetry_Info();
279  num_nonvirt_residues_ = symm_info->num_independent_residues();
280  num_protein_residues_ = symm_info->num_independent_residues();
281  }
284  set_core_chunks(core_chunks);
285 
286  // save previous
289 
290  // set new
291  choose_anchors();
294 
295  assert(chunks_.num_loop());
296 
297  // Add a virtual residue at the center of mass (updates the fold tree)
298  if (!symm_info) // pose is asymm
300 
301  virtual_res_ = pose.total_residue();
302 
303  // do the actual foldtree updates
304  update(pose);
305 
307 }
308 
309 
310 // strand pairings
312  core::Size const chunk_index,
313  utility::vector1<core::Size> & pair_chunks,
314  utility::vector1<std::pair<core::Size, core::Size> > & pair_chunks_pairs
315 ) {
316  utility::vector1<core::Size> pair_chunks_tmp;
318  for (core::Size i=1; i<=strand_pairs_.size(); ++i) {
319  core::Size idx = 0;
320  if (core_chunks_[chunk_index].start() <= strand_pairs_[i].first && core_chunks_[chunk_index].stop() >= strand_pairs_[i].first) {
322  if (idx) pair_chunks_pairs_tmp.push_back(std::pair<core::Size, core::Size>( strand_pairs_[i].first, strand_pairs_[i].second ));
323  } else if (core_chunks_[chunk_index].start() <= strand_pairs_[i].second && core_chunks_[chunk_index].stop() >= strand_pairs_[i].second) {
325  if (idx) pair_chunks_pairs_tmp.push_back(std::pair<core::Size, core::Size>( strand_pairs_[i].second, strand_pairs_[i].first ));
326  }
327  if (idx) pair_chunks_tmp.push_back(idx);
328  }
329  assert( pair_chunks_tmp.size() == pair_chunks_pairs_tmp.size() );
330  pair_chunks = pair_chunks_tmp;
331  pair_chunks_pairs = pair_chunks_pairs_tmp;
332 } // strand pairings
333 
335  for (core::Size i = 1; i<=core_chunks_.num_loop(); ++i) {
336  if (core_chunks_[i].start() <= position && core_chunks_[i].stop() >= position) {
337  index = i;
338  break;
339  }
340  }
341 }
342 
343 
344 
346  core::pose::Pose & pose
347  ) {
348 
349  if (pose.total_residue() > saved_n_residue_) {
351  }
352  pose.conformation().fold_tree( saved_ft_ );
353 
355 }
356 
357 // stolen from protocols::forge::methods::jumps_and_cuts_from_pose
359 
360  for ( core::Size i = 1; i<= ft.num_jump(); ++i ) {
361  core::Size down ( ft.downstream_jump_residue(i) );
362  core::Size up ( ft.upstream_jump_residue(i) );
363  jumps.push_back( std::pair<core::Size,core::Size>( down, up ) );
364  }
365  cuts = ft.cutpoints();
366 }
367 
369  using core::Size;
370  using core::Real;
373  using utility::vector1;
374 
375  assert(chunks_.num_loop());
376 
377  bool use_symm = core::pose::symmetry::is_symmetric(pose);
378 
379  // Define jumps, cuts
380  vector1<core::Size> cuts;
382 
383  // "symmetry-safe" version
385  Size jump_root = num_nonvirt_residues_+1;
386  if (use_symm) jump_root = anchor_positions_[1];
387 
388  // keep a copy of cuts and jumps, if they are in the region outside of the chunk definition
389  vector1<Size> cuts_old;
390  vector1<std::pair<Size, Size> > jumps_old;
391  core::Size last_chunk_residue(chunks_[chunks_.num_loop()].stop());
392 
393  //if (!use_symm) {
394  //if ( ! initial_asymm_foldtree_.is_simple_tree() ) {
395 
397 
398  for (Size i = 1; i <= jumps_old.size(); ++i) {
399  //if (jumps_old[i].first == jump_root) continue; // no need to skip this any more
400  //if (jumps_old[i].second == jump_root) continue;
401 
402  if ( jumps_old[i].first > last_chunk_residue && jumps_old[i].first <= num_nonvirt_residues_) {
403  jumps.push_back(std::make_pair(jump_root, jumps_old[i].first));
404  TR.Debug << "Adding additional jump: " << jump_root << jumps_old[i].first << std::endl;
405  }
406  else if ( jumps_old[i].second > last_chunk_residue && jumps_old[i].second <= num_nonvirt_residues_) {
407  jumps.push_back(std::make_pair(jump_root, jumps_old[i].second));
408  TR.Debug << "Adding additional jump: " << jump_root << jumps_old[i].second << std::endl;
409  }
410  }
411  for (Size i = 1; i <= cuts_old.size(); ++i) {
412  if ( cuts_old[i] > last_chunk_residue && cuts_old[i] <= num_nonvirt_residues_) {
413  cuts.push_back(cuts_old[i]);
414  TR.Debug << "Adding additional cut: " << cuts_old[i] << std::endl;
415  }
416  }
417  if (!use_symm) {
419  cuts.push_back(initial_asymm_foldtree_.nres());
420  TR.Debug << "Adding a cut on the last residue: " << initial_asymm_foldtree_.nres() << std::endl;
421  }
422  }
423  //}
424 
425  // add root jumps and cuts for chunks that should be rooted to the star fold tree
426  // these should be chunks from a template or if none exist, the first strand pair chunk
427  std::set<core::Size> root_chunk_indices = template_core_chunk_indices_;
428  if (!root_chunk_indices.size()) {
429  TR << "Template core chunks do not exist so using first chunk" << std::endl;
430  root_chunk_indices.insert(1);
431  }
432  std::set<core::Size>::iterator set_iter;
433  for (Size i = 1; i <= chunks_.num_loop(); ++i) {
434  const Loop& chunk = chunks_[i];
435  const Size cut_point = chunk.stop();
436  const Size jump_point = anchor_positions_[i];
437 
438  Size j_root = num_nonvirt_residues_+1;
439  if (use_symm && i>1) j_root = anchor_positions_[1];
440 
441  TR.Debug << "Adding chunk cut: " << cut_point << std::endl;
442  cuts.push_back(cut_point);
443 
444  if (root_chunk_indices.count(i)) {
445  rooted_chunk_indices_.insert(i);
446  TR.Debug << "Adding root jump: " << j_root << " " << jump_point << std::endl;
447  jumps.push_back(std::make_pair(j_root, jump_point));
448  }
449  }
450 
451  // strand pairings
452 
453  if (strand_pairs_.size()) {
454  // add jumps and cuts to strand pair chunks that are from a rooted branch
455  std::set<core::Size> rooted_chunk_indices; // keep track of all rooted branch chunks
456  for (set_iter = rooted_chunk_indices_.begin(); set_iter != rooted_chunk_indices_.end(); ++set_iter)
457  add_overlapping_pair_chunks( *set_iter, cuts, jumps, rooted_chunk_indices );
458  // at this point all pair chunks that overlap with a rooted chunk or overlap with the branch should have cuts and jumps. These overlapping pair chunks
459  // are in the global coordinate frame since they are branched from template core chunks (or the first strand pair chunk if templates do not exist)
460  // i.e. like |*-|-|-| where |* is a star tree rooted chunk, - is a jump and | are pair chunks
461 
462  // now lets add cuts to chunks that are not rooted yet (i.e. left over pairs, these are floating pairs with no reference to the global coordinate frame)
463  // i.e. |*
464  // |-| <- this is a pair that is not rooted yet and adjacent in sequence to the rooted chunk |*, so cuts have to be made to these pair chunks
465  // and if a cut already exists between the rooted chunk and the pair chunk, the cut has to be removed
466  std::set<core::Size> floating_pair_chunks;
467  for (core::Size i=1; i<=strand_pairs_.size(); ++i) {
468  core::Size i_index = 0;
469  core::Size j_index = 0;
472  assert( i_index && j_index );
473  core::Size paircnt = 0;
474  if (!rooted_chunk_indices.count(i_index) && !rooted_chunk_indices_.count(i_index)) {
475  floating_pair_chunks.insert(i_index);
476  paircnt++;
477  }
478  if (!rooted_chunk_indices.count(j_index) && !rooted_chunk_indices_.count(j_index)) {
479  floating_pair_chunks.insert(j_index);
480  paircnt++;
481  }
482  assert( paircnt == 0 || paircnt == 2 );
483  }
484 
485  // first check if adjacent chunks are from the original rooted chunks and if they are add them to the rooted branch
486  // i.e. check if adjacent chunks are from a template and then add the floating chunk and overlapping floating chunks
487  for (set_iter = rooted_chunk_indices_.begin(); set_iter != rooted_chunk_indices_.end(); ++set_iter) {
488  // check upstream
489  core::Size up_index = *set_iter+1;
490  if (floating_pair_chunks.count(up_index) && !rooted_chunk_indices.count(up_index)) {
491  // remove cut of rooted chunk
492  TR << "Removing root cut: " << chunks_[*set_iter].stop() << std::endl;
493  remove_cut( chunks_[*set_iter].stop(), cuts );
494  TR.Debug << "Adding floating pair chunk cut: " << chunks_[up_index].stop() << std::endl;
495  cuts.push_back(chunks_[up_index].stop());
496  rooted_chunk_indices.insert(up_index);
497  add_overlapping_pair_chunks( up_index, cuts, jumps, rooted_chunk_indices );
498  }
499  // check downstream
500  if (*set_iter > 1) {
501  core::Size down_index = *set_iter-1;
502  if (floating_pair_chunks.count(down_index) && !rooted_chunk_indices.count(down_index)) {
503  rooted_chunk_indices.insert(down_index);
504  add_overlapping_pair_chunks( down_index, cuts, jumps, rooted_chunk_indices );
505  }
506  }
507  }
508 
509  // remove rooted floating pairs from set
510  for (set_iter = rooted_chunk_indices.begin(); set_iter != rooted_chunk_indices.end(); ++set_iter)
511  floating_pair_chunks.erase(*set_iter);
512 
513  // second check if adjacent chunks are from a built up rooted branch chunk and if they are add them to the rooted branch
514  // i.e. check if adjacent chunks are from a rooted branch and then add the floating chunk and overlapping floating chunks
515  while (floating_pair_chunks.size()) {
516  for (set_iter = rooted_chunk_indices.begin(); set_iter != rooted_chunk_indices.end(); ++set_iter) {
517  // check upstream
518  core::Size up_index = *set_iter+1;
519  if (floating_pair_chunks.count(up_index) && !rooted_chunk_indices.count(up_index)) {
520  // remove cut of rooted chunk
521  TR << "Removing root cut: " << chunks_[*set_iter].stop() << std::endl;
522  remove_cut( chunks_[*set_iter].stop(), cuts );
523  TR.Debug << "Adding floating pair chunk cut: " << chunks_[up_index].stop() << std::endl;
524  cuts.push_back(chunks_[up_index].stop());
525  rooted_chunk_indices.insert(up_index);
526  add_overlapping_pair_chunks( up_index, cuts, jumps, rooted_chunk_indices );
527  }
528  // check downstream
529  if (*set_iter > 1) {
530  core::Size down_index = *set_iter-1;
531  if (floating_pair_chunks.count(down_index) && !rooted_chunk_indices.count(down_index)) {
532  rooted_chunk_indices.insert(down_index);
533  add_overlapping_pair_chunks( down_index, cuts, jumps, rooted_chunk_indices );
534  }
535  }
536  }
537  // remove rooted floating pairs from set
538  for (set_iter = rooted_chunk_indices.begin(); set_iter != rooted_chunk_indices.end(); ++set_iter)
539  floating_pair_chunks.erase(*set_iter);
540  }
541 
542  // hopefully all chunks are covered now
543  assert( chunks_.size() == rooted_chunk_indices.size() + rooted_chunk_indices_.size() );
544  } // strand pairings
545 
546 
547 
548  // Remember to include the original cutpoint at the end of the chain
549  // (before the virtual residue)
550  // TR << "Adding the last cut: " << num_nonvirt_residues_ << std::endl;
551  // cuts.push_back(num_nonvirt_residues_);
552 
553  TR.Debug << "jump size: " << jumps.size() << " cut size: " << cuts.size() << std::endl;
554 
555  ObjexxFCL::FArray2D_int ft_jumps(2, jumps.size());
556  for (Size i = 1; i <= jumps.size(); ++i) {
557  TR.Debug << "jump " << i << " " << jumps[i].first << " " << jumps[i].second << std::endl;
558  ft_jumps(1, i) = std::min(jumps[i].first, jumps[i].second);
559  ft_jumps(2, i) = std::max(jumps[i].first, jumps[i].second);
560  }
561 
562  ObjexxFCL::FArray1D_int ft_cuts(cuts.size());
563  for (Size i = 1; i <= cuts.size(); ++i) {
564  TR.Debug << "cut " << i << " " << cuts[i] << std::endl;
565  ft_cuts(i) = cuts[i];
566  }
567 
568  bool status = tree.tree_from_jumps_and_cuts(num_nonvirt_residues_+1, // nres_in
569  jumps.size(), // num_jump_in
570  ft_jumps, // jump_point
571  ft_cuts, // cuts
572  num_nonvirt_residues_+1); // root
573 
574 
575 
576  // strand pairings
577  if (strand_pairs_.size()) {
578  // must join adjacent peptide edges (cannot use FoldTree::delete_extra_vertices() because it skips jumps)
579  // this might not be necessary because of the code following this
580  TR << "tree_from_jumps_and_cuts: " << tree << std::endl;
582  bool join_edges = true;
583  bool updated = false;
584  while (join_edges) {
585  join_edges = false;
586  core::kinematics::FoldTree const const_tree( tree );
587  tmp_tree.clear();
588  for ( core::kinematics::FoldTree::const_iterator it = const_tree.begin(), it_end = const_tree.end(); it != it_end; ++it ) {
590  if (it_next != it_end) {
591  if ( it->label() == core::kinematics::Edge::PEPTIDE && it_next->label() == core::kinematics::Edge::PEPTIDE &&
592  it->stop() == it_next->start() ) {
593  join_edges = true;
594  tmp_tree.add_edge( it->start(), it_next->stop(), core::kinematics::Edge::PEPTIDE );
595  ++it;
596  updated = true;
597  continue;
598  }
599  tmp_tree.add_edge( it->start(), it->stop(), it->label() );
600  } else {
601  tmp_tree.add_edge( it->start(), it->stop(), it->label() );
602  }
603  }
604  tree = tmp_tree;
605  }
606  if (updated) TR << "joined adjacent peptide edges: " << tree << std::endl;
607  // join continuous peptide edges starting from a rooted jump point
608  utility::vector1< core::Size > jump_points;
609  core::kinematics::FoldTree const const_tree( tree );
610  for ( core::kinematics::FoldTree::const_iterator it = const_tree.begin(), it_end = const_tree.end(); it != it_end; ++it ) {
611  if (it->start() == (int)jump_root) jump_points.push_back(it->stop());
612  }
613  for (core::Size i=1;i<=jump_points.size();++i) {
614  std::set< std::pair< core::Size, core::Size > > remove; // keep track of edges to replace
615  tmp_tree.clear();
616  core::kinematics::FoldTree const const_new_tree( tree );
617  for ( core::kinematics::FoldTree::const_iterator it = const_new_tree.begin(), it_end = const_new_tree.end(); it != it_end; ++it ) {
618  std::set< std::pair< core::Size, core::Size > > remove_tmp;
619  if (it->start() == (int)jump_points[i] && it->label() == core::kinematics::Edge::PEPTIDE) {
620  core::Size start = it->start();
621  core::Size stop = it->stop();
622  remove_tmp.insert(std::pair< core::Size, core::Size >( start, stop ));
623  for ( core::kinematics::FoldTree::const_iterator jt = it+1, jt_end = const_new_tree.end(); jt != jt_end; ++jt ) {
624  if (jt->start() == (int)stop && jt->label() == core::kinematics::Edge::PEPTIDE) {
625  stop = jt->stop();
626  remove_tmp.insert(std::pair< core::Size, core::Size >( jt->start(), jt->stop() ));
627  }
628  }
629  tmp_tree.add_edge( start, stop, it->label() );
630  if (remove_tmp.size() > 1) remove.insert(remove_tmp.begin(),remove_tmp.end());
631  } else {
632  tmp_tree.add_edge( it->start(), it->stop(), it->label() );
633  }
634  }
635  core::kinematics::FoldTree const const_tmp_tree( tmp_tree );
637  for ( core::kinematics::FoldTree::const_iterator it = const_tmp_tree.begin(), it_end = const_tmp_tree.end(); it != it_end; ++it ) {
638  if (!remove.count(std::pair< core::Size, core::Size >( it->start(), it->stop() ))) {
639  new_tree.add_edge( it->start(), it->stop(), it->label() );
640  } else {
641  updated = true;
642  }
643  }
644  tree = new_tree;
645  if (updated) TR << "joined continuous rooted peptide edges: " << tree << std::endl;
646  }
647  } // strand pairings
648 
649  if (!status) {
650  utility_exit_with_message("HybridizeFoldtreeDynamic: failed to build fold tree from cuts and jumps");
651  }
652 
653  // Update the pose's fold tree
655 }
656 
657 
658 // strand pairings
660  core::Size const index,
662  utility::vector1<std::pair<core::Size, core::Size> > & jumps,
663  std::set<core::Size> & rooted_chunk_indices
664 ) {
665  utility::vector1<core::Size> pair_chunks; // pair chunks that pair with root chunk (index)
666  utility::vector1<std::pair<core::Size, core::Size> > pair_chunks_pairs; // positions of pair chunks, first is from the root chunk
667  get_pair_core_chunks( index, pair_chunks, pair_chunks_pairs );
670  if ( pair_chunks.size() ) {
671  start_pair_chunks.push_back(std::pair< core::Size, utility::vector1<core::Size> >( index, pair_chunks ));
672  start_pair_chunks_pairs.push_back(std::pair< core::Size, utility::vector1<std::pair<core::Size, core::Size> > >( index, pair_chunks_pairs ));
673  }
674  while (start_pair_chunks.size()) {
677  for (core::Size i=1;i<=start_pair_chunks.size();++i) {
678  //core::Size root = start_pair_chunks[i].first;
679  utility::vector1<core::Size>this_pair_chunks = start_pair_chunks[i].second;
680  utility::vector1<std::pair<core::Size, core::Size> >this_pair_chunks_pairs = start_pair_chunks_pairs[i].second;
681  assert( this_pair_chunks.size() == this_pair_chunks_pairs.size() );
682  for (core::Size j=1;j<=this_pair_chunks.size();++j) {
683  if (rooted_chunk_indices_.count(this_pair_chunks[j])) {
684  //TR.Debug << "WARNING! Strand pairings between two template chunks overlap. Chunk " << index << " and " << this_pair_chunks[j] << ". Geometry may be funky!" << std::endl;
685  continue;
686  }
687  if (!rooted_chunk_indices.count(this_pair_chunks[j])) {
688  // add jump if not rooted already
689  TR << "Adding strand pair root " << index << " tree jump: " << this_pair_chunks_pairs[j].first << " " << this_pair_chunks_pairs[j].second << std::endl;
690  jumps.push_back(this_pair_chunks_pairs[j]);
691  TR << "Adding strand pair root " << index << " tree cut: " << chunks_[this_pair_chunks[j]].stop() << std::endl;
692  cuts.push_back(chunks_[this_pair_chunks[j]].stop());
693  rooted_chunk_indices.insert(this_pair_chunks[j]);
694  utility::vector1<core::Size> new_pair_chunks;
696  get_pair_core_chunks( this_pair_chunks[j], new_pair_chunks, new_pair_chunks_pairs );
697  if ( new_pair_chunks.size() ) {
698  start_pair_chunks_tmp.push_back(std::pair< core::Size, utility::vector1<core::Size> >( this_pair_chunks[j], new_pair_chunks ));
699  start_pair_chunks_pairs_tmp.push_back(std::pair< core::Size, utility::vector1<std::pair<core::Size, core::Size> > >( this_pair_chunks[j], new_pair_chunks_pairs ));
700  }
701  }
702  }
703  }
704  start_pair_chunks = start_pair_chunks_tmp;
705  start_pair_chunks_pairs = start_pair_chunks_pairs_tmp;
706  }
707 }
708 
711  for (core::Size i=1; i<=cuts.size(); ++i)
712  if (cuts[i] != cut) cuts_tmp.push_back(cuts[i]);
713  cuts = cuts_tmp;
714 }
715 
718  core_chunks_ = chunks;
719 }
720 
721 } // namespace hybridization
722 } // namespace protocols