Rosetta 3.5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
BondedAtom.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 core/kinematics/tree/BondedAtom.cc
11 /// @brief Kinematics
12 /// @author Phil Bradley
13 
14 
15 // Unit headers
17 
18 // Package headers
19 #include <core/id/DOF_ID.hh>
20 // AUTO-REMOVED #include <core/id/DOF_ID_Mask.hh>
21 #include <core/kinematics/Jump.hh>
23 
24 // Project headers
25 #include <core/id/AtomID_Map.hh>
26 #include <core/types.hh>
27 
28 // Numeric headers
29 #include <numeric/constants.hh>
30 #include <numeric/xyz.functions.hh>
31 
32 // Utility headers
33 #include <utility/exit.hh>
34 #include <utility/vector1.hh>
35 
36 // AUTO-REMOVED #include <ObjexxFCL/ObjexxFCL.hh>
37 //#include <ObjexxFCL/string.functions.hh>
38 
39 // C++ headers
40 #include <cassert>
41 #include <iostream>
42 
43 #include <core/id/DOF_ID_Map.hh>
44 #include <core/kinematics/types.hh>
45 
46 
47 
48 namespace core {
49 namespace kinematics {
50 namespace tree {
51 
52 /// @details Invokes Atom_ dfs function before, optionally recursing to younger siblings
53 /// should those younger siblings be effected by a DOF change on this node (e.g. phi_ change).
54 void
56  AtomDOFChangeSet & changeset,
57  ResidueCoordinateChangeList & res_change_list,
58  Size const start_atom_index
59 ) const
60 {
61 
62  Atom_::dfs( changeset, res_change_list, start_atom_index );
63  if ( start_atom_index == dof_refold_index() ) {
65  assert( parent_ );
66  Atoms_Iterator iter = parent_->atoms_begin();
67  /// you had better find yourself in your parent's atom list.
68  while ( (*iter)() != this ) { ++iter; assert( iter != parent_->atoms_end() );}
69  ++iter; // point to your next-youngest sibling.
70  while ( iter != parent_->atoms_end() ) {
71  (*iter)->dfs( changeset, res_change_list, start_atom_index );
72  ++iter;
73  }
74  }
75  }
76 }
77 
78 /// @details Relies on get_input_stub, which will use the coordinates of this atom's ancestors to
79 /// build a stub. If this function has been invoked by AtomTree update_xyz_coords(), then these
80 /// coordinates are guaranteed correct, since this atom is the root of a tree which needs to be
81 /// refolded. Ergo, nothing in the tree above this atom needs to be refolded.
82 void
84 {
85 
86 
87  /// dof_change_propagates_to_younger_siblings_ will be set to false inside
88  /// update_xyz_coords -- keep a local copy.
89  bool local_dof_change_propagates_to_younger_siblings( dof_change_propagates_to_younger_siblings_ );
90 
91  /// Ancestral coordinates are up-to-date since this node
92  /// is the root of a subtree that needs refolding.
93  /// The stub is passed to update_xyz_coords, and this atom will modify it;
94  /// after which the stub is ready to be passed to the younger siblings.
95  Stub stub( get_input_stub() );
96 
98 
99  if ( local_dof_change_propagates_to_younger_siblings ) {
100  assert( parent_ );
101  Atoms_Iterator iter = parent_->atoms_begin();
102  /// you had better find yourself in your parent's atom list.
103  while ( (*iter)() != this ) { ++iter; assert( iter != Atom_::parent()->atoms_end() );}
104  ++iter; // point to your next-youngest sibling.
105  while ( iter != parent_->atoms_end() ) {
106  (*iter)->update_xyz_coords( stub );
107  ++iter;
108  }
109  }
110 }
111 
112 
113 /////////////////////////////////////////////////////////////////////////////
114 /// @details starting from the input stub, calculate xyz position of this atom from
115 /// its internal coordinates d_, theta_ and phi_. If recusrvie is true,
116 /// obtain the new stub centered at this atom and pass the new stub to
117 /// all its children atoms to update their xyz positions recursively.
118 /// @note stub passed in is modified by rotating phi_ around x in the stub frame
119 void
121  Stub & stub
122 )
123 {
124  using numeric::x_rotation_matrix_radians;
125  using numeric::z_rotation_matrix_radians;
126  using numeric::constants::d::pi;
127 
128  assert( stub.is_orthogonal( 1e-3 ) );
129 
130  stub.M *= x_rotation_matrix_radians( phi_ ); // this gets passed out
131 
132  Stub new_stub( stub.M * z_rotation_matrix_radians( theta_ ), stub.v );
133 
134  if ( std::abs( theta_ - pi ) < 1e-6 ) {
135  // very special case
136  if ( keep_dof_fixed( THETA ) ) {
137  new_stub.M *= x_rotation_matrix_radians( pi );
138  }
139  }
140 
141  new_stub.v += d_ * new_stub.M.col_x();
142 
143  position( new_stub.v );
144 
145  for ( Atoms_Iterator it=atoms_begin(), it_end = atoms_end();
146  it != it_end; ++it ) {
147  (*it)->update_xyz_coords( new_stub );
148  }
149 
150  /// Reset the output-sensitive refold information
153 }
154 
155 
156 /////////////////////////////////////////////////////////////////////////////
157 /// @details starting from the input stub, calculate the internal coordinates d_, theta_ and
158 /// phi_ for this atom. If recusrvie is true, obtain the new stub centered at
159 /// this atom and pass the new stub to all its children atoms to update their
160 /// internal coordinates recursively.
161 /// @note stub passed in is modified by rotating phi_ around x in the stub frame
162 void
164  Stub & stub,
165  bool const recursive // = true
166 )
167 {
168  using numeric::x_rotation_matrix_radians;
169  using numeric::z_rotation_matrix_radians;
170  using numeric::constants::d::pi;
171 
172  assert( stub.is_orthogonal( 1e-3 ) );
173 
175 
176  d_ = w.length();
177 
178  bool flip_stub( false );
179  if ( d_ < 1e-2 ) {
180  // phi, theta dont make much sense
181  // std::cerr << "WARNING:: very small d= " << d_ << ' ' << id() << std::endl;
182  phi_ = 0.0;
183  theta_ = 0.0;
184  } else {
185  //if ( d_ < 1e-1 ) {
186  //std::cerr << "WARNING:: small d but we are calculating phi,theta: " << d_ << std::endl;
187  //}
188  w.normalize();
189  Real const x( dot( w, stub.M.col_x() ) );
190  Real const y( dot( w, stub.M.col_y() ) );
191  Real const z( dot( w, stub.M.col_z() ) );
192 
193  Real const tol( 1e-6 );
194  if ( x < -1.0 + tol ) {
195  // very special case:
196  // confirm that we are the stub_atom2 of a jump:
197  if ( keep_dof_fixed( THETA ) ) {
198  theta_ = pi;
199  phi_ = 0.0;
200  flip_stub = true; // very special case
201  } else {
202  theta_ = pi;
203  phi_ = 0.0;
204  }
205  } else if ( x > 1.0 - tol ) {
206  //std::cout << "WARNING:: update_internal_coords: exactly parallel? " << id() << std::endl;
207  theta_ = 0.0;
208  phi_ = 0.0;
209  } else {
210  theta_ = std::acos( x ); // DANGER
211  if ( theta_ < 1e-2 || pi - theta_ < 1e-2 ) {
212  // less than 0.57 degrees
213  //std::cout << "WARNING:: small theta but we are calculating phi: " <<
214  // theta_ << std::endl;
215  }
216  phi_ = std::atan2( z, y );
217  } // small theta
218  } // small d
219 
220  stub.M *= x_rotation_matrix_radians( phi_ );
221 
222 
223 
224  if ( recursive ) {
225  Stub new_stub( stub.M * z_rotation_matrix_radians( theta_ ), position() );
226 
227  if ( flip_stub ) {
228  // special case if I'm stub_atom2 of my parent (who is a jump)
229  new_stub.M *= x_rotation_matrix_radians( pi );
230  }
231 
232  for ( Atoms_Iterator it=atoms_begin(), it_end = atoms_end();
233  it != it_end; ++it ) {
234  (*it)->update_internal_coords( new_stub );
235  }
236  }
237 }
238 
239 /////////////////////////////////////////////////////////////////////////////
240 /// @details pass out the stub we would pass out if we were actually updating
241 /// coords or DOFs, which is rotate the stub around its x axis by phi_.
242 void
244  Stub & stub
245 ) const
246 {
247  stub.M *= numeric::x_rotation_matrix_radians( phi_ ); // this gets passed out
248 }
249 
250 
251 /////////////////////////////////////////////////////////////////////////////
252 void
254  DOF_Type const type,
255  Real const value
256 )
257 {
258  if ( type == PHI ) {
259  phi_ = value;
260  } else if ( type == THETA ) {
261  theta_ = value;
262  } else if ( type == D ) {
263  d_ = value;
264  } else {
265  std::cout << "bad torsion type for Atom: " << type << std::endl;
266  }
267 }
268 
269 /// @details calls set_dof non-polymorphically: assumption is that BondedAtom is not subclassed,
270 /// or, that if it is, that the derived class implements this overloaded set_dof function.
271 void
273  DOF_Type const type,
274  Real const value,
275  AtomDOFChangeSet & set
276 )
277 {
278  BondedAtom::set_dof( type, value );
279  Atom_::note_dof_change( set );
281 }
282 
283 
284 /////////////////////////////////////////////////////////////////////////////
285 Real
287  DOF_Type const type
288 ) const
289 {
290  if ( type == PHI ) {
291  return phi_;
292  } else if ( type == THETA ) {
293  return theta_;
294  } else if ( type == D ) {
295  return d_;
296  } else {
297  std::cout << "bad torsion type for Atom: " << type << std::endl;
298  utility_exit();
299  }
300  return 0.0;
301 }
302 
303 /////////////////////////////////////////////////////////////////////////////
304 /// @note This will recursively clone all this atom's offspring atoms
305 /// @note Assumes that atom_pointer has already been properly dimensioned
306 
307 AtomOP
308 BondedAtom::clone( AtomAP parent_in, AtomPointer2D & atom_pointer ) const
309 {
310 
311  BondedAtomOP new_me = new BondedAtom( *this );
312  new_me->set_weak_ptr_to_self( new_me() );
313 
314  atom_pointer[ id() ] = new_me; // handles memory management
315 
316  new_me->id( id() );
317  new_me->parent( parent_in );
318 
319  // copy DOFs
320  new_me->set_dof( PHI, dof( PHI ) );
321  new_me->set_dof( THETA, dof( THETA ) );
322  new_me->set_dof( D, dof( D ) );
323 
324  // copy coords
325  new_me->position( position() );
326 
327  new_me->dof_change_propagates_to_younger_siblings_ = dof_change_propagates_to_younger_siblings_;
328 
329  // copy atoms
330  for ( Atoms_ConstIterator a=atoms_begin(), a_end = atoms_end();
331  a != a_end; ++a ) {
332  new_me->append_atom( (*a)->clone( new_me() /*the new parent*/, atom_pointer ) );
333  }
334 
335  return new_me;
336 }
337 
338 
339 /////////////////////////////////////////////////////////////////////////////
340 /// @details last torsion is the torsion( Phi for BondedAtom and RB for JumpAtom) of the
341 /// parent atom or previous bonded sibling. Since BondedAtom's PHI is dependent
342 /// on its previous sibling BondedAtom,this may modify last_torsion, if our bond
343 /// torsion angle is changing and this atom has other sibling atoms after itself.
344 /// recursively done all its offspring
345 void
347  DOF_ID & last_torsion,
348  DOF_ID_Mask const & allow_move,
349  MinimizerMapBase & min_map
350 ) const
351 {
352 
353  DOF_ID phi_torsion ( id(), PHI );
354  DOF_ID theta_torsion( id(), THETA );
355  DOF_ID d_torsion ( id(), D );
356 
357  if ( allow_move[ phi_torsion ] && !keep_dof_fixed( PHI ) ) {
358  min_map.add_torsion( phi_torsion, last_torsion );
359  last_torsion = phi_torsion;
360  }
361 
362  // no more changes to last_torsion from now on //
363 
364  DOF_ID last_torsion_local( last_torsion );
365 
366  if ( allow_move[ theta_torsion ] && !keep_dof_fixed( THETA ) ) {
367  min_map.add_torsion( theta_torsion, last_torsion_local );
368  last_torsion_local = theta_torsion;
369  }
370 
371  if ( allow_move[ d_torsion ] && !keep_dof_fixed( D ) ) {
372  min_map.add_torsion( d_torsion, last_torsion_local );
373  last_torsion_local = d_torsion;
374  }
375 
376  // add me to the min_map
377  min_map.add_atom( id(), last_torsion_local );
378 
379  for ( Atoms_ConstIterator it=atoms_begin(), it_end = atoms_end();
380  it != it_end; ++it ) {
381  (*it)->setup_min_map( last_torsion_local, allow_move, min_map );
382  }
383 }
384 
385 /////////////////////////////////////////////////////////////////////////////
386 ///@li axis is the unit vector along the rotation axis for that DOF(Eab).
387 ///@li end_pos is the ending point of this unit vector(Vb).
388 ///
389 /// @details consider simple case like, A->B->C->D and we want to know the change of D position
390 /// with respect to the rotation along B->C bond( dr/dphi). In this case, Eab is
391 /// the unit vector along B->C, end_positon is C, and dr/dphi is given as Eab x (D-C).\n
392 /// For B->C bond rotation is the DOF(PHI) of Atom D, so end_pos is input_stub.v which is
393 /// the position of Atom C and axis is input_stub.M.col(1) which is the unit vector pointing
394 /// from B to C.\n
395 /// For DOF(THETA) of Atom D, it is a rotation around a unit vector (ending at C)
396 /// which is perpendicular to B->C->D plane. So the end_pos is the position of Atom C and the
397 /// axix is the my_stub.M.col(3).
398 /// For DOF(D) of Atom D, it is a translation along C->D axis and that is my_stub.M.col(1)
399 
400 void
402  Vector & axis,
403  Position & end_pos,
404  DOF_Type const type
405 ) const
406 {
407  Stub const my_stub( get_stub() );
408  Stub const input_stub( get_input_stub() );
409 
410  if ( type == PHI ) {
411  end_pos = input_stub.v;
412  axis = input_stub.M.col(1);
413  } else if ( type == THETA ) {
414  end_pos = input_stub.v;
415  axis = my_stub.M.col(3);
416  } else if ( type == D ) {
417  axis = my_stub.M.col(1);
418  } else {
419  std::cout << "Bad torsion type for Atom" << type << std::endl;
420  utility_exit();
421  }
422 }
423 
424 /////////////////////////////////////////////////////////////////////////////
425 /// @details
426 /// - bond distance D can always be flexible
427 /// - bond angle THETA is not meaningful if it is defined by A-B-A in some
428 /// special cases, for example N-CA-C in which CA is a jump atom, then THETA
429 /// of the N atom is defined by N-CA-N.
430 /// - torsion angle PHI is not meaningful if it is defined by A-B-A-D or A-B-D-A
431 /// or A-D-B-A in some special cases.
432 bool
434  DOF_Type const type
435 ) const
436 {
437  if ( type == D ) {
438  return false;
439  } else if ( type == THETA ) {
440  return ( parent()->is_jump() && id() == parent()->stub_atom2_id() );
441  } else if ( type == PHI ) {
442  return
443  ( ( parent()->is_jump() &&
444  ( id() == parent()->stub_atom2_id() ||
445  id() == parent()->stub_atom3_id() ) ) ||
446  ( parent()->parent() && parent()->parent()->is_jump() &&
447  id() == parent()->parent()->stub_atom3_id() ) );
448  } else {
449  std::cout << "BondedAtom::keep_dof_fixed: BAD_TYPE: " <<type <<
450  std::endl;
451  assert( false );
452  utility_exit();
453  }
454  return false;
455 }
456 
457 
458 ///////////////////////////////////////////////////////////////////////////
459 /// @details copy DOFs, xyz's.
460 /// this asserts equal topology.
461 /// do recursively to copy for all its children
462 void
464 {
465  phi_ = src.dof( PHI );
466  theta_ = src.dof( THETA );
467  d_ = src.dof( D );
468 
469  // copy xyz as well as the dof_change_index_
470  Super::operator= ( static_cast< Atom_ const & > ( src ));
471 
472  // check for topology mismatch
473  assert( atom_id() == src.atom_id() && n_children() == src.n_children() );
474 
475  // call recursively for my children
476  int i(0);
477  for ( Atoms_Iterator it=atoms_begin(), it_end = atoms_end();
478  it != it_end; ++it, ++i ) {
479  (*it)->copy_coords( *(src.child(i)) );
480  }
481 }
482 
483 ///
485 
486 }
487 } // namespace kinematics
488 } // namespace core