Rosetta 3.5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
AtomTreeSCMinMinimizerMap.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/pack/scmin/AtomTreeSCMinMinimizerMap.cc
11 /// @brief Class for identifying the sidechain DOFs in the AtomTree which are free during
12 /// any particular call to the minimizer.
13 /// @author Andrew Leaver-Fay (aleaverfay@gmail.com)
14 
15 
16 // Unit headers
18 
19 // Package Headers
20 // AUTO-REMOVED #include <core/pack/rotamer_set/RotamerSet.fwd.hh>
21 // AUTO-REMOVED #include <core/pack/rotamer_set/RotamerSets.fwd.hh>
23 
24 // Project Headers
25 #include <core/types.hh>
30 
31 //#include <core/pose/Pose.fwd.hh>
32 //#include <core/scoring/ScoreFunction.fwd.hh>
33 
34 // Utility headers
35 #include <utility/vector1.hh>
36 #include <utility/pointer/ReferenceCount.hh>
37 
39 #include <utility/options/BooleanVectorOption.hh>
40 #include <numeric/constants.hh>
41 
42 namespace core {
43 namespace pack {
44 namespace scmin {
45 
48  dof_mask_( 1, false ),
49  n_active_dof_nodes_( 0 ),
50  dof_start_for_focused_residue_( 0 ),
51  ndofs_added_for_focused_residue_( 0 )
52 {
53 
54 }
55 
57 
59 {
62  active_residues_.resize( total_residue );
63  active_residue_index_for_res_.resize( total_residue );
64  chi_start_for_active_residue_.resize( total_residue );
65  active_residue_atom_to_dofnode_index_.resize( total_residue );
66  atom_derivatives_.resize( total_residue );
67 
68  domain_map_.dimension( total_residue );
69  atcs_for_residues_.resize( total_residue );
70  if ( dof_nodes_.size() < total_residue ) dof_nodes_.reserve( total_residue ); // just a guess
71  std::fill( active_residues_.begin(), active_residues_.end(), 0 );
72  std::fill( active_residue_index_for_res_.begin(), active_residue_index_for_res_.end(), 0 );
73  std::fill( chi_start_for_active_residue_.begin(), chi_start_for_active_residue_.end(), 0 );
74  //std::fill( domain_map_.begin(), domain_map_.end(), 1 );
75  for ( Size ii = 1; ii <= domain_map_.size(); ++ii ) domain_map_( ii ) = 1;
76 }
77 
78 /// @brief Disable the minimization for all residues. Ammortized O(1).
80 {
81  for ( Size ii = 1; ii <= nactive_residues_; ++ii ) {
82  domain_map_( active_residues_[ ii ] ) = 1;
84  active_residue_index_for_res_[ active_residues_[ ii ] ] = 0;
85 
86  active_residues_[ ii ] = 0;
89  }
92 }
93 
94 /// @details This should be called at most once per residue between calls to "clear_active_chi"
96 {
97  assert( domain_map_( resindex ) == 1 ); // activate_residue_chi should not have already been called.
98  assert( active_residue_index_for_res_[ resindex ] == 0 ); // activate_residue_chi should not have already been called.
99 
100  domain_map_( resindex ) = 0;
101  active_residues_[ ++nactive_residues_ ] = resindex;
103 
104 }
105 
106 /// @brief Convenience lookup -- turns over the request to the AtomTreeCollection
107 conformation::Residue const &
109 {
110  return atcs_for_residues_[ seqpos ]->active_residue();
111 }
112 
115 {
116  return atcs_for_residues_[ atid.rsd() ]->active_atom_tree().atom( id::AtomID( atid.atomno(), 1 ) );
117 }
118 
119 
121 {
122  if ( atom_derivatives_[ resid ].size() < natoms ) {
123  atom_derivatives_[ resid ].resize( natoms );
124  }
125 }
126 
127 /// @brief Invoked during the depth-first traversal through the AtomTree. The AtomTree
128 /// is indicating that a particular torsion is dependent on another torsion. Record
129 /// that fact.
130 void
132  DOF_ID const & new_torsion,
133  DOF_ID const & parent
134 )
135 {
136  DOF_ID new_torsion_corrected( id::AtomID( new_torsion.atomno(), focused_residue_ ), new_torsion.type() );
137 
138  //std::cerr << "add_torsion " << new_torsion << " " << parent << std::endl;
139  DOF_NodeOP pnode( 0 );
140  if ( parent.valid() ) {
141  Size dofind=0;
142  if (parent.type() == core::id::PHI) {
143  dofind = atoms_representing_chis_[ parent.atomno() ];
144  } else if (parent.type() == core::id::D) {
145  dofind = atoms_representing_ds_[ parent.atomno() ];
146  } else if (parent.type() == core::id::THETA) {
147  dofind = atoms_representing_thetas_[ parent.atomno() ];
148  }
149  assert( dofind != 0 );
150  Size const pind = dof_start_for_focused_residue_ + dofind - 1;
151  assert( pind != 0 && pind <= n_active_dof_nodes_ );
152  pnode = dof_nodes_[ pind ];
153  }
154 
156  if (new_torsion.type() == core::id::PHI) {
157  assert( atoms_representing_chis_[ new_torsion.atomno() ] == 0 );
159  } else if (new_torsion.type() == core::id::D) {
160  assert( atoms_representing_ds_[ new_torsion.atomno() ] == 0 );
162  } else if (new_torsion.type() == core::id::THETA) {
163  assert( atoms_representing_thetas_[ new_torsion.atomno() ] == 0 );
165  }
166 
167  if ( n_active_dof_nodes_ >= dof_nodes_.size() ) {
168  dof_nodes_.push_back( new optimization::DOF_Node( new_torsion_corrected, pnode ) );
170  } else {
172  dof_nodes_[ n_active_dof_nodes_ ]->set_id( new_torsion_corrected );
173  dof_nodes_[ n_active_dof_nodes_ ]->set_parent( pnode );
174  }
175 }
176 
177 /// @brief Invoked during the depth-first traversal through the AtomTree; the atom
178 /// tree is indicating that a given atom is controlled by a particular DOF. Record
179 /// that fact.
180 void
182  AtomID const & atom_id,
183  DOF_ID const & dof_id
184 )
185 {
186  //std::cerr << "add_atom " << atom_id << " " << dof_id << std::endl;
187 
188  if ( dof_id.valid() ) {
189  Size dofind;
190 
191  if (nonideal_) {
192  Size const d = atoms_representing_ds_[ dof_id.atomno() ];
193  assert( d != 0 );
194  dofind = dof_start_for_focused_residue_ + d - 1;
195  assert( dofind <= n_active_dof_nodes_ );
196  dof_nodes_[ dofind ]->add_atom( id::AtomID( atom_id.atomno(), focused_residue_ ) );
197 
198  Size const theta = atoms_representing_thetas_[ dof_id.atomno() ];
199  assert( theta != 0 );
200  dofind = dof_start_for_focused_residue_ + theta - 1;
201  assert( dofind <= n_active_dof_nodes_ );
202  dof_nodes_[ dofind ]->add_atom( id::AtomID( atom_id.atomno(), focused_residue_ ) );
203  }
204 
205  Size const chi = atoms_representing_chis_[ dof_id.atomno() ];
206  assert( chi != 0 || nonideal_); //fpd with nonideality we may have a case where theta or d is movable but chi is not
207 
208  if (chi != 0) {
209  dofind = dof_start_for_focused_residue_ + chi - 1;
210  assert( dofind <= n_active_dof_nodes_ );
211  /// add the atom, but give it the correct residue id, since the input atom_id will be 1.
212  dof_nodes_[ dofind ]->add_atom( id::AtomID( atom_id.atomno(), focused_residue_ ) );
213  }
214  }
215 }
216 
217 /// @brief Traverse the atom trees in preparation for minimization to tie together all the
218 /// DOFs and the atoms they control.
219 void
221 {
222  reset_dof_nodes();
223  atom_tree_collection_ = trees;
224  for ( Size ii = 1; ii <= nactive_residues_; ++ii ) {
225  Size iiresid = active_residues_[ ii ];
226  //assert( atcs_for_residues_[ iiresid ] == 0 );
227  atcs_for_residues_[ iiresid ] = trees->residue_atomtree_collection_op( iiresid );
228  active_residue_atom_to_dofnode_index_[ ii ].resize( atcs_for_residues_[ iiresid ]->active_residue().natoms(), 0 );
229 
230  focused_residue_ = iiresid;
231 
232  conformation::Residue const & iires( atcs_for_residues_[ iiresid ]->active_residue() );
233 
234  /// mark the DOFs in the DOF_ID_Mask for the chi in this residue as being free
235  assert( dof_mask_.n_atom( 1 ) == ((nonideal_) ?
237  if ( dof_mask_.n_atom( 1 ) < ((nonideal_?3:1)*iires.natoms()) ) {
238  atoms_representing_chis_.resize( iires.natoms(), 0 );
239  if (nonideal_) {
240  dof_mask_.resize( 1, 3*iires.natoms(), false ); //fpd at most 3 DOFS per atom
241  atoms_representing_ds_.resize( iires.natoms(), 0 );
242  atoms_representing_thetas_.resize( iires.natoms(), 0 );
243  } else {
244  dof_mask_.resize( 1, iires.natoms(), false );
245  }
246  }
247  for ( Size jj = 1; jj <= iires.nchi(); ++jj ) {
248  dof_mask_[ id::DOF_ID( id::AtomID( iires.chi_atoms( jj )[ 4 ], 1 ), id::PHI ) ] = true;
249  if (nonideal_) {
250  if (jj == 1) {
251  dof_mask_[ id::DOF_ID( id::AtomID( iires.chi_atoms( jj )[ 3 ], 1 ), id::D ) ] = true;
252  dof_mask_[ id::DOF_ID( id::AtomID( iires.chi_atoms( jj )[ 3 ], 1 ), id::THETA ) ] = true;
253  }
254  dof_mask_[ id::DOF_ID( id::AtomID( iires.chi_atoms( jj )[ 4 ], 1 ), id::D ) ] = true;
255  dof_mask_[ id::DOF_ID( id::AtomID( iires.chi_atoms( jj )[ 4 ], 1 ), id::THETA ) ] = true;
256  }
257  }
260 
261  // descend through the atom tree for this residue.
262  // In this call, add_atom() and add_torsion() wil be invoked on this MinimizerMap.
263  DOF_ID invalid;
264  atcs_for_residues_[ iiresid ]->active_atom_tree().root()->setup_min_map( invalid, dof_mask_, *this );
265 
266  // now mark the DOFs in the DOF_ID_Mask for the chi in this residue as being fixed
267  for ( Size jj = 1; jj <= iires.nchi(); ++jj ) {
268  dof_mask_[ id::DOF_ID( id::AtomID( iires.chi_atoms( jj )[ 4 ], 1 ), id::PHI ) ] = false;
269  if (nonideal_) {
270  if (jj == 1) {
271  dof_mask_[ id::DOF_ID( id::AtomID( iires.chi_atoms( jj )[ 3 ], 1 ), id::D ) ] = false;
272  dof_mask_[ id::DOF_ID( id::AtomID( iires.chi_atoms( jj )[ 3 ], 1 ), id::THETA ) ] = false;
273  }
274  dof_mask_[ id::DOF_ID( id::AtomID( iires.chi_atoms( jj )[ 4 ], 1 ), id::D ) ] = false;
275  dof_mask_[ id::DOF_ID( id::AtomID( iires.chi_atoms( jj )[ 4 ], 1 ), id::THETA ) ] = false;
276  }
277  }
278  std::fill( atoms_representing_chis_.begin(), atoms_representing_chis_.end(), 0 ); // overkill
279  if (nonideal_) {
280  std::fill( atoms_representing_thetas_.begin(), atoms_representing_thetas_.end(), 0 ); //fpd also overkill (?)
281  std::fill( atoms_representing_ds_.begin(), atoms_representing_ds_.end(), 0 ); //fpd also overkill (?)
282  }
283  }
284 }
285 
286 void
288 {
289  dof.resize( n_active_dof_nodes_ );
290 
291  for ( Size ii = 1; ii <= n_active_dof_nodes_; ++ii ) {
292  DOF_Node const & iinode( * dof_nodes_[ ii ] );
293  Size const iirsd = iinode.rsd();
294 
295  DOF_ID new_torsion_uncorrected( id::AtomID( iinode.atomno(), 1 ), iinode.type() );
296 
297  if (iinode.type() == core::id::PHI) {
298  Size const iichi = atcs_for_residues_[ iirsd ]->active_restype().last_controlling_chi( iinode.atomno() );
299  assert( atcs_for_residues_[ iirsd ]->active_restype().chi_atoms( iichi )[ 4 ] == (Size) iinode.atomno() );
300  dof[ ii ] = atcs_for_residues_[ iirsd ]->active_residue().chi( iichi );
301  } else if (iinode.type() == core::id::D) {
302  dof[ ii ] = atcs_for_residues_[ iirsd ]->dof( new_torsion_uncorrected );
303  } else if (iinode.type() == core::id::THETA) {
304  dof[ ii ] = numeric::constants::d::radians_to_degrees * atcs_for_residues_[ iirsd ]->dof( new_torsion_uncorrected );
305  }
306  }
307 
308  //fpd previous version
309  //for ( Size ii = 1; ii <= n_active_dof_nodes_; ++ii ) {
310  // DOF_Node const & iinode( * dof_nodes_[ ii ] );
311  // Size const iirsd = iinode.rsd();
312  // Size const iichi = atcs_for_residues_[ iirsd ]->active_restype().last_controlling_chi( iinode.atomno() );
313  // assert( atcs_for_residues_[ iirsd ]->active_restype().chi_atoms( iichi )[ 4 ] == (Size) iinode.atomno() );
314  // dof[ ii ] = atcs_for_residues_[ iirsd ]->active_residue().chi( iichi );
315  //}
316 }
317 
318 void
320 {
321  assert( dofs.size() == n_active_dof_nodes_ );
322 
323  for ( Size ii = 1; ii <= n_active_dof_nodes_; ++ii ) {
324  DOF_Node const & iinode( * dof_nodes_[ ii ] );
325  Size const iirsd = iinode.rsd();
326 
327  //fpd for thetas and ds this is a bit of a hack
328  // the only d- and theta- minimizable atom not controlled by a chi is CB
329  // so we'll treat chi==0 in ResidueAtomTreeCollection::set_d/set_theta
330  // as the dist/angle completed by atoms 2 & 3 of chi 1
331  Size const iichi = atcs_for_residues_[ iirsd ]->active_restype().last_controlling_chi( iinode.atomno() );
332  assert( atcs_for_residues_[ iirsd ]->active_restype().chi_atoms( iichi==0?1:iichi )[ iichi==0?3:4 ] == (Size) iinode.atomno() );
333 
334  if (iinode.type() == core::id::PHI) {
335  atcs_for_residues_[ iirsd ]->set_chi( iichi, dofs[ ii ] );
336  } else if (iinode.type() == core::id::D) {
337  atcs_for_residues_[ iirsd ]->set_d( iichi, dofs[ ii ] );
338  } else if (iinode.type() == core::id::THETA) {
339  atcs_for_residues_[ iirsd ]->set_theta( iichi, dofs[ ii ] );
340  }
341  }
342 
343  //fpd previous version
344  //for ( Size ii = 1; ii <= n_active_dof_nodes_; ++ii ) {
345  // DOF_Node const & iinode( * dof_nodes_[ ii ] );
346  // Size const iirsd = iinode.rsd();
347  // Size const iichi = atcs_for_residues_[ iirsd ]->active_restype().last_controlling_chi( iinode.atomno() );
348  // assert( atcs_for_residues_[ iirsd ]->active_restype().chi_atoms( iichi )[ 4 ] == (Size) iinode.atomno() );
349  // atcs_for_residues_[ iirsd ]->set_chi( iichi, chi[ ii ] );
350  //}
351 
352  for ( Size ii = 1; ii <= nactive_residues_; ++ii ) {
353  atcs_for_residues_[ active_residues_[ ii ] ]->update_residue();
354  }
355 }
356 
359 {
360  Size atno = atcs_for_residues_[ resid ]->active_residue().chi_atoms( chiid )[ 4 ];
361  Size actid = active_residue_index_for_res_[ resid ];
362  Size dofnode_ind = active_residue_atom_to_dofnode_index_[ actid ][ atno ];
363  return * dof_nodes_[ dofnode_ind ];
364 }
365 
368 {
369  if (dofid.type() != core::id::PHI) return core::id::BOGUS_TORSION_ID;
370 
371  Size const rsd( dofid.rsd() );
372  Size const chi( residue( rsd ).type().last_controlling_chi( dofid.atomno() ) );
373  id::TorsionID torid( rsd, id::CHI, chi );
374  return torid;
375 }
376 
377 /// @details super simple -- no need for a sort (nor is there a need in the optimization::MinimizerMap for that matter).
379 {
380  /// by construction, DOFs are added such that index( parent ) < index( child ).
381  /// (i.e. we have a partial order of DOFs and DOF_Nodes are added in a monotonically increasing manner in that partial order)
382  //fpd this still holds for Ds/thetas
383  for ( Size ii = n_active_dof_nodes_; ii >= 1; --ii ) {
384  dof_nodes_[ ii ]->link_vectors();
385  }
386 }
387 
389 {
390  for ( Size ii = 1; ii <= nactive_residues_; ++ii ) {
391  Size iiresid = active_residues_[ ii ];
392  for ( Size jj = 1, jjend = atom_derivatives_[ iiresid ].size(); jj <= jjend; ++jj ) {
393  atom_derivatives_[ iiresid ][ jj ].f1() = 0.0;
394  atom_derivatives_[ iiresid ][ jj ].f2() = 0.0;
395  }
396  }
397 }
398 
400 {
401  for ( Size ii = 1; ii <= n_active_dof_nodes_; ++ii ) {
402  dof_nodes_[ ii ]->set_parent( 0 );
403  dof_nodes_[ ii ]->clear_atoms();
404  }
406 }
407 
408 
409 
410 } // namespace scmin
411 } // namespace pack
412 } // namespace core
413