Rosetta 3.5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
util.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 some utils for fragments
11 /// @author Oliver Lange
12 
13 // Unit Headers
14 #include <core/fragment/util.hh>
15 
16 // Package Headers
19 
24 
25 // Project Headers
27 
28 #include <core/pose/Pose.hh>
29 #include <core/pose/util.hh>
30 #include <core/pose/PDBInfo.hh> //for reading in fragsets from a pdb
31 #include <core/io/pdb/pose_io.hh>
34 
35 #include <core/types.hh>
36 
37 // ObjexxFCL Headers
38 #include <ObjexxFCL/format.hh>
39 
40 // Utility headers
41 #include <utility/vector1.fwd.hh>
42 #include <basic/Tracer.hh>
43 #include <numeric/random/random.hh>
44 
45 //#include <utility/pointer/ReferenceCount.hh>
46 //#include <numeric/numeric.functions.hh>
47 #include <numeric/random/random_permutation.hh>
48 #include <numeric/xyz.functions.hh>
49 
50 //#include <core/pose/util.hh>
51 #include <utility/io/ozstream.hh>
52 
53 #include <basic/options/option.hh>
54 #include <basic/options/keys/abinitio.OptionKeys.gen.hh>
55 #include <basic/options/keys/frags.OptionKeys.gen.hh>
56 #include <basic/options/keys/in.OptionKeys.gen.hh>
58 
59 //// C++ headers
60 #include <cstdlib>
61 #include <string>
62 #include <fstream>
63 
67 #include <utility/vector0.hh>
68 #include <utility/vector1.hh>
69 
70 //Auto Headers
72 
73 namespace core {
74 namespace fragment {
75 
76 static basic::Tracer tr("core.fragment");
77 static numeric::random::RandomGenerator RG(125923489); // <- Magic number, do not change it!
78 
79 using namespace ObjexxFCL::fmt;
80 
81 void retain_top(core::Size k, FragSetOP fragments) {
82  for (FrameIterator i = fragments->begin(); i != fragments->end(); ++i) {
83  FrameOP existing_frame = *i;
84 
85  // create a new frame containing only the desired fragments
86  Frame new_frame(existing_frame->start(),
87  existing_frame->stop(),
88  existing_frame->length());
89 
90  for (core::Size j = 1; j <= std::min(k, existing_frame->nr_frags()); ++j)
91  new_frame.add_fragment(existing_frame->fragment_ptr(j));
92 
93  *existing_frame = new_frame;
94  }
95 }
96 
98  //Size nbb ( 3 ); // three backbone torsions for Protein
99  Size len = fragset.max_frag_length();
100  runtime_assert( len > 0 );
101  FrameOP frame;
102  pose::Pose pose = pose_in;
103  pose::set_ss_from_phipsi( pose );
104  for ( Size pos = 1; pos <= pose.total_residue() - len + 1; ++pos ) {
105 
106  //don't want to use fragments that go across a cutpoint... certainly non-ideal geometry there
107  // check for cutpoints
108  bool free_of_cut = true;
109  for ( Size icut = 1; icut <= (Size) pose.fold_tree().num_cutpoint(); icut++ ) {
110  Size const cut ( pose.fold_tree().cutpoint( icut ) );
111  if (cut >= pos && cut < pos+len-1 ) {
112  free_of_cut = false;
113  break;
114  }
115  }
116 
117  //steal backbone torsion fragment
118  if ( free_of_cut ) {
119  frame = new Frame( pos, new FragData( new BBTorsionSRFD, len) );
120  frame->steal( pose );
121  fragset.add( frame );
122  }
123  }
124 }
125 
126 void steal_frag_set_from_pose ( pose::Pose const& pose_in, FragSet& fragset, core::fragment::FragDataOP frag_type ) {
127  //Size nbb ( 3 ); // three backbone torsions for Protein
128  Size const len( frag_type->size() );
129  runtime_assert( len > 0 );
130  FrameOP frame;
131  pose::Pose pose = pose_in;
132  pose::set_ss_from_phipsi( pose );
133  for ( Size pos = 1; pos <= pose.total_residue() - len + 1; ++pos ) {
134  frame = new Frame( pos, frag_type );
135  frame->steal( pose );
136  fragset.add( frame );
137  }
138 }
139 
140 void steal_frag_set_from_pose ( pose::Pose const& pose_in, Size const begin, Size const end, FragSet& fragset, core::fragment::FragDataOP frag_type ) {
141 
142  Size const len( frag_type->size() );
143  runtime_assert( len > 0 );
144  FrameOP frame;
145  pose::Pose pose = pose_in;
146  pose::set_ss_from_phipsi( pose );
147  for ( Size pos = begin; pos <= end - len + 1; ++pos ) {
148  frame = new Frame( pos, frag_type );
149  frame->steal( pose );
150  fragset.add( frame );
151  }
152 }
153 
155  pose::Pose const& pose_in,
156  FragSet& fragset,
157  core::fragment::FragDataOP frag_type,
158  std::set< core::Size > const& selected_residues )
159 {
160  //Size nbb ( 3 ); // three backbone torsions for Protein
161  Size const len( frag_type->size() );
162  runtime_assert( len == 1 ); // for this type of residue-by-residue we only support 1-mers
163  FrameOP frame;
164  pose::Pose pose = pose_in;
165  pose::set_ss_from_phipsi( pose );
166  for ( std::set< core::Size >::const_iterator pos = selected_residues.begin();
167  pos != selected_residues.end(); ++pos ) {
168  frame = new Frame( *pos, frag_type );
169  frame->steal( pose );
170  fragset.add( frame );
171  }
172 }
173 
174 // chop fragments into sub-fragments
176  Size slen( source.max_frag_length() );
177  Size tlen( dest.max_frag_length() );
178  runtime_assert( tlen < slen );
179  FrameList dest_frames;
180  for ( Size pos = 1; pos <= source.max_pos() - tlen + 1; pos++ ) {
181  dest_frames.push_back( new Frame( pos, tlen ) );
182  }
183  for ( FrameIterator it=source.begin(), eit=source.end(); it!=eit; ++it ) {
184  Frame& fr( **it );
185  for ( Size pos = fr.start(); pos<= fr.end() - tlen + 1; pos++ ) {
186  Frame& dest_fr( *dest_frames[ pos ] );
187  for ( Size nr = 1; nr <= fr.nr_frags(); ++nr ) {
188  FragData& long_frag( fr.fragment( nr ) );
189  dest_fr.add_fragment( long_frag.generate_sub_fragment( pos-fr.start()+1, pos-fr.start()+tlen ) );
190  }
191  }
192  }
193  for ( FrameList::const_iterator it = dest_frames.begin(), eit = dest_frames.end(); it!=eit; ++it ) {
194  if ( (*it)->nr_frags() ) {
195  dest.add( *it );
196  }
197  }
198 }
199 
201  if ( nr_frags.size() < _frags.max_pos() ) {
202  nr_frags.resize( _frags.max_pos(), 0 );
203  }
204 
205  for ( FrameIterator it=_frags.begin(), eit=_frags.end(); it!=eit; ++it ) {
206  // so far this implementation doesn't work for non-continous frames
207  runtime_assert( it->is_continuous() );
208 
209  for ( Size i = it->start(); i<=it->stop(); i++ ) {
210  nr_frags[ i ] += it->nr_frags();
211  }
212  }
213 }
214 
215 void flatten_list( FrameList& frames, FragID_List& frag_ids ) {
216  frag_ids.reserve( frag_ids.size() + frames.flat_size() );
217  for ( FragID_Iterator it = frames.begin(), eit=frames.end();
218  it!=eit; ++it) {
219  frag_ids.push_back( *it );
220  }
221 }
222 
223 FragSetOP
224 merge_frags( FragSet const& good_frags, FragSet const& filling, Size min_nr_frags, bool bRandom ) {
225 
226  // all good_frags go into final set
227  FragSetOP merged_frags = good_frags.clone();
228 
229  utility::vector1< Size > nr_frags( filling.max_pos(), 0 );
230  compute_per_residue_coverage( good_frags, nr_frags );
231  tr.Info << "fragment coverage:";
232  for ( Size pos = 1; pos <= nr_frags.size(); pos++ ) {
233  tr.Info << " " << pos << " " << nr_frags[ pos ];
234  }
235  tr.Info << std::endl;
236  //fill up with filling fragments:
237  for ( Size pos = 1; pos<=filling.max_pos(); pos++ ) {
238  if ( nr_frags[ pos ] < min_nr_frags ) {
239  FrameList fill_frames;
240  filling.frames( pos, fill_frames );
241  Size nr_fill( min_nr_frags - nr_frags[ pos ] );
242  tr.Info << nr_frags[ pos ] << " fragments at pos " << pos << ". required: " << min_nr_frags << std::endl;
243  tr.Info << "attempt to fill up with " << nr_fill << " frags at position " << pos << " ... ";
244  // select randomly from filling?
245  // generate random sequence from 1 .. N
246  FragID_List frag_ids;
247  flatten_list( fill_frames, frag_ids );
248  if ( bRandom ) {
249  numeric::random::random_permutation( frag_ids, RG );
250  numeric::random::random_permutation( frag_ids, RG ); //playing safe
251  }
252 
253  for ( FragID_List::iterator it = frag_ids.begin(), eit = frag_ids.end();
254  it != eit && nr_fill; ++it, --nr_fill ) {
255  merged_frags->add( *it );
256  // book keeping: raise counter for affected residues
257  runtime_assert( it->frame().is_continuous() );
258  for ( Size p = it->frame().start(); p<=it->frame().stop(); p++ ) nr_frags[ p ]++;
259 
260  }
261  if ( nr_fill ) {
262  tr.Info << nr_fill << " fragments short " << std::endl;
263  } else {
264  tr.Info << "succeeded! " << std::endl;
265  }
266  } //pos needs fill up
267  }// loop over pos
268  return merged_frags;
269 }
270 
271 
272 void
274  pose::Pose & pose,
275  Frame const & frame,
276  scoring::ScoreFunction const & sfxn
277 )
278 {
279 
280  if( frame.nr_frags() < 1 ) return;
281 
282  frame.apply( 1, pose );
283 
284  core::Size best_frag(1);
285 
286  core::Real best_score( sfxn( pose ) );
287 
288  //tr << "frag 1 has score " << best_score << std::endl;
289 
290  for( core::Size i = 2; i <= frame.nr_frags(); ++i ){
291 
292  frame.apply( i, pose );
293 
294  core::Real cur_score( sfxn( pose ) );
295  //tr << "frag " << i << " has score " << cur_score << std::endl;
296 
297  if( cur_score < best_score ){
298  best_frag = i;
299  best_score = cur_score;
300  }
301 
302  }
303 
304  frame.apply( best_frag, pose );
305  //tr << "applying frag " << best_frag << std::endl;
306 
307  //tr << "pose score before exit is " << sfxn( pose ) << std::endl;
308 
309 } //apply_best_scoring_fragdata
310 
312  pose::Pose const & pose,
313  utility::vector1< FrameOP > const & frames,
314  std::string const filename,
315  Size const start_frag
316 )
317 {
318 
319  //we need to make a copy of the pose to muck around with
320  pose::Pose frame_pose = pose;
321  Size model_count(1), atom_counter(0);
322 
323  std::ofstream outfile( filename.c_str() );
324  outfile << "REMARK 666 Fragment set for outtag pose \n";
325 
326  //now let's go through every fragment of every frame and dump to pdb
327  for( utility::vector1< FrameOP >::const_iterator frame_it = frames.begin(); frame_it != frames.end(); ++frame_it ){
328 
329  for( Size frag = start_frag; frag <= (*frame_it)->nr_frags(); ++frag){
330 
331  (*frame_it)->apply( frag, frame_pose );
332 
333  outfile << "MODEL" << I(9, model_count) << "\n";
334 
335  for( Size rescount = (*frame_it)->start(); rescount <= (*frame_it)->end(); ++rescount ){
336 
337  core::io::pdb::dump_pdb_residue( frame_pose.residue( rescount ), atom_counter, outfile );
338 
339  } //loop over residues of fragment
340 
341  outfile << "ENDMDL\n";
342 
343  model_count++;
344 
345  } //loop over all fragments to apply
346 
347  } //iterator over all frames
348 
349  outfile.close();
350 
351 } //dump_frames_as_pdb
352 
353 
354 
355 /// @details this is a little tricky: this should support functionality for both creating a frameset entirely from
356 /// @details the input pdb (i.e. with no prior information about frag data length or srfds ), but it should also
357 /// @details be possible to pass in non_empty frames such that the information in the pdb will generate FragData
358 /// @details objects that are compatible to the ones already in the passed in frames. hmpf
359 /// @details
361  pose::Pose const & pose,
362  utility::vector1< FrameOP > const & template_frames,
363  std::string const filename
364 )
365 {
366 
367  //we rely on the multimodel pdb reader for file processing
369  core::import_pose::pose_from_pdb( in_poses, filename );
370 
371  Size frame_counter(1);
372  bool return_val( true );
373  pose::Pose frag_pose = pose;
374 
375  for( utility::vector1< pose::Pose >::const_iterator pose_it = in_poses.begin(); pose_it != in_poses.end(); ++pose_it){
376 
377  //first we need to figure out which residues we are dealing with
378  Size pdb_start_res( pose_it->pdb_info()->number( 1 ) );
379  Size pdb_stop_res( pose_it->pdb_info()->number( pose_it->total_residue() ) );
380  char pdb_res_chain( pose_it->pdb_info()->chain( 1 ) );
381  char pdb_start_res_icode( pose_it->pdb_info()->icode( 1 ) );
382  char pdb_stop_res_icode( pose_it->pdb_info()->icode( pose_it->total_residue() ) );
383 
384  //safety check
385  if( pose_it->pdb_info()->chain( pose_it->total_residue() ) != pdb_res_chain ){
386  utility_exit_with_message("PDB file containing fragments is corrupted, one model contains multiple chains");
387  }
388 
389  Size frame_start = pose.pdb_info()->pdb2pose( pdb_res_chain, pdb_start_res, pdb_start_res_icode );
390  Size frame_stop = pose.pdb_info()->pdb2pose( pdb_res_chain, pdb_stop_res, pdb_stop_res_icode );
391 
392 
393  while( pose_it->total_residue() != template_frames[ frame_counter ]->length()
394  && frame_start != template_frames[ frame_counter ]->start()
395  && frame_stop != template_frames[ frame_counter]->stop() )
396  {
397  frame_counter++;
398  if ( frame_counter > template_frames.size() ) return false; //means there were input poses not compatible with the requested frames.
399  }
400 
401  frag_pose.copy_segment( template_frames[ frame_counter ]->length(), *pose_it, template_frames[ frame_counter ]->start(), 1 );
402  template_frames[ frame_counter ]->steal( frag_pose );
403 
404  } //iterator over input poses
405 
406 
407  return return_val;
408 
409 } //get_frames_from_pdb
410 
411 void read_std_frags_from_cmd( FragSetOP& fragset_large, FragSetOP& fragset_small ) { //needed for setup_broker_from_cmdline
412  using namespace basic::options;
413  using namespace basic::options::OptionKeys;
414 
415  std::string frag_large_file( "NoFile" );
416  std::string frag_small_file( "NoFile" );
417  if (option[ in::file::frag9 ].user()) {
418  frag_large_file = option[ in::file::frag9 ]();
419  }
420 
421  if (option[ in::file::frag3 ].user()) {
422  frag_small_file = option[ in::file::frag3 ]();
423  }
424 
425  if ( frag_large_file != "NoFile" ) {
426  // fragset_large_ = FragmentIO().read( frag_large_file );
427  fragset_large = FragmentIO(
428  option[ OptionKeys::abinitio::number_9mer_frags ](),
429  option[ OptionKeys::frags::nr_large_copies ](),
430  option[ OptionKeys::frags::annotate ]()
431  ).read_data( frag_large_file );
432  }
433 
434  if ( frag_small_file != "NoFile" ) {
435  fragset_small = FragmentIO(
436  option[ OptionKeys::abinitio::number_3mer_frags ],
437  1, //nr_copies
438  option[ OptionKeys::frags::annotate ]
439  ).read_data( frag_small_file );
440  }
441 
442  if ( option[ OptionKeys::abinitio::steal_3mers ]() || option[ OptionKeys::abinitio::steal_9mers ]() ) {
443  // read native pose to get sequence
444  pose::PoseOP native_pose = new pose::Pose;
445  if ( option[ in::file::native ].user() ) {
446  core::import_pose::pose_from_pdb( *native_pose, option[ in::file::native ]() );
447  pose::set_ss_from_phipsi( *native_pose );
448  } else {
449  utility_exit_with_message(" can't steal natie fragments without in:file:native " );
450  }
451  tr.Info << " stealing fragments from native pose: ATTENTION: native pose has to be IDEALIZED!!! " << std::endl;
452  // utility_exit_with_message(" stealing fragments from pose: currently not supported! ask Oliver " );
453  if ( option[ OptionKeys::abinitio::steal_9mers ]() ) {
454  if ( !fragset_large ) fragset_large = new ConstantLengthFragSet( 9 );
455  steal_frag_set_from_pose( *native_pose, *fragset_large, new FragData( new BBTorsionSRFD, fragset_large->max_frag_length() ) );
456  }
457  if ( option[ OptionKeys::abinitio::steal_3mers ]() ) {
458  if ( !fragset_small ) fragset_small = new ConstantLengthFragSet( 3 );
459  steal_frag_set_from_pose( *native_pose, *fragset_small, new FragData( new BBTorsionSRFD, fragset_small->max_frag_length() ) );
460  }
461  }
462 
463  if ( fragset_small && option[ OptionKeys::abinitio::dump_frags ]() ) { //diagnosis
464  utility::io::ozstream dump_frag_small( "fragset_small.dump" );
465  for ( FrameIterator it=fragset_small->begin(), eit=fragset_small->end(); it!=eit; ++it ) {
466  (*it)->show( dump_frag_small );
467  }
468  }
469  if ( fragset_large && option[ OptionKeys::abinitio::dump_frags ]() ) { //diagnosis
470  utility::io::ozstream dump_frag_large( "fragset_large.dump" );
471  for ( FrameIterator it=fragset_large->begin(), eit=fragset_large->end(); it!=eit; ++it ) {
472  (*it)->show( dump_frag_large );
473  }
474  }
475 }
476 
477 
478 /// @brief given a JumpFrame with Up and DownJumpSRFDs as LAST SRFDs this will make a fold-tree compatible with the
479 /// Frame... this is NOT GOOD for sampling, since it introduces cut-points outside of fragments
480 /// later for sampling: one could probably write a routine that looks if it can move existing Jumps in Fold-tree to
481 /// fit the FRAME ... if not it returns failure...
482 
483 /// one little assumption: create frames always like this:
484 /// contigues piece JUMP contig. piec JUMP contig. piece.
485 /// then good candidates for cutpoints are the last contig.piece residue before a jump
486 void make_simple_fold_tree_from_jump_frame( Frame const& frame, Size total_residue, kinematics::FoldTree& new_fold_tree ) {
487  ///@brief how many actual jumps are in this Frame?
491 
492  runtime_assert( frame.nr_frags() >= 1 );
493  FragData const& fragdata( frame.fragment( 1 ) );
494  for ( Size i=1; i<=frame.length(); ++i ) {
495  if ( typeid( *fragdata.get_residue( i ) ) == typeid( UpJumpSRFD ) ) {
496  runtime_assert( i + 1 <= frame.length() && typeid( *fragdata.get_residue( i + 1 ) ) == typeid( DownJumpSRFD ) );
497  ups.push_back( frame.seqpos( i ) );
498  downs.push_back( frame.seqpos( i+1 ) );
499 
500  //the following configuration is not impossible, but if it should be allowed we need to change our heuristic to find cut-points
501  runtime_assert( i >= 2 && typeid( *fragdata.get_residue( i ) ) != typeid( DownJumpSRFD ) );
502  cuts.push_back( frame.seqpos( i-1 ) );
503 
504  // we have used up two positions...
505  ++i;
506  }
507  }
508  ObjexxFCL::FArray2D_int jump_point( 2, ups.size(), 0 );
509  ObjexxFCL::FArray1D_int cut_point( ups.size() );
510  for ( Size i = 1; i <= ups.size() ; ++i ){
511  jump_point( 1, i ) = ups[ i ];
512  jump_point( 2, i ) = downs[ i ];
513  cut_point( i ) = cuts[ i ];
514  }
515  new_fold_tree.tree_from_jumps_and_cuts( total_residue, ups.size(), jump_point, cut_point );
516 }
517 
518 void fragment_set_slice ( ConstantLengthFragSetOP & fragset, Size const & min_res, Size const & max_res ){
519 
520  Size const len( fragset->max_frag_length() );
521 
523 
524  assert( max_res >= min_res + len - 1);
525 
526  for ( Size pos = min_res; pos <= max_res - len + 1 ; ++pos ) {
527 
528  FrameList frames;
529  fragset->frames( pos, frames );
530 
531  // CURRENTLY ONLY WORKS FOR CONST FRAG LENGTH SETS!!!! ASSUMES ONE FRAME!!!
532  assert( frames.size() == 1 );
533 
534  FrameOP & frame( frames[1] );
535  FrameOP frame_new = new Frame( pos - min_res + 1, len );
536 
537  for ( Size n = 1; n <= frame->nr_frags(); n++ ) {
538  frame_new->add_fragment( frame->fragment_ptr( n ) );
539  }
540 
541  fragset_new->add( frame_new );
542 
543  }
544 
545  fragset = fragset_new;
546 
547 }
548 /// @brief Finds the fold tree boundaries to the left and right of <pos>.
550  using core::Size;
551  assert(left);
552  assert(right);
553 
554  Size lower_cut = 0;
555  Size upper_cut = tree.nres();
556  Size num_cutpoints = tree.num_cutpoint();
557  for (Size i = 1; i <= num_cutpoints; ++i) {
558  Size cutpoint = tree.cutpoint(i);
559 
560  // find the upper boundary (inclusive)
561  if (cutpoint >= pos && cutpoint < upper_cut)
562  upper_cut = cutpoint;
563 
564  // find the lower boundary (exclusive)
565  if (cutpoint < pos && cutpoint > lower_cut)
566  lower_cut = cutpoint;
567  }
568 
569  // set output parameters
570  *left = lower_cut + 1;
571  *right = upper_cut;
572 }
573 
581  s.M = alignVectorSets(m1-m2, m3-m2, f1-f2, f3-f2);
582  s.v = f2-s.M*m2;
583  return s;
584 }
585 
587  const core::kinematics::Stub& s,
588  core::Size sres,
589  core::Size eres ) {
590  using core::id::AtomID;
591  if(eres==0) eres = pose.n_residue();
592  for (core::Size ir = sres; ir <= eres; ++ir) {
593  for (core::Size ia = 1; ia <= pose.residue_type(ir).natoms(); ++ia) {
594  AtomID aid(AtomID(ia,ir));
595  pose.set_xyz(aid, s.local2global(pose.xyz(aid)));
596  }
597  }
598 }
599 
600 // frags must be ordered by sequence position
601 void make_pose_from_frags( pose::Pose & pose, std::string sequence, utility::vector1<FragDataCOP> frags, bool chains ) {
602  // clear the pose
603  pose.clear();
604  // generate pose
605  core::pose::make_pose_from_sequence(pose, sequence, "centroid");
606  // idealize and extend pose
607  for ( Size pos = 1; pos<=pose.total_residue(); pos++ ) {
609  }
610  Real const init_phi ( -150.0 );
611  Real const init_psi ( 150.0 );
612  Real const init_omega( 180.0 );
613  for ( Size pos = 1; pos<=pose.total_residue(); pos++ ) {
614  if( pos != 1 ) pose.set_phi( pos, init_phi );
615  if( pos != pose.total_residue() ) pose.set_psi( pos, init_psi );
616  if( ( pos != 1 ) && ( pos != pose.total_residue() ) ) pose.set_omega( pos, init_omega );
617  }
618  // insert the torsions from the fragments
619  Size insert_pos = 1;
620  for (Size i = 1; i <= frags.size(); ++i) {
621  FragDataCOP frag = frags[i];
622  frag->apply(pose, insert_pos, insert_pos + frag->size() - 1);
623  insert_pos += frag->size();
624  }
625 
626  // if single fragment, reorientation is not necessary so just return
627  if (frags.size() == 1) return;
628 
629  // construct fold tree
631  Size total_size = 0;
632  for (Size i = 1; i < frags.size(); ++i) {
633  FragDataCOP frag_1 = frags[i];
634  FragDataCOP frag_2 = frags[i+1];
635  Size midpoint_1 = static_cast<Size>(ceil(frag_1->size() / 2.0)) + total_size;
636  total_size += frag_1->size();
637  Size midpoint_2 = static_cast<Size>(ceil(frag_2->size() / 2.0)) + total_size + 1;
638  int jump_id = tree.new_jump(midpoint_1, midpoint_2, total_size);
639  tree.set_jump_atoms(jump_id, "CA", "CA");
640  }
641  pose.fold_tree(tree);
642 
643  // Ensure that the FoldTree is left in a consistent state
644  assert(pose.fold_tree().check_fold_tree());
645 
646  // orient the fragments in the pose based on CA fragment data
647  total_size = 0;
648  for (Size i = 1; i <= frags.size(); ++i) {
649  FragDataCOP frag = frags[i];
650  // Construct stubs from the 3 central CA atoms
651  Size central_residue = static_cast< Size >(ceil(frag->size() / 2.0));
652  BBTorsionSRFDCOP f1 = reinterpret_cast< BBTorsionSRFD const * >(frag->get_residue(central_residue - 1)());
653  BBTorsionSRFDCOP f2 = reinterpret_cast< BBTorsionSRFD const * >(frag->get_residue(central_residue)());
654  BBTorsionSRFDCOP f3 = reinterpret_cast< BBTorsionSRFD const * >(frag->get_residue(central_residue + 1)());
655  numeric::xyzVector<Real> fa1(f1->x(), f1->y(), f1->z());
656  numeric::xyzVector<Real> fa2(f2->x(), f2->y(), f2->z());
657  numeric::xyzVector<Real> fa3(f3->x(), f3->y(), f3->z());
658  Size midpoint_pose = central_residue + total_size;
659  total_size += frag->size();
660  numeric::xyzVector<Real> m1 = pose.residue(midpoint_pose - 1).xyz("CA");
661  numeric::xyzVector<Real> m2 = pose.residue(midpoint_pose).xyz("CA");
662  numeric::xyzVector<Real> m3 = pose.residue(midpoint_pose + 1).xyz("CA");
663  // Compute the transform
664  core::kinematics::Stub x = getxform(m1, m2, m3, fa1, fa2, fa3);
665  // Starting at the midpoint of the insertion point in the pose, propagate
666  // the change to the left and right until we reach either the end of the
667  // chain or a cutpoint
668  core::Size region_start, region_stop;
669  FindBoundaries(tree, midpoint_pose, &region_start, &region_stop);
670  xform_pose(pose, x, region_start, region_stop);
671  if (chains && i < frags.size()) pose.conformation().insert_chain_ending( total_size );
672  }
673 }
674 
675 } //fragment
676 } //core
677