Rosetta 3.5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
RNA_AnalyticLoopCloser.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 /// @file RNA_AnalyticLoopCloser
11 /// @brief protocols that are specific to RNA_AnalyticLoopCloser
12 /// @detailed
13 /// @author Rhiju Das
14 
15 // Unit headers
17 
18 // Package headers
19 #include <core/types.hh>
22 #include <core/id/AtomID.hh>
23 #include <core/id/NamedAtomID.hh>
24 #include <core/id/DOF_ID.hh>
28 #include <core/pose/Pose.hh>
31 #include <numeric/random/random.hh>
32 #include <numeric/angle.functions.hh>
33 #include <numeric/xyz.functions.hh>
34 #include <numeric/xyzVector.hh>
35 #include <numeric/conversions.hh>
36 #include <numeric/kinematic_closure/bridgeObjects.hh>
37 #include <numeric/kinematic_closure/kinematic_closure_helpers.hh>
38 #include <utility/exit.hh>
39 #include <utility/vector1.hh>
40 #include <ObjexxFCL/FArray1D.hh>
41 #include <ObjexxFCL/string.functions.hh>
42 #include <ObjexxFCL/format.hh>
43 
44 using namespace core;
45 
46 static numeric::random::RandomGenerator RG ( 26640 ); // <- Magic number, do not change it!
47 using ObjexxFCL::fmt::I;
48 using ObjexxFCL::fmt::F;
49 using core::id::AtomID;
51 using core::id::DOF_ID;
53 using numeric::conversions::radians;
54 using numeric::conversions::degrees;
55 using numeric::angle_radians;
56 using numeric::principal_angle;
57 using numeric::dihedral_radians;
58 
59 namespace protocols {
60 namespace swa {
61 namespace rna {
62 
63 RNA_AnalyticLoopCloser::RNA_AnalyticLoopCloser ( Size const moving_suite, Size const chainbreak_suite ) :
64  moving_suite_ ( moving_suite ),
65  chainbreak_suite_ ( chainbreak_suite ),
66  verbose_ ( false ),
67  nsol_ ( 0 ),
68  choose_least_perturb_solution_ ( true ),
69  choose_best_solution_ ( false ),
70  choose_random_solution_ ( false ),
71  save_all_solutions_ ( false ) {
72  Mover::type ( "RNA_AnalyticLoopCloser" );
73 }
74 
75 /// @brief Clone this object
77  return new RNA_AnalyticLoopCloser ( *this );
78 }
79 
80 /////////////////////////////////////////////////////////////////////////////////////////////////////////////
81 /// @details Apply the RNA Loop Closer -- set up for Full Atom Representation.
82 ///
83 void
85  close_at_cutpoint ( pose );
86 }
87 
88 
89 /////////////////////////////////////////////////////////////////////////////////////////////////////////////
90 bool
92  using namespace core::kinematics;
93  using namespace numeric::kinematic_closure;
94  ///// kinematic loop close.
95  // Following copied from, e.g., KinematicMover.cc. Need to elaborate for terminal residues!
96  // inputs to loop closure
98  utility::vector1<Size> pivots ( 3 ), order ( 3 );
99  utility::vector1<Real> dt_ang, db_len, db_ang;
100  // doesn't matter.
101  order[1] = 1;
102  order[2] = 2;
103  order[3] = 3;
104  atom_ids_.clear();
105  atom_ids_.push_back ( NamedAtomID ( " C3*", moving_suite_ ) );
106  atom_ids_.push_back ( NamedAtomID ( " O3*", moving_suite_ ) );
107  atom_ids_.push_back ( NamedAtomID ( " P ", moving_suite_ + 1 ) );
108  atom_ids_.push_back ( NamedAtomID ( " O5*", moving_suite_ + 1 ) );
109  atom_ids_.push_back ( NamedAtomID ( " C5*", moving_suite_ + 1 ) );
110  atom_ids_.push_back ( NamedAtomID ( " C4*", moving_suite_ + 1 ) );
111  atom_ids_.push_back ( NamedAtomID ( " C3*", chainbreak_suite_ ) );
112  atom_ids_.push_back ( NamedAtomID ( " O3*", chainbreak_suite_ ) );
113  atom_ids_.push_back ( NamedAtomID ( " P ", chainbreak_suite_ + 1 ) );
114  atom_ids_.push_back ( NamedAtomID ( " O5*", chainbreak_suite_ + 1 ) );
115  atom_ids_.push_back ( NamedAtomID ( " C5*", chainbreak_suite_ + 1 ) );
116  atom_ids_.push_back ( NamedAtomID ( " C4*", chainbreak_suite_ + 1 ) );
117  atom_ids_.push_back ( NamedAtomID ( " C3*", chainbreak_suite_ + 1 ) );
118  atom_ids_.push_back ( NamedAtomID ( " O3*", chainbreak_suite_ + 1 ) );
119  atom_ids_.push_back ( NamedAtomID ( " C2*", chainbreak_suite_ + 1 ) );
120 
121  for ( Size i = 1; i <= 3; i++ ) {
122  pivots[ i ] = 3 * i + 2;
123  }
124 
125  fill_chainTORS ( pose, atom_ids_, atoms, dt_ang, db_ang, db_len );
126 
127  if ( verbose_ ) output_chainTORS ( dt_ang, db_ang, db_len );
128 
129  // These atoms_xyz are the same as computed in fill_chainTORS, but I'm
130  // having some trouble sending them out (can't clear or copy vector1< Vector > ?)
131  utility::vector1< Vector > atoms_xyz;
132 
133  for ( Size i = 1; i <= atoms.size(); i++ ) {
134  atoms_xyz.push_back ( Vector ( atoms[i][1], atoms[i][2], atoms[i][3] ) );
135  }
136 
137  //////////////////////////////////////////////
138  // Parameter at chainbreak.
139  // This looks a bit weird, because of a hack.
140  Size cutpos_ = chainbreak_suite_;
141  ////////////////////////////////////////////////////////////////////////////////////
142  Real const d_O3star_nextP = ( pose.xyz ( NamedAtomID ( " O3*", cutpos_ ) ) -
143  pose.xyz ( NamedAtomID ( "OVL1", cutpos_ ) ) ).length();
144  db_len[ 8 ] = d_O3star_nextP;
145  ////////////////////////////////////////////////////////////////////////////////////
146  Real const theta_C3star_O3star_nextP = degrees ( angle_radians ( pose.xyz ( NamedAtomID ( " C3*", cutpos_ ) ),
147  pose.xyz ( NamedAtomID ( " O3*", cutpos_ ) ),
148  pose.xyz ( NamedAtomID ( "OVL1", cutpos_ ) ) ) );
149  db_ang[ 8 ] = theta_C3star_O3star_nextP;
150  Real const theta_O3star_nextP_nextO5star = degrees ( angle_radians ( pose.xyz ( NamedAtomID ( " O3*", cutpos_ ) ),
151  pose.xyz ( NamedAtomID ( "OVL1", cutpos_ ) ),
152  pose.xyz ( NamedAtomID ( "OVL2", cutpos_ ) ) ) );
153  db_ang[ 9 ] = theta_O3star_nextP_nextO5star;
154  ////////////////////////////////////////////////////////////////////////////////////
155  Real const phi_C4star_C3star_O3star_nextP = degrees ( dihedral_radians ( pose.xyz ( NamedAtomID ( " C4*", moving_suite_ + 1 ) ),
156  pose.xyz ( NamedAtomID ( " C3*", cutpos_ ) ),
157  pose.xyz ( NamedAtomID ( " O3*", cutpos_ ) ),
158  pose.xyz ( NamedAtomID ( "OVL1", cutpos_ ) ) ) );
159  dt_ang[ 7 ] = phi_C4star_C3star_O3star_nextP;
160  Real const phi_C3star_O3star_nextP_nextO5star = degrees ( dihedral_radians (
161  pose.xyz ( NamedAtomID ( " C3*", cutpos_ ) ),
162  pose.xyz ( NamedAtomID ( " O3*", cutpos_ ) ),
163  pose.xyz ( NamedAtomID ( "OVL1", cutpos_ ) ),
164  pose.xyz ( NamedAtomID ( "OVL2", cutpos_ ) ) ) );
165  dt_ang[ 8 ] = phi_C3star_O3star_nextP_nextO5star;
166  Real const phi_O3star_nextP_nextO5star_nextC5star = degrees ( dihedral_radians ( pose.xyz ( NamedAtomID ( "OVU1", cutpos_ + 1 ) ),
167  pose.xyz ( NamedAtomID ( " P ", cutpos_ + 1 ) ),
168  pose.xyz ( NamedAtomID ( " O5*", cutpos_ + 1 ) ),
169  pose.xyz ( NamedAtomID ( " C5*", cutpos_ + 1 ) ) ) );
170  dt_ang[ 9 ] = phi_O3star_nextP_nextO5star_nextC5star;
171 
172  if ( verbose_ ) {
173  std::cout << "after chainbreak geometry fix" << std::endl;
174  output_chainTORS ( dt_ang, db_ang, db_len );
175  }
176 
177  ///////////////////////////////////
178  // Perform loop closure
179  ///////////////////////////////////
180  t_ang_.clear();
181  b_ang_.clear();
182  b_len_.clear();
183  nsol_ = 0;
184  bridgeObjects ( atoms, dt_ang, db_ang, db_len, pivots, order, t_ang_, b_ang_, b_len_, nsol_ );
185 
186  if ( nsol_ == 0 ) return false;
187 
188  figure_out_dof_ids_and_offsets ( pose, dt_ang );
189  apply_solutions ( pose );
190  return true;
191 }
192 
193 ///////////////////////////////////////////////////////////////////////////////////////
194 void
196  utility::vector1<Real> const & dt_ang ) {
197  ////////////////////////////////////////////////////////////////////////////////////
198  // Note that the torsion angles that we solved for do not directly correspond to
199  // torsion angles in the atom-tree. But they are right up to an *offset*, which
200  // we pre-calculate now. Also this is a good time to figure out exactly which
201  // DOFs need to be changed in the atom-tree.
202  //
203  // Just be totally explicit.
204  //
205  ////////////////////////////////////////////////////////////////////////////////////
206  offset_save_.clear();
207  dof_ids_.clear();
208  DOF_ID dof_id;
209  AtomID id1, id2, id3, id4;
210  /////////////////////////////////////////
211  // pivot 1
212  /////////////////////////////////////////
213  id1 = AtomID ( pose.residue(moving_suite_ + 1).atom_index ( " P " ), moving_suite_ + 1 );
214  id2 = AtomID ( pose.residue(moving_suite_ + 1).atom_index ( " O5*" ), moving_suite_ + 1 );
215  id3 = AtomID ( pose.residue(moving_suite_ + 1).atom_index ( " C5*" ), moving_suite_ + 1 );
216  id4 = AtomID ( pose.residue(moving_suite_ + 1).atom_index ( " C4*" ), moving_suite_ + 1 );
217  dof_id = pose.atom_tree().torsion_angle_dof_id ( id1, id2, id3, id4 );
218  figure_out_offset ( pose, dof_id, dt_ang[ 3 * 1 + 1 ], offset_save_ );
219  id1 = AtomID ( pose.residue(moving_suite_ + 1).atom_index ( " O5*" ), moving_suite_ + 1 );
220  id2 = AtomID ( pose.residue(moving_suite_ + 1).atom_index ( " C5*" ), moving_suite_ + 1 );
221  id3 = AtomID ( pose.residue(moving_suite_ + 1).atom_index ( " C4*" ), moving_suite_ + 1 );
222  id4 = AtomID ( pose.residue(moving_suite_ + 1).atom_index ( " C3*" ), moving_suite_ + 1 );
223  dof_id = pose.atom_tree().torsion_angle_dof_id ( id1, id2, id3, id4 );
224  figure_out_offset ( pose, dof_id, dt_ang[ 3 * 1 + 2 ], offset_save_ );
225  /////////////////////////////////////////
226  // pivot 2
227  /////////////////////////////////////////
228  id1 = AtomID ( pose.residue(chainbreak_suite_).atom_index ( " C4*" ), chainbreak_suite_ );
229  id2 = AtomID ( pose.residue(chainbreak_suite_).atom_index ( " C3*" ), chainbreak_suite_ );
230  id3 = AtomID ( pose.residue(chainbreak_suite_).atom_index ( " O3*" ), chainbreak_suite_ );
231  id4 = AtomID ( pose.residue(chainbreak_suite_).atom_index ( "OVL1" ), chainbreak_suite_ );
232  dof_id = pose.atom_tree().torsion_angle_dof_id ( id1, id2, id3, id4 );
233  figure_out_offset ( pose, dof_id, dt_ang[ 3 * 2 + 1 ], offset_save_ );
234  id1 = AtomID ( pose.residue(chainbreak_suite_).atom_index ( " C3*" ), chainbreak_suite_ );
235  id2 = AtomID ( pose.residue(chainbreak_suite_).atom_index ( " O3*" ), chainbreak_suite_ );
236  id3 = AtomID ( pose.residue(chainbreak_suite_).atom_index ( "OVL1" ), chainbreak_suite_ );
237  id4 = AtomID ( pose.residue(chainbreak_suite_).atom_index ( "OVL2" ), chainbreak_suite_ );
238  dof_id = pose.atom_tree().torsion_angle_dof_id ( id1, id2, id3, id4 );
239  figure_out_offset ( pose, dof_id, dt_ang[ 3 * 2 + 2 ], offset_save_ );
240  /////////////////////////////////////////
241  // pivot 3
242  /////////////////////////////////////////
243  id1 = AtomID ( pose.residue(chainbreak_suite_ + 1).atom_index ( " P " ), chainbreak_suite_ + 1 );
244  id2 = AtomID ( pose.residue(chainbreak_suite_ + 1).atom_index ( " O5*" ), chainbreak_suite_ + 1 );
245  id3 = AtomID ( pose.residue(chainbreak_suite_ + 1).atom_index ( " C5*" ), chainbreak_suite_ + 1 );
246  id4 = AtomID ( pose.residue(chainbreak_suite_ + 1).atom_index ( " C4*" ), chainbreak_suite_ + 1 );
247  dof_id = pose.atom_tree().torsion_angle_dof_id ( id1, id2, id3, id4 );
248  figure_out_offset ( pose, dof_id, dt_ang[ 3 * 3 + 1 ], offset_save_ );
249  id1 = AtomID ( pose.residue(chainbreak_suite_ + 1).atom_index ( " O5*" ), chainbreak_suite_ + 1 );
250  id2 = AtomID ( pose.residue(chainbreak_suite_ + 1).atom_index ( " C5*" ), chainbreak_suite_ + 1 );
251  id3 = AtomID ( pose.residue(chainbreak_suite_ + 1).atom_index ( " C4*" ), chainbreak_suite_ + 1 );
252  id4 = AtomID ( pose.residue(chainbreak_suite_ + 1).atom_index ( " C3*" ), chainbreak_suite_ + 1 );
253  dof_id = pose.atom_tree().torsion_angle_dof_id ( id1, id2, id3, id4 );
254  figure_out_offset ( pose, dof_id, dt_ang[ 3 * 3 + 2 ], offset_save_ );
255 }
256 
257 ////////////////////////////////////////////////////////////////////////////////////
258 void
260  core::pose::Pose const & pose,
261  core::id::DOF_ID const & dof_id,
262  core::Real const & original_torsion_value,
263  utility::vector1< core::Real > & offset_save ) {
264  if ( dof_id == BOGUS_DOF_ID ) { //expected at cutpoint!
265  std::cout << "Problem with DOF_ID " << dof_id << std::endl;
266  utility_exit_with_message ( "Problem with DOF_ID" );
267  // }
268  } else {
269  offset_save.push_back ( pose.dof ( dof_id ) - radians ( original_torsion_value ) );
270  dof_ids_.push_back ( dof_id );
271 
272  if ( verbose_ ) {
273  std::cout << dof_id;
274  std::cout << " offset " << pose.dof ( dof_id ) << " " << radians ( original_torsion_value )
275  << " " << pose.dof ( dof_id ) - radians ( original_torsion_value ) << std::endl;
276  }
277  }
278 }
279 
280 /////////////////////////////////////////////////////////////////////////////////////////////////////////
281 void
283  assert ( t_ang_.size() == Size ( nsol_ ) );
284 
285  /////////////////////////////////////////////////////////////////////////////////////////////////////
286  // Finally, ready to check out the solutions
287  /////////////////////////////////////////////////////////////////////////////////////////////////////
288  if ( nsol_ == 0 ) return;
289 
291  if ( verbose_ ) {
292  std::cout << "---------------------------------- " << std::endl;
293  std::cout << " start pose " << std::endl;
294  std::cout << "---------------------------------- " << std::endl;
295  utility::vector1<Real> dt_ang, db_len, db_ang;
297  fill_chainTORS ( pose, atom_ids_, atoms, dt_ang, db_ang, db_len );
298  output_chainTORS ( dt_ang, db_ang, db_len );
299  pose.dump_pdb ( "before_closed.pdb" );
300  }
301 
302  Real best_deviation2 ( 0.0 );
303  Size best_sol ( 0 );
304  // could save time by just looking over a subset of residues. But I don't think this is rate limiting
305  utility::vector1< Vector > ref_vectors;
306  Size const ref_atom ( 1 );
307 
308  for ( Size i = 1; i <= pose.total_residue(); i++ ) {
309  ref_vectors.push_back ( pose.xyz ( id::AtomID ( ref_atom, i ) ) );
310  }
311 
312  for ( Size n = 1; n <= Size ( nsol_ ); n++ ) {
313  fill_solution ( pose, n );
314  Real deviation2 ( 0.0 );
315 
316  for ( Size i = 1; i <= pose.total_residue(); i++ ) {
317  deviation2 += ( pose.xyz ( id::AtomID ( ref_atom, i ) ) - ref_vectors[i] ).length_squared();
318  }
319 
320  if ( n == 1 || deviation2 < best_deviation2 ) {
321  best_deviation2 = deviation2;
322  best_sol = n;
323  }
324  }
325 
326  fill_solution ( pose, best_sol );
327 
328  if ( verbose_ ) { //consistency check.
329  std::cout << "---------------------------------- " << std::endl;
330  std::cout << " solution " << best_sol << std::endl;
331  std::cout << "---------------------------------- " << std::endl;
332  output_chainTORS ( t_ang_[best_sol], b_ang_[best_sol], b_len_[best_sol] );
333  }
334 
335  // fill_solution( pose, best_sol );
336 
337  if ( verbose_ ) {
338  std::cout << "pose " << best_sol << ": " << std::endl;
339  utility::vector1<Real> dt_ang, db_len, db_ang;
341  fill_chainTORS ( pose, atom_ids_, atoms, dt_ang, db_ang, db_len );
342  output_chainTORS ( dt_ang, db_ang, db_len );
343  pose.dump_pdb ( "closed.pdb" );
344  }
345  } else if ( choose_best_solution_ ) {
346  assert ( scorefxn_ != 0 );
347  Real best_score ( 0.0 );
348  Size best_sol ( 0 );
349 
350  for ( Size n = 1; n <= Size ( nsol_ ); n++ ) {
351  fill_solution ( pose, n );
352  Real const score = ( *scorefxn_ ) ( pose );
353 
354  if ( score < best_score || n == 1 ) {
355  best_score = score;
356  best_sol = n;
357  }
358 
359  if ( verbose_ && n == 2 ) { //consistency check.
360  std::cout << "solution " << n << ": " << std::endl;
361  output_chainTORS ( t_ang_[n], b_ang_[n], b_len_[n] );
362  std::cout << "pose " << n << ": " << std::endl;
363  utility::vector1<Real> dt_ang, db_len, db_ang;
365  fill_chainTORS ( pose, atom_ids_, atoms, dt_ang, db_ang, db_len );
366  output_chainTORS ( dt_ang, db_ang, db_len );
367  }
368  }
369 
370  fill_solution ( pose, best_sol );
371  } else {
372  assert ( choose_random_solution_ );
373  Size const n = static_cast<int> ( nsol_ * RG.uniform() ) + 1;
374  fill_solution ( pose, n );
375  }
376 }
377 
378 //////////////////////////////////////////////////////////////////////////////////////////////
379 void
382  pose_list.clear();
383 
384  for ( Size n = 1; n <= Size ( nsol_ ); n++ ) {
385  fill_solution ( pose, n );
386  core::pose::PoseOP pose_save = new Pose;
387  *pose_save = pose;
388  pose_list.push_back ( pose_save );
389 
390  if ( verbose_ ) {
391  pose.dump_pdb ( "KIC_" + ObjexxFCL::string_of ( n ) + ".pdb" );
392  }
393  }
394 }
395 
396 
397 //////////////////////////////////////////////////////////////////////////////////////////////////////////
398 void
400  Size const n ) const {
401  Size count ( 0 );
402 
403  for ( Size i = 1; i <= 3; i++ ) {
404  count++;
405  pose.set_dof ( dof_ids_[count], principal_angle ( radians ( t_ang_[ n ][ 3 * i + 1 ] ) + offset_save_[count] ) );
406  count++;
407  pose.set_dof ( dof_ids_[count], principal_angle ( radians ( t_ang_[ n ][ 3 * i + 2 ] ) + offset_save_[count] ) );
408  }
409 }
410 
411 
412 //////////////////////////////////////////////////////////////////////////////////////////////////////////
415  assert ( n <= t_ang_.size() );
416  utility::vector1< Real > torsions;
417  Size count ( 0 );
418 
419  for ( Size i = 1; i <= 3; i++ ) {
420  count++;
421  torsions.push_back ( degrees ( principal_angle ( radians ( t_ang_[ n ][ 3 * i + 1 ] ) + offset_save_[count] ) ) );
422  count++;
423  torsions.push_back ( degrees ( principal_angle ( radians ( t_ang_[ n ][ 3 * i + 2 ] ) + offset_save_[count] ) ) );
424  }
425 
426  return torsions;
427 }
428 
429 //////////////////////////////////////////////////////////////////////////////////////////////////////////
432  utility::vector1< utility::vector1< Real > > torsions_for_all_solutions;
433 
434  for ( Size n = 1; n <= t_ang_.size(); n++ ) torsions_for_all_solutions.push_back ( get_torsions ( n ) );
435 
436  return torsions_for_all_solutions;
437 }
438 
439 
440 //////////////////////////////////////////////////////////////////////////////////////////////////////////
441 void
443  choose_best_solution_ = true;
445  scorefxn_ = scorefxn;
446 }
447 
448 //////////////////////////////////////////////////////////////////////////////////////////////////////////
449 void
451  choose_best_solution_ = false;
453 }
454 
455 ///////////////////////////////////////////////////////////////////////////
456 void
458  utility::vector1< core::Real > const & db_ang,
459  utility::vector1< core::Real > const & db_len ) const {
460  std::cout << "------ chainTORS output ---- " << std::endl;
461 
462  for ( Size i = 1; i <= dt_ang.size(); i++ ) {
463  std::cout << I ( 3, i ) << " ";
464  std::cout << "TORSIONS: ";
465  std::cout << F ( 8, 3, dt_ang[ i ] ) << " ";
466  std::cout << " BOND_ANGLES: ";
467  std::cout << F ( 8, 3, db_ang[ i ] ) << " ";
468  std::cout << " BOND_LENGTHS: ";
469  std::cout << F ( 8, 3, db_len[ i ] ) << " ";
470  std::cout << std::endl;
471  }
472 }
473 
474 ///////////////////////////////////////////////////////////
475 void
477  core::pose::Pose const & pose,
480  utility::vector1<Real> & dt_ang,
481  utility::vector1<Real> & db_ang,
482  utility::vector1<Real> & db_len ) const {
483  using namespace core::kinematics;
484  using namespace numeric::kinematic_closure;
486  utility::vector1<Real> R0 ( 3 );
487  utility::vector1< Vector > atoms_xyz;
488 
489  for ( Size i = 1; i <= atom_ids_.size(); i++ ) {
490  // std::cout << "filling: " << atom_ids_[i].atomno() << " " << atom_ids_[i].rsd() << std::endl;
491  atoms_xyz.push_back ( pose.xyz ( atom_ids_[ i ] ) );
492  }
493 
494  // //replace first and last with coordinate systems?
495  // atoms_xyz[ 1 ] = Vector( 0.0, 0.0, 0.0 );
496  // atoms_xyz[ 2 ] = Vector( 0.0, 0.0, 1.0 );
497  // atoms_xyz[ 3 ] = Vector( 0.0, 1.0, 0.0 );
498  // atoms_xyz[ atom_ids_.size() - 2 ] = Vector( 1.0, 0.0, 0.0 );
499  // atoms_xyz[ atom_ids_.size() - 1 ] = Vector( 1.0, 0.0, 1.0 );
500  // atoms_xyz[ atom_ids_.size() ] = Vector( 1.0, 1.0, 0.0 );
501  // Some of the pivot atoms may not be distinct -- nan.
502  // luckily there's a little hack we can do.
503  // where we nudge one atom the slightest bit.
504  // static Real const nudge( 0.000001 );
505  // for ( Size n = 1; n <= ( (atom_ids_.size()/3) - 3 ) ; n++ ){
506  // Size const i = 3 + (n * 3); // Look at S at the end of one triplet that may overlap with starting S of next triplet
507  // if ( atom_ids_[ i ] == atom_ids_[ i+1 ] ){
508  // // This should be the S at the end of one triplet overlapping with
509  // // the S beginning the next triplet.
510  // Size const seqpos = atom_ids_[ i ].rsd();
511  // atoms_xyz[ i+1 ] = atoms_xyz[ i ] +
512  // nudge * ( pose.xyz( NamedAtomID( " CEN", seqpos ) ) - atoms_xyz[i] ).normalize();
513  // }
514  // }
515  // formatting.
516  atoms.clear();
517 
518  for ( Size i = 1; i <= atom_ids_.size(); i++ ) {
519  utility::vector1< Real > atom_xyz_vals;
520  atom_xyz_vals.push_back ( atoms_xyz[i].x() );
521  atom_xyz_vals.push_back ( atoms_xyz[i].y() );
522  atom_xyz_vals.push_back ( atoms_xyz[i].z() );
523  atoms.push_back ( atom_xyz_vals );
524  }
525 
526  chainTORS ( atoms.size(), atoms, dt_ang, db_ang, db_len, R0, Q0 );
527 }
528 
529 
530 } // namespace rna
531 } // namespace swa
532 } // namespace protocols