Rosetta 3.5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
Conformation.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 /// @brief conformation container
11 /// @file core/conformation/Conformation.hh
12 /// @author Phil Bradley
13 
14 
15 #ifndef INCLUDED_core_conformation_Conformation_hh
16 #define INCLUDED_core_conformation_Conformation_hh
17 
18 
19 // Unit headers
22 
23 #ifdef WIN32
29 #endif
30 
31 // Project headers
33 #include <core/types.hh>
34 
35 #include <core/id/AtomID.hh>
36 // AUTO-REMOVED #include <core/id/NamedAtomID.hh>
37 #include <core/id/AtomID_Map.hh>
38 // AUTO-REMOVED #include <core/id/AtomID_Mask.hh>
39 #include <core/id/DOF_ID.hh>
40 // AUTO-REMOVED #include <core/id/TorsionID.hh>
41 // AUTO-REMOVED #include <core/kinematics/FoldTree.hh>
42 // AUTO-REMOVED #include <core/kinematics/AtomTree.hh>
43 #include <core/kinematics/Jump.hh>
44 // AUTO-REMOVED #include <core/kinematics/DomainMap.hh>
45 
46 // Utility headers
47 // AUTO-REMOVED #include <utility/vector1.hh>
48 #include <utility/pointer/access_ptr.hh>
49 #include <utility/pointer/owning_ptr.hh>
50 #include <utility/pointer/ReferenceCount.hh>
51 #include <utility/signals/BufferedSignalHub.hh>
52 #include <utility/signals/Link.hh>
53 #include <utility/signals/PausableSignalHub.hh>
54 #include <numeric/xyzVector.hh>
55 
56 // C++ headers
57 // AUTO-REMOVED #include <list>
58 
60 #include <core/id/TorsionID.fwd.hh>
61 // AUTO-REMOVED #include <core/kinematics/tree/Atom.hh>
62 #include <utility/vector1.hh>
63 
64 //Auto Headers
74 
75 
76 
77 namespace core {
78 namespace conformation {
79 
80 /// @brief A container of Residues and the kinematics to manage them
82 
83 public: // typedefs
84 
90  typedef id::AtomID AtomID;
91 
92  //typedef id::AtomID_Map AtomID_Map;
93 
95  typedef id::DOF_ID DOF_ID;
98 
104 
105  // Mirroring typedefs in AtomTree.hh to avoid it's #inclusion.
106  // for fragment insertions
107  typedef std::map< id::AtomID, Vector > FragXYZ;
108  typedef std::map< id::StubID, kinematics::RT > FragRT;
109 
110 public:
111 
112  /// APL Removing accessor functions that voilate the data integrity guarantees of this class.
113  /// Conformation forbids non-const access to its residues. Iterate from 1 to total_residue and
114  /// request a Residue const & instead of iterating from res_begin to res_end.
115  /// @brief HIGHLY HIGHLY ILLEGAL ACCESS GRANTED TO CONFORMATION DATA.
116  /// This function will be removed very very shortly.
117  /// @brief Returns a random-access iterator that points at the first residue in the Conformation.
118  /// ResidueOPs::iterator res_begin() { return residues_.begin(); }
119  /// @brief Returns a random-access iterator that points just beyond the last residue in the Conformation.
120  /// ResidueOPs::iterator res_end () { return residues_.end (); }
121 
122  /////////////////////////////////////////////////////////////////////////////
123 
124  /// @brief constructor
125  /// if you are using PyRosetta, you should NOT BE HERE!
126  Conformation();
127  // utility::pointer::ReferenceCount(),
128  //residue_coordinates_need_updating_( false ),
129  //residue_torsions_need_updating_( false ),
130  //structure_moved_( true )
131  //{}
132 
133  /// @brief default destructor
134  virtual
135  ~Conformation();
136 
137  /// @brief copy constructor
138  Conformation( Conformation const & src );
139 
140  /// @brief operator
141  virtual
142  Conformation &
143  operator=( Conformation const & src );
144 
145  /// @brief clone the conformation
146  virtual
148  clone() const;
149 
150  ///@details determine the type of the ConformationOP
151  virtual
152  bool
153  same_type_as_me( Conformation const & other, bool recurse /* = true */ ) const;
154 
155  /// @brief do the names of all residues in this and src match?
156  bool
157  sequence_matches( Conformation const & other ) const;
158 
159  /// @brief Returns the number of residues in the Conformation
160  Size
161  size() const
162  {
163  return residues_.size();
164  }
165 
166  /// @brief Returns true if this conformation does not have any residues
167  bool
168  empty() const
169  {
170  return residues_.empty();
171  }
172 
173  /// @brief Returns the position number of the last residue in <chain>
174  Size
175  chain_end( Size const chain ) const
176  {
177  if ( chain <= chain_endings_.size() ) return chain_endings_[chain];
178  else return size();
179  }
180 
181  /// @brief Returns the position number of the first residue in <chain>
182  Size
183  chain_begin( Size const chain ) const
184  {
185  if ( chain == 1 ) return 1;
186  else return chain_endings_[ chain-1 ]+1;
187  }
188 
189  /// @brief Returns the number of chains
190  Size
191  num_chains() const
192  {
193  return chain_endings_.size() + 1; // last residue is not counted as chain ending
194  }
195 
196  /// @brief Returns the secondary structure the position <seqpos>
197  /// @return character representing secondary structure; returns 'L' if the
198  /// requested sequence position is larger than the length in the
199  /// secondary structure array
200  char secstruct( Size const seqpos ) const
201  {
202  if ( Size(seqpos) > secstruct_.size() ) return 'L';
203  return secstruct_[seqpos];
204  }
205 
206  /// @brief Sets the secondary structure of the position <seqpos> to <setting>
207  /// @details Sets secondary structure character of a sequence position.
208  /// Will resize the secondary structure array if the requested sequence
209  /// position is larger than the length of the array.
210  virtual void
211  set_secstruct( Size const seqpos, char const setting )
212  {
213  if ( secstruct_.size() < Size(seqpos) ) secstruct_.resize( seqpos, 'L' );
214  secstruct_[seqpos] = setting;
215  }
216 
217  /// @brief Returns the conformation's FoldTree
218  virtual FoldTree const &
219  fold_tree() const
220  {
221  return *fold_tree_;
222  }
223 
224  /// @brief Returns the conformation's AtomTree
225  AtomTree const &
226  atom_tree() const
227  {
228  return *atom_tree_;
229  }
230 
231  /// @brief Sets the FoldTree to <fold_tree_in>
232  virtual void
233  fold_tree( FoldTree const & fold_tree_in );
234 
235 
236  /// @brief Returns the list of chain endings
238  chain_endings() const;
239 
240 
241  /// @brief Sets the list of chain endings
242  /// @remarks All positions must be strictly less than the number of
243  /// residues in the Conformation, otherwise the routine will fail fast.
244  /// Note that the last residue position is not counted as a chain end.
245  void
246  chain_endings( utility::vector1< Size > const & endings );
247 
248 
249  /// @brief Marks <seqpos> as the end of a new chain
250  /// @remarks The last residue position is not counted as a chain ending.
251  /// Also increases the chain ID number by 1 for all residues upstream from seqpos.
252  void
253  insert_chain_ending( Size const seqpos );
254 
255  /// @brief Deletes <seqpos> from the list of chain endings
256  /// @remarks The last residue position is not counted as a chain ending.
257  void
258  delete_chain_ending( Size const seqpos );
259 
260 
261  /// @brief Resets chain data so that the Conformation is marked as a single chain
262  void
264 
265 
266  /// @brief Rederive the chains from the termini/polymer status
267  void
269 
270  /////////////////////////////////////////////////////////////////////////////
271 
272  /// @brief Returns the AA enum for position <seqpos>
273  chemical::AA const &
274  aa( Size const seqpos ) const {
275  assert( seqpos >= 1 );
276  assert( seqpos <= size() );
277  return residues_[seqpos]->aa();
278  }
279 
280  /// @brief access one of the residues; this access is inlined, since otherwise it
281  /// shows up in the profiler. This will call non-inlined refold methods if necessary.
282  ///
283  /// @details update coordinates and torsions for this and all other residues before
284  /// allowing read access
285  inline
286  Residue const &
287  residue( Size const seqpos ) const {
288  runtime_assert( seqpos >= 1 );
289  runtime_assert( seqpos <= size() );
292  return *( residues_[ seqpos ] );
293  }
294 
295  /// @brief access one of the residue's types -- avoids coord/torsion update
296  chemical::ResidueType const &
297  residue_type( Size const seqpos ) const
298  {
299  assert( seqpos >=1 );
300  assert( seqpos <= size() );
301  return residues_[seqpos]->type();
302  }
303 
304  ///////////////////////////////////////////////////////////////////////////////////
305  ///////////////////////////////////////////////////////////////////////////////////
306  // insert/append/delete residues
307  ///////////////////////////////////////////////////////////////////////////////////
308  ///////////////////////////////////////////////////////////////////////////////////
309 
310  /// @brief Append a new residue by a jump.
311  virtual
312  void
314  conformation::Residue const & new_rsd,
315  Size const anchor_residue,
316  std::string const& anchor_atom = "", // the atom in the anchor_residue
317  std::string const& root_atom = "", // the atom in the new residue
318  bool const start_new_chain = false
319  );
320 
321 
322  /// @brief Insert a new residue by jump. If new_chain is "true", then seqpos must be the last
323  /// residue of one chain (i.e. residue(seqpos).chain() != residue(seqpos+1).chain() )
324  void
326  Residue const & new_rsd_in,
327  Size const seqpos, // desired seqpos of new_rsd
328  Size anchor_pos, // in the current sequence numbering, ie before insertion of seqpos
329  std::string const& anchor_atom = "",
330  std::string const& root_atom = "",
331  bool new_chain = false // insert this residue as a new chain, displacing all downstream chains
332  );
333 
334  /// @brief Append a new residue by a bond.
335  void
337  conformation::Residue const & new_rsd,
338  bool const build_ideal_geometry = false,
339  int connection_index = 0,
340  Size anchor_residue = 0,
341  int anchor_connection_index = 0,
342  bool const start_new_chain = false,
343  bool const lookup_bond_length = false
344  );
345 
346  /// @brief glues to seqpos and perhaps also seqpos+1
347  void
349  Residue const & new_rsd,
350  Size const seqpos,
351  bool const build_ideal_geometry
352  );
353 
354  /// @brief glues to seqpos and perhaps also seqpos+1, removes termini variants if necessary
355  void
357  Residue const & new_rsd,
358  Size const seqpos,
359  bool const build_ideal_geometry
360  );
361 
362  /// @brief glues to seqpos and perhaps also seqpos-1
363  void
365  Residue const & new_rsd,
366  Size const seqpos,
367  bool const build_ideal_geometry
368  );
369 
370  /// @brief glues to seqpos and perhaps also seqpos-1, removes termini variants if necessary
371  void
373  Residue const & new_rsd,
374  Size const seqpos,
375  bool const build_ideal_geometry
376  );
377 
378  /// @brief replace residue
379  virtual void
381  Size const seqpos,
382  Residue const & new_rsd,
383  bool const orient_backbone
384  );
385 
386  /// @brief funtion to replace a residue based on superposition on
387  /// @brief the specified input atom pairs
388  /// @brief NOTE: at the moment, only superposition on 3 atoms works
389  virtual void
391  Size const seqpos,
392  Residue const & new_rsd,
393  utility::vector1< std::pair< std::string, std::string > > const & atom_pairs
394  );
395 
396  /// @brief Delete polymer residue at the given sequence position
397  void
398  delete_polymer_residue( Size const seqpos );
399 
400  /// @brief Slow method that relies on FoldTree::delete_seqpos, rebuilds atomtree, can handle jumps/root residue
401  void
402  delete_residue_slow( Size const seqpos );
403 
404  /// @brief Slow method that relies on FoldTree::delete_seqpos, rebuilds atomtree, can handle jumps/root residue
405  void
406  delete_residue_range_slow( Size const range_begin, Size const range_end );
407 
408  /// @brief Declare that a chemical bond exists between two residues
409  void
411  Size const seqpos1,
412  std::string const & atom_name1,
413  Size const seqpos2,
414  std::string const & atom_name2
415  );
416 
417 
418  /// @brief Insert one conformation into another. See FoldTree::insert_fold_tree_by_jump
419  virtual
420  void
422  Conformation const & conf, // the conformation to be inserted
423  Size const insert_seqpos, // rsd 1 in conf goes here
424  Size const insert_jumppos, // jump#1 in conf goes here, see insert_fold_tree_by_jump
425  Size const anchor_pos, // in the current sequence numbering, ie before insertion of conf
426  Size const anchor_jump_number = 0, // the desired jump number of the anchoring jump, default=0
427  std::string const & anchor_atom = "", // "" means take default anchor atom
428  std::string const & root_atom = "" // "" means take default root atom
429  );
430 
431  //////////////////////////////////////////////////////////////////////////
432  /// @brief copy a stretch of coordinates/torsions from another Conformation
433  void
434  copy_segment(
435  Size const size,
436  Conformation const & src,
437  Size const begin,
438  Size const src_begin
439  );
440 
441  /// @brief Rebuild the atoms ( like HN(seqpos), OC(seqpos+1) ) that are dependent on the polymer bond between seqpos and seqpos+1
442  void
444 
445  /// @brief Set the transform between two stubs -- only works if there's a jump between the two sets of stubatoms
446  void
448  id::StubID const & stub_id1,
449  id::StubID const & stub_id2,
450  kinematics::RT const & target_rt
451  );
452  //{
453  // set_dof_moved( atom_tree_.set_stub_transform( stub_id1, stub_id2, target_rt ) );
454  //}
455 
456  /// @brief get the transform between two stubs
459  id::StubID const & stub_id1,
460  id::StubID const & stub_id2
461  ) const;
462  //{
463  // return atom_tree_.get_stub_transform( stub_id1, stub_id2 );
464  //}
465 
466 
467  void
468  set_jump_atom_stub_id( id::StubID const& id );
469  //{
470  // atom_tree_.set_jump_atom_stub_id( id );
471  //}
472 
474  stub_from_id( id::StubID const& id ) const;
475  //{
476  // return atom_tree_.stub_from_id( id );
477  //}
478 
479  void
480  rebuild_residue_connection_dependent_atoms( Size const seqpos, Size const connid );
481 
482 
483  /// @brief Inefficient -- constructs copy of residues_
485  const_residues() const;
486 
487  /////////////////////////////////////////////////////////////////////////////
488  // access/modify dofs/xyz's
489 
490  /// @brief Returns the AtomTree degree of freedom (DOF) <id>
491  Real
492  dof( DOF_ID const & id ) const;
493  //{
494  // return atom_tree_.dof( id );
495  //}
496 
497  /// @brief Sets the AtomTree degree of freedom (DOF) <id> to <setting>
498  virtual
499  void
500  set_dof( DOF_ID const & id, Real const setting );
501  //{
502  // set_dof_moved( id );
503  // residue_torsions_need_updating_ = true; // might have been a torsion angle
504  // atom_tree_.set_dof( id, setting );
505  //}
506 
507  /// @brief Returns the torsion angle <id>
508  Real
509  torsion( TorsionID const & id ) const;
510 
511  /// @brief Sets the AtomTree DOF and the torsion in the corresponding Residue
512  virtual
513  void
514  set_torsion( TorsionID const & id, Real const setting );
515 
516  ///
517  void
519 
520  void
521  insert_ideal_geometry_at_residue_connection( Size const pos1, Size const connid1 );
522 
523  /// @brief Sets the torsion angle defined by <atom[1-4]> to <setting>
524  virtual
525  void
527  AtomID const & atom1,
528  AtomID const & atom2,
529  AtomID const & atom3,
530  AtomID const & atom4,
531  Real const setting
532  );
533 
534  /// @brief Sets the bond angle defined by <atom[1-3]> to <setting>
535  virtual
536  void
538  AtomID const & atom1,
539  AtomID const & atom2,
540  AtomID const & atom3,
541  Real const setting
542  );
543 
544  /// @brief Sets the cond length between <atom1> and <atom2> to <setting>
545  virtual
546  void
548  AtomID const & atom1,
549  AtomID const & atom2,
550  Real const setting
551  );
552 
553  ///
554  void
556  id::StubID const & instub_id,
557  FragRT const & outstub_transforms,
558  FragXYZ const & frag_xyz
559  );
560 
561  /// @brief Returns the torsion angle defined by <atom[1-4]>
562  Real
564  AtomID const & atom1,
565  AtomID const & atom2,
566  AtomID const & atom3,
567  AtomID const & atom4
568  ) const;
569  //{
570  // return atom_tree_.torsion_angle( atom1, atom2, atom3, atom4 );
571  //}
572 
573  /// @brief Returns the bond angle defined by <atom[1-3]>
574  Real
575  bond_angle(
576  AtomID const & atom1,
577  AtomID const & atom2,
578  AtomID const & atom3
579  ) const;
580  //{
581  // return atom_tree_.bond_angle( atom1, atom2, atom3 );
582  //}
583 
584  /// @brief Returns the bond length between <atom1> and <atom2>
585  Real
586  bond_length(
587  AtomID const & atom1,
588  AtomID const & atom2
589  ) const;
590  //{
591  // return atom_tree_.bond_length( atom1, atom2 );
592  //}
593 
594 
595  /// @brief Returns the Jump with jump number <jump_number>
596  const Jump &
597  jump( int const jump_number ) const;
598  //{
599  // return atom_tree_.jump( jump_atom_id( jump_number ) );
600  //}
601 
602  /// @brief Sets the jump <jump_number> to <new_jump>
603  virtual
604  void
605  set_jump(
606  int const jump_number,
607  Jump const & new_jump
608  );
609  //{
610  // assert( new_jump.ortho_check() );
611  // AtomID const id( jump_atom_id( jump_number ) );
612  // atom_tree_.set_jump( id, new_jump );
613  // set_dof_moved( id );
614  //}
615 
616  /// @brief Sets a jump and forces immediate calculation of affected XYZ coords
617  virtual
618  void
619  set_jump_now(
620  int const jump_number,
621  Jump const & new_jump
622  );
623  //{
624  // AtomID const id( jump_atom_id( jump_number ) );
625  // assert( new_jump.ortho_check() );
626  // atom_tree_.set_jump_now( id, new_jump );
627  // set_dof_moved( id );
628  //}
629 
630  /// @brief access a jump
631  const Jump &
632  jump( AtomID const & id ) const;
633  //{
634  // return atom_tree_.jump( id );
635  //}
636 
637  /// @brief set a jump
638  virtual
639  void
640  set_jump(
641  AtomID const & id,
642  Jump const & new_jump
643  );
644  //{
645  // assert( new_jump.ortho_check() );
646  // atom_tree_.set_jump( id, new_jump );
647  // set_dof_moved( id );
648  //}
649 
650  /// @brief identify polymeric connections
651  void
653  Size res_id_lower,
654  Size res_id_upper
655  );
656 
657  /// @brief Update the polymer connection status between lower_seqpos and lower_seqpos+1 based on chainID's and termini
658  void
659  update_polymeric_connection( Size const lower_seqpos );
660 
661  void
662  detect_bonds();
663 
664  void
666 
667  /// @brief Detect existing disulfides from the protein structure.
668  /// @note Assumes full atom
669  /// @details looks at SG-SG distance. If the SG-SG are about 2.02 A apart, calls
670  /// it a disulfide bond.
671  virtual
672  void
674 
675  /// @brief Assigns disulfide bonds based on a pre-determined list
676  /// @note works in centroid and full-atom modes
677  void
678  fix_disulfides(utility::vector1< std::pair<Size, Size> > disulf_bonds);
679 
680  // void find_disulfides();
681 
682  /// @brief The upstream and downstream Stubs are the coordinate frames between which this jump is transforming
684  upstream_jump_stub( int const jump_number ) const;
685  //{
686  // return atom_tree_.atom( jump_atom_id( jump_number ) ).get_input_stub();
687  //}
688 
689  /// @brief The upstream and downstream Stubs are the coordinate frames between which this jump is transforming
691  downstream_jump_stub( int const jump_number ) const;
692  //{
693  // return atom_tree_.atom( jump_atom_id( jump_number ) ).get_stub();
694  //}
695 
696  /// @brief access xyz coordinates of an atom
697  PointPosition const &
698  xyz( AtomID const & id ) const;
699  //{
700  // return atom_tree_.xyz( id );
701  //}
702 
703  ///
704  virtual
705  void
706  set_xyz( AtomID const & id, PointPosition const & position );
707 
708  ///
709  virtual
710  void
712 
713  ///
714  virtual
715  void
717 
718  //
719  void
721 
722  void
723  update_actcoord( Size resid );
724 
725  void update_orbital_coords( Residue & rsd) const;
726 
727  void
728  update_orbital_coords( Size resid );
729 
730  /////////////////////////////////////////////////////////////////////////////
731  // ID access and conversions
732 
733  ///
734  DOF_ID
735  dof_id_from_torsion_id( TorsionID const & id ) const;
736 
737  ///
738  id::AtomID
739  jump_atom_id( int const jump_number ) const;
740 
741  ///@brief get four atoms which defined this torsion
742  ///@note Returns TRUE to signal FAILURE
743  bool
745  TorsionID const & tor_id,
746  AtomID & id1,
747  AtomID & id2,
748  AtomID & id3,
749  AtomID & id4
750  ) const;
751 
752 
753  /////////////////////////////////////////////////////////////////////////////
754  // for tracking changes to the structure
755 
756  /// @brief Generate a domain_map from the current dof/xyz moved data
757  void
758  update_domain_map( DomainMap & domain_map ) const;
759 
760  /// @brief has the structure moved since the last call to reset_move_data or reset_structure_moved
761  bool
763  {
764  return structure_moved_;
765  }
766 
767  /// @brief reset the structure_moved_ bool
768  void
770  {
771  structure_moved_ = false;
772  }
773 
774  /// @brief forget all the structure modifications
775  /**
776  called after domain map information is transferred to the Energies class
777  **/
778  void
779  reset_move_data();
780  //{
781  // structure_moved_ = false;
782  // dof_moved_.fill_with( false );
783  // xyz_moved_.fill_with( false );
784  //}
785 
786 
787  /////////////////////////////////////////////////////////////////////////////
788  /// @brief clear data
789  void
790  clear();
791 
792 
793  /////////////
794  /// @brief debugging
795  void
796  debug_residue_torsions( bool verbose = false ) const;
797 
798  /// @brief Show residue connections for debugging purposes.
799  void
800  show_residue_connections() const;
801 
802  /// @brief Show residue connections for debugging purposes.
803  void
804  show_residue_connections(std::ostream &os) const;
805 
806  /// @brief This returns the AtomID of the atom in the other residue to which the "connection_index"-th
807  /// @brief connection of residue seqpos is connected to.
808 
809  AtomID
811  Size const seqpos,
812  int const connection_index
813  ) const;
814 
815 
816  /// @brief get all atoms bonded to another
819  core::id::AtomID atomid,
820  bool virt = false
821  ) const;
822 
823  ///
824  void
826  id::AtomID_Mask missing
827  );
828 
829  bool
830  atom_is_backbone_norefold( Size const pos, Size const atomno ) const;
831 
832  /// @brief returns a mask of residues to be used in scoring
833  virtual utility::vector1<bool>
834  get_residue_mask() const;
835 
836  /// @brief returns a residue-pair weight
837  virtual Real
839 
840 public: // observer management
841 
842 
843  /// @brief attach ConnectionEvent observer function
844  /// @param fn pointer to observer's unary member function with signature void( ConnectionEvent const & )
845  /// @param ptr pointer to observer object
846  /// @return Link that can be used to manage the connection
847  /// @remarks ConnectionEvent observers will only be notified upon a change
848  /// in the state of the connection with the Conformation, e.g. if the
849  /// Conformation is destroyed or if the connection is being transferred.
850  /// SUGGESTION: Try to use the Link objects that are returned when attaching
851  /// observers instead of attaching via this function and watching for
852  /// ConnectionEvents, as it typically makes connection management easier.
853  template< typename MemFn, typename Ptr >
854  inline
855  utility::signals::Link
856  attach_connection_obs( MemFn fn, Ptr ptr ) const {
857  return connection_obs_hub_.connect( fn, ptr );
858  }
859 
860 
861  /// @brief detach ConnectionEvent observer function
862  /// @param fn pointer to observer's unary member function with signature void( ConnectionEvent const & )
863  /// @param ptr pointer to observer object
864  /// @return true if disconnect successful, false if connection does not exist
865  /// @remarks ConnectionEvent observers will only be notified upon a change
866  /// in the state of the connection with the Conformation, e.g. if the
867  /// Conformation is destroyed or if the connection is being transferred.
868  /// SUGGESTION: Try to use the Link objects that are returned when attaching
869  /// observers instead of attaching via this function and watching for
870  /// ConnectionEvents, as it typically makes connection management easier.
871  template< typename MemFn, typename Ptr >
872  inline
873  bool
874  detach_connection_obs( MemFn fn, Ptr ptr ) const {
875  return connection_obs_hub_.disconnect( fn, ptr );
876  }
877 
878 
879  /// @brief attach GeneralEvent observer function
880  /// @param fn pointer to observer's unary member function with signature void( GeneralEvent const & )
881  /// @param ptr pointer to observer object
882  /// @return Link that can be used to manage the connection
883  /// @remarks GeneralEvent observers will be notified whenever any signal
884  /// derived from GeneralEvent occurs.
885  template< typename MemFn, typename Ptr >
886  inline
887  utility::signals::Link
888  attach_general_obs( MemFn fn, Ptr ptr ) const {
889  return general_obs_hub_.connect( fn, ptr );
890  }
891 
892 
893  /// @brief detach GeneralEvent observer function
894  /// @param fn pointer to observer's unary member function with signature void( GeneralEvent const & )
895  /// @param ptr pointer to observer object
896  /// @return true if disconnect successful, false if connection does not exist
897  /// @remarks GeneralEvent observers will be notified whenever any signal
898  /// derived from GeneralEvent occurs.
899  template< typename MemFn, typename Ptr >
900  inline
901  bool
902  detach_general_obs( MemFn fn, Ptr ptr ) const {
903  return general_obs_hub_.disconnect( fn, ptr );
904  }
905 
906 
907  /// @brief attach IdentityEvent observer function
908  /// @param fn pointer to observer's unary member function with signature void( IdentityEvent const & )
909  /// @param ptr pointer to observer object
910  /// @return Link that can be used to manage the connection
911  template< typename MemFn, typename Ptr >
912  inline
913  utility::signals::Link
914  attach_identity_obs( MemFn fn, Ptr ptr ) const {
915  return identity_obs_hub_.connect( fn, ptr );
916  }
917 
918 
919  /// @brief detach IdentityEvent observer function
920  /// @param fn pointer to observer's unary member function with signature void( IdentityEvent const & )
921  /// @param ptr pointer to observer object
922  /// @return true if disconnect successful, false if connection does not exist
923  template< typename MemFn, typename Ptr >
924  inline
925  bool
926  detach_identity_obs( MemFn fn, Ptr ptr ) const {
927  return identity_obs_hub_.disconnect( fn, ptr );
928  }
929 
930 
931  /// @brief attach LengthEvent observer function
932  /// @param fn pointer to observer's unary member function with signature void( LengthEvent const & )
933  /// @param ptr pointer to observer object
934  /// @return Link that can be used to manage the connection
935  template< typename MemFn, typename Ptr >
936  inline
937  utility::signals::Link
938  attach_length_obs( MemFn fn, Ptr ptr ) const {
939  return length_obs_hub_.connect( fn, ptr );
940  }
941 
942 
943  /// @brief detach LengthEvent observer function
944  /// @param fn pointer to observer's unary member function with signature void( LengthEvent const & )
945  /// @param ptr pointer to observer object
946  /// @return true if disconnect successful, false if connection does not exist
947  template< typename MemFn, typename Ptr >
948  inline
949  bool
950  detach_length_obs( MemFn fn, Ptr ptr ) const {
951  return length_obs_hub_.disconnect( fn, ptr );
952  }
953 
954 
955  /// @brief attach XYZEvent observer function
956  /// @param fn pointer to observer's unary member function with signature void( XYZEvent const & )
957  /// @param ptr pointer to observer object
958  /// @return Link that can be used to manage the connection
959  template< typename MemFn, typename Ptr >
960  inline
961  utility::signals::Link
962  attach_xyz_obs( MemFn fn, Ptr ptr ) const {
963  return xyz_obs_hub_.connect( fn, ptr );
964  }
965 
966 
967  /// @brief detach XYZEvent observer function
968  /// @param fn pointer to observer's unary member function with signature void( XYZEvent const & )
969  /// @param ptr pointer to observer object
970  /// @return true if disconnect successful, false if connection does not exist
971  template< typename MemFn, typename Ptr >
972  inline
973  bool
974  detach_xyz_obs( MemFn fn, Ptr ptr ) const {
975  return xyz_obs_hub_.disconnect( fn, ptr );
976  }
977 
978 
979  /// @brief clear all observers
980  /// @remarks ConnectionEvent::DISCONNECT will be sent to all observers
981  void clear_observers();
982 
983 
984  /// @brief fire a ConnectionEvent::TRANSFER to transfer observers from some
985  /// source Conformation
986  /// @param src Take observers from this source Conformation.
987  /// @remarks Only observers that properly honor the TRANSFER event by
988  /// re-attaching themselves to 'this' Conformation will be transferred.
989  void receive_observers_from( Conformation const & src );
990 
991 
992 public: // additional observer behavior
993 
994 
995  /// @brief wait for stdin after sending a GeneralEvent signal
996  void
997  debug_pause( bool const flag ) const;
998 
999 
1000  /// @brief waiting for stdin after sending a GeneralEvent signal?
1001  bool
1002  debug_pause() const;
1003 
1004 
1005 public: // signal management
1006 
1007  ///@brief convenience test for residue_type_set ( based on two middle residue -- to avoid hitting on ligands or pseudos )
1008  ///@brief this is nt a good test --Doug
1009  bool is_residue_typeset( std::string tag ) const;
1010 
1011  ///@brief convenience test for residue_type_set ( based on two middle residue -- to avoid hitting on ligands or pseudos )
1012  ///@brief this is not a good test --Doug
1013  bool is_fullatom() const;
1014 
1015  ///@brief convenience test for residue_type_set ( based on two middle residue -- to avoid hitting on ligands or pseudos )
1016  ///@brief this is not a good test --Doug
1017  bool is_centroid() const;
1018 
1019 
1020  /// @brief block signals from being sent and buffer them to be
1021  /// sent after unblocking
1022  void
1023  buffer_signals();
1024 
1025 
1026  /// @brief block signals from being sent
1027  /// @warning for safety, ConnectionEvent are never blocked
1028  void
1029  block_signals();
1030 
1031 
1032  /// @brief allow signals to be sent
1033  void
1034  unblock_signals();
1035 
1036 
1037  /// @brief are signals being blocked and buffered?
1038  bool
1039  buffering_signals() const;
1040 
1041 
1042  /// @brief are signals being blocked?
1043  bool
1044  blocking_signals() const;
1045 
1046 
1047  /////////////////////////////////////////////////////////////////////////////
1048  /////////////////////////////////////////////////////////////////////////////
1049  // private methods
1050  /////////////////////////////////////////////////////////////////////////////
1051  /////////////////////////////////////////////////////////////////////////////
1052 
1053 private:
1054 
1055 #ifdef USEBOOSTSERIALIZE
1056  friend class boost::serialization::access;
1057 
1058  template<class Archive>
1059  void save(Archive & ar, const unsigned int version) const {
1060  int m = residues_.size();
1061  ar << m;
1062  Residue * tmp;
1063  for( int i = 1; i <= residues_.size(); i++ ) {
1064  tmp = residues_[i].get();
1065  ar << tmp;
1066  }
1067  // second passthrough is to turn off serialized flag inside ResidueType
1068  // This is how we store each new ResType only once, even though there may
1069  // be many residues using it
1070  for( int i = 1; i <= residues_.size(); i++ ) {
1071  residues_[i]->serialized(false);
1072  }
1073  ar << secstruct_;
1074  ar << fold_tree_;
1075  ar << chain_endings_;
1078  ar << dof_moved_;
1079  ar << xyz_moved_;
1080  ar << structure_moved_;
1081  }
1082 
1083  template<class Archive>
1084  void load(Archive & ar, const unsigned int version) {
1085  int idx;
1086  ar >> idx;
1087  Residue * tmpp = NULL;
1088  for( int i = 1; i <= idx; i++ ) {
1089  ar >> tmpp;
1090  ResidueOP tmp( tmpp );
1091  residues_.push_back( tmp );
1092  }
1093  ar >> secstruct_;
1094  ar >> fold_tree_;
1095  ar >> chain_endings_;
1096  setup_atom_tree();
1099  ar >> dof_moved_;
1100  ar >> xyz_moved_;
1101  ar >> structure_moved_;
1102  }
1103  BOOST_SERIALIZATION_SPLIT_MEMBER()
1104 #endif
1105 
1106  /// @brief Returns a residue without triggering coordinate/torsion update
1107  /// Use with care. Useful inside torsion/coordinate setters where we want chemical info
1108  /// about a given residue but don't want to trigger the coordinate/torsion updates that go along
1109  /// with a call to residue(seqpos)
1110  Residue const &
1111  residue_( Size const seqpos ) const
1112  {
1113  assert( seqpos >=1 );
1114  assert( seqpos <= size() );
1115  return *residues_[ seqpos ];
1116  }
1117 
1118  /// @brief remap *_moved arrays, sequence numbering in the residues_ arrays, etc, after insertion or deletion of rsds
1119  void
1121  Size const new_size,
1122  utility::vector1< Size > const & old2new
1123  );
1124 
1125  /// @brief rebuild atoms in residue seqpos dependent on either the lower (-1) or upper(1) polymer residue
1126  void
1127  rebuild_polymer_bond_dependent_atoms( Size const seqpos, int const upper_lower );
1128 
1129  ///
1130  void
1132  Residue const & new_rsd_in,
1133  Size const seqpos, // desired seqpos of new_rsd
1134  bool const join_lower,
1135  bool const join_upper
1136  );
1137 
1138  /// @brief Now a private method
1139  /// public interface: append_residue_by_bond or append_residue_by_jump
1140  ///
1141  void
1143  Residue const & new_rsd_in,
1144  bool const attach_by_jump,
1145  std::string const& root_atom,
1146  id::NamedAtomID anchor_id,
1147  bool const start_new_chain
1148  );
1149 
1150 
1151  ////////////////////////////////////////////////////////////////////////////
1152  /// @brief wrap direct access to the Residues container
1153  void
1155  Size const seqpos,
1156  Residue const & new_rsd
1157  );
1158 
1159  ///
1160  void
1162  Size const seqpos,
1163  Residue const & new_rsd,
1164  bool const use_lower_chain = false,
1165  bool const new_chain = false
1166  );
1167 
1168  ///
1169  void
1170  residues_append( Residue const & new_rsd, bool const start_new_chain );
1171 
1172  ///
1173  void
1174  residues_delete( Size const seqpos );
1175  //////////////////////////////////////////////////////////////////////////////
1176 
1177 
1178 
1179  /// @brief (re-)builds the AtomTree using the FoldTree and the Residues
1180  void
1181  setup_atom_tree();
1182 
1183  /// @brief access a torsion from the atom_tree
1184  Real
1185  atom_tree_torsion( TorsionID const & tor_id ) const;
1186 
1187  ///@brief get four backbone atoms which define this backbone torsion
1188  ///@note Returns TRUE to signal FAILURE
1189  bool
1191  TorsionID const & id,
1192  AtomID & id1,
1193  AtomID & id2,
1194  AtomID & id3,
1195  AtomID & id4
1196  ) const;
1197 
1198 
1199  /////////////////////////////////////////////////////////////////////////////
1200  // setting the moved data
1201 
1202  /// @brief notify of xyz-change
1203  void
1204  set_xyz_moved( AtomID const & id )
1205  {
1206  structure_moved_ = true;
1207  xyz_moved_[ id ] = true;
1209  }
1210 
1211  /// @brief notify of mutiple-xyz-change
1212  void
1214  {
1215  structure_moved_ = true;
1216  for(core::Size i=1; i<=ids.size(); ++i)
1217  xyz_moved_[ ids[i] ] = true;
1219  }
1220 
1221 
1222  /// @brief notify of dof-change
1223  void
1224  set_dof_moved( AtomID const & id )
1225  {
1226  structure_moved_ = true;
1227  dof_moved_[ id ] = true;
1228  // Residues xyz not in sync with internal xyz
1230  }
1231 
1232  /// @brief notify of dof-change
1233  void
1234  set_dof_moved( DOF_ID const & id )
1235  {
1236  structure_moved_ = true;
1237  dof_moved_[ id.atom_id() ] = true;
1238  // Residues xyz not in sync with internal xyz
1240  }
1241 
1242 
1243  /// @brief Will (if necessary) copy the xyz coordinates from the AtomTree to the Residues being managed
1244  /// Always safe to call. Nothing will happen unless coords_need_updating_
1245  /// is true.
1246  void
1248 
1249  /// @brief called by above
1250  void
1251  update_residue_coordinates( Size const seqpos, bool const fire_signal = true ) const;
1252 
1253  ///
1254  void
1256 
1257  ///
1258  void
1260 
1261  /// @brief Will (if necessary) copy the torsion angles (mainchain/chi) from the AtomTree to the Residues being managed
1262  /// Always safe to call. Nothing will happen unless torsions_need_updating_
1263  /// is true.
1264  void
1265  update_residue_torsions() const;
1266 
1267  /// called by above
1268  void
1269  update_residue_torsions( Size const seqpos, bool const fire_signal = true ) const;
1270 
1271  void
1273  Size lr,
1274  Size lr_connid,
1275  Size ur,
1276  Size ur_connid,
1277  Size nbonds
1278  );
1279 
1280  void
1281  in_place_copy(
1282  Conformation const & src
1283  );
1284 
1285  /// @brief The Conformation must transfer lazily accumulated "moved" data from the AtomTree before
1286  /// changing the number of residues.
1287  void
1289 
1290  private: // observer notifications
1291 
1292 
1293  /// @brief notify ConnectionEvent observers
1294  /// @remarks called upon a change in the state of connection between
1295  /// the Conformation and the observer (e.g. destruction of Conformation
1296  /// or transfer of connection)
1297  void
1298  notify_connection_obs( ConnectionEvent const & e ) const;
1299 
1300 
1301  /// @brief notify GeneralEvent observers
1302  /// @remarks should only be called when there are no other suitable event types
1303  /// since specific event notifications will automatically fire a GeneralEvent signal
1304  void
1305  notify_general_obs( GeneralEvent const & e ) const;
1306 
1307 
1308  /// @brief notify IdentityEvent observers
1309  /// @param e the event
1310  /// @param fire_general fire a GeneralEvent afterwards? default true
1311  void
1312  notify_identity_obs( IdentityEvent const & e, bool const fire_general = true ) const;
1313 
1314 
1315  /// @brief notify LengthEvent observers
1316  /// @param e the event
1317  /// @param fire_general fire a GeneralEvent afterwards? default true
1318  void
1319  notify_length_obs( LengthEvent const & e, bool const fire_general = true ) const;
1320 
1321 
1322  /// @brief notify XYZEvent observers
1323  /// @param e the event
1324  /// @param fire_general fire a GeneralEvent afterwards? default true
1325  void
1326  notify_xyz_obs( XYZEvent const & e, bool const fire_general = true ) const;
1327 
1328 private:
1329  /////////////////////////////////////////////////////////////////////////////
1330  /////////////////////////////////////////////////////////////////////////////
1331  // data
1332  /////////////////////////////////////////////////////////////////////////////
1333  /////////////////////////////////////////////////////////////////////////////
1334 
1335 protected:
1336  /// @brief container of Residues
1338 
1339 private:
1340  /// ResidueCOPs const_residues_; // mirrors residues_ allowing const access -- this will be reinstated soon.
1341 
1342  /// @brief chain number for each position
1343  /**
1344  conformation is in charge of making sure that the Residue chain
1345  ID's and the chain_endings_ vector stay in sync.
1346  **/
1348 
1349  /// @brief fold tree for the kinematics
1351  /// @brief atom tree for the kinematics
1353 
1354  /// @brief do we need to update the coordinates in the Residues?
1356 
1357  /// @brief do we need to update the torsion angles in the Residues?
1359 
1360 
1361  /// @brief book-keeping array for energy evaluations
1362  /**
1363  store which DOF's have changed since the last call to reset_move_data
1364  note that we are not currently differentiating dof's from the same atom
1365  **/
1367 
1368 
1369  /// @brief book-keeping array for energy evaluations
1370  /**
1371  store which xyz's have changed since the last call to reset_move_data
1372  **/
1374 
1375 
1376  /// @brief has the structure moved since the last call to reset_move_data?
1377  mutable bool structure_moved_;
1378 
1379  ///
1381 
1382  /// @brief ConnectionEvent observers
1383  /// @remarks Notification only occurs when there is a change in the state
1384  /// of the connection between observers and the Conformation object, e.g.
1385  /// destruction or transfer of the connection.
1386  mutable utility::signals::BufferedSignalHub< void, ConnectionEvent > connection_obs_hub_;
1387 
1388  /// @brief GeneralEvent observers
1389  /// @remarks GeneralEvent observers will be notified whenever any signal
1390  /// derived from GeneralEvent occurs.
1391  mutable utility::signals::PausableSignalHub< void, GeneralEvent > general_obs_hub_;
1392 
1393  /// @brief IdentityEvent observers
1394  mutable utility::signals::BufferedSignalHub< void, IdentityEvent > identity_obs_hub_;
1395 
1396  /// @brief LengthEvent observers
1397  mutable utility::signals::BufferedSignalHub< void, LengthEvent > length_obs_hub_;
1398 
1399  /// @brief LengthEvent observers
1400  mutable utility::signals::BufferedSignalHub< void, XYZEvent > xyz_obs_hub_;
1401 
1402 
1403 };
1404 
1405 std::ostream &operator<< (std::ostream &os, Conformation const &conf);
1406 
1407 } // conformation
1408 } // core
1409 
1410 
1411 
1412 #endif