Rosetta 3.5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
SurfaceInteractionGraph.hh
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/interaction_graph/SurfaceInteractionGraph.hh
11 /// @brief Interaction graph which implements a non-PD, environment-dependent score for surface residues
12 /// @author Ron Jacak (ron.jacak@gmail.com)
13 
14 #ifndef INCLUDED_core_pack_interaction_graph_SurfaceInteractionGraph_hh
15 #define INCLUDED_core_pack_interaction_graph_SurfaceInteractionGraph_hh
16 
17 //Rosetta Headers
23 
28 #include <core/pose/Pose.hh>
30 
31 //Utility Headers
32 #include <basic/Tracer.hh>
33 #include <utility/exit.hh>
34 
35 //ObjexxFCL Headers
36 #include <ObjexxFCL/FArray1D.hh>
37 // AUTO-REMOVED #include <ObjexxFCL/FArray1.io.hh>
38 
39 //C++ Headers
40 #include <vector>
41 // AUTO-REMOVED #include <typeinfo> //required by GCC 4.3.2
42 
43 #include <utility/vector1.hh>
44 
45 
46 /// Tracer instance for this file
47 static basic::Tracer TR_NODE("core.pack.surfaceig.node");
48 static basic::Tracer TR_EDGE("core.pack.surfaceig.edge");
49 static basic::Tracer TR_BGNODE("core.pack.surfaceig.bgnode");
50 static basic::Tracer TR_BGEDGE("core.pack.surfaceig.bgedge");
51 static basic::Tracer TR_SIG("core.pack.surfaceig.sig");
52 static basic::Tracer TR_STATS("core.pack.surfaceig.stats");
53 
54 //#define DOUBLE_CHECK_COUNTS 1
55 //#define FILE_DEBUG 1
56 
57 namespace core {
58 namespace pack {
59 namespace interaction_graph {
60 
61 template < typename V, typename E, typename G > class SurfaceNode;
62 template < typename V, typename E, typename G > class SurfaceBackgroundNode;
63 template < typename V, typename E, typename G > class SurfaceEdge;
64 template < typename V, typename E, typename G > class SurfaceBackgroundEdge;
65 template < typename V, typename E, typename G > class SurfaceInteractionGraph;
66 
67 
68 //----------------------------------------------------------------------------//
69 //---------------------------- Surface Node Class ----------------------------//
70 //----------------------------------------------------------------------------//
71 
72 ///
73 /// @begin SurfaceNode
74 ///
75 /// @brief
76 /// Defines a FirstClass node which will keep track of changes in the surface energy.
77 /// FirstClassNode is defined and implemented in AdditionalBackgroundNodesInteractionGraph.
78 ///
79 /// @remarks
80 /// No public default constructor makes this class uncopyable.
81 ///
82 template < typename V, typename E, typename G >
83 class SurfaceNode : public FirstClassNode< V, E, G > {
84 
85  public:
87 
88  public:
89  SurfaceNode( G* owner, int node_index, int num_states );
90  virtual ~SurfaceNode();
91 
92  virtual void assign_zero_state();
93  virtual bool state_unassigned() const { return parent::get_current_state() == 0; }
94 
95  void assign_state_surface( int state );
97  Real project_deltaE_for_substitution_surface( int alternate_state, core::PackerEnergy & prev_energy_for_node, float deltaE_thresh_for_avoiding_surface_calcs );
98 
99  Real get_surface_deltaE_for_neighbors_state_substitution( SurfaceNode<V,E,G>* node_considering_substitution, int changing_nodes_curr_state, int changing_nodes_alt_state );
100 
103 
104  bool detect_neighborship_with_node( int node_id, bool first_class ) const;
105 
106  static void print_surface_avoidance_stats();
107  static void reset_surface_avoidance_stats();
108 
109  // virtual methods from NodeBase class
110  virtual void print() const;
111 
112  virtual void prepare_for_simulated_annealing();
113  virtual unsigned int getMemoryUsageInBytes() const;
114  virtual unsigned int count_static_memory() const;
115  virtual unsigned int count_dynamic_memory() const;
116 
117  // setter for the rotamers object.
118  void set_rotamers( rotamer_set::RotamerSetCOP rotamers );
119  conformation::ResidueCOP get_rotamer( int state ) const;
120 
121  // hold on to these so we can look up is_hydrophobic on state changes
124 
125  inline
126  int wt_seqpos_for_node() const {
127  return get_surface_owner()->rotamer_sets().moltenres_2_resid( parent::get_node_index() );
128  }
129  inline
131  return get_surface_owner()->pose().residue( (get_surface_owner()->rotamer_sets().moltenres_2_resid( parent::get_node_index() )) );
132  }
133 
134 
136 
137  bool is_surface_exposed() const;
138  void surface_exposed( bool value );
140  void is_below_buried_residue_no_hsasa_cutoff( bool value );
141 
143 
145  int num_neighbors_counting_self() const;
146 
147  void init_hASA_variables();
149  Real average_residue_hASA() const;
150  Real average_residue_hASA( chemical::AA residue_type, Size num_nbs ) const;
151  Real hASA_energy( Real patch_area ) const;
152 
153  void verify_patch_areas_correct( int node_id, int previous_state, Real previous_state_hASA );
154 
155  // Extra methods only used only for the unit tests.
157  std::vector<Real> get_hASA_for_node_and_nbs();
158  std::vector<Real> get_alt_state_hASA_for_node_and_nbs();
160  Real get_alt_hASA();
161 
162  protected:
163  inline
165  return (SurfaceEdge< V, E, G >*) parent::get_incident_edge( index );
166  }
167 
168  inline
171  }
172 
173  inline
175  return (SurfaceInteractionGraph< V, E, G >*) parent::get_owner();
176  }
177 
178  private:
180  void track_surface_E_min();
181 
182  bool decide_procrastinate_surface_computations( Real const pd_deltaE, Real const threshold ) const;
183 
186 
189 
191 
196 
199  std::map< std::pair<int, int >, int > fc_neighbor_map;
200  std::map< std::pair<int, int >, int > bg_neighbor_map;
201 
203 
205  static const int MAX_SURFACE_ENERGY;
206  static const int INTERACTION_RADIUS = 10;
207  static const int SURFACE_EXPOSED_CUTOFF = 20;
208  static const int BURIED_RESIDUE_NO_HSASA_CUTOFF = 24;
209  static const int MAX_PATCH_SURFACE_AREA = 1100;
210 
214 
215  //no default constructor, uncopyable
216  SurfaceNode();
219 
220 
221 };
222 
223 
224 //----------------------------------------------------------------------------//
225 //------------------- Surface Background Node Class -----------------------//
226 //----------------------------------------------------------------------------//
227 
228 ///
229 /// @begin SurfaceBackgroundNode
230 ///
231 /// @brief
232 /// Defines a BackgroundResidue node which will contribute to changes in surface energy
233 /// due to state changes on neighboring nodes, and not because of state changes to it.
234 ///
235 template < typename V, typename E, typename G >
236 class SurfaceBackgroundNode : public BackgroundNode< V, E, G > {
237 
238  public:
240 
241  public:
242 
244  virtual ~SurfaceBackgroundNode();
245 
246  bool detect_neighborship( SurfaceNode< V, E, G >* node ) const;
247 
249  int changing_nodes_curr_state, int changing_nodes_alt_state );
250 
252  Real get_surface_score() const;
253 
254  virtual void prepare_for_simulated_annealing();
255  void print() const;
256 
257  virtual unsigned int count_static_memory() const;
258  virtual unsigned int count_dynamic_memory() const;
259 
260  inline
262  return get_surface_owner()->pose().residue( (get_surface_owner()->bg_node_2_resid(parent::get_node_index())) );
263  }
264 
265  bool is_surface_exposed() const;
266  void surface_exposed( bool value );
268  void is_below_buried_residue_no_hsasa_cutoff( bool value );
269 
271 
273  int num_neighbors_counting_self() const;
274 
275  void init_hASA_variables();
277  Real average_residue_hASA() const;
278  Real average_residue_hASA( chemical::AA residue_type, Size num_nbs ) const;
279  Real hASA_energy( Real patch_area ) const;
280 
281  // Only used for the unit tests.
283  Real get_alt_hASA();
284 
285  protected:
286  inline
289  }
290 
291  inline
294  }
295 
296  private:
298  static const int MAX_SURFACE_ENERGY;
299  static const int INTERACTION_RADIUS = 10;
300  static const int SURFACE_EXPOSED_CUTOFF = 20;
301  static const int BURIED_RESIDUE_NO_HSASA_CUTOFF = 24;
302  static const int MAX_PATCH_SURFACE_AREA = 1100;
303 
306 
308 
312 
313  //no default constructor, uncopyable
317 
318 };
319 
320 
321 //----------------------------------------------------------------------------//
322 //-------------------------- Surface Edge Class ---------------------------//
323 //----------------------------------------------------------------------------//
324 
325 ///
326 /// @begin SurfaceEdge
327 ///
328 /// @brief
329 /// Defines a Surface edge which will be used in determining surface energy.
330 ///
331 template < typename V, typename E, typename G >
332 class SurfaceEdge : public FirstClassEdge< V, E, G > {
333 
334  public:
336 
337  public:
338  SurfaceEdge( G* owner, int node1, int node2 );
339  virtual ~SurfaceEdge();
340 
341  void acknowledge_state_zeroed_surface( int node_index );
342 
343  Real get_surface_deltaE_for_neighbor( int node_considering_substitution, int alt_state );
344 
347 
348  //Virtual methods from EdgeBase
349  virtual void declare_energies_final();
350  virtual void prepare_for_simulated_annealing();
351  virtual unsigned int getMemoryUsageInBytes() const;
352 
353  Real get_max_surface_deltaE_guess( int node_changing ) const;
354 
355  virtual unsigned int count_static_memory() const;
356  virtual unsigned int count_dynamic_memory() const;
357 
358  // this method used only for testing
359  inline
362  }
363 
364 // protected:
365  public:
366  // Need to make this method public so that SurfaceNodes can call methods on the SurfaceBackgroundNode connected to them
367  // via this Edge. The class hierarchy/design does not necessitate this; just some debugging checks in the SurfaceNode that need
368  // access to the BackgroundNode object.
369  inline
371  return (SurfaceNode< V, E, G >*) E::get_node( index );
372  }
373 
374  private:
375  inline
377 
382 
387 
389 
390  //no default constructor, uncopyable
391  SurfaceEdge();
394 };
395 
396 
397 
398 //----------------------------------------------------------------------------//
399 //------------------- Surface Background Edge Class -----------------------//
400 //----------------------------------------------------------------------------//
401 
402 ///
403 /// @begin SurfaceBackgroundEdge
404 ///
405 /// @brief
406 /// Defines an edge between a FirstClass (SurfaceNode) and a background node (SurfaceBackgroundNode)
407 ///
408 /// @detailed
409 /// In addition to implementing the virtual base class methods, this class additionally defines methods
410 /// relating to keeping track of data relating to surface.
411 ///
412 template < typename V, typename E, typename G >
413 class SurfaceBackgroundEdge : public BackgroundToFirstClassEdge< V, E, G > {
414 
415  public:
417 
418  public:
419  SurfaceBackgroundEdge( AdditionalBackgroundNodesInteractionGraph< V, E, G >* owner, int first_class_node_index, int background_node_index );
420  virtual ~SurfaceBackgroundEdge();
421 
423 
424  Real get_surface_deltaE_for_substitution( int alt_state );
426  void acknowledge_state_change( int new_state );
428 
429  virtual unsigned int count_static_memory() const;
430  virtual unsigned int count_dynamic_memory() const;
431 
432  // this function only used for unit tests
433  inline
436  }
437 
438  public:
439  // Making this method public also so that a BGNode can call a method on a Node via this Edge.
440  inline
443  }
444 
445  public:
446  // Need to make this method public so that SurfaceNodes can call methods on the SurfaceBackgroundNode connected to them
447  // via this Edge. The class hierarchy/design does not necessitate this; just some debugging checks in the SurfaceNode that need
448  // access to the BackgroundNode object.
449  inline
452  }
453 
454  private:
457 
462 
464 
465  //no default constructor, uncopyable
469 
470 };
471 
472 
473 
474 
475 //----------------------------------------------------------------------------//
476 //--------------------- Surface Interaction Graph -------------------------//
477 //----------------------------------------------------------------------------//
478 
479 ///
480 /// @begin SurfaceInteractionGraph
481 ///
482 /// @brief
483 /// Defines the interaction graph that will keep track of changes to the surface score.
484 ///
485 /// @detailed
486 /// In addition to implementing the virtual base class methods, this class additionally defines methods
487 /// relating to keeping track of data relating to surface.
488 ///
489 template < typename V, typename E, typename G >
491 
492  public:
494 
495  public:
496  SurfaceInteractionGraph( int num_nodes );
497  virtual ~SurfaceInteractionGraph();
498 
499  void initialize( rotamer_set::RotamerSetsBase const & rot_sets );
500 
501  // Virtual public methods from InteractionGraphBase
502  virtual void prepare_for_simulated_annealing();
503  virtual void blanket_assign_state_0();
504  virtual core::PackerEnergy set_state_for_node( int node_ind, int new_state );
505  virtual core::PackerEnergy set_network_state( FArray1_int& node_states );
506 
507  virtual void consider_substitution( int node_ind, int new_state, core::PackerEnergy & delta_energy, core::PackerEnergy & prev_energy_for_node );
510 
511  using parent::set_errorfull_deltaE_threshold;
512 
513  virtual void set_errorfull_deltaE_threshold( Real deltaE );
514 
515  void set_num_residues_in_protein( int num_res );
516  void set_num_background_residues( int num_background_residues );
517  void set_residue_as_background_residue( int residue );
518 
520 
521  virtual int get_edge_memory_usage() const;
522  virtual unsigned int count_static_memory() const;
523  virtual unsigned int count_dynamic_memory() const;
524  void print() const;
525 
526  inline
527  pose::Pose const & pose() const { return *pose_; }
528  void set_pose( pose::Pose const & pose );
529 
530  inline
531  task::PackerTask const & packer_task() const { return *packer_task_; }
532  void set_packer_task( task::PackerTask const & task );
533 
536 
537  inline
539  void set_rotamer_sets( rotamer_set::RotamerSets const & rotsets );
540 
541  int bg_node_2_resid( int node_index );
542 
543  // methods used only by unit tests
544  std::vector<int> get_network_state() const;
546  std::vector<Real> get_hASA_for_node_and_nbs(int index);
547  std::vector<Real> get_alt_state_hASA_for_node_and_nbs(int index);
548 
549  protected:
550 
551  //Factory Methods:
552  //From InteractionGraphBase
553  virtual core::pack::interaction_graph::NodeBase* create_new_node( int node_index, int num_states );
554  virtual core::pack::interaction_graph::EdgeBase* create_new_edge( int index1, int index2);
555 
556  //From AdditionalBackgroundNodesInteractionGraph
557  virtual BackgroundNode< V, E, G >* create_background_node( int node_index );
558  virtual BackgroundToFirstClassEdge< V, E, G >* create_background_edge( int fc_node_index, int bg_node_index);
559 
560  inline
562  return (SurfaceNode< V, E, G >*) G::get_node( index );
563  }
564 
565  inline
568  }
569 
571 
572  private:
575 
578 
581 
588 
589  static const int COMMIT_LIMIT_BETWEEN_UPDATES = 1024; // 2^10
590  static const int SURFACE_EXPOSED_CUTOFF = 20;
591  static const int BURIED_RESIDUE_NO_HSASA_CUTOFF = 24;
592 
597 
598  //no default constructor, uncopyable
602 
603 };
604 
605 
606 // Begin implementation: must be contained within this header file due to use of templates!
607 
608 
609 //----------------------------------------------------------------------------//
610 //-------------------------- Surface Node Class ---------------------------//
611 //----------------------------------------------------------------------------//
612 
613 template < typename V, typename E, typename G >
615 
616 template < typename V, typename E, typename G >
618 
619 template < typename V, typename E, typename G >
621 
622 template < typename V, typename E, typename G >
624 
625 template < typename V, typename E, typename G >
627 
628 
629 ///
630 /// @begin SurfaceNode< V, E, G >::SurfaceNode
631 ///
632 /// @brief
633 /// SurfaceNode constructor
634 ///
635 /// @param
636 /// owner - [in] - the owning interaction graph
637 /// node_id - [in] - the index for this node amongst its owners set
638 /// num_states - [in] - the number of states for this node
639 ///
640 template < typename V, typename E, typename G >
641 SurfaceNode< V, E, G >::SurfaceNode( G* owner, int node_index, int num_states ) :
642  FirstClassNode< V, E, G > ( owner, node_index, num_states ),
643  rotamers_vector_( num_states ),
644  calculated_surface_deltaE_( false ),
645  deltaE_for_substitution_( 0.0f ),
646  curr_state_total_hASA_( 0.0 ),
647  alt_state_total_hASA_( 0 ),
648  have_prepared_for_simA_( false ),
649  surface_score_min_last_100_( 0 ),
650  surface_score_min_recent_( 0 ),
651  num_substitutions_since_surface_min_update_( 0 ),
652  observed_sufficient_surface_E_to_predict_min_( false ),
653  surface_exposed_( false ),
654  is_below_buried_residue_no_hsasa_cutoff_( false ),
655  num_neighbors_counting_self_(-1)
656 {
657  // the weight to apply to the surface score is stored in the packer task. this allows users to change the
658  // weight with a command line option
659  surface_energy_weight_ = get_surface_owner()->surface_score_weight();
660 #ifdef FILE_DEBUG
661  TR_NODE << "Setting surface_energy_weight to " << surface_energy_weight_ << std::endl;
662 #endif
663 }
664 
665 
666 ///
667 /// @begin SurfaceNode< V, E, G >::~SurfaceNode
668 ///
669 /// @brief
670 /// destructor -- no dynamically allocated data, does nothing
671 ///
672 template < typename V, typename E, typename G >
674 
675 
676 ///
677 /// @begin SurfaceNode::prepare_for_simulated_annealing
678 ///
679 /// @brief
680 /// invokes V's prep_for_simA method
681 /// Also populates a map defining which nodes are neighbors according to the tenA neighbor graph. This map will be
682 /// checked whenever iterating over all edges defined by the energy graph to see if a Node really needs to be updated
683 /// for the surface score.
684 ///
685 template < typename V, typename E, typename G >
687 
688  // parent is AddtlBGNodesIG; V is either PDIG or LinmemIG; here we want to call the templated classes prep_for_simA
689  // method so that it can get ready for all the pairwise-decomposable energy term stuff
690  V::prepare_for_simulated_annealing();
691 
692  if ( ! parent::get_bg_edge_vector_up_to_date_() ) {
693  parent::update_bg_edge_vector();
694  }
695 
696  have_prepared_for_simA_ = true;
697 
698  // populate the neighbor map for fast lookups of "are they neighbors" later
699  // Important: this map is also used in the calculate_amount_total_hydrophobic_ASA method, so make sure to init the map before
700  // calling this method.
701  int this_nodes_index = parent::get_node_index();
702 
703  for ( int ii = 1; ii <= parent::get_num_incident_edges(); ++ii ) {
704  int other_nodes_index = get_incident_surface_edge(ii)->get_other_ind( this_nodes_index );
705  // set i,j and j,i in case when we do the lookup one key pair is not set
706  if ( this->detect_neighborship_with_node( other_nodes_index, true /* this node is a FC node */ ) ) {
707  fc_neighbor_map[ std::pair<int,int>(this_nodes_index, other_nodes_index) ] = 1;
708  fc_neighbor_map[ std::pair<int,int>(other_nodes_index, this_nodes_index) ] = 1;
709  }
710  }
711 
712  for ( int ii = 1; ii <= parent::get_num_edges_to_background_nodes(); ++ii ) {
713  int bg_nodes_index = get_edge_to_surface_bg_node( ii )->get_other_ind( this );
714  if ( this->detect_neighborship_with_node( bg_nodes_index, false /* not a FC node */ ) ) {
715  bg_neighbor_map[ std::pair<int,int>(this_nodes_index, bg_nodes_index) ] = 1;
716  bg_neighbor_map[ std::pair<int,int>(bg_nodes_index, this_nodes_index) ] = 1;
717  }
718  }
719 
720  init_hASA_variables();
721 
722 }
723 
724 
725 ///
726 /// @begin SurfaceNode::detect_neighborship_with_node
727 ///
728 /// @brief
729 /// Determines if this vertex neighbors the calling node
730 /// Called by all other nodes, and if true is returned an Edge of some sort is created between the nodes.
731 ///
732 /// @detailed
733 /// To determine whether the passed in fc node is neighbors with this one, we need to iterate through the
734 /// list of neighbors in the tenA neighbor graph (a ContextGraph) that's stored in the Pose Energies object. Assumes
735 /// that the Pose has already been scored by some ScoreFunction.
736 /// The tenA neighbor graph is cool if we want to look at an interaction distance of 10A. But what if we want to only
737 /// find patches of exposed hydrophobics within an 8A sphere. Then we can't use the tenA neighbor. Instead use an
738 /// expensive distance measurement between the centroids of the wild-type residues to determine "are they neighbors".
739 ///
740 /// The only problem with making this method generic for fc nodes or bg nodes is that when an index is passed in, it's
741 /// not possible to really tell if it's a fc node index or bg node index. Rather than making two separate methods for
742 /// detecting neighborship, add a second parameter to this function which specificies if the node being checked is fc
743 /// or not. That way we can get the pose residue object correct.
744 ///
745 /// This method basically makes the decision for whether to create a SurfaceEdge or SurfaceBackgroundEdge between
746 /// two Nodes. It really is what defines how much of the surface we design for.
747 ///
748 template < typename V, typename E, typename G >
749 bool SurfaceNode< V, E, G >::detect_neighborship_with_node( int node_index, bool first_class ) const {
750 
751  // owner is the graph which has a reference to the Pose
752  pose::Pose poseRef = get_surface_owner()->pose();
753  // core::scoring::TenANeighborGraph const & tenA_neighbor_graph( poseRef.energies().tenA_neighbor_graph() );
754 
755  int fc_node_index = parent::get_node_index();
756 
757  // since this method is generic for detecting neighborship with either bg nodes or fc nodes, we need to figure out
758  // whether the passed in node_index is for a background node or fc node. Only way I can think of to do that here
759  // is to check the bg node array in the SIG and see if it returns a non-negative value. If it return -1, then that
760  // node_index was not found and it must be a fc node. Right?
761  // Changing this method to have a second parameter. Use the second parameter boolean to tell what type of node it is
762  int other_node_resid;
763  if ( first_class ) {
764  other_node_resid = get_surface_owner()->rotamer_sets().moltenres_2_resid( node_index );
765  } else {
766  other_node_resid = get_surface_owner()->bg_node_2_resid( node_index );
767  }
768 
769  // we need to determine whether the centroid of the side chain (is that the same as the action coordinate?)
770  // of this residue has a distance less than the centroid of the res1 sidechain. This method is a brute
771  // force way of determining "neighbor".
772  conformation::Residue const & rsd1 = poseRef.residue( get_surface_owner()->rotamer_sets().moltenres_2_resid( fc_node_index ) );
773  conformation::Residue const & rsd2 = poseRef.residue( other_node_resid );
774 
775  Real distanceBetweenAtoms = rsd1.xyz( rsd1.nbr_atom() ).distance( rsd2.xyz( rsd2.nbr_atom() ) );
776 
777 #ifdef FILE_DEBUG
778  // toooo much output
779  //TR_NODE << "detect_neighborship_with_node: fc node " << fc_node_index << " (resid: " <<
780  // get_surface_owner()->rotamer_sets().moltenres_2_resid( fc_node_index ) << ") checking if ";
781  //if ( first_class ) { TR_NODE << "fc node "; } else { TR_NODE << "bg node "; }
782  //TR_NODE << node_index << " (resid: " << other_node_resid << ") is a neighbor; distance between atoms " << rsd1.name3() << " " << rsd1.seqpos()
783  // << " " << rsd1.atom_name( rsd1.nbr_atom() ) << " - " << rsd2.atom_name( rsd2.nbr_atom() )
784  // << rsd2.name3() << " " << rsd2.seqpos() << ": " << distanceBetweenAtoms << std::endl;
785 #endif
786 
787  if ( distanceBetweenAtoms <= INTERACTION_RADIUS ) {
788  return true;
789  }
790 
791  // for every Edge in the neighbor graph, figure out if that residue is surface exposed *and* hydrophobic
792  /* for ( core::graph::EdgeListConstIterator eli = tenA_neighbor_graph.get_node( fc_node_index )->const_edge_list_begin(),
793  eli_end = tenA_neighbor_graph.get_node( fc_node_index )->const_edge_list_end(); eli != eli_end; ++eli ) {
794  if ( (*eli)->get_other_ind( fc_node_index ) == node_index ) {
795  return true;
796  }
797  } */
798 
799  // if not within the interaction radius, not neighbors
800  return false;
801 
802 }
803 
804 
805 
806 ///
807 /// @begin SurfaceNode::assign_zero_state
808 ///
809 /// @brief
810 /// Assign the node to state 0 -- the "unassigned" state.
811 ///
812 /// @detailed
813 /// A node in state 0 produces no surface score. Its neighbors have to adjust their scores appropriately. This method
814 /// iterates over all the edges emanating from this node and tells them to acknowledge that they've been zeroed out.
815 ///
816 template < typename V, typename E, typename G >
818 
819 #ifdef FILE_DEBUG
820  //TR_NODE << "assign_zero_state - node " << parent::get_node_index() << " going to state 0." << std::endl;
821 #endif
822 
823  // depending on the type of interaction graph (linmem, standard pd) used for the simulation, this will call
824  // the appropriate assign_zero_state() method and initialize the one- and two-body energy term variables to zero
825  // parent refers to the AddtlBGNodesIG; G refers to either PDIG or LinmemIG. AddtlBGNodesIG doesn't define
826  // a assign_zero_state() method! But it extends from the other two classes so it will eventually find the right method.
827  parent::assign_zero_state(); // was this a bug previously? apparently not...
828  //V::assign_zero_state();
829 
830  // get_incident_surface edge() is an inlined protected method which just calls the parents get_incident_edge() method
831  for ( int ii = 1; ii <= parent::get_num_incident_edges(); ++ii ) {
832  get_incident_surface_edge( ii )->acknowledge_state_zeroed_surface( parent::get_node_index() );
833  }
834 
835  parent::update_bg_edge_vector();
836 
837  for (int ii = 1; ii <= parent::get_num_edges_to_background_nodes(); ++ii ) {
838  get_edge_to_surface_bg_node( ii )->acknowledge_state_change( 0 );
839  }
840 
841 }
842 
843 
844 ///
845 /// @begin SurfaceNode::acknowledge_neighbors_substitution_surface
846 ///
847 /// @brief
848 /// bookkeeping to follow a neighbors state substitution. this method gets called when a SurfaceNode commits a sub
849 /// and then broadcasts that change to all its neighboring fc nodes via the incident SurfaceEdges. basically we need
850 /// to set current state equal to alt state here. (Hopefully alt state is still correct!!) Since there's no way for
851 /// a SurfaceNode to know what other SurfaceNodes are connected to it except via SurfaceEdges, the calls seem a bit
852 /// complicated. A SurfaceNode has to call acknowledge_state on each Edge. The Edges have to figure out which Node
853 /// is changing/not changing and then they call an inform_non_changing node of change method. That method then makes
854 /// the call to this method on the correct SurfaceNode. The inform_non_changing method can not be removed, because
855 /// it's used during the substitution evaluations as well.
856 ///
857 template < typename V, typename E, typename G >
859 
860 #ifdef FILE_DEBUG
861  // too much output...
862  //if ( std::fabs( curr_state_total_hASA_ - alt_state_total_hASA_ ) > 0.01 ) {
863  // TR_NODE << "acknowledge_neighbors_substitution_surface - node " << parent::get_node_index() << " changing curr_state_total_hASA_ from "
864  // << curr_state_total_hASA_ << " to " << alt_state_total_hASA_ << std::endl;
865  //}
866 #ifdef DOUBLE_CHECK_COUNTS
867  Real previous_state_hASA = curr_state_total_hASA_;
868 #endif
869 #endif
870 
871  curr_state_total_hASA_ = alt_state_total_hASA_;
872 
873 #ifdef DOUBLE_CHECK_COUNTS
874  if ( std::fabs( curr_state_total_hASA_ - previous_state_hASA ) > 0.01 ) {
875  // only double-check the counts for nodes that will be assigned a surface score, i.e. surface_exposed bool set to true
876  if ( parent::get_current_state() != 0 && is_surface_exposed() ) {
877  verify_patch_areas_correct( parent::get_node_index(), parent::get_current_state(), previous_state_hASA );
878  }
879  }
880 #endif
881 
882 }
883 
884 
885 ///
886 /// @begin SurfaceNode::assign_state_surface
887 ///
888 /// @brief
889 /// Assigns the node to one of the states in its state space or to the unassigned state.
890 ///
891 /// @detailed
892 /// Piggy backs on the standard project_deltaE/commit_considered_substitution protocol. Slightly inefficient; however,
893 /// this code is executed once per simulated annealing run. Not worth optimizing. (apl)
894 ///
895 template < typename V, typename E, typename G >
897 
898 #ifdef FILE_DEBUG
899  TR_NODE << "assign_state_surface(): node " << parent::get_node_index() << " being assigned state " << state << std::endl;
900 #endif
901 
902  if ( state == 0 ) {
903  assign_zero_state();
904  return;
905  }
906 
907  // the inefficiency lies in the fact that every time assign_state_surface is called with a nonzero value,
908  // the above conditional is evaluated before project deltaE is called.
909  float temp(0.0f);
910  project_deltaE_for_substitution_surface( state, temp, -1.0f /* threshold for avoiding calculations; basically, don't procrastinate */ );
911  commit_considered_substitution_surface();
912 }
913 
914 
915 ///
916 /// @begin SurfaceNode::get_curr_state_surface_energy()
917 ///
918 /// @brief
919 /// returns the surface energy for the node in its current state assignment
920 ///
921 template < typename V, typename E, typename G >
923 
924  if ( !(this->is_surface_exposed()) ) {
925  return 0.0;
926  }
927 
928  // the surface energy should be zero in the unassigned state? yup!
929  if ( parent::get_current_state() == 0 ) {
930  return 0.0;
931  }
932 
933  if ( curr_state_total_hASA_ > MAX_PATCH_SURFACE_AREA ) {
934  return surface_energy_weight_ * MAX_SURFACE_ENERGY;
935  }
936 
937  return surface_energy_weight_ * hASA_energy( curr_state_total_hASA_ );
938 }
939 
940 
941 ///
942 /// @begin SurfaceNode::project_deltaE_for_substitution_surface
943 ///
944 /// @brief
945 /// Returns the (possibly approximate) change in energy induced by changing a node from its current state into some alternate state.
946 ///
947 /// @detailed
948 /// Iterates across the edges first to determine the sum of the pairwise
949 /// decomposable (PD) energy. If the PD difference implies a collision, then
950 /// the SurfaceNode pretends as if the state substitution causes the best
951 /// improvement possible in surface score for it and its neighbors, returns
952 /// the PD difference + pretend surface difference. It will procrastinate
953 /// computing the actual surface score difference until the guiding SimAnnealer
954 /// decides to commit the substitution. If the SimAnnealer rejects the
955 /// substitution, then the work to compute the surface score is never done.
956 /// If it is unclear that the SimAnnealer will reject the substitution
957 /// based on the PD difference, then the vertex computes the change in
958 /// surface score that it induces on its neighbors.
959 /// The surface score calculation really isn't that intensive but it doesn't
960 /// make sense to calculate it needlessly. (apl)
961 ///
962 /// Bug source: Incident edges to a node are edges which have some energy on them based on the score function used (meaning they connect
963 /// to nodes that interact with this node). This set of nodes is larger than the set of nodes that the tenA neighbor graph in the Pose
964 /// considers neighbors for this node. Thus, when calculating the true number of se hp neighbors, some nodes are updated when
965 /// they shouldn't be leading to incorrect counts. Possible solutions include 1) keeping some type of data structure (e.g. a map)
966 /// which specifies which residues are neighbors (in the tenA neighbor graph sort of way) and whenever iterating over incident edges
967 /// checking to make sure nodes are really neighbors before doing any updating of the counts; 2) forget about which nodes are truly
968 /// neighbors (as determined by the tenA neighbor graph) and just use whatever the energy function thinks neighbors should be. I don't
969 /// like this approach though, because I want to have the freedom to adjust what kind of radius I use for residue neighbors for future
970 /// versions of the surface energy term. Not just assume that the energy function picks neighors correctly.
971 ///
972 /// Where should the neighbor cache be kept? If I keep it on the Node, then the lookups would have to occur in the Node methods that
973 /// change the counts. If I keep it on the Edges though, I can check for neighborship when iterating over edges and not ever even
974 /// go into the Node methods. Keep it on the Nodes. That's where it makes sense to keep it.
975 ///
976 ///
977 /// @param
978 /// alternate_state - [in] - the alternate state that the node must consider
979 /// prev_PDenergies_for_node - [out] - the sum of the PD energies (one-and two-body) for the node in its current state
980 /// deltaE_thresh_for_avoiding_surface_calcs - [in] - the minimum deltaE for which the SimAnnealer will accept slopyness in the deltaE projections
981 ///
982 template < typename V, typename E, typename G >
984  int alternate_state, core::PackerEnergy & prev_PDenergies_for_node, float deltaE_thresh_for_avoiding_surface_calcs ) {
985 
986  runtime_assert( alternate_state > 0 && alternate_state <= parent::get_num_states() );
987 
988  ++num_state_substitutions_considered_;
989  calculated_surface_deltaE_ = false;
990 
991  prev_PDenergies_for_node = parent::get_curr_pd_energy_total();
992 
993  // have base class perform deltaE computations for PD portion of energy function
994  // parent refers to AddtlBGNodesIG; G refers to either PDIG or LinmemIG. Which do I want here? AddtlBGNodesIG doesn't
995  // implement the calc_deltaEpd method but it extends either PDIG or LinmemIG so the runtime will eventually find the
996  // right function to call.
997  parent::calc_deltaEpd( alternate_state );
998 
999  deltaE_for_substitution_ = parent::get_alt_pd_energy_total() - parent::get_curr_pd_energy_total();
1000 
1001  if ( decide_procrastinate_surface_computations( deltaE_for_substitution_, deltaE_thresh_for_avoiding_surface_calcs ) ) {
1002  ++num_surface_comps_procrastinated_;
1003  } else {
1004 #ifdef FILE_DEBUG
1005  TR_NODE << "deltaE for PD: " << deltaE_for_substitution_ << std::endl;
1006 #endif
1007  deltaE_for_substitution_ += project_surface_deltaE();
1008  }
1009 
1010  return deltaE_for_substitution_;
1011 }
1012 
1013 
1014 ///
1015 /// @begin SurfaceNode< V, E, G >::project_surface_deltaE()
1016 ///
1017 /// @brief
1018 /// returns the change in surface score for this node and all of its neighbors produced by switching from its current
1019 /// state to an alternate state.
1020 ///
1021 template < typename V, typename E, typename G >
1023 
1024 #ifdef FILE_DEBUG
1025  TR_NODE << "project_surface_deltaE(): current_state:" << parent::get_current_state();
1026  if ( parent::get_current_state() == 0 ) {
1027  TR_NODE << " (" << wt_residue_for_node().name3() << "-";
1028  if ( wt_residue_for_node().is_polar() ) { TR_NODE << "P)"; } else { TR_NODE << "HP)"; }
1029  } else {
1030  TR_NODE << " (" << get_rotamer( parent::get_current_state() )->name() << "-";
1031  if ( get_rotamer( parent::get_current_state() )->is_polar() ) { TR_NODE << "P)"; } else { TR_NODE << "HP)"; }
1032  }
1033  TR_NODE << ", alternate_state: " << parent::get_alternate_state() << " (" << get_rotamer( parent::get_alternate_state() )->name() << "-";
1034  if ( get_rotamer( parent::get_alternate_state() )->is_polar() ) { TR_NODE << "P)"; } else { TR_NODE << "HP)"; }
1035  TR_NODE << std::endl;
1036 #endif
1037 
1038 
1039  // Next is where we update the total hASA of *all* se nbs by incrementing or decrementing the cached amount (instead of
1040  // reiterating over all edges and recalculating). The cached amount is just a float of the amount of hASA total this
1041  // node has. We should only change that amount if *this* node is SE and changing states. One bug I previously had
1042  // was that the SE check was not being done and amounts were getting incremented too high!
1043 
1044  // only change the total hASA (at this node) if this residue is surface exposed! but don't quit here because the change
1045  // at this node could influence the total hASA at a neighboring node!
1046  if ( this->is_surface_exposed() ) {
1047 
1048  // Previously, hASA calculations were only done for certain state changes. But in this version of the SIG, we're
1049  // going to consider all neighbors NOT just the hydrophobic ones. So every substitution that causes a state change
1050  // will lead to a change in the hASA
1051 
1052  if ( parent::get_current_state() == 0 ) { // runs only once per sim annealing run
1053 
1054  chemical::AA curr_AA = wt_residue_for_node().aa();
1055  chemical::AA alt_AA = get_rotamer( parent::get_alternate_state() )->aa();
1056  Size nbs = num_neighbors_counting_self();
1057 
1058  alt_state_total_hASA_ = curr_state_total_hASA_ - average_residue_hASA( curr_AA, nbs ) + average_residue_hASA( alt_AA, nbs );
1059 
1060  if ( alt_state_total_hASA_ < -0.001 ) {
1061  this->print();
1062  utility_exit_with_message( "Nonsensical alt_state reached (alt state total hASA < 0). Exiting. " );
1063  }
1064 
1065  } else { // node wasn't in the unassigned state - 99% of calls will follow this branch
1066 
1067  chemical::AA curr_AA = get_rotamer( parent::get_current_state() )->aa();
1068  chemical::AA alt_AA = get_rotamer( parent::get_alternate_state() )->aa();
1069  Size nbs = num_neighbors_counting_self();
1070 
1071  alt_state_total_hASA_ = curr_state_total_hASA_ - average_residue_hASA( curr_AA, nbs ) + average_residue_hASA( alt_AA, nbs );
1072 
1073  }
1074  }
1075 
1076 
1077  // iterate over all the edges coming from this node and get the deltaE for surface from the neighboring nodes
1078  Real surface_deltaE = 0;
1079 
1080  // the incident edges of the "parent" are the edges of the PDNode or LinearMemNode
1081 #ifdef FILE_DEBUG
1082  TR_NODE << "project_surface_deltaE(): calculating deltaE for " << parent::get_num_incident_edges() << " first class and "
1083  << parent::get_num_edges_to_background_nodes() << " background neighbors." << std::endl;
1084 #endif
1085  for ( int ii = 1; ii <= parent::get_num_incident_edges(); ++ii ) {
1086  int other_nodes_index = get_incident_surface_edge(ii)->get_other_ind( parent::get_node_index() );
1087  // "search" through the map to make sure this edge is in the map (if not found, find returns map.end() which is what I check for)
1088  if ( fc_neighbor_map.find( std::pair<int,int>( parent::get_node_index(), other_nodes_index) ) != fc_neighbor_map.end() ) {
1089  surface_deltaE += get_incident_surface_edge(ii)->get_surface_deltaE_for_neighbor( parent::get_node_index(), parent::get_alternate_state() );
1090  }
1091  }
1092 
1093  for ( int ii = 1; ii <= parent::get_num_edges_to_background_nodes(); ++ii ) {
1094  int other_nodes_index = get_edge_to_surface_bg_node(ii)->get_other_ind( this );
1095  // "search" through the map to make sure this edge is in the map (if not found, find returns map.end() which is what I check for)
1096  if ( bg_neighbor_map.find( std::pair<int,int>( parent::get_node_index(), other_nodes_index) ) != bg_neighbor_map.end() ) {
1097  surface_deltaE += get_edge_to_surface_bg_node( ii )->get_surface_deltaE_for_substitution( parent::get_alternate_state() );
1098  }
1099  }
1100 
1101  calculated_surface_deltaE_ = true;
1102 
1103  surface_deltaE += get_surface_score_difference();
1104 
1105 #ifdef FILE_DEBUG
1106  if ( get_surface_score_difference() != 0 ) {
1107  TR_NODE << "project_surface_deltaE(): curr state hASA: " << curr_state_total_hASA_ << ", alt state hASA: " << alt_state_total_hASA_
1108  << ", score difference: " << get_surface_score_difference() << std::endl;
1109  }
1110 #endif
1111 
1112 #ifdef FILE_DEBUG
1113  if ( surface_deltaE > 100000 || surface_deltaE < -100000 ) {
1114  std::cerr << "project_surface_deltaE(): deltaE for PD: " << deltaE_for_substitution_ << std::endl;
1115  std::cerr << "project_surface_deltaE(): deltaE for surfaceE: " << surface_deltaE << std::endl;
1116 
1117  std::cerr << "project_surface_deltaE(): current_state:" << parent::get_current_state();
1118  if ( parent::get_current_state() == 0 ) {
1119  std::cerr << " (" << wt_residue_for_node().name3() << "-";
1120  if ( wt_residue_for_node().is_polar() ) { std::cerr << "P)"; } else { std::cerr << "HP)"; }
1121  } else {
1122  std::cerr << " (" << get_rotamer( parent::get_current_state() )->name() << "-";
1123  if ( get_rotamer( parent::get_current_state() )->is_polar() ) { std::cerr << "P)"; } else { std::cerr << "HP)"; }
1124  }
1125  std::cerr << ", alternate_state: " << parent::get_alternate_state() << " (" << get_rotamer( parent::get_alternate_state() )->name() << "-";
1126  if ( get_rotamer( parent::get_alternate_state() )->is_polar() ) { std::cerr << "P)"; } else { std::cerr << "HP)"; }
1127  std::cerr << std::endl;
1128 
1129  get_surface_owner()->print();
1130  utility_exit_with_message( "surface deltaE went crazy. Terminating." );
1131  }
1132 #endif
1133 
1134 #ifdef FILE_DEBUG
1135  if ( surface_deltaE != 0 ) {
1136  TR_NODE << "deltaE for surfaceE: " << surface_deltaE << std::endl;
1137  }
1138 #endif
1139 
1140  return surface_deltaE;
1141 
1142 }
1143 
1144 
1145 ///
1146 /// @begin SurfaceNode< V, E, G >::decide_procrastinate_surface_computations()
1147 ///
1148 /// @detailed
1149 /// Makes the decision whether or not to procrastinate calculating the surface score. Basically, if the PD energy got better (dE < 0)
1150 /// then return false so we don't procrastinate the calculation (because the alternate state probably will be accepted?). If the best
1151 /// guess for the surface deltaE also comes back better (dE < 0), then return false. Finally, if the difference between the deltaE
1152 /// for the PD terms and the (guessed) surface deltaE is greater than the threshold, return true so we do procrastinate. So basically
1153 /// if the energy (especially the PD energy) gets worse, procrastinate. Otherwise, don't.
1154 ///
1155 template < typename V, typename E, typename G >
1156 bool SurfaceNode< V, E, G >::decide_procrastinate_surface_computations( Real const pd_deltaE, Real const threshold ) const {
1157 
1158  Real surface_deltaE_max = 0;
1159 
1160  if ( ! observed_sufficient_surface_E_to_predict_min_ )
1161  return false;
1162 
1163  if ( threshold < 0 || pd_deltaE < 0 )
1164  return false;
1165 
1166  for( int ii = 1; ii <= parent::get_num_incident_edges(); ++ii) {
1167  Real mag_deltaE = get_incident_surface_edge(ii)->get_max_surface_deltaE_guess( parent::get_node_index() );
1168  if ( mag_deltaE < 0.0f ) {
1169  return false;
1170  }
1171  surface_deltaE_max += mag_deltaE;
1172  }
1173 
1174  for ( int ii = 1; ii <= parent::get_num_edges_to_background_nodes(); ++ii ) {
1175  Real mag_deltaE = get_edge_to_surface_bg_node( ii )->get_max_surface_deltaE_guess();
1176  if ( mag_deltaE < 0.0f ) {
1177  return false;
1178  }
1179  surface_deltaE_max += mag_deltaE;
1180  }
1181 
1182  surface_deltaE_max += (surface_energy_weight_ * hASA_energy( curr_state_total_hASA_ ) ) - surface_score_min_last_100_;
1183 
1184  // pd_deltaE must be positive, surface deltaE must also be positive.
1185  // threshold of 5 means, if the PD got more than 5 worse than the guessed surface deltaE (e.g. 10 - 3(?) = 7 > 5), procrastinate
1186 #ifdef FILE_DEBUG
1187  TR_NODE << "decide_procrastinate_surface_computations(): pd_deltaE: " << pd_deltaE << ", surface_deltaE_max: " << surface_deltaE_max
1188  << ", threshold: " << threshold << std::endl;
1189 #endif
1190  if ( (pd_deltaE - surface_deltaE_max) > threshold ) {
1191  return true;
1192  }
1193  return false;
1194 
1195 }
1196 
1197 
1198 
1199 ///
1200 /// @begin SurfaceNode< V, E, G >::get_surface_deltaE_for_neighbors_state_substitution
1201 ///
1202 /// @brief
1203 /// returns the change in surface score for this node induced by a state substitution at a neighboring node.
1204 ///
1205 /// @detailed
1206 /// So a neighboring first class node that is changing is invoking (via the SurfaceEdge that connects them) this method
1207 /// so that this node can update its counts and then return a change in surface score for this node. This method needs
1208 /// to check if the alt_state that the connected node is considering is going to change the counts here and then perform
1209 /// the lookup for the change in score.
1210 ///
1211 /// is the rotamer id (state) the same for every node? no. need to either do the work in the edge class method
1212 /// or pass a reference to the node. oooooh, we can use the SIG to get the node changing, too!!! NO! Can't. The
1213 /// SIG get_surface_node( index ) method is protected. Lame.
1214 /// Since I need a way to check the rotamer vector for the changing node (to see what the changing states are) I have to
1215 /// make this method take a raw pointer to the node changing. The alternative would be to do all the state checking in the
1216 /// edge class method, but I feel like this sort of state checking should be done by a Node, not an Edge. Further, this
1217 /// frees the Edge class from having to keep any of the data that the Nodes contains (i.e. the counts of neighbors).
1218 /// The edges just pass along the message (from the changing node) to the other Node, not doing any kind of Node-specific
1219 /// behaviour.
1220 ///
1221 /// the current state of this node may be unassigned (0). if so, we need to initialize the hASA properly.
1222 /// as of 7/22, the current amount of hydrophobic surface area should be init'd after prep for simA runs. alt state also.
1223 /// if ( parent::get_current_state() == 0 )
1224 /// curr_state_total_hASA_ = get_surface_owner()->calculate_amount_total_hydrophobic_ASA;
1225 ///
1226 /// 07/24/08 problem situation
1227 /// it's probable that a sub that was considered before wasn't committed, so the alt state count at this node needs to go
1228 /// back to what the current state count is. the problem that may crop up with the reset here is that on a previous consider
1229 /// call, a set of nodes will update their counts. if commit is not called, and a second consider is called, then this node
1230 /// will have its alt state count reset but what about all the other nodes in the previous set. how will their counts get
1231 /// reset to the current state count? perhaps a check in the commit method can be added. nope, a new method has been
1232 /// added to Nodes and BGNodes to handle this case.
1233 /// alt_state_total_hASA_ = curr_state_total_hASA_;
1234 ///
1235 /// 02/20/09 Changed all variable names above to reflect hASA instead of counts.
1236 ///
1237 template < typename V, typename E, typename G >
1239  SurfaceNode<V,E,G>* node_considering_substitution, int changing_nodes_curr_state, int changing_nodes_alt_state ) {
1240 
1241  // If this node is not surface exposed, then it doesn't have a surface score. Even if another neighboring node is
1242  // changing state, this node should be unaffected because it's not on the surface. Only residues which are on the
1243  // surface have a surface score associated with them. So don't bother updating the hASA if we're just going to return
1244  // 0.0 anyway. Can't think of any reason for updating the hASA, thus I'm moving this check up here.
1245  // Is this the correct usage of is_se()? Yes. This node won't have a surface deltaE because it has fewer nbs than the
1246  // cutoff we're using. But this node *could* still add hASA to other nodes that will get surface scores.
1247  if ( !(this->is_surface_exposed()) ) {
1248  return 0.0;
1249  }
1250 
1251  // only change the count(hASA) here if the node that is changing is surface exposed!!!! otherwise, leave it at what it was
1252  // initialized in the hASA function to be. this nodes hASA only needs to change if the changing node is both surface
1253  // exposed and is changing state.
1254  // WRONG! The neighboring Node might not be surface exposed, but if it's below the buried residue cutoff it could still
1255  // contribute some hASA to this Node.
1256  //if ( node_considering_substitution->is_surface_exposed() ) {
1257  if ( node_considering_substitution->is_below_buried_residue_no_hsasa_cutoff() ) {
1258 
1259  // it may also be that the node undergoing substitution is in the unassigned state, right?
1260  // if that's the case, we need to look up the wild-type residue info for that node (NOT FOR THIS NODE!)
1261  if ( changing_nodes_curr_state == 0 ) {
1262 
1263  chemical::AA curr_AA = node_considering_substitution->wt_residue_for_node().aa();
1264  chemical::AA alt_AA = node_considering_substitution->get_rotamer( changing_nodes_alt_state )->aa();
1265  Size nbs = node_considering_substitution->num_neighbors_counting_self();
1266 
1267  alt_state_total_hASA_ = curr_state_total_hASA_ - average_residue_hASA( curr_AA, nbs ) + average_residue_hASA( alt_AA, nbs );
1268 
1269  if ( alt_state_total_hASA_ < -0.001 ) {
1270  this->print();
1271  utility_exit_with_message( "Nonsensical alt_state reached (total hASA < 0). Exiting. " );
1272  }
1273 
1274  } else { // node wasn't in the unassigned state - 99% of calls will follow this branch
1275 
1276  chemical::AA curr_AA = node_considering_substitution->get_rotamer( changing_nodes_curr_state )->aa();
1277  chemical::AA alt_AA = node_considering_substitution->get_rotamer( changing_nodes_alt_state )->aa();
1278  Size nbs = node_considering_substitution->num_neighbors_counting_self();
1279 
1280  alt_state_total_hASA_ = curr_state_total_hASA_ - average_residue_hASA( curr_AA, nbs ) + average_residue_hASA( alt_AA, nbs );
1281  }
1282  }
1283 
1284 #ifdef FILE_DEBUG
1285  if ( curr_state_total_hASA_ != alt_state_total_hASA_ ) {
1286  TR_NODE << "get_surface_deltaE_for_neighbors_state_substitution: node " << parent::get_node_index()
1287  << " calc. deltaE for changing node " << node_considering_substitution->get_node_index()
1288  << ", curr hASA: " << curr_state_total_hASA_ << ", alt hASA: " << alt_state_total_hASA_
1289  << ", score_difference: " << get_surface_score_difference() << std::endl;
1290  }
1291 #endif
1292 
1293  return get_surface_score_difference();
1294 }
1295 
1296 
1297 ///
1298 /// @begin SurfaceNode::get_surface_score_difference
1299 ///
1300 /// @brief
1301 /// Returns the difference alt state score - current state score
1302 ///
1303 /// @detailed
1304 /// This method requires that the variables current_state_ and alternate_state_ hold the correct values. An assert guard
1305 /// checks to make sure an out-of-bounds exception won't occur.
1306 ///
1307 ///
1308 template < typename V, typename E, typename G >
1310 
1311  if ( curr_state_total_hASA_ == alt_state_total_hASA_ ) { return 0.0; }
1312 
1313  if ( curr_state_total_hASA_ < -0.001 ) {
1314  this->print();
1315  utility_exit_with_message( "Nonsensical curr_state reached (total hASA < 0). Exiting. " );
1316  }
1317  if ( alt_state_total_hASA_ < -0.001 ) {
1318  this->print();
1319  utility_exit_with_message( "Nonsensical alt_state reached (total hASA < 0). Exiting. " );
1320  }
1321 
1322  if ( ( curr_state_total_hASA_ > MAX_PATCH_SURFACE_AREA ) && ( alt_state_total_hASA_ > MAX_PATCH_SURFACE_AREA ) ) {
1323  // this sub could be good or bad, but let the contributions of the other nodes decide what happens
1324  return 0.0;
1325  }
1326 
1327  // if the alt state is greater than 800A^2, return a really bad energy!
1328  if ( alt_state_total_hASA_ > MAX_PATCH_SURFACE_AREA ) {
1329  return surface_energy_weight_ * MAX_SURFACE_ENERGY;
1330  }
1331  // alt state must be 800 or less, which is in bounds; moving on
1332 
1333  if ( curr_state_total_hASA_ > MAX_PATCH_SURFACE_AREA ) {
1334  // then, the current state has more hASA than the alt state, which is a favorable change
1335  return surface_energy_weight_ * -1 * MAX_SURFACE_ENERGY; // yeah, it's a *really* favorable change, but oh well
1336  }
1337 
1338  return surface_energy_weight_ * ( hASA_energy(alt_state_total_hASA_) - hASA_energy(curr_state_total_hASA_) );
1339 
1340 }
1341 
1342 
1343 ///
1344 /// @begin SurfaceNode::commit_considered_substitution_surface
1345 ///
1346 /// @brief
1347 /// Sets the current state to the alternate state this node was asked to
1348 /// consider. Copies appropriate score information. Notifies all of its
1349 /// neighbors that it is going through with the state substitution it had been
1350 /// considering.
1351 ///
1352 /// @detailed
1353 /// If the node had procrastinated the surface deltaE computation because it
1354 /// thought the sim-annealer unlikely to accept the substitition, then the
1355 /// node must now do the work it procrastinated.
1356 ///
1357 /// There's a potential situation with considers() and commits() that needs to be checked for here. It's possible that
1358 /// a consider() call is made which causes a set of Nodes to update their alt state counts correspondingly. Since the
1359 /// consider() only gets processed by (or actually the call only goes out to) Nodes which are neighbor graph neighbors,
1360 /// only those Nodes will have their counts updated. Assume that the first consider() is really bad and no commit goes out.
1361 /// If we then consider() another sub, the alt state counts at the previous consider()'s set of nodes are incorrect. If
1362 /// get_deltaE is called by this consider() on some of those nodes, some of them will have their alt states reset. But
1363 /// when the commit goes out to ALL Nodes that are neighbors (NOT just the neighbor graph neighbors) it's possible that
1364 /// some of the Nodes will save the wrong alt state count. One way I think this can be avoided to is check at this node,
1365 /// if the alt state count is different from current, whether the node that originally changed is a neighbor graph neighbor
1366 /// of this node. If it is, that means the counts changed because of that node. If it's not, then this Node must have
1367 /// been one of the ones that fell out of sync.
1368 /// Oooooh, I just thought of another way. When the SIG consider() method is called, I could have a reset alt state
1369 /// counts method that will deal with Nodes that are out of sync. That's more elegant than yet another if statement here!
1370 ///
1371 template < typename V, typename E, typename G >
1373 
1374  assert( parent::considering_alternate_state() );
1375 
1376 #ifdef DOUBLE_CHECK_COUNTS
1377  int previous_state = parent::get_current_state();
1378  Real previous_state_hASA = curr_state_total_hASA_;
1379 #endif
1380 
1381  if ( ! calculated_surface_deltaE_ ) {
1382  ++num_surface_comps_later_made_;
1383  Real temp = project_surface_deltaE();
1384  deltaE_for_substitution_ = parent::get_alt_pd_energy_total() - parent::get_curr_pd_energy_total() + temp;
1385  }
1386 
1387  // call base class method
1388  parent::commit_considered_substitution();
1389 
1390  curr_state_total_hASA_ = alt_state_total_hASA_;
1391 
1392 
1393 #ifdef DOUBLE_CHECK_COUNTS
1394  if ( ( parent::get_current_state() != 0 ) && is_surface_exposed() ) {
1395  verify_patch_areas_correct( parent::get_node_index(), previous_state, previous_state_hASA );
1396  }
1397 #endif
1398 
1399 #ifdef FILE_DEBUG
1400  TR_NODE << "Committed substitution node " << parent::get_node_index() << std::endl;
1401 #endif
1402 
1403  for ( int ii = 1; ii <= parent::get_num_incident_edges(); ++ii ) {
1404  get_incident_surface_edge(ii)->acknowledge_substitution_surface();
1405  }
1406  for (int ii = 1; ii <= parent::get_num_edges_to_background_nodes(); ++ii) {
1407  get_edge_to_surface_bg_node(ii)->acknowledge_substitution_surface();
1408  }
1409 
1410  track_surface_E_min();
1411 
1412  return deltaE_for_substitution_;
1413 }
1414 
1415 
1416 
1417 ///
1418 /// @begin SurfaceNode< V, E, G >::verify_patch_areas_correct
1419 ///
1420 /// @brief
1421 /// Checks to make sure that the current state num se hp nbs is correct, by going through all residues in the Pose and
1422 /// brute-force recounting.
1423 ///
1424 template < typename V, typename E, typename G >
1425 void SurfaceNode< V, E, G >::verify_patch_areas_correct( int node_id, int previous_state, Real previous_state_hASA ) {
1426 
1427  // do a little double checking here to make sure things aren't getting off track somehow
1428  // keep all this wrapped within a #ifdef because it's very, very slow and inefficient
1429  // the only nodes that are going to have counts that are correct, though, will be the ones that are surface exposed;
1430  // nodes that aren't surface exposed don't update their counts but instead return immediately to save computational time
1431 
1432  Real total_hASA = 0.0;
1433  if ( this->is_surface_exposed() ) {
1434  //total_hASA += average_residue_hASA( wt_residue_for_node().aa(), num_neighbors_counting_self() );
1435  total_hASA += average_residue_hASA(); // not sure why this was wt_residue before
1436  TR_NODE << "verify_patch_areas_correct(): adding " << average_residue_hASA() << " to total_hASA for self; total_hASA: " << total_hASA << std::endl;
1437  }
1438 
1439  // have to iterate through the edges emanating from this node in the tenA neighbor graph stored in the Pose.
1440  // Using the edges that are connected to this SurfaceNode (via SurfaceEdges) is not correct because some
1441  // of the EnergyMethods produce energies between Nodes that are not considered neighbors in the tenA neighor graph
1442  // and hence persist as SurfaceEdges. But just because these two Nodes have an Edge between them in the PDGraph
1443  // doesn't mean we should count them as neighbors from the Pose neighbor standpoint.
1444  //
1445  // the tenA neighbor graph gives us the index of the other node, but how do we get that Node as an object so we
1446  // can call is_se() on it? do the really slow operation of iterating over all the SurfaceEdges until we find the
1447  // to the Node we're interested in.
1448  //
1449  // as of 7/25, changing the above to iterate over all residues that fall within the radius of interaction instead of
1450  // whatever the tenA neighbor graph has in it. instead of performing the expensive distance calculation though, use
1451  // the distance neighbor map that was created earlier to determine which nodes are close by. No! Can't do that
1452  // because then we don't have two independent methods of checking the true count. Iterate over all residues here
1453  // and redo the expensive calculation. The map is used to speed things up during the actual simulation.
1454  //
1455 
1456  //core::scoring::TenANeighborGraph const & tenA_neighbor_graph( get_surface_owner()->pose().energies().tenA_neighbor_graph() );
1457 
1458  //for ( core::graph::EdgeListConstIterator eli = tenA_neighbor_graph.get_node( parent::get_node_index() )->const_edge_list_begin(),
1459  // eli_end = tenA_neighbor_graph.get_node( parent::get_node_index() )->const_edge_list_end(); eli != eli_end; ++eli ) {
1460 
1461  pose::Pose poseRef = get_surface_owner()->pose();
1462 
1463  conformation::Residue const & rsd1 = poseRef.residue( get_surface_owner()->rotamer_sets().moltenres_2_resid( parent::get_node_index() ) );
1464  Real distanceBetweenAtoms = 0.0;
1465 
1466  for ( Size rr = 1; rr <= get_surface_owner()->rotamer_sets().nmoltenres(); ++rr ) {
1467 
1468  if ( (int)rr == parent::get_node_index() ) { continue; } // skip if we're on the current residue
1469 
1470  // moltenres_2_resid will go from the node/mr_id to the pose residue id
1471  conformation::Residue const & rsd2 = poseRef.residue( get_surface_owner()->rotamer_sets().moltenres_2_resid( rr ) );
1472 
1473  distanceBetweenAtoms = rsd1.xyz( rsd1.nbr_atom() ).distance( rsd2.xyz( rsd2.nbr_atom() ) );
1474  if ( distanceBetweenAtoms > INTERACTION_RADIUS ) {
1475  continue; // that residue is not a neighbor
1476  }
1477  // if less than the cutoff, then we need to figure out which Edge to signal. the index 'rr' is just the moltenres_id which
1478  // should be the same as the node id.
1479 
1480  // save the value to simplify code ahead
1481  // int other_node_index = (*eli)->get_other_ind( parent::get_node_index() );
1482  int other_node_index = rr;
1483  for ( int ii = 1; ii <= parent::get_num_incident_edges(); ++ii ) {
1484 
1485  if ( get_incident_surface_edge(ii)->get_other_ind( parent::get_node_index() ) == other_node_index ) {
1486  // got the right SurfaceEdge, now call the right methods on the Node object - but how do we get access
1487  // to the Node. We need to determine which index (0 or 1) the changing node is.
1488  // An inefficient way to do it is to get the node with index 0 and call get_node_index on it, and check if that
1489  // node has the index that we have here. If not, get the node with index 1. There has to be a better way, but
1490  // this way will work. This is just debugging code after all.
1491  int edge_index = ( other_node_index == get_incident_surface_edge(ii)->get_surface_node(0)->get_node_index() ? 0 : 1 );
1492 
1493  //if ( get_incident_surface_edge(ii)->get_surface_node( edge_index )->is_surface_exposed() ) {
1494 
1495  // don't bother checking the patch areas if there's still unassigned nodes
1496  if ( (get_incident_surface_edge(ii)->get_surface_node( edge_index ))->get_current_state() == 0 ) {
1497  return;
1498  }
1499  total_hASA += (get_incident_surface_edge(ii)->get_surface_node( edge_index ))->average_residue_hASA();
1500  TR_NODE << "verify_patch_areas_correct(): adding " << (get_incident_surface_edge(ii)->get_surface_node( edge_index ))->average_residue_hASA()
1501  << " to total_hASA for incident edge " << ii << ", total_hASA: " << total_hASA << std::endl;
1502  //}
1503  }
1504  }
1505  }
1506 
1507  // now do all of this over again for the background nodes! the total number of background nodes is just the total number
1508  // of residue - number of moltenresidues. need to add a method which allows access to the bgenumeration_2_resid array
1509  // kept in the SIG.
1510  int nbackground = poseRef.total_residue() - get_surface_owner()->rotamer_sets().nmoltenres();
1511  for ( int id = 1; id <= nbackground; ++id ) {
1512 
1513  conformation::Residue const & rsd2 = poseRef.residue( get_surface_owner()->bg_node_2_resid( id ) );
1514 
1515  distanceBetweenAtoms = rsd1.xyz( rsd1.nbr_atom() ).distance( rsd2.xyz( rsd2.nbr_atom() ) );
1516  if ( distanceBetweenAtoms > INTERACTION_RADIUS ) {
1517  continue; // that residue is not a neighbor
1518  }
1519  // if less than the cutoff, then we need to figure out which BGEdge to signal. we can iterate over all the BGEdges
1520  // and look for the one that has a node id the same as the index 'id'.
1521 
1522  int other_node_index = id;
1523  for ( int ii = 1; ii <= parent::get_num_edges_to_background_nodes(); ++ii ) {
1524  if ( get_edge_to_surface_bg_node(ii)->get_other_ind( this ) == other_node_index ) {
1525 
1526  // got the right SurfaceBackgroundEdge, now call the right methods on the BackgroundNode object
1527  //if ( get_edge_to_surface_bg_node(ii)->get_surface_bg_node()->is_surface_exposed() ) {
1528  total_hASA += (get_edge_to_surface_bg_node(ii)->get_surface_bg_node())->average_residue_hASA();
1529  TR_NODE << "verify_patch_areas_correct(): adding " << (get_edge_to_surface_bg_node(ii)->get_surface_bg_node())->average_residue_hASA()
1530  << " to total_hASA for incident bg edge " << ii << ", total_hASA: " << total_hASA << std::endl;
1531  //}
1532  }
1533  }
1534 
1535  }
1536 
1537  if ( std::fabs( total_hASA - curr_state_total_hASA_ ) > 0.01 ) {
1538 
1539  TR_NODE << "verify_patch_areas_correct(): calling node " << node_id << "; this node current_state: " << parent::get_current_state();
1540  TR_NODE << " (" << get_rotamer( parent::get_current_state() )->name() << "-";
1541  if ( get_rotamer( parent::get_current_state() )->is_polar() ) { TR_NODE << "P)"; } else { TR_NODE << "HP)"; }
1542 
1543  TR_NODE << ", previous_state: " << previous_state;
1544  if ( previous_state != 0 ) {
1545  TR_NODE << " (" << get_rotamer( previous_state )->name() << "-";
1546  if ( get_rotamer( previous_state )->is_polar() ) { TR_NODE << "P)"; } else { TR_NODE << "HP)"; }
1547  }
1548  TR_NODE << ", previous_state hASA: " << previous_state_hASA << std::endl;
1549 
1550  std::cout << "This node:" << std::endl;
1551  this->print();
1552 
1553  std::cout << "Neighboring nodes:" << std::endl;
1554  for ( int ii = 1; ii <= parent::get_num_incident_edges(); ++ii ) {
1555  int other_nodes_index = get_incident_surface_edge(ii)->get_other_ind( parent::get_node_index() );
1556  int edge_index = ( other_nodes_index == get_incident_surface_edge(ii)->get_surface_node(0)->get_node_index() ? 0 : 1 );
1557  // "search" through the map to make sure this edge is in the map (if not found, find returns map.end() which is what I check for)
1558  if ( fc_neighbor_map.find( std::pair<int,int>( parent::get_node_index(), other_nodes_index) ) != fc_neighbor_map.end() ) {
1559 
1560  if ( get_incident_surface_edge(ii)->get_surface_node( edge_index )->is_surface_exposed() ) {
1561  std::cout << "**";
1562  }
1563  get_incident_surface_edge(ii)->get_surface_node( edge_index )->print();
1564  }
1565  }
1566 
1567  for ( int ii = 1; ii <= parent::get_num_edges_to_background_nodes(); ++ii ) {
1568  int other_nodes_index = get_edge_to_surface_bg_node(ii)->get_other_ind( this );
1569  // "search" through the map to make sure this edge is in the map (if not found, find returns map.end() which is what I check for)
1570  if ( bg_neighbor_map.find( std::pair<int,int>( parent::get_node_index(), other_nodes_index) ) != bg_neighbor_map.end() ) {
1571  if ( get_edge_to_surface_bg_node(ii)->get_surface_bg_node()->is_surface_exposed() ) {
1572  std::cout << "**";
1573  }
1574  get_edge_to_surface_bg_node(ii)->get_surface_bg_node()->print();
1575  }
1576  }
1577 
1578  std::cout << "Nodes counted iterating over all residues:" << std::endl;
1579 
1580  { // complete duplication of code above, but this is all debugging code!
1581  for ( Size rr = 1; rr <= get_surface_owner()->rotamer_sets().nmoltenres(); ++rr ) {
1582 
1583  if ( (int)rr == parent::get_node_index() ) { continue; } // skip if we're on the current residue
1584 
1585  // moltenres_2_resid will go from the node/mr_id to the pose residue id
1586  conformation::Residue const & rsd2 = poseRef.residue( get_surface_owner()->rotamer_sets().moltenres_2_resid( rr ) );
1587 
1588  distanceBetweenAtoms = rsd1.xyz( rsd1.nbr_atom() ).distance( rsd2.xyz( rsd2.nbr_atom() ) );
1589  if ( distanceBetweenAtoms > INTERACTION_RADIUS ) {
1590  continue;
1591  }
1592  // if less than the cutoff, then we need to figure out which Edge to signal. the index 'rr' is just the moltenres_id which
1593  // should be the same as the node id.
1594 
1595  // save the value to simplify code ahead
1596  // int other_node_index = (*eli)->get_other_ind( parent::get_node_index() );
1597  int other_node_index = rr;
1598  for ( int ii = 1; ii <= parent::get_num_incident_edges(); ++ii ) {
1599 
1600  if ( get_incident_surface_edge(ii)->get_other_ind( parent::get_node_index() ) == other_node_index ) {
1601  // got the right SurfaceEdge, now call the right methods on the Node object - but how do we get access
1602  // to the Node. We need to determine which index (0 or 1) the changing node is.
1603  // An inefficient way to do it is to get the node with index 0 and call get_node_index on it, and check if that
1604  // node has the index that we have here. If not, get the node with index 1. There has to be a better way, but
1605  // this way will work. This is just debugging code after all.
1606  int edge_index = ( other_node_index == get_incident_surface_edge(ii)->get_surface_node(0)->get_node_index() ? 0 : 1 );
1607  if ( get_incident_surface_edge(ii)->get_surface_node( edge_index )->is_surface_exposed() ) {
1608  std::cout << "**";
1609  }
1610  get_incident_surface_edge(ii)->get_surface_node( edge_index )->print();
1611  }
1612  }
1613  }
1614 
1615  // now do all of this over again for the background nodes! the total number of background nodes is just the total number
1616  // of residue - number of moltenresidues. need to add a method which allows access to the bgenumeration_2_resid array
1617  // kept in the SIG.
1618  int nbackground = poseRef.total_residue() - get_surface_owner()->rotamer_sets().nmoltenres();
1619  for ( int id = 1; id <= nbackground; ++id ) {
1620 
1621  conformation::Residue const & rsd2 = poseRef.residue( get_surface_owner()->bg_node_2_resid( id ) );
1622 
1623  distanceBetweenAtoms = rsd1.xyz( rsd1.nbr_atom() ).distance( rsd2.xyz( rsd2.nbr_atom() ) );
1624  if ( distanceBetweenAtoms > INTERACTION_RADIUS ) {
1625  continue; // that residue is not a neighbor
1626  }
1627  // if less than the cutoff, then we need to figure out which BGEdge to signal. we can iterate over all the BGEdges
1628  // and look for the one that has a node id the same as the index 'id'.
1629 
1630  int other_node_index = id;
1631  for ( int ii = 1; ii <= parent::get_num_edges_to_background_nodes(); ++ii ) {
1632  if ( get_edge_to_surface_bg_node(ii)->get_other_ind( this ) == other_node_index ) {
1633  if ( get_edge_to_surface_bg_node(ii)->get_surface_bg_node()->is_surface_exposed() ) {
1634  std::cout << "**";
1635  }
1636  get_edge_to_surface_bg_node(ii)->get_surface_bg_node()->print();
1637  }
1638  }
1639 
1640  }
1641  }
1642 
1643  TR_NODE << "total_hASA: " << total_hASA << ", curr_state_total_hASA_: " << curr_state_total_hASA_ << std::endl;
1644  utility_exit_with_message( "total hASA values are out of sync. Something is wrong. Quitting." );
1645  }
1646 }
1647 
1648 
1649 ///
1650 /// @begin SurfaceNode< V, E, G >::track_surface_E_min
1651 ///
1652 /// @brief
1653 /// Keeps track of the minimum surface score seen. Every 100 substitutions, updates the variable surface_score_min_last_100.
1654 ///
1655 template < typename V, typename E, typename G >
1657 
1658  ++num_substitutions_since_surface_min_update_;
1659 
1660  Real alt_surfaceE = surface_energy_weight_ * hASA_energy( alt_state_total_hASA_ );
1661 
1662  if ( surface_score_min_recent_ > alt_surfaceE )
1663  surface_score_min_recent_ = alt_surfaceE;
1664 
1665  // every 100 substitutions, update the variable surface_score_min_last_100 with the value held in
1666  // surface_score_min_recent_. That explains the difference between last_100 and recent.
1667  if ( num_substitutions_since_surface_min_update_ == 100 ) {
1668  surface_score_min_last_100_ = surface_score_min_recent_;
1669  Real curr_surfaceE = surface_energy_weight_ * hASA_energy( curr_state_total_hASA_ );
1670  if (curr_surfaceE < surface_score_min_last_100_ ) {
1671  surface_score_min_last_100_ = curr_surfaceE;
1672  }
1673  observed_sufficient_surface_E_to_predict_min_ = true;
1674  num_substitutions_since_surface_min_update_ = 0;
1675  }
1676 
1677 }
1678 
1679 
1680 ///
1681 /// @begin SurfaceNode::print
1682 ///
1683 /// @brief
1684 /// useful for debugging - writes information about a node to the tracer
1685 ///
1686 template < typename V, typename E, typename G >
1688 
1689  std::cout << "(node id:" << parent::get_node_index() << ", current_state: " << parent::get_current_state();
1690 
1691  if ( parent::get_current_state() == 0 ) {
1692  std::cout << " (" << wt_residue_for_node().name3() << "-";
1693  if ( wt_residue_for_node().is_polar() ) { std::cout << "P)"; } else { std::cout << "HP)"; }
1694  } else {
1695  std::cout << " (" << get_rotamer( parent::get_current_state() )->name() << "-";
1696  if ( get_rotamer( parent::get_current_state() )->is_polar() ) { std::cout << "P)"; } else { std::cout << "HP)"; }
1697  }
1698 
1699  if ( parent::get_current_state() == 0 ) {
1700  std::cout << ", hASA: " << average_residue_hASA( wt_residue_for_node().aa(), num_neighbors_counting_self() );
1701  } else {
1702  std::cout << ", hASA: " << average_residue_hASA();
1703  }
1704 
1705  std::cout << ", one body energy: " << parent::get_one_body_energy_current_state()
1706  << ", curr: " << curr_state_total_hASA_ << ", alt: " << alt_state_total_hASA_ << ", surface energy: " << get_curr_state_surface_energy()
1707  << ", se: " << surface_exposed_ << std::endl;
1708 
1709  //for ( int ii = 1; ii <= parent::get_num_incident_edges(); ++ii ) {
1710  // std::cout << "e:" << get_incident_surface_edge(ii)->get_first_node_ind() << "-" << get_incident_surface_edge(ii)->get_second_node_ind() << ", ";
1711  //}
1712  //std::cout << std::endl << std::endl;
1713 }
1714 
1715 
1716 ///
1717 /// @begin SurfaceNode::count_static_memory
1718 ///
1719 /// @brief
1720 /// Returns the amount of static memory used by this Node object
1721 ///
1722 template < typename V, typename E, typename G >
1724  return sizeof( SurfaceNode< V, E, G > );
1725 }
1726 
1727 ///
1728 /// @begin SurfaceNode::count_dynamic_memory
1729 ///
1730 /// @brief
1731 /// Returns the amount of dynamic memory used by this Node object
1732 ///
1733 template < typename V, typename E, typename G >
1735 
1736  unsigned int total_memory = parent::count_dynamic_memory();
1737 
1738  // additional memory used?
1739 
1740  return total_memory;
1741 }
1742 
1743 
1744 ///
1745 /// @begin SurfaceNode::getMemoryUsageInBytes
1746 ///
1747 /// @brief
1748 /// Not implemented, but needs to be!
1749 ///
1750 template < typename V, typename E, typename G >
1752  return 0;
1753 }
1754 
1755 
1756 ///
1757 /// @begin SurfaceNode::print_surface_avoidance_stats
1758 ///
1759 /// @brief
1760 /// reports on the level of success for surface score calculation procrastination
1761 ///
1762 template < typename V, typename E, typename G >
1764 
1765  if (num_state_substitutions_considered_ == 0)
1766  return;
1767 
1768  TR_STATS << "SurfaceE Calculation Avoidance Statistics:" << std::endl;
1769  TR_STATS << "num state substitutions considered: " << num_state_substitutions_considered_ << ", "
1770  << "num surface calcs procrastinated: " << num_surface_comps_procrastinated_ << ", "
1771  << "num surface calcs later computed: " << num_surface_comps_later_made_ << std::endl;
1772  TR_STATS << "Percent Avoided: " << (double)(num_surface_comps_procrastinated_ - num_surface_comps_later_made_) / num_state_substitutions_considered_ << ", ";
1773 
1774  if ( num_surface_comps_procrastinated_ != 0 ) {
1775  TR_STATS << "Percent Procrastinated worthwhile: " <<
1776  (double)(num_surface_comps_procrastinated_ - num_surface_comps_later_made_) / num_surface_comps_procrastinated_ << std::endl;
1777  } else {
1778  TR_STATS << "Percent Procrastinated worthwhile: " << "N/A" << std::endl;
1779  }
1780 
1781 }
1782 
1783 
1784 ///
1785 /// @begin SurfaceNode::reset_surface_avoidance_stats
1786 ///
1787 /// @brief
1788 /// resets static member variables of SurfaceNode that measure how worthwhile
1789 /// surface score calculation procrastination is.
1790 ///
1791 template < typename V, typename E, typename G >
1793  num_state_substitutions_considered_ = 0;
1794  num_surface_comps_procrastinated_ = 0;
1795  num_surface_comps_later_made_ = 0;
1796 }
1797 
1798 
1799 ///
1800 /// @begin SurfaceNode::set_rotamers
1801 ///
1802 /// @details
1803 /// Need to save a reference to the rotamer_set so that we can determine what a particular state change will do to the score
1804 ///
1805 template < typename V, typename E, typename G >
1807 
1808  // get_num_states should call the parent graph's method?
1809  if ( rotamers->num_rotamers() != (Size) parent::get_num_states() ) {
1810  utility_exit_with_message( "Number of rotamers is not equal to parents number of states. Quitting.");
1811  }
1812 
1813 #ifdef FILE_DEBUG
1814  TR_NODE << "set_rotamers: adding " << rotamers->num_rotamers() << " to local rotamers vector." << std::endl;
1815 #endif
1816 
1817  for ( Size ii = 1; ii <= rotamers->num_rotamers(); ++ii ) {
1818  rotamers_vector_[ ii ] = rotamers->rotamer( ii );
1819  }
1820 
1821 #ifdef FILE_DEBUG
1822  TR_NODE << "rotamers_vector_: [ ";
1823  for ( Size ii = 1; ii <= rotamers_vector_.size(); ++ii ) {
1824  TR_NODE << ii << ":" << rotamers_vector_[ ii ]->name1() << "-" << rotamers_vector_[ ii ]->seqpos() << ", ";
1825  }
1826  TR_NODE << "]" << std::endl;
1827 #endif
1828 
1829 }
1830 
1831 ///
1832 /// @begin SurfaceNode::get_rotamer
1833 ///
1834 /// @details
1835 /// Need to save a reference to the rotamer_set so that we can determine what a particular state change will do to the score
1836 ///
1837 template < typename V, typename E, typename G >
1839  return rotamers_vector_[ state ];
1840 }
1841 
1842 
1843 
1844 
1845 ///
1846 /// @begin SurfaceNode::is_surface_exposed
1847 ///
1848 /// @brief
1849 /// Returns the value of surface_exposed_ which gets set during the SIG initialize() method.
1850 ///
1851 template < typename V, typename E, typename G >
1853  return surface_exposed_;
1854 }
1855 
1856 ///
1857 /// @begin SurfaceNode::surface_exposed
1858 ///
1859 /// @brief
1860 /// setter for the surface_exposed_ bool
1861 ///
1862 template < typename V, typename E, typename G >
1864  surface_exposed_ = value;
1865 }
1866 
1867 
1868 ///
1869 /// @begin SurfaceNode::is_below_buried_residue_no_hsasa_cutoff
1870 ///
1871 /// @brief
1872 /// Returns the value of is_below_buried_residue_no_hsasa_cutoff_ which gets set during the SIG initialize() method.
1873 ///
1874 template < typename V, typename E, typename G >
1876  return is_below_buried_residue_no_hsasa_cutoff_;
1877 }
1878 
1879 ///
1880 /// @begin SurfaceNode::is_below_buried_residue_no_hsasa_cutoff
1881 ///
1882 /// @brief
1883 /// setter for the is_below_buried_residue_no_hsasa_cutoff_ bool
1884 ///
1885 template < typename V, typename E, typename G >
1887  is_below_buried_residue_no_hsasa_cutoff_ = value;
1888 }
1889 
1890 
1891 ///
1892 /// @begin SurfaceNode::reset_alt_state_total_hASA
1893 ///
1894 /// @brief
1895 /// Sets the alt state total hASA to the current state total hASA. See comments in SIG and commit_considered_substitution_surface
1896 /// for more information about why this method exists.
1897 ///
1898 template < typename V, typename E, typename G >
1900 
1901  // since we're only incrementing and decrementing the alt_state hASA, we need a way to reset it each iteration of consider()
1902  // so we don't get alt_state total hASA of nonsenical values which screw up the score.
1903  //
1904  if ( alt_state_total_hASA_ != curr_state_total_hASA_ ) {
1905  alt_state_total_hASA_ = curr_state_total_hASA_;
1906 #ifdef FILE_DEBUG
1907  TR_NODE << "reset_alt_state_total_hASA(): alt state total hASA was not equal to current state total hASA, but is now." << std::endl;
1908 #endif
1909  }
1910 
1911 }
1912 
1913 
1914 ///
1915 /// @begin SurfaceNode::initialize_num_neighbors_counting_self
1916 ///
1917 /// @brief
1918 /// Returns the number of neighbors within the interaction threshold, counting self.
1919 
1920 /// @detailed
1921 /// A member variable stores the value so that this method only has to run once and lookups can be performed thereafter.
1922 /// The reason we need to know the number of neighbors is that determining whether a residue is surface exposed depends
1923 /// on how many neighbors it has. For most applications, we have been using the approximation that residues with fewer
1924 /// than 16 neighbors in a 10A radius are surface-exposed.
1925 /// The original method of doing this was done with the tenA nb graph. Then I switched to using cB-cB distances and
1926 /// using the INTERACTION_RADIUS to define neighbors. I'm reverting back to using the tenA neighbor graph. The number
1927 /// of neighbors variable is only used to determine whether a residue is surface exposed or not. It's not like the detect
1928 /// neighborship between Node objects method that effectively defines how much of the surface gets looked at per substitution.
1929 /// Thus, using the tenA nb graph here is ok.
1930 ///
1931 ///
1932 template < typename V, typename E, typename G >
1934 
1935  /* pose::Pose poseRef = get_surface_owner()->pose();
1936 
1937  conformation::Residue const & rsd1 = poseRef.residue( get_surface_owner()->rotamer_sets().moltenres_2_resid( parent::get_node_index() ) );
1938  Real distanceBetweenAtoms = 0.0;
1939 
1940  for ( Size ii=1; ii < poseRef.total_residue(); ++ii ) {
1941 
1942  if ( ii == get_surface_owner()->rotamer_sets().moltenres_2_resid( parent::get_node_index() ) ) { continue; }
1943 
1944  conformation::Residue const & rsd2 = poseRef.residue( ii );
1945 
1946  distanceBetweenAtoms = rsd1.xyz( rsd1.nbr_atom() ).distance( rsd2.xyz( rsd2.nbr_atom() ) );
1947  if ( distanceBetweenAtoms <= INTERACTION_RADIUS ) {
1948  num_neighbors_counting_self_++;
1949  }
1950 
1951  }
1952 
1953  // finally, count ourselves...
1954  num_neighbors_counting_self_++;
1955  */
1956 
1957  core::scoring::TenANeighborGraph const & tenA_neighbor_graph( get_surface_owner()->pose().energies().tenA_neighbor_graph() );
1958 
1959  num_neighbors_counting_self_ =
1960  tenA_neighbor_graph.get_node( get_surface_owner()->rotamer_sets().moltenres_2_resid( parent::get_node_index() ) )->num_neighbors_counting_self();
1961 
1962 
1963 #ifdef FILE_DEBUG
1964  TR_NODE << "initialize_num_neighbors_counting_self(): fc node index " << parent::get_node_index() << " (PDB: "
1965  << wt_residue_for_node().seqpos() << "): " << num_neighbors_counting_self_ << " nbs" << std::endl;
1966 #endif
1967 
1968 }
1969 
1970 
1971 ///
1972 /// @begin SurfaceNode::num_neighbors_counting_self
1973 ///
1974 /// @brief
1975 /// Returns the value stored in the member variable.
1976 ///
1977 template < typename V, typename E, typename G >
1979 
1980  if ( num_neighbors_counting_self_ == -1 ) {
1981  initialize_num_neighbors_counting_self();
1982  }
1983 
1984  return num_neighbors_counting_self_;
1985 }
1986 
1987 
1988 ///
1989 /// @begin SurfaceNode::init_hASA_variables
1990 ///
1991 template < typename V, typename E, typename G >
1993  curr_state_total_hASA_ = calculate_amount_total_hydrophobic_ASA();
1994  alt_state_total_hASA_ = curr_state_total_hASA_;
1995 
1996 }
1997 
1998 ///
1999 /// @begin SurfaceNode::calculate_amount_total_hydrophobic_ASA
2000 ///
2001 /// @detailed
2002 /// Iterates over all the edges emanating from a residues context graph and determines how many surface-exposed
2003 /// total neighbors that residue has including itself. Uses the context graph in the Pose
2004 /// object because this function is only used for initialization. After being calculated once, incrementing and
2005 /// decrementing can be used instead of reiterating over all edges.
2006 ///
2007 /// Bug source. This function is not just used once during initialization.
2008 ///
2009 /// As of 8/1/08, changing this function to iterate over all residues in the pose to determine the number of se
2010 /// nbs instead of using the tenA neighbor graph. This change is so that different interaction thresholds can be
2011 /// used. For example, say I want to find all patches within 8A, not 10A. Can't use the 10A to initialize with
2012 /// or certain correctness checks fail in the Node methods.
2013 ///
2014 /// Big change: Making this method be part of Node/BGNodes. It's just too difficult to keep this method as part of the
2015 /// SIG. And I can't immediately think of a good reason to keep it in the SIG. It's more a functionality which the
2016 /// nodes should handle.
2017 ///
2018 /// 02/20/09, Changing the method to return the total amount of hydrophobic accessibile surface area instead of the
2019 /// number of hydrophobic neighbors. But most of the code remains the same. We want to sum up the average residue hASA
2020 /// for all of the surface-exposed neighbors within 10A.
2021 ///
2022 template < typename V, typename E, typename G >
2024 
2025  Real total_hASA = 0.0;
2026 
2027 #ifdef FILE_DEBUG
2028  TR_NODE << "calculate_amount_total_hydrophobic_ASA(): ";
2029 #endif
2030 
2031  if ( num_neighbors_counting_self() <= SURFACE_EXPOSED_CUTOFF ) {
2032  total_hASA += average_residue_hASA( wt_residue_for_node().aa(), num_neighbors_counting_self() );
2033  }
2034 
2035  // now iterate through all the other nodes. have to use the nodes/bgnodes because they have se defined.
2036  // neighboring nodes should be reachable via edge objects that were init'd before.
2037  for ( int ii = 1; ii <= parent::get_num_incident_edges(); ++ii ) {
2038 
2039  int other_node_index = get_incident_surface_edge(ii)->get_other_ind( parent::get_node_index() );
2040 
2041  // "search" through the map to make sure this edge is in the map (if not found, find returns map.end() which is what I check for)
2042  if ( fc_neighbor_map.find( std::pair<int,int>( parent::get_node_index(), other_node_index ) ) != fc_neighbor_map.end() ) {
2043 
2044 #ifdef FILE_DEBUG
2045  TR_NODE << other_node_index << "-";
2046 #endif
2047  int edge_index = ( other_node_index == get_incident_surface_edge(ii)->get_surface_node(0)->get_node_index() ? 0 : 1 );
2048  chemical::AA other_nodes_type = (get_incident_surface_edge(ii)->get_surface_node( edge_index )->wt_residue_for_node()).aa();
2049  Size nbs = get_incident_surface_edge(ii)->get_surface_node( edge_index )->num_neighbors_counting_self();
2050  Real hASA = average_residue_hASA( other_nodes_type, nbs );
2051 
2052 #ifdef FILE_DEBUG
2053  TR_NODE << ":" << hASA;
2054 #endif
2055  total_hASA += hASA;
2056 #ifdef FILE_DEBUG
2057  TR_NODE << ", ";
2058 #endif
2059  }
2060  }
2061 
2062  for ( int ii = 1; ii <= parent::get_num_edges_to_background_nodes(); ++ii ) {
2063  int other_node_index = get_edge_to_surface_bg_node(ii)->get_other_ind( this );
2064  // "search" through the map to make sure this edge is in the map (if not found, find returns map.end() which is what I check for)
2065  if ( bg_neighbor_map.find( std::pair<int,int>( parent::get_node_index(), other_node_index) ) != bg_neighbor_map.end() ) {
2066 
2067 #ifdef FILE_DEBUG
2068  TR_NODE << "b" << other_node_index << "-";
2069 #endif
2070  chemical::AA bg_nodes_type = (get_edge_to_surface_bg_node(ii)->get_surface_bg_node()->wt_residue_for_node()).aa();
2071  Size nbs = get_edge_to_surface_bg_node(ii)->get_surface_bg_node()->num_neighbors_counting_self();
2072  Real hASA = average_residue_hASA( bg_nodes_type, nbs );
2073 #ifdef FILE_DEBUG
2074  TR_NODE << ":" << hASA;
2075 #endif
2076 
2077  total_hASA += hASA;
2078 #ifdef FILE_DEBUG
2079  TR_NODE << ", ";
2080 #endif
2081  }
2082  }
2083 
2084  //if ( total_hASA > 1200 ) {
2085  // utility_exit_with_message( "Nonsensical amount of hydrophobic accessible surface area found for residue. Quitting." );
2086  //}
2087 
2088 #ifdef FILE_DEBUG
2089  TR_NODE << "returning patch area of " << total_hASA << " for node index " << parent::get_node_index()
2090  << " (PDB: " << wt_residue_for_node().seqpos() << ")" << std::endl;
2091 #endif
2092  return total_hASA;
2093 
2094 }
2095 
2096 ///
2097 /// @begin SurfaceNode::average_residue_hASA
2098 ///
2099 /// @brief
2100 /// Returns the amount of hydrophobic ASA this node/residue adds to a patch.
2101 ///
2102 /// @detailed
2103 /// This method is oblivious to whether a given residue should contribute to the patch area. This function just does
2104 /// the lookup for the hASA (using the SurfacePotential class). Calls to this function should be surrounded by is-this-
2105 /// a-surface-exposed-hydrophobic checks.
2106 ///
2107 template < typename V, typename E, typename G >
2109  return average_residue_hASA( get_rotamer( parent::get_current_state() )->aa(), num_neighbors_counting_self() /* this nodes num nbs */ );
2110 }
2111 
2112 ///
2113 /// @begin SurfaceNode::average_residue_hASA
2114 ///
2115 /// @brief
2116 /// Same function as above, but this one allows you to specify what type and num_nbs. This function is meant to be used
2117 /// only when initializing all of the Nodes/BGNodes because at that point we have to use the wild-type residue type, not
2118 /// the new rotamers residue type (which is what the above function will do).
2119 ///
2120 template < typename V, typename E, typename G >
2122  if ( num_nbs > (Size)BURIED_RESIDUE_NO_HSASA_CUTOFF ) return 0.00;
2123  return SurfacePotential::get_instance()->average_residue_hASA( residue_type, num_nbs );
2124 }
2125 
2126 
2127 ///
2128 /// @begin SurfaceNode::hASA_energy()
2129 ///
2130 /// @brief
2131 /// Calls a SurfacePotential class method to get the energy for a given patch area.
2132 /// Only nodes with number of nbs less than or equal to SURFACE_EXPOSED_CUTOFF will get a score. All other nodes will
2133 /// have a score of 0.0.
2134 ///
2135 template < typename V, typename E, typename G >
2137  if ( patch_area > MAX_PATCH_SURFACE_AREA ) {
2138  return surface_energy_weight_ * MAX_SURFACE_ENERGY;
2139  }
2140  if ( num_neighbors_counting_self() > SURFACE_EXPOSED_CUTOFF ) {
2141  return 0.0;
2142  }
2143  return SurfacePotential::get_instance()->hASA_patch_energy( patch_area, (Size)num_neighbors_counting_self() );
2144 }
2145 
2146 
2147 
2148 //----------------------------------------------------------------------------//
2149 //----------------- Surface Background Node Class -------------------------//
2150 //----------------------------------------------------------------------------//
2151 
2152 
2153 template < typename V, typename E, typename G >
2155 
2156 template < typename V, typename E, typename G >
2158 
2159 
2160 ///
2161 /// @begin SurfaceBackgroundNode::SurfaceBackgroundNode
2162 ///
2163 /// @brief
2164 /// main constructor. No default constructor, copy constructor or assignment operator
2165 ///
2166 /// @param
2167 /// owner - [in] - the owning interaction graph
2168 /// node_id - [in] - the index for this node amongst its owners set
2169 ///
2170 template < typename V, typename E, typename G >
2172  BackgroundNode< V, E, G > ( owner, node_index ),
2173  curr_state_total_hASA_( 0.0 ),
2174  alt_state_total_hASA_( 0.0 ),
2175  have_prepared_for_simA_( false ),
2176  surface_exposed_( false ),
2177  is_below_buried_residue_no_hsasa_cutoff_( false ),
2178  num_neighbors_counting_self_(-1)
2179 {
2180  surface_energy_weight_ = get_surface_owner()->surface_score_weight();
2181 #ifdef FILE_DEBUG
2182  TR_BGNODE << "Setting surface_energy_weight to " << surface_energy_weight_ << std::endl;
2183 #endif
2184 }
2185 
2186 
2187 ///
2188 /// @begin SurfaceBackgroundNode::~SurfaceBackgroundNode
2189 ///
2190 /// @brief
2191 /// destructor - no dynamicly allocated memory to manage -> empty
2192 ///
2193 template < typename V, typename E, typename G >
2195 
2196 
2197 ///
2198 /// @begin SurfaceBackgroundNode::prepare_for_simulated_annealing
2199 ///
2200 /// @brief
2201 /// Sets the hASA of surface exposed hydrophobic neighbors using the pose's neighbor graph. There's
2202 /// no need for BGNodes to keep track of which Nodes are really neighbors (energy graph vs neighbor graph) because they
2203 /// never broadcast changes to their neighboring Nodes.
2204 ///
2205 template < typename V, typename E, typename G >
2207 
2208  if ( ! parent::get_edge_vector_up_to_date() )
2209  parent::update_edge_vector();
2210 
2211  // initialize the areas for this background node properly
2212  // the calculate ASA method assumes that BGNodes have edges to other FC nodes by this point.
2213  init_hASA_variables(); // make this a separate function so that we can redo this initialization if prep_for_simA gets called again
2214 
2215  have_prepared_for_simA_ = true;
2216 
2217 }
2218 
2219 
2220 ///
2221 /// @begin SurfaceBackgroundNode::detect_neighborship
2222 ///
2223 /// @brief
2224 /// returns true if this background residue neighbors with any rotamer of a SurfaceNode
2225 ///
2226 /// @detailed
2227 /// If this node is in the list of neighbors for the passed in SurfaceNode, return true. Leave the responsibility
2228 /// of figuring out neighborship to the first class node.
2229 ///
2230 template < typename V, typename E, typename G >
2232  return node->detect_neighborship_with_node( parent::get_node_index(), false /* i.e. this node is not a FC node */ );
2233 }
2234 
2235 
2236 ///
2237 /// @begin SurfaceBackgroundNode::project_surface_deltaE_for_substitution
2238 ///
2239 /// @brief
2240 /// returns the change in surface induced by a SurfaceNode undergoing a state substitution.
2241 ///
2242 /// @detailed
2243 /// Is it possible for a background node to have a state of zero (or unassigned state). Not really - there's no state
2244 /// for background nodes since they're not changing.
2245 /// What happens if the first class node undergoing sub is in the unassigned state? We have to figure out what the wild-type
2246 /// residue at the changing position is. Should I pass in the node index to this method? I have to pass in a pointer
2247 /// to the node because that's how to get the rotamer information stored there. But get_node_index() is a protected
2248 /// method so I can't call that using the pointer.
2249 ///
2250 /// Bug fix: Turns out that if you do multiple loops of pack_rotamers, then the method blanket assign state 0 gets called.
2251 /// Have to handle the case where the current state is some nonzero value and the alt_state is going to the zero state.
2252 /// If not, you get seg faults. But, if we're going into the unassigned state, does it make sense in actually calculating
2253 /// a "correct" surface deltaE. Doesn't seem like it. Going to just add a instant return of a bad value!
2254 ///
2255 /// There's a potential problem with the setting of the alt state count that can creep up on multiple rounds of consider()
2256 /// without concomitant commit(). A separate method has been added to this class to handle these cases. It basically
2257 /// executes the following line each round of consider().
2258 /// alt_state_num_se_hp_nbs_ = curr_state_num_se_hp_nbs_;
2259 ///
2260 /// 02/20/2009/ Updating the function to do everything with hASA rather than hp counts.
2261 ///
2262 template < typename V, typename E, typename G >
2264  SurfaceNode< V, E, G >* fc_node_changing, int changing_nodes_curr_state, int changing_nodes_alt_state ) {
2265 
2266  // keep the value of the alt state in case this substitution is committed later. is this even used?
2267  // parent::set_alternate_state( parent::get_current_state() );
2268  // activating this as of 02/23/09 because parent::get_alternate_state() is called in at least one place
2269  // deactivating becase the method does not exist (at least in parent)
2270 
2271  // it may also be that the node undergoing substitution is in the unassigned state, right?
2272  // if that's the case, we need to look up the wild-type residue info
2273  //
2274  // the node undergoing sub is a first class node. so we need to get that nodes index so we can look it up
2275  // using the pose object. get_index_of_adjacent_first_class_node is a method in BackgroundNode which looks in a vector
2276  // that holds all the adjacent first class node. Only problem is that this particular bg node may have a number of adjacent
2277  // first class nodes. How do we determine the index of the one that is changing?!?
2278  // get_node_index() is a protected method of Nodes!
2279  // Have to pass the index in to this method. Hopefully the BGEdge can get the index!
2280 
2281  parent::update_edge_vector();
2282 
2283  // for when blanket assign zero state gets called; it doesn't really matter what we return since it's an unassigned state
2284  if ( changing_nodes_alt_state == 0 ) {
2285  return MAX_SURFACE_ENERGY;
2286  }
2287 
2288  // If it's not a surface exposed residue then don't bother updating any of the hASA and stuff, just return 0.0.
2289  if ( !(this->is_surface_exposed()) ) {
2290  return 0.0;
2291  }
2292 
2293  // this is where we update the hASA for this node.
2294  // rather than recalculating the sum by going over all neighboring nodes, we can just take away the average contribution
2295  // to the patch of the current residue and add in the alt state residues contribution
2296 
2297  if ( changing_nodes_curr_state == 0 ) {
2298  // curr_state_total_hASA_ should have been init'd during the call to 'prep for simA'
2299  // likewise, alt_state = curr_state above
2300 
2301  // the hASA here should only be changed if the fc node that's changing is surface exposed
2302  // WRONG. the hASA can still change if the nb node isn't surface exposed. it might have more nbs than the surface
2303  // exposed cutoff but still not be completely buried.
2304  //if ( fc_node_changing->is_surface_exposed() ) {
2305  if ( fc_node_changing->is_below_buried_residue_no_hsasa_cutoff() ) {
2306 
2307  chemical::AA curr_AA = fc_node_changing->wt_residue_for_node().aa();
2308  chemical::AA alt_AA = fc_node_changing->get_rotamer( changing_nodes_alt_state )->aa();
2309  Size nbs = fc_node_changing->num_neighbors_counting_self();
2310 
2311  alt_state_total_hASA_ = curr_state_total_hASA_ - average_residue_hASA( curr_AA, nbs ) + average_residue_hASA( alt_AA, nbs );
2312 
2313  if ( alt_state_total_hASA_ < -0.001 ) {
2314  TR_BGNODE << "curr_state_total_hASA_: " << curr_state_total_hASA_ << ", alt_state_total_hASA_: " << alt_state_total_hASA_
2315  << ", curr_AA: " << curr_AA << ", alt_AA: " << alt_AA << std::endl;
2316  this->print();
2317  utility_exit_with_message("Nonsensical alt_state reached (alt_state total hASA < 0). Exiting.");
2318  }
2319  }
2320 
2321  } else { // node wasn't in the unassigned state - 99% of calls will follow this branch
2322 
2323  // the hASA here should only be changed if the fc node that's changing is surface exposed
2324  //if ( fc_node_changing->is_surface_exposed() ) { // WRONG!
2325  if ( fc_node_changing->is_below_buried_residue_no_hsasa_cutoff() ) {
2326 
2327  chemical::AA curr_AA = fc_node_changing->get_rotamer( changing_nodes_curr_state )->aa();
2328  chemical::AA alt_AA = fc_node_changing->get_rotamer( changing_nodes_alt_state )->aa();
2329  Size nbs = fc_node_changing->num_neighbors_counting_self();
2330 
2331  alt_state_total_hASA_ = curr_state_total_hASA_ - average_residue_hASA( curr_AA, nbs ) + average_residue_hASA( alt_AA, nbs );
2332  }
2333  }
2334 
2335  Real difference = 0.0;
2336 
2337  if ( curr_state_total_hASA_ == alt_state_total_hASA_ ) { return 0.0; } // not sure if this is possible anymore
2338 
2339  if ( curr_state_total_hASA_ < -0.001 ) { this->print(); utility_exit_with_message( "Nonsensical curr_state reached (curr_state total hASA < 0). Exiting." ); }
2340  if ( alt_state_total_hASA_ < -0.001 ) { this->print(); utility_exit_with_message( "Nonsensical alt_state reached (alt_state total hASA < 0). Exiting." ); }
2341 
2342  if ( ( curr_state_total_hASA_ > MAX_PATCH_SURFACE_AREA ) && ( alt_state_total_hASA_ > MAX_PATCH_SURFACE_AREA ) ) {
2343  // this sub could be good or bad, but let the contributions of the other nodes decide what happens
2344  return 0.0;
2345  }
2346 
2347  // if the alt state is greater than 800A2,
2348  if ( alt_state_total_hASA_ > MAX_PATCH_SURFACE_AREA ) { // cutoff the distribution at 800A^2
2349  difference = surface_energy_weight_ * MAX_SURFACE_ENERGY;
2350 #ifdef FILE_DEBUG
2351  TR_BGNODE << "project_surface_deltaE_for_substitution: bg node " << parent::get_node_index()
2352  << " calculated deltaE for changing surface resid " << fc_node_changing->wt_seqpos_for_node() << "; "
2353  << "curr state hASA: " << curr_state_total_hASA_ << ", alt hASA: " << alt_state_total_hASA_
2354  << ", score difference: " << difference << std::endl;
2355 #endif
2356  return difference;
2357  }
2358  // alt state must be 800A2 or less, which is in bounds
2359 
2360  if ( curr_state_total_hASA_ > MAX_PATCH_SURFACE_AREA ) {
2361  // then, the current state has less hASA than the alt state, so this would be a favorable change
2362  difference = surface_energy_weight_ * -1 * MAX_SURFACE_ENERGY;
2363 #ifdef FILE_DEBUG
2364  TR_BGNODE << "project_surface_deltaE_for_substitution: bg node " << parent::get_node_index()
2365  << " calculated deltaE for changing surface resid " << fc_node_changing->wt_seqpos_for_node() << "; "
2366  << "curr state hASA: " << curr_state_total_hASA_ << ", alt hASA: " << alt_state_total_hASA_
2367  << ", score difference: " << difference << std::endl;
2368 #endif
2369  return difference;
2370  }
2371 
2372  difference = surface_energy_weight_ * ( hASA_energy( alt_state_total_hASA_ ) - hASA_energy( curr_state_total_hASA_ ) );
2373 
2374 #ifdef FILE_DEBUG
2375  TR_BGNODE << "project_surface_deltaE_for_substitution: bg node " << parent::get_node_index()
2376  << " calculated deltaE for changing surface resid " << fc_node_changing->wt_seqpos_for_node() << "; "
2377  << "curr state hASA: " << curr_state_total_hASA_ << ", alt hASA: " << alt_state_total_hASA_
2378  << ", score difference: " << difference << std::endl;
2379 #endif
2380 
2381  return difference;
2382 
2383 }
2384 
2385 
2386 ///
2387 /// @begin SurfaceBackgroundNode::acknowledge_substitution
2388 ///
2389 /// @brief
2390 /// bookkeeping to reflect a SurfaceNode's state substitution.
2391 ///
2392 template < typename V, typename E, typename G >
2394  curr_state_total_hASA_ = alt_state_total_hASA_;
2395 }
2396 
2397 
2398 ///
2399 /// @begin SurfaceBackgroundNode< V, E, G >::get_surface_score
2400 ///
2401 /// @brief
2402 /// returns the surface score under the current state assignment
2403 ///
2404 template < typename V, typename E, typename G >
2406 
2407  if ( !(this->is_surface_exposed()) ) {
2408  return 0.0;
2409  }
2410 
2411  if ( curr_state_total_hASA_ > MAX_PATCH_SURFACE_AREA ) {
2412  return surface_energy_weight_ * MAX_SURFACE_ENERGY;
2413  }
2414 
2415  return surface_energy_weight_ * hASA_energy( curr_state_total_hASA_ );
2416 }
2417 
2418 
2419 ///
2420 /// @begin SurfaceBackgroundNode::print
2421 ///
2422 /// @brief
2423 /// used only for debugging
2424 ///
2425 template < typename V, typename E, typename G >
2427 
2428  std::cout << "(bgnode id:" << parent::get_node_index() << ", hASA: " << average_residue_hASA()
2429  << ", curr: " << curr_state_total_hASA_ << ", alt: " << alt_state_total_hASA_
2430  << ", score: " << get_surface_score() << ", se: " << surface_exposed_ << std::endl;
2431 }
2432 
2433 ///
2434 /// @begin SurfaceBackgroundNode::count_static_memory
2435 ///
2436 template < typename V, typename E, typename G >
2438  return sizeof( SurfaceBackgroundNode< V, E, G > );
2439 }
2440 
2441 
2442 ///
2443 /// @begin SurfaceBackgroundNode::count_dynamic_memory
2444 ///
2445 template < typename V, typename E, typename G >
2447  unsigned int total_memory = parent::count_dynamic_memory();
2448 
2449  // any other dynamic memory that needs to be counted?
2450  return total_memory;
2451 }
2452 
2453 
2454 ///
2455 /// @begin SurfaceBackgroundNode::is_surface_exposed
2456 ///
2457 /// @brief
2458 /// Returns the value of surface_exposed_ which gets set during the SIG initialize() method.
2459 ///
2460 template < typename V, typename E, typename G >
2462  return surface_exposed_;
2463 }
2464 
2465 
2466 ///
2467 /// @begin SurfaceBackgroundNode::surface_exposed
2468 ///
2469 /// @brief
2470 /// using this for debugging
2471 ///
2472 template < typename V, typename E, typename G >
2474  surface_exposed_ = value;
2475 }
2476 
2477 
2478 ///
2479 /// @begin SurfaceBackgroundNode::is_below_buried_residue_no_hsasa_cutoff
2480 ///
2481 /// @brief
2482 /// Returns the value of is_below_buried_residue_no_hsasa_cutoff_ which gets set during the SIG initialize() method.
2483 ///
2484 template < typename V, typename E, typename G >
2486  return is_below_buried_residue_no_hsasa_cutoff_;
2487 }
2488 
2489 ///
2490 /// @begin SurfaceBackgroundNode::is_below_buried_residue_no_hsasa_cutoff
2491 ///
2492 /// @brief
2493 /// setter for the is_below_buried_residue_no_hsasa_cutoff_ bool
2494 ///
2495 template < typename V, typename E, typename G >
2497  is_below_buried_residue_no_hsasa_cutoff_ = value;
2498 }
2499 
2500 
2501 ///
2502 /// @begin SurfaceBackgroundNode::reset_alt_state_total_hASA
2503 ///
2504 /// @brief
2505 /// Sets the alt state total hASA to the current state total hASA. See comments in SIG and commit_considered_substitution_surface
2506 /// for more information about why this method exists.
2507 ///
2508 template < typename V, typename E, typename G >
2510 
2511  if ( alt_state_total_hASA_ != curr_state_total_hASA_ ) {
2512  alt_state_total_hASA_ = curr_state_total_hASA_;
2513 #ifdef FILE_DEBUG
2514  TR_BGNODE << "reset_alt_state_total_hASA(): alt state total hASA was not equal to current state total hASA, but is now." << std::endl;
2515 #endif
2516  }
2517 
2518 }
2519 
2520 
2521 ///
2522 /// @begin SurfaceBackgroundNode::initialize_num_neighbors_counting_self
2523 ///
2524 /// @brief
2525 /// Returns the number of neighbors within the interaction threshold, counting self. A member variable stores the
2526 /// value so that this method only has to run once and lookups can be performed thereafter.
2527 ///
2528 /// @detailed
2529 /// See comments in SurfaceNode::initialize_num_neighbors_counting_self for details.
2530 ///
2531 template < typename V, typename E, typename G >
2533 
2534  /*pose::Pose poseRef = get_surface_owner()->pose();
2535 
2536  conformation::Residue const & rsd1 = poseRef.residue( get_surface_owner()->bg_node_2_resid( parent::get_node_index() ) );
2537  Real distanceBetweenAtoms = 0.0;
2538 
2539  for ( Size ii=1; ii < poseRef.total_residue(); ++ii ) {
2540 
2541  if ( ii == get_surface_owner()->rotamer_sets().moltenres_2_resid( parent::get_node_index() ) ) { continue; }
2542 
2543  conformation::Residue const & rsd2 = poseRef.residue( ii );
2544 
2545  distanceBetweenAtoms = rsd1.xyz( rsd1.nbr_atom() ).distance( rsd2.xyz( rsd2.nbr_atom() ) );
2546  if ( distanceBetweenAtoms <= INTERACTION_RADIUS ) {
2547  num_neighbors_counting_self_++;
2548  }
2549 
2550  }
2551 
2552  // finally, count ourselves...
2553  num_neighbors_counting_self_++;
2554  */
2555 
2556  core::scoring::TenANeighborGraph const & tenA_neighbor_graph( get_surface_owner()->pose().energies().tenA_neighbor_graph() );
2557 
2558  num_neighbors_counting_self_ = tenA_neighbor_graph.get_node( get_surface_owner()->bg_node_2_resid( parent::get_node_index() ) )->num_neighbors_counting_self();
2559 
2560 #ifdef FILE_DEBUG
2561  TR_BGNODE << "initialize_num_neighbors_counting_self(): bg node index " << parent::get_node_index() << " (PDB: "
2562  << get_surface_owner()->bg_node_2_resid( parent::get_node_index() )
2563  << "): " << num_neighbors_counting_self_ << " nbs" << std::endl;
2564 #endif
2565 
2566 }
2567 
2568 
2569 ///
2570 /// @begin SurfaceBackgroundNode::num_neighbors_counting_self
2571 ///
2572 /// @brief
2573 /// Returns the value stored in the member variable.
2574 ///
2575 template < typename V, typename E, typename G >
2577 
2578  if ( num_neighbors_counting_self_ == -1 ) {
2579  initialize_num_neighbors_counting_self();
2580  }
2581 
2582  return num_neighbors_counting_self_;
2583 }
2584 
2585 
2586 ///
2587 /// @begin SurfaceBackgroundNode::init_hASA_variables
2588 ///
2589 template < typename V, typename E, typename G >
2591  curr_state_total_hASA_ = calculate_amount_total_hydrophobic_ASA();
2592  alt_state_total_hASA_ = curr_state_total_hASA_;
2593 
2594 }
2595 
2596 
2597 ///
2598 /// @begin SurfaceBackgroundNode::calculate_amount_total_hydrophobic_ASA
2599 ///
2600 /// @detailed
2601 /// See comments in SurfaceNode for more info.
2602 ///
2603 template < typename V, typename E, typename G >
2605 
2606  Real total_hASA = 0.0;
2607 
2608 #ifdef FILE_DEBUG
2609  TR_BGNODE << "calculate_amount_total_hydrophobic_ASA(): ";
2610 #endif
2611  if ( num_neighbors_counting_self() <= SURFACE_EXPOSED_CUTOFF ) {
2612  total_hASA += average_residue_hASA( wt_residue_for_node().aa(), num_neighbors_counting_self() );
2613  }
2614 
2615  // now iterate through all the other nodes. have to use the nodes/bgnodes because they have se defined.
2616  // neighboring nodes should be reachable via edge objects that were init'd before.
2617  // only need to iterate over fc nodes edging with this node, because bgnode-bgnode edges don't exist
2618  for ( int ii = 1; ii <= parent::get_num_incident_edges(); ++ii ) {
2619 
2620  // num_incident_edges may contain more edges than just the ones we want here, so call detect neighborship to determine
2621  // if we're in the cutoff since the neighbor_map doesn't exist in this class
2622  if ( get_surface_bg_edge(ii)->get_surface_node()->detect_neighborship_with_node( parent::get_node_index(), false ) ) {
2623 
2624 #ifdef FILE_DEBUG
2625  int other_node_index = get_surface_bg_edge(ii)->get_other_ind( this );
2626  TR_BGNODE << other_node_index << "-";
2627 #endif
2628  chemical::AA fc_nodes_type = ( get_surface_bg_edge(ii)->get_surface_node()->wt_residue_for_node() ).aa();
2629  Size nbs = get_surface_bg_edge(ii)->get_surface_node()->num_neighbors_counting_self();
2630  Real hASA = average_residue_hASA( fc_nodes_type, nbs );
2631 #ifdef FILE_DEBUG
2632  TR_BGNODE << ":" << hASA;
2633 #endif
2634 
2635  total_hASA += hASA;
2636 #ifdef FILE_DEBUG
2637  TR_BGNODE << ", ";
2638 #endif
2639  }
2640  }
2641 
2642  //if ( total_hASA > 1200 ) {
2643  // TR_BGNODE << "calculate_amount_total_hydrophobic_ASA(): calculating patch area for residue " << wt_residue_for_node().name3() << " "
2644  // << get_surface_owner()->bg_node_2_resid( parent::get_node_index() ) << std::endl;
2645  // print();
2646  //}
2647 
2648 #ifdef FILE_DEBUG
2649  TR_BGNODE << "returning patch area of " << total_hASA << " for bg node index " << parent::get_node_index()
2650  << " (PDB " << get_surface_owner()->bg_node_2_resid( parent::get_node_index() ) << ")" << std::endl;
2651 #endif
2652  return total_hASA;
2653 
2654 }
2655 
2656 
2657 ///
2658 /// @begin SurfaceBackgroundNode::average_residue_hASA
2659 ///
2660 /// @brief
2661 /// Returns the amount of hydrophobic ASA this residue adds to a patch.
2662 ///
2663 /// @detailed
2664 /// This method is oblivious to whether a given residue should contribute to the patch area. This function just does
2665 /// the lookup for the hASA (using the SurfacePotential class). Calls to this function should be surrounded by is-this-
2666 /// a-surface-exposed-hydrophobic checks.
2667 /// Since background nodes don't actually change type, whatever the wild type residue's aa type is what we use for the score.
2668 ///
2669 template < typename V, typename E, typename G >
2671  return average_residue_hASA( wt_residue_for_node().aa(), num_neighbors_counting_self() /* this nodes num nbs */ );
2672 }
2673 
2674 ///
2675 /// @begin SurfaceBackgroundNode::average_residue_hASA
2676 ///
2677 /// @brief
2678 /// Same function as above, but this one allows you to specify what type and num_nbs. This function is meant to be used
2679 /// only when initializing all of the Nodes/BGNodes because at that point we have to use the wild-type residue type, not
2680 /// the new rotamers residue type (which is what the above function will do).
2681 ///
2682 template < typename V, typename E, typename G >
2684  if ( num_nbs > (Size)BURIED_RESIDUE_NO_HSASA_CUTOFF ) return 0.00;
2685  return SurfacePotential::get_instance()->average_residue_hASA( residue_type, num_nbs );
2686 }
2687 
2688 
2689 ///
2690 /// @begin SurfaceBackgroundNode::hASA_energy()
2691 ///
2692 /// @brief
2693 /// Calls a SurfacePotential class method to get the energy for a given patch area.
2694 /// Not sure if I should take num neighbors as a parameter to the function, or just use the class method
2695 /// num_neighbors_counting_self().
2696 ///
2697 template < typename V, typename E, typename G >
2699  if ( patch_area > MAX_PATCH_SURFACE_AREA ) {
2700  return surface_energy_weight_ * MAX_SURFACE_ENERGY;
2701  }
2702  if ( num_neighbors_counting_self() > SURFACE_EXPOSED_CUTOFF ) {
2703  return 0.0;
2704  }
2705  return SurfacePotential::get_instance()->hASA_patch_energy( patch_area, (Size)num_neighbors_counting_self() );
2706 }
2707 
2708 
2709 
2710 //----------------------------------------------------------------------------//
2711 //-------------------------- Surface Edge Class ---------------------------//
2712 //----------------------------------------------------------------------------//
2713 
2714 ///
2715 /// @begin SurfaceEdge::SurfaceEdge
2716 ///
2717 /// @brief
2718 /// main constructor. No default, or copy constructors, no assignment operator
2719 ///
2720 /// @param
2721 /// owner - [in] - the owning interaction graph object
2722 /// node1 - [in] - the index of the lower-indexed SurfaceNode
2723 /// node2 - [in] - the index of the higher-indexed SurfaceNode
2724 ///
2725 template < typename V, typename E, typename G >
2726 SurfaceEdge< V, E, G >::SurfaceEdge( G* owner, int node1, int node2 ) :
2727  FirstClassEdge< V, E, G > ( owner, node1, node2 ),
2728  node_changing_( -1 ),
2729  node_not_changing_( -1 )
2730 {
2731 
2732  nodes_curr_states_[ 0 ] = nodes_curr_states_[ 1 ] = 0;
2733  nodes_alt_states_[ 0 ] = nodes_alt_states_[ 1 ] = 0;
2734 
2735  //variables for tracking the magnitude of the surface_deltaE's
2740 
2741 }
2742 
2743 
2744 ///
2745 /// @begin SurfaceEdge::~SurfaceEdge
2746 ///
2747 template < typename V, typename E, typename G >
2749 
2750 
2751 ///
2752 /// @begin SurfaceEdge::prepare_for_simulated_annealing
2753 ///
2754 /// @brief
2755 /// drops zero submatrices of the AminoAcidNeighborSparseMatrix and if the two_body_energies_ member then holds nothing,
2756 /// it checks whether or not its incident nodes have any sphere overlaps. If they don't then the edge deletes itself.
2757 ///
2758 template < typename V, typename E, typename G >
2760 
2761  parent::prepare_for_simulated_annealing_no_deletion();
2762 
2763  if ( parent::pd_edge_table_all_zeros() ) {
2764 
2765  // if the two fc nodes aren't neighbors, then we don't need to keep this edge
2766  if ( !( get_surface_node(0)->detect_neighborship_with_node( parent::get_node_index(1), true ) ) ) {
2767 
2768  // if the two fc nodes aren't neighbors, then we don't need to keep this edge
2769 //#ifdef FILE_DEBUG
2770 // TR_EDGE << "prepare_for_simulated_annealing - dropping edge e(" << parent::get_node_index( 0 )
2771 // << "," << parent::get_node_index( 1 ) << ")" << std::endl;
2772 //#endif
2773  delete this;
2774  }
2775  }
2776 }
2777 
2778 
2779 ///
2780 /// @begin SurfaceEdge::acknowledge_state_zeroed_surface
2781 ///
2782 /// @brief
2783 /// respond to when one of its vertices enters the "unassigned" state
2784 ///
2785 /// @param
2786 /// node_that_changed - [in] - the index of the node that changed
2787 ///
2788 template < typename V, typename E, typename G >
2790 
2791  // node_changing_ is the node of this edge that is changing
2792  node_changing_ = ( node_that_changed == parent::get_node_index(0) ? 0 : 1 );
2793  node_not_changing_ = !node_changing_;
2794 
2795  nodes_curr_states_[ node_changing_ ] = 0;
2796  inform_non_changing_node_of_neighbors_change();
2797 }
2798 
2799 
2800 ///
2801 /// @begin SurfaceEdge::get_surface_deltaE_for_neighbor
2802 ///
2803 /// @brief
2804 /// returns the change in surface score for the neighbor of a node that is
2805 /// produced by the state substitution it is considering.
2806 ///
2807 /// @detailed
2808 /// Need to tell the node that's not changing which node is considering the change and what the alternate state it
2809 /// might change to is. Then that node can recompute it's change in se hp nb count and return a change in score.
2810 ///
2811 ///
2812 template < typename V, typename E, typename G >
2813 Real SurfaceEdge< V, E, G >::get_surface_deltaE_for_neighbor( int node_considering_substitution, int alt_state ) {
2814 
2815  node_changing_ = ( node_considering_substitution == parent::get_node_index(0) ? 0 : 1 );
2816  node_not_changing_ = ! node_changing_;
2817 
2818  // save the index to the alt_state in a local array called nodes_alt_states_
2819  // the nodes_curr_states_ and nodes_alt_state_ are int arrays of size 2 that just hold the rotamer id (state) for
2820  // convenient access
2821  nodes_alt_states_[ node_changing_ ] = alt_state;
2822  nodes_alt_states_[ node_not_changing_ ] = nodes_curr_states_[ node_not_changing_ ];
2823 
2824  // nodes_curr_states_[ node_changing_ ] is the current state at the node considering substitution
2825 
2826  Real surface_deltaE = get_surface_node( node_not_changing_ )->get_surface_deltaE_for_neighbors_state_substitution(
2827  get_surface_node( node_changing_ ), nodes_curr_states_[ node_changing_ ], alt_state );
2828 
2829  magnitude_last_surface_deltaE_[ node_changing_ ] = std::abs( surface_deltaE );
2830 
2831 #ifdef FILE_DEBUG
2832  // this line just generates waaaay too much output
2833  //TR_EDGE << "get_surface_deltaE_for_neighbor() for changing node: " << node_considering_substitution
2834  // << " and node: " << parent::get_node_index( node_not_changing_ ) << " returning deltaE of " << surface_deltaE << std::endl;
2835 #endif
2836 
2837  return surface_deltaE;
2838 
2839 }
2840 
2841 
2842 ///
2843 /// @begin SurfaceEdge::acknowledge_substitution_surface
2844 ///
2845 /// @brief
2846 /// bookkeeping following the decision to substitute a nodes current state with the alternate it was asked to consider.
2847 ///
2848 template < typename V, typename E, typename G >
2850 
2851  inform_non_changing_node_of_neighbors_change();
2852 
2853  nodes_curr_states_[ node_changing_ ] = nodes_alt_states_[ node_changing_ ];
2854 
2855  track_max_magnitude_surface_deltaE();
2856 
2857  return;
2858 }
2859 
2860 ///
2861 /// @begin SurfaceEdge::inform_non_changing_node_of_neighbors_change
2862 ///
2863 /// @brief
2864 /// tells the node that isn't considering a substitution or changing state
2865 /// that its neighbor who is has changed.
2866 ///
2867 template < typename V, typename E, typename G >
2868 inline
2870  get_surface_node( node_not_changing_ )->acknowledge_neighbors_substitution_surface();
2871 }
2872 
2873 
2874 
2875 ///
2876 /// @begin SurfaceEdge::track_max_magnitude_surface_deltaE
2877 ///
2878 /// @brief
2879 /// Keeps track of the maximum surface deltaE seen in the last 50 commits
2880 ///
2881 template < typename V, typename E, typename G >
2883 
2884  ++num_surface_deltaE_observations_since_update_[ node_changing_ ];
2885 
2886  //TR_EDGE << "(e: " << get_node_index( 0 ) << " " << get_node_index( 1 );
2887  //TR_EDGE << "-- "<< get_node_index( node_changing_ ) << ", " << num_surface_deltaE_observations_since_update_[ node_changing_ ] << ") ";
2888 
2889  if ( magnitude_last_surface_deltaE_[ node_changing_ ] > max_surface_deltaE_recent_50_commits_[ node_changing_ ] ) {
2890  max_surface_deltaE_recent_50_commits_[ node_changing_ ] = magnitude_last_surface_deltaE_[ node_changing_ ];
2891  }
2892 
2893  if ( num_surface_deltaE_observations_since_update_[ node_changing_] == 50 ) {
2894  //TR_EDGE << "Edge: " << get_node_index( 0 ) << " " << get_node_index( 1 );
2895  //TR_EDGE << " max_surface_delatE for node "<< get_node_index( node_changing_ ) << ": " << max_surface_deltaE_recent_50_commits_[ node_changing_ ] << std::endl;
2896  max_surface_deltaE_last_50_commits_[ node_changing_ ] = max_surface_deltaE_recent_50_commits_[ node_changing_ ];
2897  num_surface_deltaE_observations_since_update_[ node_changing_] = 0;
2898  max_surface_deltaE_recent_50_commits_[ node_changing_ ] = -1.0f;
2899  }
2900 }
2901 
2902 
2903 ///
2904 /// @begin SurfaceEdge::declare_energies_final
2905 ///
2906 /// @brief
2907 /// Reduces memory usage in the two body energy table after the energy
2908 /// calculating function declares that the energies will not change thereafter
2909 ///
2910 /// @remarks (all by apl)
2911 /// In the PDEdge's version of this method, after invoking two_body_energies_.drop_zero_submatrices_where_possible();
2912 /// the PDEdge checks if the two body energy table it now holds is empty. If the table is empty, the edge deletes itself.
2913 ///
2914 /// A SASAEdge should not delete itself if the pair energies are all zero since the Minkowski sum of a water and a van
2915 /// der Waal's sphere extends further out from an atoms center than its (lj_atr, lj_rep, lksolv) interaction sphere.
2916 /// However, if a SASAEdge holds no pair energies, it's a very good candidate for removal -- it just first needs to check
2917 /// that no (vdw + 1.4 A) spheres overlap between any pair of rotamers on the edges it connects.
2918 ///
2919 template < typename V, typename E, typename G >
2921  parent::declare_energies_final_no_deletion();
2922 }
2923 
2924 
2925 ///
2926 /// @begin SurfaceEdge::get_max_surface_deltaE_guess
2927 ///
2928 template < typename V, typename E, typename G >
2930  return max_surface_deltaE_last_50_commits_[ node_changing_ ];
2931 }
2932 
2933 
2934 ///
2935 /// @begin SurfaceEdge::getMemoryUsageInBytes
2936 ///
2937 /// @remarks
2938 /// Not implemented.
2939 ///
2940 template < typename V, typename E, typename G >
2942  return 0;
2943 }
2944 
2945 
2946 ///
2947 /// @begin SurfaceEdge::count_static_memory
2948 ///
2949 template < typename V, typename E, typename G >
2951  return sizeof( SurfaceEdge< V, E, G > );
2952 }
2953 
2954 
2955 ///
2956 /// @begin SurfaceEdge::count_dynamic_memory
2957 ///
2958 template < typename V, typename E, typename G >
2960 
2961  unsigned int total_memory = parent::count_dynamic_memory();
2962 
2963  // any additional memory that needs to be counted?
2964  return total_memory;
2965 }
2966 
2967 
2968 
2969 //----------------------------------------------------------------------------//
2970 //-------------------- SurfaceBackgroundEdge Class ------------------------//
2971 //----------------------------------------------------------------------------//
2972 
2973 ///
2974 /// @begin SurfaceBackgroundEdge< V, E, G >::SurfaceBackgroundEdge
2975 ///
2976 /// @brief
2977 /// main constructor
2978 ///
2979 /// @param
2980 /// owner - [in] - the owning graph
2981 /// first_class_node_index - [in] - the index of the first class node upon which this new edge is incident
2982 /// second_class_node_index - [in] - the index of the second class node upon which this new edge is incident
2983 ///
2984 template < typename V, typename E, typename G >
2986  ( AdditionalBackgroundNodesInteractionGraph < V, E, G >* owner, int first_class_node_index, int background_node_index ):
2987  BackgroundToFirstClassEdge< V, E, G >( owner, first_class_node_index, background_node_index ),
2988  fc_node_curr_state_( 0 ),
2989  fc_node_alt_state_( 0 )
2990 {
2991  max_surface_deltaE_last_50_commits_ = -1.0f;
2992  max_surface_deltaE_recent_50_commits_ = -1.0f;
2993  magnitude_last_surface_deltaE_ = -1.0f;
2994  num_surface_deltaE_observations_since_update_ = 0;
2995 }
2996 
2997 
2998 ///
2999 /// @begin SurfaceBackgroundEdge::~SurfaceBackgroundEdge
3000 ///
3001 /// @brief
3002 ///
3003 template < typename V, typename E, typename G >
3005 
3006 
3007 ///
3008 /// @begin SurfaceBackgroundEdge::prepare_for_simulated_annealing
3009 ///
3010 /// @brief
3011 /// Invoked by AdditionalBackgroundNodesInteractionGraph::prepare_for_simulated_annealing.
3012 ///
3013 /// @remarks
3014 /// The SurfaceBackgroundEdge has no responsibilities in this function. However,
3015 /// when the AdditionalBackgroundNodesInteractionGraph invokes
3016 /// prepare_for_simulated_annealing on the SurfaceBackgroundNode that this edge
3017 /// is incident upon, that node will invoke initialize_overlap_cache on
3018 /// this edge
3019 ///
3020 template < typename V, typename E, typename G >
3022 
3023 
3024 ///
3025 /// @begin SurfaceBackgroundEdge::acknowledge_state_change
3026 ///
3027 /// @brief
3028 /// bookkeeping in response to a SurfaceNode switching states (without having
3029 /// gone through the usual consider-substitution/commit-substitution pattern).
3030 ///
3031 /// @param
3032 /// new_state - [in] - the state the SurfaceNode switched to
3033 ///
3034 template < typename V, typename E, typename G >
3036 
3037  if ( new_state == fc_node_curr_state_ )
3038  return;
3039 
3040  get_surface_deltaE_for_substitution( new_state );
3041  acknowledge_substitution_surface();
3042 }
3043 
3044 
3045 ///
3046 /// @begin SurfaceBackgroundEdge::get_surface_deltaE_for_substitution
3047 ///
3048 /// @brief
3049 /// returns the change in surface energy produced by a background node in response to a considered state
3050 /// substitution of the first class node
3051 ///
3052 /// @detailed
3053 /// Need to tell the bg node that's not changing that the fc node is considering a change and what the alternate state it
3054 /// might change to is. Then that node can recompute it's change in se hp nb total hASA and return a change in score.
3055 /// Called once by acknowledge_state_change method in this class when blanket setting the state of all the nodes
3056 /// to zero during initialization.
3057 ///
3058 /// @param
3059 /// alt_state - [in] - the alternate state (i.e. rotamer id) that the first class node is considering
3060 ///
3061 template < typename V, typename E, typename G >
3063 
3064  // keep the alt_state around in case the fc node commits this sub being considered
3065  fc_node_alt_state_ = alt_state;
3066 
3067  // so what we need to do here is update the alt state hASA based on the first class nodes alt state.
3068  // do we want the edge to handle this update or leave it to the node? for the surface (first class) edge class
3069  // method comparable to this one, we passed a reference to the first class node and current state of the node that
3070  // was changing. the current state (and alt_state) of the changing node is kept as a member variable in this class.
3071 
3072  Real const surface_deltaE = get_surface_bg_node()->project_surface_deltaE_for_substitution(
3073  get_surface_node(), fc_node_curr_state_, fc_node_alt_state_ );
3074 
3075  magnitude_last_surface_deltaE_ = std::abs( surface_deltaE );
3076 
3077  return surface_deltaE;
3078 
3079 }
3080 
3081 
3082 ///
3083 /// @begin SurfaceBackgroundEdge::acknowledge_substitution_surface
3084 ///
3085 /// @brief
3086 /// bookkeeping in response to the SurfaceNode committing the considered substitution
3087 ///
3088 template < typename V, typename E, typename G >
3090 
3091  fc_node_curr_state_ = fc_node_alt_state_;
3092 
3093  get_surface_bg_node()->acknowledge_substitution_surface();
3094 
3095  track_max_magnitude_surface_deltaE();
3096 }
3097 
3098 
3099 ///
3100 /// @begin SurfaceBackgroundEdge::track_max_magnitude_surface_deltaE
3101 ///
3102 /// @brief
3103 /// Keeps track of the maximum surface deltaE seen in the last 50 commits. Used possibly for procrastinating
3104 /// recalculations of the surface score.
3105 ///
3106 template < typename V, typename E, typename G >
3108 
3109  ++num_surface_deltaE_observations_since_update_;
3110 
3111  if ( magnitude_last_surface_deltaE_ > max_surface_deltaE_recent_50_commits_) {
3112  max_surface_deltaE_recent_50_commits_ = magnitude_last_surface_deltaE_;
3113  }
3114 
3115  if ( num_surface_deltaE_observations_since_update_ == 1000 ) {
3116  max_surface_deltaE_last_50_commits_ = max_surface_deltaE_recent_50_commits_;
3117  num_surface_deltaE_observations_since_update_= 0;
3118  max_surface_deltaE_recent_50_commits_ = -1.0f;
3119  }
3120 }
3121 
3122 
3123 ///
3124 /// @begin SurfaceBackgroundEdge::get_max_surface_deltaE_guess
3125 ///
3126 /// @brief
3127 /// Returns the value of max_surface_deltaE_last_50_commits_
3128 ///
3129 template < typename V, typename E, typename G >
3131  return max_surface_deltaE_last_50_commits_;
3132 }
3133 
3134 
3135 ///
3136 /// @begin SurfaceBackgroundEdge::count_static_memory
3137 ///
3138 template < typename V, typename E, typename G >
3140  return sizeof( SurfaceBackgroundEdge< V, E, G > );
3141 }
3142 
3143 
3144 ///
3145 /// @begin SurfaceBackgroundEdge::count_dynamic_memory
3146 ///
3147 template < typename V, typename E, typename G >
3149 
3150  unsigned int total_memory = parent::count_dynamic_memory();
3151  return total_memory;
3152 }
3153 
3154 
3155 
3156 //----------------------------------------------------------------------------//
3157 //--------------------- Surface Interaction Graph -------------------------//
3158 //----------------------------------------------------------------------------//
3159 
3160 
3161 ///
3162 /// @begin SurfaceInteractionGraph::SurfaceInteractionGraph
3163 ///
3164 /// @brief
3165 /// Main constructor
3166 ///
3167 /// @param
3168 /// num_nodes - [in] - the number of first class nodes in the graph. The number
3169 /// of second class nodes is reported to the graph much later.
3170 ///
3171 template < typename V, typename E, typename G >
3173  AdditionalBackgroundNodesInteractionGraph< V, E, G > ( num_nodes ),
3174  num_total_residues_( 0 ),
3175  num_residues_assigned_as_background_( 0 ),
3176  num_commits_since_last_update_( 0 ),
3177  total_energy_current_state_assignment_( 0 ),
3178  total_energy_alternate_state_assignment_( 0 ),
3179  node_considering_alt_state_( 0 ),
3180  deltaE_threshold_for_avoiding_surface_calcs_( -1.0f ),
3181  prepared_for_simulated_annealing_( false ),
3182  surface_score_weight_( 1 )
3183 {}
3184 
3185 
3186 ///
3187 /// @begin SurfaceInteractionGraph::~SurfaceInteractionGraph
3188 ///
3189 template < typename V, typename E, typename G >
3191 
3192 
3193 ///
3194 /// @begin SurfaceInteractionGraph::initialize()
3195 ///
3196 /// @detailed
3197 /// This initialize() method needs to do two things: 1) it needs to set residues that are not changing as background
3198 /// residues and 2) it needs to save references to the rotamer set or sets so that nodes can later figure out whether
3199 /// a particular rotamer change is a hydrophobic or not.
3200 ///
3201 /// In ++, there's a file InteractionGraphSupport.cc which is an analog of the InteractionGraphFactory in mini. In ++,
3202 /// the InteractionGraphSupport file instantiates and initializes, depending on the command line switches, the right
3203 /// interaction graph. For the SASAInteractionGraph, it first initializes the PDInteractionGraph (which is the base)
3204 /// and then calls the SASAIG initialize method.
3205 ///
3206 /// The thing is that this initialize method can't be called when the graph is constructed in the InteractionGraphFactory.
3207 /// The reason is that the PDInteractionGraph base initialize() method is NOT called until later in the pack rotamers
3208 /// process. (Actually it's called from within rotsets->compute_energies().) Only after the rotsets->compute energies
3209 /// returns can I stick in an initialize() method call for the SurfaceInteractionGraph (SIG). But then that's too late because
3210 /// the rotsets object has already computed some energies. Perhaps that's ok though. The rotsets object only calculates
3211 /// the PD energy terms - it doesn't do anything with non-PD terms.
3212 ///
3213 /// If a SIG init method is called during construction of the SIG, then the init method that's called by the rotsets object
3214 /// causes all the node info that was set in the SIG init method to be lost because the rotsets init method recreates all
3215 /// the nodes in the interaction graph when it runs. (That was a fun behaviour to figure out.)
3216 ///
3217 /// So the solution I'm going for is to call this init method in the prepare for simulated annealing method of this class.
3218 /// That gets called just before SA starts, so it will do tasks 1) and 2) above then. It doesn't really matter when the
3219 /// tasks get done as long as it happens before SA starts. This also means that the SIG will now have to keep a reference
3220 /// to the Pose, the Task, and the RotamerSets objects since it needs all of these things to do tasks 1) and 2).
3221 ///
3222 ///
3223 /// prepare_for_simulated_annealing gets called by the FixbbSA::run() method. Before this method, the
3224 /// rotamersets object has called compute_energies() (the whole process being started in pack_rotamers)
3225 /// which calls initialize() on the IG. I need to place the SIG init method directly after the IG init
3226 /// method that the RS object calls.
3227 ///
3228 /// Older comments:
3229 /// This interaction graph is templated so that it can be used with the original PD or the OTF graphs. If it's an OTF
3230 /// graph, then a reference to the pose object is available with the pose() method. However, I can't rely on having that
3231 /// method for the case when an OTF graph is not used. Thus, take the pose reference in as a parameter and refactor later
3232 /// if necessary.
3233 ///
3234 /// Newest comments:
3235 /// Don't call the parent classes initialize method because that calls create_new_node for all designable position, making
3236 /// every node in the graph a first class residue (erroneously!). Then after that, some residues are set as background
3237 /// residues so I'm surprised things were even working at all! Unfortunately, the class hierarchy makes setting designable
3238 /// residues that are surface-exposed be the only FirstClassNodes difficult. What has to happen is that non-designable
3239 /// positions will be the BGNodes and molten positions will be FCNodes. Then, each type of node will store a boolean flagging
3240 /// whether it is surface-exposed or not. Then, when a consider sub call is made, the nodes will immediately check the
3241 /// value of the boolean and return 0 immediately if it's not surface-exposed.
3242 ///
3243 /// 07/16/2008- Unfortunately, I can't just replicate all of the functionality of the parent classes initialize method
3244 /// here because it's different for PDIGs and LMIGs. And some of the their corresponding function calls are not defined
3245 /// in both classes so I get compile errors if I try to do it this way. There are a few possible solutions I could use
3246 /// for the problem of schizophrenic node (nodes which are getting assigned as BG and FC nodes). 1) I could just use
3247 /// Andrew's LFs designation that any designable or packable node is a FC node and any node not being packed or designed
3248 /// is a BGNode. This approach is the easiest to implement but since nodes that are only being packed aren't changing in
3249 /// sequence, their surface score shouldn't be changing so it's an inefficiency. 2) I could change the "create_node"
3250 /// call in this class to return either a Node or BGNode depending on what the packer_task has in it. Then the parent
3251 /// templated IG classes would get the right kind of node. But then, I would have to potentially change the AddtlBGNodesIG
3252 /// class method "setNumResiduesAsBackground" because in that call is a for loop which creates background nodes. This
3253 /// would complicate creating new non-PD terms in mini, because it would be specific for this case (surface). 3) Figure
3254 /// out some OO way of handling the distinction between packable and nonpackable residues. The OO-correct way to do this
3255 /// would probably be to subclass AdditionalBackgroundNodesInteractionGraph to something like
3256 /// SurfaceExposedNodesInteractionGraph and then make the SurfaceInteractionGraph inherit that one. Then
3257 /// "FirstClassNodes" would be nodes that are designable and surface-exposed; all other nodes would be "BackgroundNodes".
3258 ///
3259 /// Since it would require alot of work to write another derived class for probably not that significant (or necessary)
3260 /// performance improvement, I'll just make packable residues be FC nodes also. So continue to call the parent classes
3261 /// initialize() method. Just set residues which are not packable nor designable to BG nodes.
3262 ///
3263 template < typename V, typename E, typename G >
3265 
3266  /// TEMP!!!!
3267  // APL wants to create a parent/base class for RotamerSets called RotamerSetsBase which will hold variables and functions
3268  // that are common to RotamerSets and FlexbbRotamerSets. Each interaction graph will be passed a RotamerSetsBase object
3269  // to its initialize method, and functions in this class should use only access common base-class functions. However,
3270  // this would require changing quite a bit of code and making sure that only base-class RotamerSetsBase methods are used
3271  // here which I'm not interested in doing right now. So we can cast the RotamerSetsBase object to a RotamerSets object
3272  // and use it the way it was previously.
3273  rotamer_set::RotamerSets const & rot_sets( static_cast< rotamer_set::RotamerSets const & > (rot_sets_base) );
3274 
3275 #ifdef FILE_DEBUG
3276  TR_SIG << "initialize() called" << std::endl;
3277  TR_SIG << "calling set_rotamers on " << rotamer_sets().nmoltenres() << " molten residues." << std::endl;
3278 #endif
3279 
3280  // parent refers to AdditionalBackgroundNodesIG; G refers to the templated IG: PD or LMIG
3281  // call the parent initialize() method
3282  G::initialize( rot_sets );
3283 
3284  // save references to the rotamer_set because this will be needed later to figure out whether a new rotamer/state is hydrophobic or not
3285  for ( Size ii = 1; ii <= rotamer_sets().nmoltenres(); ++ii ) {
3286  get_surface_node( ii )->set_rotamers( rotamer_sets().rotamer_set_for_moltenresidue( ii ) );
3287  }
3288 
3289  // initializes some local variables that translate between the ig enumeration and resid
3290  set_num_residues_in_protein( pose().total_residue() );
3291 
3292  // unfortunately can't just use nmolten res here because moltenres includes residues which are being just repacked
3293  // and those shouldn't be considered first class nodes (would be very inefficient to do so!)
3294  //int num_designed = 0;
3295  //for (Size ii = 1; ii <= pose().total_residue(); ++ii) {
3296  // if ( packer_task().being_designed(ii) ) {
3297  // num_designed++;
3298  // }
3299  //}
3300  //int nbackground = pose().total_residue() - num_designed;
3301 
3302  // 7/15/08 can just use nmolten res because that includes NATAA (packable) residues
3303  int nbackground = pose().total_residue() - rot_sets.nmoltenres();
3304  set_num_background_residues( nbackground );
3305 
3306  for (Size ii = 1; ii <= pose().total_residue(); ++ii) {
3307 
3308  // IS THE NEIGHBOR GRAPH even going to be populated at this point? Hopefully, yes. It seems that at the
3309  // start of pack_rotamers, the scorefunction is evaulated on the pose which should populate the graphs.
3310 
3311  // in our case, first class residues are residues that are designable or packable (see notes in function comment).
3312  // This decision leads to the possibility of designable/packable residues that are not surface-exposed but are
3313  // still considered FC nodes. That's ok because in most of the functions, there are checks for being surface-exposed
3314  // and if those fail, the nodes immediately return 0.0.
3315  if ( packer_task().being_packed(ii) || packer_task().being_designed(ii) ) {
3316  // it's probably that being_packed() includes being_designed() so that the conditional needs only to say
3317  // being_packed(), but it'll short circuit the OR if being_packed() is true so it doesn't matter too much.
3318  continue;
3319  } else {
3320  set_residue_as_background_residue( ii );
3321  }
3322  }
3323 
3324 
3325  //core::scoring::TenANeighborGraph const & tenA_neighbor_graph( pose().energies().tenA_neighbor_graph() );
3326 
3327  // set the surface_exposed_ and is_below_buried_residue_no_hsasa booleans for all FC nodes, then BG nodes
3328  Size node_num_nbs = 0;
3329  for (int ii = 1; ii <= parent::get_num_nodes(); ++ii) {
3330  node_num_nbs = get_surface_node( ii )->num_neighbors_counting_self();
3331 
3332  // Note: we have to set two booleans here: surface_exposed_ and is_below_buried_residue_no_hsasa_cutoff_.
3333  // a Node may have more than the SURFACE_EXPOSED_CUTOFF number of neighbors, but still contribute hSASA to other nodes.
3334 
3335  if ( node_num_nbs <= (Size)SURFACE_EXPOSED_CUTOFF ) {
3336  // old way commented below
3337  // if ( tenA_neighbor_graph.get_node(ii)->num_neighbors_counting_self() <= SURFACE_EXPOSED_CUTOFF ) {
3338  get_surface_node( ii )->surface_exposed( true );
3339  get_surface_node( ii )->is_below_buried_residue_no_hsasa_cutoff( true );
3340 #ifdef FILE_DEBUG
3341  TR_SIG << "initialize_surface_ig: setting surface_exposed and is_below_buried_residue_no_hsasa_cutoff bools to true for FC node " << ii << std::endl;
3342 #endif
3343  } else if ( node_num_nbs > (Size)SURFACE_EXPOSED_CUTOFF && node_num_nbs <= (Size)BURIED_RESIDUE_NO_HSASA_CUTOFF ) {
3344  get_surface_node( ii )->is_below_buried_residue_no_hsasa_cutoff( true );
3345 #ifdef FILE_DEBUG
3346  TR_SIG << "initialize_surface_ig: setting is_below_buried_residue_no_hsasa_cutoff bool to true for FC node " << ii << std::endl;
3347 #endif
3348  }
3349 
3350  }
3351 
3352  for (int ii = 1; ii <= parent::get_num_background_nodes(); ++ii) {
3353  node_num_nbs = get_surface_bg_node( ii )->num_neighbors_counting_self();
3354  if ( node_num_nbs <= (Size)SURFACE_EXPOSED_CUTOFF ) {
3355  // if ( tenA_neighbor_graph.get_node(ii)->num_neighbors_counting_self() <= SURFACE_EXPOSED_CUTOFF ) {
3356  get_surface_bg_node( ii )->surface_exposed( true );
3357  get_surface_bg_node( ii )->is_below_buried_residue_no_hsasa_cutoff( true );
3358 #ifdef FILE_DEBUG
3359  TR_SIG << "initialize_surface_ig: setting surface_exposed and is_below_buried_residue_no_hsasa_cutoff bools to true for BG node " << ii << std::endl;
3360 #endif
3361  } else if ( node_num_nbs > (Size)SURFACE_EXPOSED_CUTOFF && node_num_nbs <= (Size)BURIED_RESIDUE_NO_HSASA_CUTOFF ) {
3362  get_surface_node( ii )->is_below_buried_residue_no_hsasa_cutoff( true );
3363 #ifdef FILE_DEBUG
3364  TR_SIG << "initialize_surface_ig: setting is_below_buried_residue_no_hsasa_cutoff bool to true for BG node " << ii << std::endl;
3365 #endif
3366  }
3367  }
3368 
3369 
3370 #ifdef FILE_DEBUG
3371  TR_SIG << "initialize_surface_ig: DONE with initialization.\n---" << std::endl;
3372 #endif
3373 
3374 }
3375 
3376 
3377 ///
3378 /// @begin SurfaceInteractionGraph::set_num_residues_in_protein
3379 ///
3380 /// @brief
3381 /// tells the graph how many residues there are total in the protein
3382 ///
3383 /// @detailed
3384 /// The graph maintains its own enumeration for the background residues;
3385 /// but asks that anyone wanting to refer to them use their original resid.
3386 /// The graph has to switch back and forth between enumeration schemes and
3387 /// must know how many residues there are total to do that efficiently.
3388 ///
3389 /// How does this method handle cofactors, ligands that get included in pose().total_residue()?
3390 /// It definitely allocates space in the array for them, and those residues will apparently be made into first-class nodes.
3391 /// But when it comes time to do the packing, they don't matter because they're not hydrophobic - they're not
3392 /// even amino acids - so they don't get updated.
3393 ///
3394 /// @param
3395 /// num_res - [in] - the total number of residues
3396 ///
3397 template < typename V, typename E, typename G >
3399 
3400  num_total_residues_ = num_res;
3401  resid_2_bgenumeration_.resize( num_total_residues_ );
3402  for (int ii = 1; ii <= num_total_residues_; ++ii) {
3403  resid_2_bgenumeration_[ii] = 0;
3404  }
3405 }
3406 
3407 ///
3408 /// @begin SurfaceInteractionGraph::set_num_background_residues
3409 ///
3410 /// @brief
3411 /// tells the graph how many residues there are as part of the protein that are
3412 /// not part of the combinatorial optimization process -- they are part of the
3413 /// background
3414 ///
3415 /// @detailed
3416 /// The other half of switching between enumeration schemes for the background
3417 /// residues is knowing how many background residues there are.
3418 ///
3419 /// @param
3420 /// num_background_residues - [in] - the number of background residues in the protein.
3421 ///
3422 template < typename V, typename E, typename G >
3424 
3425 #ifdef FILE_DEBUG
3426  TR_SIG << "set_num_background_residues: setting num background residues to " << num_background_residues << std::endl;
3427 #endif
3428 
3429  parent::set_num_background_nodes( num_background_residues );
3430  if ( parent::get_num_background_nodes() == 0 )
3431  return;
3432 
3433  bgenumeration_2_resid_.resize( parent::get_num_background_nodes() );
3434  for (int ii = 1; ii <= parent::get_num_background_nodes(); ++ii) {
3435  bgenumeration_2_resid_[ii] = 0;
3436  }
3437 }
3438 
3439 
3440 ///
3441 /// @begin SurfaceInteractionGraph::set_residue_as_background_residue
3442 ///
3443 /// @brief
3444 /// informs the graph that a particular residue is part of the background.
3445 /// first class residues, in terms of surface, will be residues that are surface exposed and are varying. background
3446 /// residues will be ones that are surface exposed but not varying since they will contribute to the surface score
3447 /// of the first class residues and whose own surface score will change depending on the first class residues.
3448 ///
3449 /// @param
3450 /// residue - [in] - the residue identifier
3451 ///
3452 template < typename V, typename E, typename G >
3454 
3455  assert( resid_2_bgenumeration_[ residue ] == 0 );
3456 
3457 #ifdef FILE_DEBUG
3458  TR_SIG << "set_residue_as_background_residue: setting residue " << pose().residue( residue ).name3() << " " << residue << " as background node." << std::endl;
3459 #endif
3460 
3461  ++num_residues_assigned_as_background_;
3462  resid_2_bgenumeration_[ residue ] = num_residues_assigned_as_background_;
3463  bgenumeration_2_resid_[ num_residues_assigned_as_background_ ] = residue;
3464 
3465 #ifdef FILE_DEBUG
3466  //TR_SIG << bgenumeration_2_resid_ << std::endl; // does not compile
3467 #endif
3468 }
3469 
3470 
3471 ///
3472 /// @begin SurfaceInteractionGraph::bg_node_2_resid
3473 ///
3474 /// @brief
3475 /// Provides read access to the bg to resid array. Returns -1 if the index is not in bounds.
3476 ///
3477 template < typename V, typename E, typename G >
3479 
3480  if ( node_index > num_residues_assigned_as_background_ ) {
3481  utility_exit_with_message( "Out of bounds array index passed to bg_node_2_resid. Quitting." );
3482  }
3483  return bgenumeration_2_resid_[ node_index ];
3484 }
3485 
3486 
3487 ///
3488 /// @begin SurfaceInteractionGraph::prepare_for_simulated_annealing
3489 ///
3490 /// @brief
3491 /// Prepares the graph to begin simulated annealing.
3492 ///
3493 /// @detailed
3494 /// Invokes both base-class prepare_for_simulated_annealing subroutines:
3495 /// InteractionGraphBase first, to prepare the SurfaceNodes and SurfaceEdges.
3496 /// Then the AdditionalBackgroundNodesInteractionGraph, to prepare the
3497 /// SurfaceBackgroundNodes, the SurfaceBackgroundEdges, and to do a little more
3498 /// preparing of the SurfaceNodes.
3499 ///
3500 /// @remarks
3501 /// As it is written, it should only be executed once; that will change, however
3502 /// if we make SurfaceInteractionGraph work with ligands (ligands that stay fixed
3503 /// during any single sim annealing process, but that move between anealings.
3504 ///
3505 template < typename V, typename E, typename G >
3507 
3508  if ( prepared_for_simulated_annealing_ ) {
3509 
3510  // for the unit tests and potentially other use cases, prepare_for_simulated_annealing may be called more than once.
3511  // the graph will go into an unassigned state when blanket_assign_state_0 is called, but the starting hASA values
3512  // could be wrong if any consider_sub() calls were called after the first prep_for_simA() call but before the second
3513  // prep_for_simA() call. But we don't need to go through and recalculate neighbors and creating Nodes/Edges and all
3514  // that. All we really need to do is reset/re-initialize the starting hASA variables. So, if we've already gone
3515  // through this method once, just tell all Nodes/BGNodes to reinit themselves.
3516  for (int ii = 1; ii <= parent::get_num_nodes(); ++ii)
3517  get_surface_node( ii )->init_hASA_variables();
3518  for (int ii = 1; ii <= parent::get_num_background_nodes(); ++ii)
3519  get_surface_bg_node( ii )->init_hASA_variables();
3520 
3521  return;
3522  }
3523 
3524  // since the count of se nbs gets determined in the prep_for_simA method, this call needs to occur before the
3525  // Nodes and BGNodes get their prep_for_simA() methods called. Otherwise, there are no edges to traverse out to
3526  // when trying to determine how many se hp nbs a given Node has.
3527  detect_background_residue_and_first_class_residue_neighbors();
3528 
3529  // G::prepare() calls InteractionGraphBase::prepare_for_simulated_annealing() - LinmemIG implements one but it also
3530  // calls the IGBase method. The IGBase method, in turn, calls prep_for_simA() on all the FC nodes.
3531  G::prepare_for_simulated_annealing();
3532 
3533  // parent::prepare() calls prep_for_simA() on all the BGNodes
3534  parent::prepare_for_simulated_annealing();
3535 
3536  prepared_for_simulated_annealing_ = true;
3537 
3538 #ifdef FILE_DEBUG
3539  TR_SIG << "prepare_for_simulated_annealing: number edges in graph: " << parent::get_num_edges() << std::endl;
3540 #endif
3541 
3542 }
3543 
3544 
3545 ///
3546 /// @begin SurfaceInteractionGraph::detect_background_residue_and_first_class_residue_neighbors
3547 ///
3548 /// @brief
3549 /// iterates across all pairs of first- and second-class nodes to determine which should be considered neighbors.
3550 /// Adds a SurfaceBackgroundEdge between any pair that are.
3551 ///
3552 template < typename V, typename E, typename G >
3554 
3555  for (int ii = 1; ii <= parent::get_num_background_nodes(); ++ii) {
3556 
3557 #ifdef FILE_DEBUG
3558  TR_SIG << "detect_bg_and_fc_residue_neighbors: checking for neighbors of background residue " << pose().residue( bgenumeration_2_resid_[ ii ] ).name3()
3559  << " " << pose().residue( bgenumeration_2_resid_[ ii ] ).seqpos() << std::endl;
3560 #endif
3561 
3562  for (int jj = 1; jj <= parent::get_num_nodes(); ++jj) {
3563 
3564  // ii: background node index, jj: first-class node index
3565  // the background nodes and first-class nodes should be set at this point due to the initalize method above.
3566  // if the background node is a "neighbor" of the first-class node, we need to add an edge between them.
3567  if ( get_surface_bg_node( ii )->detect_neighborship( get_surface_node( jj ) ) ) {
3568 #ifdef FILE_DEBUG
3569  TR_SIG << "detect_bg_and_fc_residue_neighbors: --- adding FC/BG edge: fc node id:" << pose().residue(jj).seqpos()
3570  << " / bg resid:" << bgenumeration_2_resid_[ ii ] << std::endl;
3571 #endif
3572  parent::add_background_edge( jj, ii );
3573  }
3574  }
3575  }
3576 
3577 #ifdef FILE_DEBUG
3578  TR_SIG << "DONE detecting background and first class neighbors.\n---" << std::endl;
3579 #endif
3580 
3581 }
3582 
3583 
3584 ///
3585 /// @begin SurfaceInteractionGraph::blanket_assign_state_0
3586 ///
3587 /// @brief
3588 /// assigns state 0 -- the unassigned state -- to all (first class) vertices
3589 /// in the graph
3590 ///
3591 template < typename V, typename E, typename G >
3593 
3594 #ifdef FILE_DEBUG
3595  TR_SIG << "blanket_assign_state_0() called" << std::endl;
3596 #endif
3597  for (int ii = 1; ii <= parent::get_num_nodes(); ++ii) {
3598  get_surface_node( ii )->assign_zero_state();
3599  }
3600  update_internal_energy_totals_surface();
3601 }
3602 
3603 
3604 ///
3605 /// @begin SurfaceInteractionGraph::update_internal_energy_totals_surface
3606 ///
3607 /// @brief
3608 /// After every 2^10 commits, the graph traverses its nodes and edges and
3609 /// re-tallies the total energy of the current state assignment. This update
3610 /// prevents the accumulation of numerical drift, increasing accuracy.
3611 ///
3612 template < typename V, typename E, typename G >
3614 
3615 #ifdef FILE_DEBUG
3616  TR_SIG << "update_internal_energy_totals_surface" << std::endl;
3617  // leave the call to the print routine inside the #ifdef b/c this output is debugging related
3619 #endif
3620 
3621  parent::update_internal_energy_totals();
3622  total_energy_current_state_assignment_ = parent::get_energy_PD_current_state_assignment();
3623 
3624  for (int ii = 1; ii <= parent::get_num_nodes(); ++ii) {
3625  Real fc_surface = get_surface_node( ii )->get_curr_state_surface_energy();
3626  total_energy_current_state_assignment_ += fc_surface;
3627  }
3628 
3629  for (int ii = 1; ii <= parent::get_num_background_nodes(); ++ii) {
3630  Real bg_surface = get_surface_bg_node( ii )->get_surface_score();
3631  total_energy_current_state_assignment_ += bg_surface;
3632  }
3633 
3634  num_commits_since_last_update_ = 0;
3635 }
3636 
3637 
3638 ///
3639 /// @begin SurfaceInteractionGraph::set_errorfull_deltaE_threshold
3640 ///
3641 /// @brief
3642 /// Allows the sim-annealer to specify a deltaE threshold above which, it is
3643 /// no longer necessary to be very accurate.
3644 ///
3645 /// @detailed
3646 /// When the annealer asks the graph to consider a state substitution that
3647 /// produces a large collision, the graph may approximate the surface deltaE
3648 /// instead of recalculating it. The deltaE returned by consider_substitution() will be
3649 /// inaccurate, but if the annealer is unlikely to accept the substitution, then time can be saved.
3650 /// The graph guarantees that if the annealer does commit that substitution that it will go back and
3651 /// perform the surface computations and return an accurate total energy for the graph.
3652 ///
3653 template < typename V, typename E, typename G >
3655 
3656 #ifdef FILE_DEBUG
3657  TR_SIG << "set_errorfull_deltaE_threshold: setting threshold to " << deltaE << std::endl;
3658  // leave this inside since it's debugging output
3660 #endif
3661 
3663  deltaE_threshold_for_avoiding_surface_calcs_ = deltaE;
3664 }
3665 
3666 
3667 ///
3668 /// @begin SurfaceInteractionGraph::consider_substitution
3669 ///
3670 /// @brief
3671 /// returns the change in energy induced by switching a particular node from its
3672 /// currently assigned state to some alternate state.
3673 ///
3674 /// @detailed
3675 /// Also returns the sum of the two body energies for the node in its current
3676 /// state; the sim-annealer accepts state substitutions at higher chance if the
3677 /// original state was also at a poor energy.
3678 ///
3679 /// @param
3680 /// node_ind - [in] - the index of the (first class) node
3681 /// new_state - [in] - the alternate state that the node should consider
3682 /// delta_energy - [out] - the change in energy induced on the entire graph
3683 /// by substituting a node's current state with the alternate. This energy
3684 /// may be inaccurate if it exceeds a threshold set by the sim-annealer.
3685 /// prev_energy_for_node - [out] - the sum of the pair-wise decomposable portion
3686 /// of the energy function for the node's currently assigned state
3687 ///
3688 template < typename V, typename E, typename G >
3689 void SurfaceInteractionGraph< V, E, G >::consider_substitution( int node_ind, int new_state, core::PackerEnergy & delta_energy, core::PackerEnergy & prev_energy_for_node ) {
3690 
3691  blanket_reset_alt_state_total_hASAs();
3692 
3693 #ifdef FILE_DEBUG
3694  TR_SIG << "---" << std::endl;
3695  TR_SIG << "consider_substitution(): trying new state " << new_state << " ("
3696  << get_surface_node( node_ind )->get_rotamer( new_state )->name() << ") on node/molten res " << node_ind << " (wt: "
3697  << pose().residue( rotamer_sets().moltenres_2_resid( node_ind ) ).name3() << " " << rotamer_sets().moltenres_2_resid( node_ind ) << ") " << std::endl;
3698 #endif
3699 
3700  node_considering_alt_state_ = node_ind;
3701 
3702  delta_energy = get_surface_node( node_ind )->project_deltaE_for_substitution_surface(
3703  new_state, prev_energy_for_node, deltaE_threshold_for_avoiding_surface_calcs_ );
3704 
3705 #ifdef FILE_DEBUG
3706  TR_SIG << "consider_substitution: delta_energy: " << delta_energy << std::endl;
3707 #endif
3708  total_energy_alternate_state_assignment_ = delta_energy + total_energy_current_state_assignment_;
3709 
3710 }
3711 
3712 
3713 ///
3714 /// @begin SurfaceInteractionGraph::blanket_reset_alt_state_total_hASAs
3715 ///
3716 /// @brief
3717 /// Iterates through all Nodes and BGNodes and resets their alt state total hASA to the current state total hASA.
3718 ///
3719 /// @detailed
3720 /// the Node consider() function is the main entry point from the SIG when the annealer considers a sub. need to make sure that the
3721 /// node's alt_state hASA is the same as the current state before we start incrementing/decrementhing things or otherwise I wind
3722 /// up with total hASAs that are wrong. alt state will be the same as current state on the first time through because of
3723 /// prep for simA call, but not necessarily the case on next substitution coming from annealer. this only sets the alt state
3724 /// hASA on this particular (changing) node. all of the other nodes which were called on to consider a substitution and
3725 /// whose hASAs changed need to reset their alt state hASA also (or, otherwise, it appears as if the substitution was
3726 /// committed). More about this problem can be read in the comments for commit_considered_substitution_surface()
3727 ///
3728 /// 02/23/2009 Updated this function and the functions it calls to do everything in terms of hASA instead of se hp counts.
3729 ///
3730 template < typename V, typename E, typename G >
3732 
3733 #ifdef FILE_DEBUG
3734  TR_SIG << "blanket_reset_alt_state_total_hASAs: calling reset_alt_state_total_hASA on all FC nodes." << std::endl;
3735 #endif
3736  for (int ii = 1; ii <= parent::get_num_nodes(); ++ii) {
3737  get_surface_node( ii )->reset_alt_state_total_hASA();
3738  }
3739 
3740 #ifdef FILE_DEBUG
3741  TR_SIG << "blanket_reset_alt_state_total_hASAs: calling reset_alt_state_total_hASA on all BG nodes." << std::endl;
3742 #endif
3743  for (int ii = 1; ii <= parent::get_num_background_nodes(); ++ii) {
3744  get_surface_bg_node( ii )->reset_alt_state_total_hASA();
3745  }
3746 }
3747 
3748 
3749 ///
3750 /// @begin SurfaceInteractionGraph::commit_considered_substitution
3751 ///
3752 /// @brief
3753 /// Commits the substitution that the sim annealer had previously asked the graph to consider. Returns the accurate total
3754 /// energy for the graph.
3755 ///
3756 template < typename V, typename E, typename G >
3758 
3759 #ifdef FILE_DEBUG
3760  TR_SIG << "commit_considered_substitution(): committing sub on node " << node_considering_alt_state_ << std::endl;
3761 #endif
3762  core::PackerEnergy deltaE = get_surface_node( node_considering_alt_state_ )->commit_considered_substitution_surface();
3763 
3764  total_energy_current_state_assignment_ = total_energy_current_state_assignment_ + deltaE;
3765 
3766  node_considering_alt_state_ = -1;
3767  ++num_commits_since_last_update_;
3768  if ( num_commits_since_last_update_ == COMMIT_LIMIT_BETWEEN_UPDATES ) {
3769  update_internal_energy_totals_surface();
3770  }
3771 
3772  return total_energy_current_state_assignment_;
3773 }
3774 
3775 
3776 ///
3777 /// @begin SurfaceInteractionGraph::set_network_state
3778 ///
3779 /// @brief
3780 /// Switch the state assignment of every first class node in the graph.
3781 /// Useful, for instance, if you want to switch to the best network state
3782 /// that you've found so far. Like after simulated annealing is done with!
3783 ///
3784 /// @remarks
3785 /// Considered removing the use of FArrays here, but unfortunately it's what the Annealers use and I'm
3786 /// not qualified to be refactoring the annealers.
3787 ///
3788 /// @param
3789 /// node_states - [in] - the array of states, one for each vertex in the graph
3790 ///
3791 template < typename V, typename E, typename G >
3793 
3794 #ifdef FILE_DEBUG
3795  TR_SIG << "set_network_state() called with states: " << node_states << std::endl;
3796 #endif
3797 
3798  blanket_reset_alt_state_total_hASAs(); // why is this needed here again?
3799 
3800  for (int ii = 1; ii <= parent::get_num_nodes(); ++ii) {
3801  get_surface_node( ii )->assign_state_surface( node_states(ii) );
3802  }
3803  update_internal_energy_totals_surface();
3804 
3805  return total_energy_current_state_assignment_;
3806 }
3807 
3808 
3809 ///
3810 /// @begin SurfaceInteractionGraph::set_state_for_node
3811 ///
3812 /// @brief
3813 /// Assign new_state to the first class node with index node_ind
3814 ///
3815 /// @param
3816 /// node_ind - [in] - the index of the (first class) node
3817 /// new_state - [in] - the new state assigned to the node
3818 ///
3819 template < typename V, typename E, typename G >
3821 
3822  get_surface_node( node_ind )->assign_state_surface( new_state );
3823 
3824  update_internal_energy_totals_surface();
3825  return total_energy_current_state_assignment_;
3826 }
3827 
3828 
3829 ///
3830 /// @begin SurfaceInteractionGraph::get_energy_current_state_assignment
3831 ///
3832 /// @brief
3833 /// returns the energy of the entire graph under the current network state
3834 /// assignment.
3835 ///
3836 template < typename V, typename E, typename G >
3838  return total_energy_current_state_assignment_;
3839 }
3840 
3841 
3842 ///
3843 /// @begin SurfaceInteractionGraph::create_new_node
3844 ///
3845 /// @brief
3846 /// factory method pattern for instantiation of SurfaceNode objects, used by
3847 /// InteractionGraphBase class.
3848 ///
3849 /// @detailed
3850 /// The IGBase class calls this method for all residues that are designable.
3851 ///
3852 /// @param
3853 /// node_index - [in] - the index of the (first class) node
3854 /// num_states - [in] - the number of states for that node
3855 ///
3856 template < typename V, typename E, typename G >
3859 #ifdef FILE_DEBUG
3860  TR_SIG << "create_new_node called with node_index " << node_index << " and num_states " << num_states << std::endl;
3861 #endif
3862  return new SurfaceNode< V, E, G >( this, node_index, num_states );
3863 }
3864 
3865 
3866 ///
3867 /// @begin SurfaceInteractionGraph::create_new_edge
3868 ///
3869 /// @brief
3870 /// factory method pattern for instantiation of SurfaceEdge objects, used by
3871 /// InteractionGraphBase class.
3872 ///
3873 /// @param
3874 /// index1 - [in] - the index of the lower-indexed (first class) node
3875 /// index2 - [in] - the index of the higher-indexed (first class) node
3876 ///
3877 template < typename V, typename E, typename G >
3880 #ifdef FILE_DEBUG
3881  TR_SIG << "create_new_edge() called for indices " << index1 << " and " << index2 << std::endl;
3882 #endif
3883  return new SurfaceEdge< V, E, G >( this, index1, index2 );
3884 }
3885 
3886 
3887 ///
3888 /// @begin SurfaceInteractionGraph::create_background_node
3889 ///
3890 /// @brief
3891 /// factory method pattern for instantiation of SurfaceBackgroundResidueNode
3892 /// objects, used by AdditionalBackgroundNodesInteractionGraph class.
3893 ///
3894 /// @param
3895 /// node_index - [in] - the index of the (second class) node
3896 ///
3897 template < typename V, typename E, typename G >
3899 #ifdef FILE_DEBUG
3900  TR_SIG << "create_background_node() called for index " << node_index << std::endl;
3901 #endif
3902  return new SurfaceBackgroundNode< V, E, G >( this, node_index );
3903 }
3904 
3905 
3906 ///
3907 /// @begin SurfaceInteractionGraph::create_background_edge
3908 ///
3909 /// @brief
3910 /// factory method pattern for instantiation of SurfaceBackgroundEdge
3911 /// objects, used by AdditionalBackgroundNodesInteractionGraph class.
3912 ///
3913 /// @param
3914 /// fc_node_index - [in] - the index of the first class node
3915 /// sc_node_index - [in] - the index of the second class node
3916 ///
3917 /// @remarks
3918 /// Returns a pointer to the created SurfaceBackgroundEdge
3919 ///
3920 template < typename V, typename E, typename G >
3922  return new SurfaceBackgroundEdge< V, E, G >( this, fc_node_index, bg_node_index );
3923 }
3924 
3925 
3926 ///
3927 /// @begin SurfaceInteractionGraph::print_internal_energies_for_current_state_assignment
3928 ///
3929 /// @brief
3930 /// Prints out the one and two-body energies for every node and bgnode in the graph.
3931 ///
3932 template < typename V, typename E, typename G >
3934 
3935  // print out the one-body and surface energies for all first class nodes
3936  TR_SIG << "internal energies: " << std::endl;
3937  for (int ii = 1; ii <= parent::get_num_nodes(); ++ii) {
3938  Real one_body = get_surface_node( ii )->get_curr_state_one_body_energy();
3939  TR_SIG << "node " << ii << " 1b: " << one_body;
3940 
3941  Real surface = get_surface_node( ii )->get_curr_state_surface_energy();
3942  TR_SIG << ", surface = " << surface;
3943 
3944  if ( ii % 3 == 0) {
3945  TR_SIG << std::endl;
3946  }
3947  }
3948 
3949  TR_SIG << std::endl;
3950 
3951  // print out the surface energies for all background nodes
3952  for (int ii = 1; ii <= parent::get_num_background_nodes(); ++ii) {
3953 
3954  Real bg_surface = get_surface_bg_node( ii )->get_surface_score();
3955  TR_SIG << "bg res: " << bgenumeration_2_resid_[ ii ] << " surface: " << bg_surface << std::endl;
3956  }
3957 
3958  // print out the two-body energies for all edges between first-class nodes only?
3959  int count_edges = 0;
3960  for (std::list< core::pack::interaction_graph::EdgeBase*>::const_iterator iter = parent::get_edge_list_begin(); iter != parent::get_edge_list_end(); ++iter) {
3961  Real edge_energy = ((SurfaceEdge< V, E, G >*) (*iter))->get_current_two_body_energy();
3962  TR_SIG << "edge: " << edge_energy << " ";
3963 
3964  if ( count_edges % 5 == 0)
3965  TR_SIG << std::endl;
3966  ++count_edges;
3967  }
3968 }
3969 
3970 
3971 ///
3972 /// @begin SurfaceInteractionGraph::get_edge_memory_usage
3973 ///
3974 /// @brief
3975 /// Should return a measurement of the memory used by the interaction graph
3976 /// to store the rotamer pair energies. Unimplemented.
3977 ///
3978 template < typename V, typename E, typename G >
3980  return 0;
3981 }
3982 
3983 
3984 ///
3985 /// @begin SurfaceInteractionGraph::count_static_memory
3986 ///
3987 template < typename V, typename E, typename G >
3989  return sizeof( SurfaceInteractionGraph< V, E, G > );
3990 }
3991 
3992 
3993 ///
3994 /// @begin SurfaceInteractionGraph::count_dynamic_memory
3995 ///
3996 template < typename V, typename E, typename G >
3998 
3999  unsigned int total_memory = parent::count_dynamic_memory();
4000  total_memory += resid_2_bgenumeration_.size() * sizeof ( int );
4001  total_memory += bgenumeration_2_resid_.size() * sizeof ( int );
4002 
4003  return total_memory;
4004 }
4005 
4006 
4007 ///
4008 /// @begin SurfaceInteractionGraph::set_pose
4009 ///
4010 template < typename V, typename E, typename G >
4011 void
4013 
4014 #ifdef FILE_DEBUG
4015  TR_SIG << "set_pose() called: typeid() of base class G returned: " << typeid(G).name() << std::endl;
4016 #endif
4017 
4018  // call the set_pose function in the LinMemIG class, because it, too, uses the Pose to do its thing
4019  if ( typeid(G) == typeid( pack::interaction_graph::LinearMemoryInteractionGraph ) ) {
4020  dynamic_cast<pack::interaction_graph::LinearMemoryInteractionGraph*>(this)->set_pose( pose );
4021  }
4022 
4023  pose_ = new pose::Pose( pose );
4024 }
4025 
4026 
4027 ///
4028 /// @begin SurfaceInteractionGraph::set_packer_task
4029 ///
4030 /// @brief
4031 /// We need a copy of the packer task for 2 reasons: 1) to figure out what (if any) the weight on the surface score
4032 /// is; and 2) to determine which residues are being packed and/or designed. We have to figure the packing options
4033 /// because it determines whether a residue becomes a FirstClass (SurfaceNode) node or a background node.
4034 ///
4035 template < typename V, typename E, typename G >
4036 void
4038  packer_task_ = the_task.clone();
4039 }
4040 
4041 
4042 ///
4043 /// @begin SurfaceInteractionGraph::set_rotamer_sets
4044 ///
4045 template < typename V, typename E, typename G >
4046 void
4048  rotamer_sets_ = new rotamer_set::RotamerSets( rotsets );
4049 }
4050 
4051 
4052 ///
4053 /// @begin SurfaceInteractionGraph::print
4054 ///
4055 /// @brief
4056 /// useful for debugging
4057 ///
4058 template< typename V, typename E, typename G >
4059 void
4061 
4062  std::cout << "Surface Interaction Graph state: " << std::endl;
4063  std::cout << "nodes: " << std::endl;
4064  for (int jj = 1; jj <= parent::get_num_nodes(); ++jj) {
4065  get_surface_node( jj )->print();
4066  }
4067 
4068  std::cout << "bgnodes: " << std::endl;
4069  for (int ii = 1; ii <= parent::get_num_background_nodes(); ++ii) {
4070  get_surface_bg_node( ii )->print();
4071  }
4072 }
4073 
4074 
4075 
4076 // The below functions are only used for the unit tests. However, since most developers these days are running the unit
4077 // tests using release mode, I can't #ifdef these functions (to leave them out of release mode builds) or the unit
4078 // tests don't compile. So just compile them regardless of build mode.
4079 
4080 ///
4081 /// @begin SurfaceNode::set_observed_sufficient_boolean_true
4082 ///
4083 /// @brief
4084 /// Sets the observed_sufficient_surface_E_to_predict_min_ to true. Only used by the unit tests.
4085 ///
4086 template< typename V, typename E, typename G >
4088  observed_sufficient_surface_E_to_predict_min_ = true;
4089 
4090  for( int ii = 1; ii <= parent::get_num_incident_edges(); ++ii)
4091  get_incident_surface_edge(ii)->set_max_surface_deltaE(); // defined in header, sets value to 0.1
4092 
4093  for ( int ii = 1; ii <= parent::get_num_edges_to_background_nodes(); ++ii )
4094  get_edge_to_surface_bg_node(ii)->set_max_surface_deltaE(); // defined in header, sets value to 0.1
4095 
4096 }
4097 
4098 ///
4099 /// @begin SurfaceNode::get_hASA_for_node_and_nbs
4100 ///
4101 /// @brief
4102 /// Returns a vector of Reals containing the hASA of se hp nbs for this node in the first index, and then
4103 /// the hASA for all neighboring nodes and bgnodes. Note: Order is not guaranteed here.
4104 /// Only used by the unit tests. Should not exist in release mode.
4105 ///
4106 template< typename V, typename E, typename G >
4108 
4109  std::vector<Real> hASA_vector;
4110  hASA_vector.push_back( curr_state_total_hASA_ );
4111 
4112  for ( int ii = 1; ii <= parent::get_num_incident_edges(); ++ii ) {
4113  int other_nodes_index = get_incident_surface_edge(ii)->get_other_ind( parent::get_node_index() );
4114  int edge_index = ( other_nodes_index == get_incident_surface_edge(ii)->get_surface_node(0)->get_node_index() ? 0 : 1 );
4115  // "search" through the map to make sure this edge is in the map (if not found, find returns map.end() which is what I check for)
4116  if ( fc_neighbor_map.find( std::pair<int,int>( parent::get_node_index(), other_nodes_index) ) != fc_neighbor_map.end() ) {
4117 
4118  hASA_vector.push_back( get_incident_surface_edge(ii)->get_surface_node( edge_index )->get_current_hASA() );
4119  }
4120  }
4121 
4122  for ( int ii = 1; ii <= parent::get_num_edges_to_background_nodes(); ++ii ) {
4123  int other_nodes_index = get_edge_to_surface_bg_node(ii)->get_other_ind( this );
4124  // "search" through the map to make sure this edge is in the map (if not found, find returns map.end() which is what I check for)
4125  if ( bg_neighbor_map.find( std::pair<int,int>( parent::get_node_index(), other_nodes_index) ) != bg_neighbor_map.end() ) {
4126 
4127  hASA_vector.push_back( get_edge_to_surface_bg_node(ii)->get_surface_bg_node()->get_current_hASA() );
4128  }
4129  }
4130 
4131  return hASA_vector;
4132 }
4133 
4134 /// @begin SurfaceNode::get_current_hASA
4135 ///
4136 /// @brief
4137 /// Returns current hASA. Only used by the unit tests. Should not exist in release mode.
4138 ///
4139 template< typename V, typename E, typename G >
4140 Real SurfaceNode<V, E, G>::get_current_hASA() { return curr_state_total_hASA_; }
4141 
4142 /// @begin SurfaceBackgroundNode::get_current_count
4143 ///
4144 /// @brief
4145 /// Returns current hASA. Only used by the unit tests. Should not exist in release mode.
4146 ///
4147 template< typename V, typename E, typename G >
4148 Real SurfaceBackgroundNode<V, E, G>::get_current_hASA() { return curr_state_total_hASA_; }
4149 
4150 
4151 
4152 ///
4153 /// @begin SurfaceNode::get_alt_state_hASA_for_node_and_nbs
4154 ///
4155 /// @brief
4156 /// Returns a vector of Reals containing the hASA of se hp nbs for this node in the first index, and then
4157 /// the hASA for all neighboring nodes and bgnodes. Note: Order is not guaranteed here.
4158 /// Only used by the unit tests. Should not exist in release mode.
4159 ///
4160 template< typename V, typename E, typename G >
4162 
4163  std::vector< Real > alt_state_hASA_vector;
4164  alt_state_hASA_vector.push_back( alt_state_total_hASA_ );
4165 
4166  for ( int ii = 1; ii <= parent::get_num_incident_edges(); ++ii ) {
4167  int other_nodes_index = get_incident_surface_edge(ii)->get_other_ind( parent::get_node_index() );
4168  int edge_index = ( other_nodes_index == get_incident_surface_edge(ii)->get_surface_node(0)->get_node_index() ? 0 : 1 );
4169  // "search" through the map to make sure this edge is in the map (if not found, find returns map.end() which is what I check for)
4170  if ( fc_neighbor_map.find( std::pair<int,int>( parent::get_node_index(), other_nodes_index) ) != fc_neighbor_map.end() ) {
4171 
4172  alt_state_hASA_vector.push_back( get_incident_surface_edge(ii)->get_surface_node( edge_index )->get_alt_hASA() );
4173  }
4174  }
4175 
4176  for ( int ii = 1; ii <= parent::get_num_edges_to_background_nodes(); ++ii ) {
4177  int other_nodes_index = get_edge_to_surface_bg_node(ii)->get_other_ind( this );
4178  // "search" through the map to make sure this edge is in the map (if not found, find returns map.end() which is what I check for)
4179  if ( bg_neighbor_map.find( std::pair<int,int>( parent::get_node_index(), other_nodes_index) ) != bg_neighbor_map.end() ) {
4180 
4181  alt_state_hASA_vector.push_back( get_edge_to_surface_bg_node(ii)->get_surface_bg_node()->get_alt_hASA() );
4182  }
4183  }
4184 
4185  return alt_state_hASA_vector;
4186 }
4187 
4188 
4189 /// @begin SurfaceNode::get_alt_hASA
4190 ///
4191 /// @brief
4192 /// Returns current hASA. Only used by the unit tests. Should not exist in release mode.
4193 ///
4194 template< typename V, typename E, typename G >
4195 Real SurfaceNode<V, E, G>::get_alt_hASA() { return alt_state_total_hASA_; }
4196 
4197 /// @begin SurfaceBackgroundNode::get_alt_hASA
4198 ///
4199 /// @brief
4200 /// Returns current hASA. Only used by the unit tests. Should not exist in release mode.
4201 ///
4202 template< typename V, typename E, typename G >
4203 Real SurfaceBackgroundNode<V, E, G>::get_alt_hASA() { return alt_state_total_hASA_; }
4204 
4205 
4206 ///
4207 /// @begin SurfaceInteractionGraph::get_network_state
4208 ///
4209 /// @brief
4210 /// Returns the state on each FCNode, but not necessarily in pose resid order. Only used by the unit tests.
4211 ///
4212 template< typename V, typename E, typename G >
4214 
4215  std::vector< int > networkstate;
4216  for (int jj = 1; jj <= parent::get_num_nodes(); ++jj) {
4217  networkstate.push_back( get_surface_node(jj)->get_current_state() );
4218  }
4219  return networkstate;
4220 }
4221 
4222 ///
4223 /// @begin SurfaceInteractionGraph::get_hASA_for_node_and_nbs
4224 ///
4225 /// @brief
4226 /// Sets the observed_sufficient_surface_E_to_predict_min_ to true. Only used by the unit tests.
4227 ///
4228 template< typename V, typename E, typename G >
4230  return get_surface_node( index )->get_hASA_for_node_and_nbs();
4231 }
4232 
4233 
4234 ///
4235 /// @begin SurfaceInteractionGraph::get_alt_state_hASA_for_node_and_nbs
4236 ///
4237 /// @brief
4238 /// Sets the observed_sufficient_surface_E_to_predict_min_ to true. Only used by the unit tests.
4239 ///
4240 template< typename V, typename E, typename G >
4242  return get_surface_node( index )->get_alt_state_hASA_for_node_and_nbs();
4243 }
4244 
4245 
4246 ///
4247 /// @begin SurfaceInteractionGraph::set_observed_sufficient_boolean_true
4248 ///
4249 /// @brief
4250 /// Sets the observed_sufficient_surface_E_to_predict_min_ to true. Only used by the unit tests.
4251 ///
4252 template< typename V, typename E, typename G >
4254  for (int jj = 1; jj <= parent::get_num_nodes(); ++jj) {
4255  get_surface_node(jj)->set_observed_sufficient_boolean_true();
4256  }
4257 }
4258 
4259 
4260 }
4261 }
4262 } //end all namespaces
4263 
4264 
4265 #endif