Rosetta 3.5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
util.cc
Go to the documentation of this file.
1 // -*- mode:c++;tab-width:2;indent-tabs-mode:t;show-trailing-whitespace:t;rm-trailing-spaces:t -*-
2 // vi: set ts=2 noet:
3 //
4 // (c) Copyright Rosetta Commons Member Institutions.
5 // (c) This file is part of the Rosetta software suite and is made available under license.
6 // (c) The Rosetta software is developed by the contributing members of the Rosetta Commons.
7 // (c) For more information, see http://www.rosettacommons.org. Questions about this can be
8 // (c) addressed to University of Washington UW TechTransfer, email: license@u.washington.edu.
9 
10 /// @file core/pose/util.cc
11 /// @brief Pose class utilities
12 /// @author Phil Bradley
13 /// @author Modified by Sergey Lyskov, Rhiju Das, Steven Lewis
14 
15 // Unit headers
16 #include <core/pose/util.hh>
17 
18 // C/C++ headers
19 #include <cmath>
20 #include <iostream>
21 // Utility headers
22 #include <basic/Tracer.hh>
23 #include <basic/datacache/BasicDataCache.hh>
24 #include <basic/datacache/CacheableString.hh>
25 #include <basic/datacache/CacheableStringFloatMap.hh>
26 #include <basic/datacache/CacheableStringMap.hh>
27 #include <basic/options/option.hh>
28 #include <basic/options/keys/in.OptionKeys.gen.hh>
29 // AUTO-REMOVED #include <basic/options/keys/run.OptionKeys.gen.hh>
30 #include <numeric/constants.hh>
31 #include <numeric/xyz.functions.hh>
32 #include <numeric/xyzVector.string.hh>
33 #include <ObjexxFCL/string.functions.hh>
34 #include <utility/io/izstream.hh>
35 #include <utility/exit.hh>
36 #include <utility/string_util.hh>
37 #include <utility/excn/Exceptions.hh>
38 
39 // Project headers
40 // AUTO-REMOVED #include <core/chemical/AtomType.hh>
48 #include <core/id/DOF_ID_Map.hh>
49 // AUTO-REMOVED #include <core/id/DOF_ID_Mask.hh>
50 #include <core/id/Exceptions.hh>
51 #include <core/id/NamedStubID.hh>
52 #include <core/id/NamedAtomID.hh>
53 #include <core/id/TorsionID.hh>
58 #include <core/pose/PDBInfo.hh>
59 #include <core/pose/Pose.hh>
60 #include <core/pose/MiniPose.hh>
64 // AUTO-REMOVED #include <core/scoring/ScoreFunction.hh>
65 #include <core/scoring/Energies.hh>
69 #include <core/sequence/util.hh>
70 
71 #include <utility/vector1.hh>
72 
73 #include <boost/foreach.hpp>
74 #define foreach BOOST_FOREACH
75 
76 //Auto Headers
77 #include <core/pose/util.tmpl.hh>
78 
79 //Boost headers
80 
81 #include <boost/functional/hash.hpp>
82 
83 namespace core {
84 namespace pose {
85 
86 static basic::Tracer TR("core.pose.util");
87 
88 void jumps_from_pose(const core::pose::Pose& pose, Jumps* jumps) {
89  assert(jumps);
90  for (Size i = 1; i <= pose.num_jump(); ++i) {
91  jumps->insert(i);
92  }
93 }
94 
96  assert(pose);
97  for (core::Size i = 1; i <= pose->total_residue(); ++i) {
98  if (pose->residue_type(i).name() == "VRT")
100  }
101 }
102 
103 void swap_transform(Size jump_num, const kinematics::RT& xform, Pose* pose) {
104  assert(pose);
105  assert(jump_num <= pose->num_jump());
106 
107  const kinematics::FoldTree& tree = pose->fold_tree();
108 
109  int upstream = tree.upstream_jump_residue(jump_num);
110  int downstream = tree.downstream_jump_residue(jump_num);
111  const conformation::Residue& upstream_res = pose->residue(upstream);
112  const conformation::Residue& downstream_res = pose->residue(downstream);
113 
114  if (upstream_res.natoms() < 3 || downstream_res.natoms() < 3) {
115  TR.Warning << "Insufficient number of atoms for stub creation on one or more"
116  << " jump residues-- " << upstream << ", " << downstream
117  << std::endl;
118  return;
119  }
120 
121  id::StubID upstream_stub(
122  id::AtomID(0, upstream_res.atom_index("N")),
123  id::AtomID(1, upstream_res.atom_index("CA")),
124  id::AtomID(2, upstream_res.atom_index("C")));
125 
126  id::StubID downstream_stub(
127  id::AtomID(0, downstream_res.atom_index("N")),
128  id::AtomID(1, downstream_res.atom_index("CA")),
129  id::AtomID(2, downstream_res.atom_index("C")));
130 
131  assert(upstream_stub.valid());
132  assert(downstream_stub.valid());
133 
135  upstream_stub,
136  downstream_stub,
137  xform);
138 }
139 
140 bool is_position_conserved_residue(const Pose& pose, core::Size residue) {
141  using basic::datacache::BasicDataCache;
144 
145  assert(residue > 0);
146  assert(residue <= pose.total_residue());
147 
148  const BasicDataCache& cache = pose.data();
150  return false;
151 
153  static_cast<PositionConservedResiduesStore const *>(
155 
156  return store->is_conserved(residue);
157 }
158 
159 void
161  Pose const & src,
162  utility::vector1< Size > const & positions,
163  kinematics::FoldTree const & f,
164  Pose & pose
165 )
166 {
167  Size const nres( f.nres() );
168  assert( nres == positions.size() );
169 
170  pose.clear();
171 
172  // first add all as jumps
173  for ( Size i=1; i<= nres; ++i ) {
174  Size const seqpos( positions[i] );
175  conformation::Residue const & rsd( src.residue( seqpos ) );
176  pose.append_residue_by_jump( rsd, 1 );
177  if ( i>1 ) {
178  // check if this residue should be in a new chain. not a perfect check...
179  conformation::Residue const & prev_rsd( src.residue( positions[i-1] ) );
180  if ( prev_rsd.is_upper_terminus() || rsd.is_lower_terminus() || prev_rsd.chain() != rsd.chain() ) {
181  assert( pose.total_residue() == i );
182  pose.conformation().insert_chain_ending( i-1 );
183  }
184  }
185  }
186 
187  // now set the desired foldtree
188  pose.fold_tree(f);
189 
190 }
191 ////////////////////////////////////////////////////////////////////////////
192 void
194  pose::Pose const & src,
195  int const jump_number,
196  pose::Pose & partner1,
197  pose::Pose & partner2
198 )
199 {
200  Size const nres( src.total_residue() );
201 
202  // split src pose's foldtree
203  kinematics::FoldTree f1,f2;
204  src.fold_tree().partition_by_jump( jump_number, f1, f2 );
205 
206  TR << src.fold_tree() << '\n' << f1 << '\n' << f2 << '\n';
207 
208  // identify residues in the two partners
209  ObjexxFCL::FArray1D_bool partner1_pos( nres, false ); // FARRAY! DOH!!
210  src.fold_tree().partition_by_jump( jump_number, partner1_pos );
211 
212  utility::vector1< Size > partner1_pos_list, partner2_pos_list;
213  for ( Size i=1; i<= nres; ++i ) {
214  if ( partner1_pos(i) ) partner1_pos_list.push_back( i );
215  else partner2_pos_list.push_back( i );
216  }
217 
218  create_subpose( src, partner1_pos_list, f1, partner1 );
219 
220  create_subpose( src, partner2_pos_list, f2, partner2 );
221 
222  src.dump_pdb( "complex.pdb" );
223  partner1.dump_pdb( "partner1.pdb" );
224  partner2.dump_pdb( "partner2.pdb" );
225 }
226 ////////////////////////////////////////////////////////////////////////////////////////////////////
227 /// @details Crude way to guess secondary structure given a pose. This function
228 /// sets the sec_struct array of pose.conformation_ to the result of the
229 /// guesswork. This has been ported directly from rosetta++.
230 void
232  pose::Pose & pose
233 )
234 {
235  // ss :ss = 1 helix, ss = 2 sheet, ss = 3 other
236  const int sstemp_offset=3;
237  utility::vector1 < int > sstemp( sstemp_offset*2 + pose.total_residue() );
239 
240  sstemp[sstemp_offset-1] = 3; // assign loop to fictious residues at ends of chain
241  sstemp[sstemp_offset+0] = 3;
242  sstemp[sstemp_offset+pose.total_residue()+1] = 3;
243  sstemp[sstemp_offset+pose.total_residue()+2] = 3;
244 
245  for ( Size i = 1; i <= pose.total_residue(); ++i ) {
246 
247  // <murphp>
248  if( !pose.residue_type(i).is_protein() ) { // make sure we don't inquire about the phi/psi of a non-protein residue
249  sstemp[sstemp_offset+i] = 3;
250  }
251  else {
252  // </murphp>
253 
254  if ( pose.phi(i) < -20.0 && pose.psi(i) > -90.0 && pose.psi(i) < -10.0 ) {
255  sstemp[sstemp_offset+i] = 1;
256  } else if ( pose.phi(i) < -20.0 && (pose.psi(i) > 20.0 || pose.psi(i) < -170.0) ) {
257  sstemp[sstemp_offset+i] = 2;
258  } else {
259  sstemp[sstemp_offset+i] = 3;
260  }
261 
262  }
263  }
264 
265  for ( Size i = 1; i <= pose.total_residue(); ++i ) {
266  if ( sstemp[sstemp_offset+i] == 2 ) {
267  if ( sstemp[sstemp_offset+i-1] == 2 && sstemp[sstemp_offset+i+1] == 2 ) {
268  ss[i] = 2;
269  } else if ( sstemp[sstemp_offset+i-1] == 2 && sstemp[sstemp_offset+i-2] == 2 ) {
270  ss[i] = 2;
271  } else if ( sstemp[sstemp_offset+i+1] == 2 && sstemp[sstemp_offset+i+2] == 2 ) {
272  ss[i] = 2;
273  } else {
274  ss[i] = 3;
275  }
276  } else if ( sstemp[sstemp_offset+i] == 1 ) {
277  if ( sstemp[sstemp_offset+i-1] == 1 && sstemp[sstemp_offset+i+1] == 1 ) {
278  ss[i] = 1;
279  } else if ( sstemp[sstemp_offset+i-1] == 1 && sstemp[sstemp_offset+i-2] == 1 ) {
280  ss[i] = 1;
281  } else if ( sstemp[sstemp_offset+i+1] == 1 && sstemp[sstemp_offset+i+2] == 1 ) {
282  ss[i] = 1;
283  } else {
284  ss[i] = 3;
285  }
286  } else {
287  ss[i] = 3;
288  }
289  }
290 
291  for ( Size i = 1; i <= pose.total_residue(); ++i ) {
292  if ( ss[i] == 1 ) {
293  pose.set_secstruct(i,'H');
294  } else if ( ss[i] == 2 ) {
295  pose.set_secstruct(i,'E');
296  } else {
297  pose.set_secstruct(i,'L');
298  }
299  }
300 }
301 
302 /// @details Adds a virtual residue to a pose as the root. Jump is to the
303 /// residue closest to <xyz>. If the pose is already rooted on a VRT res,
304 /// do nothing.
306  int nres = pose.total_residue();
307 
308  // if already rooted on virtual residue, return
309  if ( pose.residue( pose.fold_tree().root() ).aa() == core::chemical::aa_vrt ) {
310  TR.Warning << "addVirtualResAsRoot() called but pose is already rooted on a VRT residue ... continuing." << std::endl;
311  return;
312  }
313 
314  // return if the pose is empty (otherwise will segfault)
315  if (nres == 0) {
316  TR.Warning << "addVirtualResAsRoot() called with empty pose!" << std::endl;
317  return;
318  }
319 
320  // check for terminal ligands
321  int last_peptide_res = nres;
322  while ( !pose.residue( last_peptide_res ).is_polymer() )
323  last_peptide_res--;
324 
325  // try to avoid putting the vrt too close to termini
326  int i_min = 1;
327 
328 #ifdef WIN32
329  int r_start = static_cast< int > ( std::floor( static_cast< double > (last_peptide_res) /3. ) );
330  int r_end = static_cast< int > ( std::ceil ( 2.* static_cast< double > (last_peptide_res)/3. ) );
331 #else
332  int r_start = static_cast< int > ( std::floor( last_peptide_res/3 ) );
333  int r_end = static_cast< int > ( std::ceil ( 2*last_peptide_res/3 ) );
334 #endif
335 
336  core::Real d_min = 99999, this_d;
337  for ( int i=r_start; i<=r_end; ++i ) {
338  conformation::Residue const & rsd( pose.residue(i) );
339 
340  if (rsd.aa() == core::chemical::aa_vrt) continue;
341  if (!rsd.is_protein() ) continue;
342 
343  conformation::Atom const & atom( rsd.atom("CA") );
344  this_d = (atom.xyz() - xyz).length();
345  if (this_d < d_min) {
346  d_min = this_d;
347  i_min = i;
348  }
349  }
350  bool fullatom = pose.is_fullatom();
351  core::chemical::ResidueTypeSetCAP const &residue_set(
354  );
355  core::chemical::ResidueTypeCOPs const & rsd_type_list( residue_set->name3_map("VRT") );
356  if (rsd_type_list.size() == 0) {
357  utility_exit_with_message("Cannot find residue type VRT" );
358  }
360 
361  // move to <xyz>
362  for ( Size j=1; j<= new_res->natoms(); ++j ) {
363  new_res->atom(j).xyz( new_res->atom(j).xyz()+xyz );
364  }
365 
366  pose.append_residue_by_jump( *new_res , i_min );
367 
368  // update PDBinfo
369  if (pose.pdb_info()) {
370  pose.pdb_info()->chain( pose.total_residue(), 'X' );
371  pose.pdb_info()->number( pose.total_residue(), 1 );
372  pose.pdb_info()->obsolete( false );
373  }
374 
375  // make the virt atom the root
376  kinematics::FoldTree newF( pose.fold_tree() );
377  newF.reorder( nres+1 );
378  TR.Debug << "addVirtualResAsRoot() setting new fold tree to " << newF << std::endl;
379  TR.Debug << " i_min = " << i_min << " d_min = " << d_min << std::endl;
380  pose.fold_tree( newF );
381 }
382 
383 /// @detail Find residue closest to center-of-mass
385  int nres = pose.total_residue();
386  int nAtms=0;
387 
388  numeric::xyzVector< core::Real > massSum(0.0,0.0,0.0);
389 
390  for ( int i=1; i<= nres; ++i ) {
391  conformation::Residue const & rsd( pose.residue(i) );
392  if (rsd.aa() == core::chemical::aa_vrt) continue;
393  for ( Size j=1; j<= rsd.nheavyatoms(); ++j ) {
394  conformation::Atom const & atom( rsd.atom(j) );
395  massSum += atom.xyz();
396  nAtms++;
397  }
398  }
399 
400  massSum /= nAtms;
401  return addVirtualResAsRoot(massSum, pose);
402 }
403 
404 ////////////////////////////////////////////////////////////////////////////////////////////////////
406  core::pose::Pose const & pose,
407  std::string const name,
408  core::Real & value
409 )
410 {
411  using basic::datacache::CacheableStringFloatMap;
412  using basic::datacache::CacheableStringFloatMapCOP;
413 
414  // make sure that the pose has one of these.
416  return false;
417  }
418 
419  CacheableStringFloatMapCOP data
420  = dynamic_cast< CacheableStringFloatMap const * >
422  assert( data.get() != NULL );
423 
424  std::map< std::string, float >::const_iterator it = data->map().find( name );
425  if ( it == data->map().end() ) {
426  return false;
427  }
428  value = it->second;
429  return true;
430 }
431 
432 ////////////////////////////////////////////////////////////////////////////////////////////////////
434  core::pose::Pose & pose,
435  std::string name,
436  core::Real value
437 )
438 {
439  using basic::datacache::CacheableStringFloatMap;
440  using basic::datacache::CacheableStringFloatMapOP;
441 
442  // make sure that the pose has one of these.
444  pose.data().set(
446  new CacheableStringFloatMap()
447  );
448  }
449 
450  CacheableStringFloatMapOP data
451  = dynamic_cast< CacheableStringFloatMap* >
453 
454  runtime_assert( data.get() != NULL );
455  data->map()[name] = value;
456 }
457 
459  core::pose::Pose & pose,
460  std::string const & key,
461  std::string const & val
462 )
463 {
464  using basic::datacache::CacheableStringMap;
465  using basic::datacache::CacheableStringMapOP;
466 
467  // make sure that the pose has a map of strings
469  pose.data().set(
471  new CacheableStringMap()
472  );
473  }
474 
475  CacheableStringMapOP data
476  = dynamic_cast< CacheableStringMap* >
478 
479  runtime_assert( data.get() != NULL );
480  data->map()[key] = val;
481 } // add_comment
482 
484  core::pose::Pose & pose,
485  std::string const & key,
486  std::string const & val
487 )
488 {
489  using basic::datacache::CacheableStringMap;
490  using basic::datacache::CacheableStringMapOP;
491 
492  // make sure that the pose has a map of strings
494  pose.data().set(
496  new CacheableStringMap()
497  );
498  }
499 
500  CacheableStringMapOP data
501  = dynamic_cast< CacheableStringMap* >
503 
504  runtime_assert( data.get() != NULL );
505  data->map()[key] = val;
506 }
507 
509  core::pose::Pose & pose
510 ) {
511 
512  {
513  using basic::datacache::CacheableStringFloatMap;
514  pose.data().set(
516  new CacheableStringFloatMap()
517  );
518  }
519 
520  {
521  using basic::datacache::CacheableStringMap;
522  pose.data().set(
524  new CacheableStringMap()
525  );
526  }
527 
528  {
529  using basic::datacache::CacheableStringMap;
530  pose.data().set(
532  new CacheableStringMap()
533  );
534  }
535 }
536 
538  core::pose::Pose & pose,
539  std::string const & name
540 )
541 {
542  using basic::datacache::CacheableStringFloatMap;
543  using basic::datacache::CacheableStringFloatMapOP;
544 
546  return;
547  }
548 
549  CacheableStringFloatMapOP data
550  = dynamic_cast< CacheableStringFloatMap* >
552  assert( data.get() != NULL );
553 
554  data->map().erase( name );
555 }
556 
558  core::pose::Pose const & pose,
559  std::string const & key,
560  std::string & val
561 ) {
562  using std::map;
563  using std::string;
564  map< string, string > comment_map = get_all_comments( pose );
565 
566  if ( comment_map.find( key ) == comment_map.end() ) {
567  return false;
568  }
569 
570  val = comment_map[ key ];
571  return true;
572 }
573 
575  core::pose::Pose const & pose,
576  std::string const & key,
577  std::string & val
578 ) {
579  using std::map;
580  using std::string;
581  map< string, string > score_line_strings_map = get_all_score_line_strings( pose );
582 
583  if ( score_line_strings_map.find( key ) == score_line_strings_map.end() ) {
584  return false;
585  }
586 
587  val = score_line_strings_map[ key ];
588  return true;
589 }
590 
592  core::pose::Pose & pose,
593  std::string const & key
594 ) {
595  using basic::datacache::CacheableStringMap;
596  using basic::datacache::CacheableStringMapOP;
597 
599  CacheableStringMapOP data
600  = dynamic_cast< CacheableStringMap* >
602  std::map< std::string, std::string >::iterator it;
603  it = data->map().find(key);
604  if ( it != data->map().end() ) {
605  data->map().erase(it);
606  }
607  }
608 }
609 
610 std::map< std::string, std::string >
612  core::pose::Pose const & pose
613 )
614 {
615  using basic::datacache::CacheableStringMap;
616  using basic::datacache::CacheableStringMapCOP;
617 
618  std::map< std::string, std::string > score_line_strings;
620  CacheableStringMapCOP data
621  = dynamic_cast< CacheableStringMap const * >
623  score_line_strings = data->map();
624  runtime_assert( data.get() != NULL );
625  }
626  return score_line_strings;
627 }
628 
629 std::map< std::string, std::string >
631  core::pose::Pose const & pose
632 )
633 {
634  using basic::datacache::CacheableStringMap;
635  using basic::datacache::CacheableStringMapCOP;
636 
637  std::map< std::string, std::string > comments;
639  CacheableStringMapCOP data
640  = dynamic_cast< const CacheableStringMap* >
641  ( pose.data().get_raw_const_ptr( core::pose::datacache::CacheableDataType::STRING_MAP ) );
642  comments = data->map();
643  runtime_assert( data.get() != NULL );
644  }
645  return comments;
646 }
647 
648 ////////////////////////////////////////////////////////////////////////////////////////////////////
650  using namespace basic::options;
651 
652  std::string filename( option[ OptionKeys::in::file::psipred_ss2 ]().name() );
653 
654  utility::vector1< char > secstructs;
655  utility::io::izstream data( filename );
656 
657  if ( !data ) {
658  TR.Warning << "Cannot open psipred_ss2 file " << filename << std::endl;
659  return secstructs;
660  }
661 
662  std::string line;
663  Size count(0);
664  while( getline( data, line ) ) {
665  if( line[0] == '#' || line == "" )
666  continue;
667  std::istringstream line_stream( line );
668  Size pos;
669  char aa, sec;
670  line_stream >> pos >> aa >> sec;
671  count++;
672  if ( sec != 'H' && sec != 'E' && sec != 'C' ) {
673  TR.Warning << "unrecognized secstruct char : " << sec << " at seqpos " << count << std::endl;
674  }
675  if ( sec == 'C' ) {
676  secstructs.push_back( 'L' );
677  } else {
678  secstructs.push_back( sec );
679  }
680  }
681 
682  // chu get number of protein residues
683  Size nres=0;
684  for ( Size i =1 ; i <= pose.total_residue(); ++i ) {
685  if ( pose.residue(i).is_protein() ) nres++;
686  }
687 
688  assert( secstructs.size() == nres);
689  if( secstructs.size() != nres )
690  secstructs.clear();
691 
692  return secstructs;
693 }
694 ////////////////////////////////////////////////////////////////////////////////////////////////////
695 
696 
697 /// @brief get Conformation chain -> PDBInfo chain mapping
698 /// @remarks Any chains whose PDBInfo chain records are marked entirely as
699 /// PDBInfo::empty_record() will be mapped to that character. Note that
700 /// Conformation -> PDBInfo is always unique, but the reverse may not be true.
701 /// @return the mapping if PDBInfo available and chains appear consistent,
702 /// otherwise returns an empty mapping
703 std::map< int, char > conf2pdb_chain( core::pose::Pose const & pose ) {
704  using core::Size;
705  using core::pose::PDBInfo;
706  typedef std::map< int, char > Conf2PDB;
707 
708  Conf2PDB conf2pdb;
709 
710  if ( !pose.pdb_info().get() ) {
711  TR.Warning << "WARNING: conf2pdb_chain(): PDBInfo does not exist, returning empty map" << std::endl;
712  return conf2pdb;
713  }
714 
715  for ( Size i = 1, ie = pose.n_residue(); i <= ie; ++i ) {
716  int const conf = pose.chain( i );
717  char const pdb = pose.pdb_info()->chain( i );
718 
719  Conf2PDB::iterator c2p = conf2pdb.find( conf );
720  if ( c2p != conf2pdb.end() ) { // must check if existing record inconsistent
721  if ( c2p->second != pdb ) {
722 
723  // three cases:
724  // (1) replace an existing empty record
725  // (2) it's an unneeded empty record, so continue
726  // (3) there is an actual problem
727  if ( pdb != PDBInfo::empty_record() && c2p->second == PDBInfo::empty_record() ) {
728  // replace the record
729  c2p->second = pdb;
730  } else if ( pdb == PDBInfo::empty_record() ) {
731  continue; // skip empty record
732  } else {
733  // something is inconsistent
734  TR.Warning << "WARNING: conf2pdb_chain(): chain mapping inconsistent, returning empty map; ";
735  TR.Warning << "existing " << c2p->first << " -> " << c2p->second << " | ";
736  TR.Warning << "new " << conf << " -> " << pdb << std::endl;
737  conf2pdb.clear();
738  return conf2pdb;
739  }
740 
741  }
742  } else { // record doesn't exist yet
743  conf2pdb[ conf ] = pdb;
744  }
745 
746  } // foreach residue
747 
748  assert( conf2pdb.size() == pose.conformation().num_chains() );
749  return conf2pdb;
750 }
751 
752 
753 /// @brief renumber PDBInfo based on Conformation chains; each chain starts from 1
754 /// @param[in,out] pose The Pose to modify.
755 /// @param[in] fix_chains If true, the procedure will attempt to fix any empty record
756 /// characters it finds in the PDBInfo. (default true)
757 /// @param[in] start_from_existing_numbering If true, will attempt to start each
758 /// chain from the existing numbering in the PDBInfo. E.g. if the first residue
759 /// of chain 2 in the Conformation is 27, then the renumbering of the chain in
760 /// PDBInfo will start from 27. (default true)
761 /// @param[in] keep_insertion_codes If true, will maintain insertion codes and
762 /// will not increment the pdb residue numbering for those residues. This means
763 /// new numbering with insertion codes will only reflect properly if the
764 /// old numbering included the base numbering of the insertion code residues,
765 /// i.e. 100 100A 100B and not just 100A 100B (with 100 never appearing).
766 /// (default false)
767 /// @param[in] rotate_chain_ids If true, allows support for more than 26 pdb chains
768 /// by rotating [A,Z] continuously. WARNING: This will break the assumption
769 /// made by the PDBPoseMap that each pdb chain id is unique, so make sure you
770 /// are not using the PDBPoseMap feature downstream in your code path without
771 /// corrections! (default false)
772 /// @remarks If fixing chains and there is only one chain and the PDBInfo exists
773 /// but all records are marked as empty, will renumber and set the PDBInfo chain
774 /// to 'A'.
775 /// @return true if renumbering successful, false otherwise
777  core::pose::Pose & pose,
778  bool fix_chains,
779  bool const start_from_existing_numbering,
780  bool const keep_insertion_codes,
781  bool const rotate_chain_ids
782 )
783 {
784  using core::Size;
785  using core::pose::PDBInfo;
786  typedef std::map< int, char > Conf2PDB;
787 
788  if ( !pose.pdb_info().get() ) {
789  TR.Warning << "WARNING: renumber_pdbinfo_based_on_conf_chains(): no PDBInfo, returning" << std::endl;
790  return false;
791  }
792 
793  Conf2PDB conf2pdb = conf2pdb_chain( pose );
794 
795  if ( fix_chains ) {
796  if ( conf2pdb.empty() ) { // something is wrong with chain consistency
797  TR.Warning << "WARNING: renumber_pdbinfo_based_on_conf_chains(): Request to fix PDBInfo chains, but ";
798  TR.Warning << "chain mapping is inconsistent, so that step will be skipped." << std::endl;
799  fix_chains = false;
800  } else { // Try to fill in any empty record characters.
801 
802  // two different schemes: rotating and fixed length
803  // WARNING: Rotating will break assumption of unique chain ids
804  // inside PDBPoseMap, so make sure you are not using the PDBPoseMap
805  // feature after calling this function without correcting!
806  // First either remove or rotate any existing chains to the end of
807  // the list.
808  std::string letters( "ABCDEFGHIJKLMNOPQRSTUVWXYZ" );
809  for ( Conf2PDB::iterator i = conf2pdb.begin(), ie = conf2pdb.end(); i != ie; ++i ) {
810  if ( i->second != PDBInfo::empty_record() ) {
811  std::string::size_type const j = letters.find( i->second );
812  if ( j != std::string::npos ) {
813  if ( rotate_chain_ids ) { // rotating
814  letters.push_back( letters.at( j ) );
815  }
816  letters.erase( j, 1 );
817  }
818  }
819  }
820 
821  // Now fill in empty records.
822  Size lidx = 0;
823  for ( Conf2PDB::iterator i = conf2pdb.begin(), ie = conf2pdb.end(); i != ie; ++i ) {
824  if ( i->second == PDBInfo::empty_record() ) {
825  if ( rotate_chain_ids ) { // rotating
826  i->second = letters.at( lidx % letters.size() );
827  } else { // fixed length
828  runtime_assert( lidx < letters.size() );
829  i->second = letters.at( lidx );
830  }
831  ++lidx;
832  }
833  }
834 
835  } // if conf2pdb.empty()
836  } // if fix_chains
837 
838  PDBInfo & pdbinfo = *pose.pdb_info();
839 
840  // grab all the chain endings
841  utility::vector1< Size > chain_endings = pose.conformation().chain_endings();
842  chain_endings.push_back( pose.n_residue() ); // add the last res, which is not in the list
843 
844  Size res = 1;
845  for ( utility::vector1< Size >::const_iterator i = chain_endings.begin(), ie = chain_endings.end(); i != ie; ++i ) {
846  Size const chain_end = *i;
847  int pdb_res = 0; // new chain, so reset pdb_res counter
848  char chain;
849  char icode;
850  if ( start_from_existing_numbering && pdbinfo.chain( res ) != PDBInfo::empty_record() ) {
851  pdb_res = pdbinfo.number( res ) - 1;
852  }
853 
854  // find the corresponding pdb chain
855  Conf2PDB::const_iterator c2p = conf2pdb.find( pose.chain( chain_end ) );
856  assert( ( fix_chains && c2p != conf2pdb.end() ) || !fix_chains ); // otherwise something's very wrong
857 
858  for ( ; res <= chain_end; ++res ) {
859  // handle the pdb chain only if necessary
860  chain = pdbinfo.chain( res );
861  if ( pdbinfo.chain( res ) == PDBInfo::empty_record() && fix_chains && c2p != conf2pdb.end() ) {
862  chain = c2p->second;
863  }
864 
865  // If keeping insertion codes, increment pdb_res counter only if
866  // no insertion code or we're at position 1, in case there's an
867  // insertion code at 1.
868  icode = pdbinfo.icode( res );
869  if ( keep_insertion_codes && ( pdbinfo.icode( res ) == ' ' || res == 1 ) ) {
870  ++pdb_res;
871  } else if ( !keep_insertion_codes ) { // always increment and clear insertion code
872  icode = ' ';
873  ++pdb_res;
874  }
875 
876  // The new pdb info for this residue must be setup in one shot.
877  // The way we're redoing the info in this function can cause the
878  // pdb2pose map to become out-of-sync if we attempt to make the
879  // changes by separately calling chain(), icode(), and number().
880  pdbinfo.set_resinfo( res, chain, pdb_res, icode );
881  }
882 
883  } // foreach chain ending
884 
885  // no point updating pdb_info if it's just thrown away
886  pose.pdb_info()->obsolete( false );
887 
888  assert( res == pose.n_residue() + 1 );
889 
890  return true;
891 }
892 
893 /// @brief checks if the pose geometry is ideal
894 /// @param[in] pose The Pose to check.
895 /// @return true if all pose positions have ideal bond lengths and angles
896 /// up to some very small epsilon
898  core::pose::Pose const & pose
899 ) {
900  bool is_ideal=true;
901  for ( core::Size i=1 ; i < pose.total_residue(); i++ ) {//leaving out last residue which always returns non-ideal for some reason
902  if ( !is_ideal_position(i, pose) ) {
903  is_ideal=false;
904  break;
905  }
906  }
907  return is_ideal;
908 }
909 
910 /// @brief checks if the pose geometry is ideal in position seqpos
911 /// @param[in] pose The Pose to check.
912 /// @return true if position seqpos has ideal bond lengths and angles
913 /// up to some very small epsilon
915  core::Size seqpos,
916  core::pose::Pose const & pose
917 )
918 {
920  seqpos, pose.conformation() );
921 }
922 
923 ///@brief this function removes all residues from the pose which are not protein residues. This removal includes, but is not limited to, metals, DNA, RNA, and ligands. It will NOT remove ligands which are canonical residues (for example, if a protein binds an alanine monomer, the monomer will be untouched).
925 {
926  core::Size i(1);
927  while(i <= pose.total_residue()) {
928  if(!pose.residue_type(i).is_protein()) pose.conformation().delete_residue_slow(i);
929  else ++i;
930  }
931 }
932 
933 ///@brief this function removes all residues with both UPPER and LOWER terminus types. This is intended for removing ligands that are canonical residues.
935 {
936  if(pose.total_residue() == 1) { //if we have only one residue, it cannot be removed, and this is going to crash
937  throw utility::excn::EXCN_Msg_Exception("Pose utility remove_ligand_canonical_residues: I have received a pose with only one residue but cannot delete the last residue of the pose.");
938  }
939 
940  core::Size i(1);
941  while(i <= pose.total_residue()) {
944  else ++i;
945  }
946 }
947 
948 
949 ///@details this function compares the 3-d coordinates of two poses. Along the way it is forced to check for certain other (in)equalities to prevent vector overrruns, etc. These include: pose length, ResidueType, and # atoms in residue. Inequalities other than 3-d coordinates result in a warning message (you shouldn't have been comparing those poses!) This is NOT a complete equality operator for a pose, but I think it does a good job with the coordinates. Note that it performs floating-point coordinate comparisons by floor(X*10^n_dec_places) - this may cause failures if your pose is a billion angstroms from 0,0,0. This comparison is preferred to an epsilon comparison std::abs( a.x - b.x ) < epsilon because it can run into situations where a == b and b == c, but a != c (thanks to APL for pointing this out). The last argument, n_dec_places, is the number of decimal places of precision when comparing.
950 bool compare_atom_coordinates(core::pose::Pose const & lhs, core::pose::Pose const & rhs, core::Size const n_dec_places){
951 
952  //number of decimal places of precision - 3 (1000) is equivalent to PDB precision.
953  core::Real const n_dec(pow(static_cast< Real > (10), static_cast< int > (n_dec_places))); //this is a Real to prevent premature rounding
954 
955  //first compare pose sizes; prerequisite to iterating through length
956  core::Size const lhssize(lhs.total_residue()), rhssize(rhs.total_residue());
957 
958  if(lhssize != rhssize) {
959  TR.Warning << "poses of different length in compare_atom_coordinates; doomed to fail!" << std::endl;
960  return false;
961  }
962 
963  //now iterate through residues and make comparisons
964  for( core::Size i(1); i<=lhssize; ++i){
965  //check equality of residue types
966  core::chemical::ResidueType const & lhstype(lhs.residue_type(i)), & rhstype(rhs.residue_type(i));
967  if(lhstype.name() != rhstype.name()) { //string matching is sufficient because ResidueType objects have unique names
968  TR.Warning << "nonmatching ResidueTypes at " << i << " in compare_atom_coordinates" << std::endl;
969  return false;
970  }
971 
972  //get atoms vectors to compare
973  core::conformation::Atoms const & lhsatoms(lhs.residue(i).atoms()), rhsatoms(rhs.residue(i).atoms());
974  core::Size const lhsatmsize(lhsatoms.size()), rhsatmsize(rhsatoms.size());
975  if(lhsatmsize != rhsatmsize) { //check vector length equality
976  TR.Warning << "nonmatching numbers of atoms at residue " << i << " in compare_atom_coordinates" << std::endl;
977  TR.Warning << "How did we even get here? ResidueType comparison should have failed!" << std::endl;
978  return false;
979  }
980 
981  //iterate through atoms vector
982  for( core::Size atm(1); atm <= lhsatmsize; ++atm){
983  if( (std::floor(lhsatoms[atm].xyz().x()*n_dec) != std::floor(rhsatoms[atm].xyz().x()*n_dec))
984  || (std::floor(lhsatoms[atm].xyz().y()*n_dec) != std::floor(rhsatoms[atm].xyz().y()*n_dec))
985  || (std::floor(lhsatoms[atm].xyz().z()*n_dec) != std::floor(rhsatoms[atm].xyz().z()*n_dec)) )
986  return false; //no warning messages, this is the "expected" failure
987  }//iterate through atoms vector
988  }//over all residues
989 
990  return true; //whoo! we made it!
991 }//compare_atom_coordinates
992 
993 
994 bool
996  Pose const & lhs,
997  Pose const & rhs
998 ) {
999  core::io::silent::BinaryProteinSilentStruct lhs_silent_struct(lhs, "" );
1000  std::stringstream lhs_str;
1001  lhs_silent_struct.print_conformation(lhs_str);
1002 
1003  core::io::silent::BinaryProteinSilentStruct rhs_silent_struct(rhs, "" );
1004  std::stringstream rhs_str;
1005  rhs_silent_struct.print_conformation(rhs_str);
1006 
1007  return lhs_str.str() == rhs_str.str();
1008 }
1009 
1010 ///////////////////////////////////////////////
1011 ///////////////////////////////////////////////
1012 /////////////////////////////////////////////////////////////////////////////////////////////////////
1013 ///@brief A very useful function that copies degrees of freedom from one pose to another. res_map defines how to map residue numbers from the large pose to the smaller "scratch" pose.
1014 /// -- rhiju, 2009.
1015 /////////////////////////////////////////////////////////////////////////////////////////////////////
1016 
1017 void
1019  pose::Pose & pose,
1020  MiniPose const & scratch_pose,
1021  core::pose::ResMap const & res_map )
1022 {
1023 
1024  std::map < id::AtomID , id::AtomID > atom_id_map;
1025  setup_atom_id_map( atom_id_map, res_map, pose ); // note that this is *not* careful about atom names, etc.
1026  copy_dofs( pose, scratch_pose, atom_id_map );
1027 
1028 }
1029 
1030 ////////////////////////////////////////////////////////////////////////////////////////////////
1031 void
1032 copy_dofs_match_atom_names( //Parin Sripakdeevong Dec 27, 2011.
1033  pose::Pose & pose,
1034  MiniPose const & chunk_pose,
1035  core::pose::ResMap const & res_map )
1036 {
1037 
1038  std::map < id::AtomID , id::AtomID > atom_id_map;
1039  setup_atom_id_map_match_atom_names( atom_id_map, res_map, pose, chunk_pose ); // note that this is CAREFUL about atom names, etc.
1040  copy_dofs( pose, chunk_pose, atom_id_map );
1041 
1042 }
1043 
1044 ////////////////////////////////////////////////////////////////////////////////////////////////
1045 void
1047  pose::Pose & pose,
1048  Pose const & scratch_pose,
1049  core::pose::ResMap const & res_map )
1050 {
1051  // Need to map atom numbers from big pose to scratch pose -- following assumes that
1052  // variant types are exactly the same.
1053  std::map < id::AtomID , id::AtomID > atom_id_map;
1054  setup_atom_id_map( atom_id_map, res_map, pose ); // note that this is *not* careful about atom names, etc.
1055  copy_dofs( pose, scratch_pose, atom_id_map );
1056 }
1057 
1058 
1059 ////////////////////////////////////////////////////////////////////////////////////////////////
1060 // slower!!!
1061 void
1063  pose::Pose & pose,
1064  Pose const & scratch_pose,
1065  core::pose::ResMap const & res_map,
1066  bool const backbone_only /* = false */,
1067  bool const ignore_virtual /* = true */ )
1068 {
1069  // Need to map atom numbers from big pose to scratch pose --
1070  std::map < id::AtomID , id::AtomID > atom_id_map;
1071  setup_atom_id_map_match_atom_names( atom_id_map, res_map, pose, scratch_pose, backbone_only, ignore_virtual );
1072  copy_dofs( pose, scratch_pose, atom_id_map );
1073 }
1074 
1075 
1076 ////////////////////////////////////////////////////////////////////////////////////////////////
1077 void
1079  pose::Pose & pose,
1080  Pose const & scratch_pose,
1081  std::map < id::AtomID , id::AtomID > const & atom_id_map )
1082 {
1083  copy_dofs( pose, MiniPose( scratch_pose ), atom_id_map );
1084 }
1085 
1086 ////////////////////////////////////////////////////////////////////////////////////////////////
1087 void
1089  pose::Pose & pose,
1090  MiniPose const & scratch_pose,
1091  std::map < id::AtomID , id::AtomID > const & atom_id_map ){
1092 
1093  std::map< id::AtomID, Size > atom_id_domain_map;
1094 
1095  // for ( std::map< id::AtomID, id::AtomID >::const_iterator it = atom_id_map.begin();
1096  // it != atom_id_map.end(); it++ ) {
1097  // atom_id_domain_map[ it->first ] = 0;
1098  // }
1099 
1100  for ( Size i = 1; i <= pose.total_residue(); i++ ){
1101  for ( Size j = 1; j <= pose.residue_type( i ).natoms(); j++ ){
1102  atom_id_domain_map[ id::AtomID( j, i ) ] = 0;
1103  }
1104  }
1105 
1106  copy_dofs( pose, scratch_pose, atom_id_map, atom_id_domain_map );
1107 }
1108 
1109 ////////////////////////////////////////////////////////////////////////////////////////////////
1110 bool
1111 check_domain_map( std::map< id::AtomID, Size > const & atom_id_domain_map,
1112  id::AtomID const & atom_id1,
1113  id::AtomID const & atom_id2 ){
1114 
1115  std::map< id::AtomID, Size >::const_iterator it1 = atom_id_domain_map.find( atom_id1 );
1116  std::map< id::AtomID, Size >::const_iterator it2 = atom_id_domain_map.find( atom_id2 );
1117 
1118  Size domain1( 999 );
1119  Size domain2( 999 );
1120 
1121  if ( it1 != atom_id_domain_map.end() ) domain1 = it1->second;
1122  if ( it2 != atom_id_domain_map.end() ) domain2 = it2->second;
1123 
1124  if ( domain1 == 0) return true; // domain "0" means OK to change.
1125 
1126  if ( domain2 == 0) return true; // domain "0" means OK to change.
1127 
1128  //in different domains is OK. [The only exception is the evil 999 --> code for a totally fixed atom.]
1129  if ( domain1 < 999 && domain2 < 999 && domain1 != domain2 ) return true;
1130 
1131 
1132  return false;
1133 
1134 }
1135 
1136 
1137 ////////////////////////////////////////////////////////////////////////////////////////////////
1138 bool
1139 check_domain_map( std::map< id::AtomID, Size > const & atom_id_domain_map,
1140  utility::vector1< id::AtomID > const & atom_ids1,
1141  utility::vector1< id::AtomID > const & atom_ids2 ){
1142 
1143  for ( Size i = 1; i <= atom_ids1.size(); i++ ) {
1144  for ( Size j = 1; j <= atom_ids2.size(); j++ ) {
1145  if ( !check_domain_map( atom_id_domain_map, atom_ids1[ i ], atom_ids2[ j ] ) ) return false;
1146  }
1147  }
1148  return true;
1149 }
1150 
1151 ////////////////////////////////////////////////////////////////////////////////////////////////
1152 void
1154  pose::Pose & pose,
1155  MiniPose const & scratch_pose,
1156  std::map < id::AtomID , id::AtomID > const & atom_id_map,
1157  std::map< id::AtomID, Size > const & atom_id_domain_map )
1158 {
1159 
1160  using namespace core::id;
1161  using namespace core::kinematics;
1162  using namespace core::pose;
1163 
1164  //Useful ID's.
1165  AtomID current_atom_scratch_atom_id( 1, 1);//( current_atom_scratch_atomno, current_atom_scratch_rsd );
1166  AtomID input_stub_atom1_scratch_atom_id( 1, 1);
1167  AtomID input_stub_atom2_scratch_atom_id( 1, 1);
1168  AtomID input_stub_atom3_scratch_atom_id( 1, 1);
1169 
1170  AtomID stub_atom1_scratch_atom_id( 1, 1);
1171  AtomID stub_atom2_scratch_atom_id( 1, 1);
1172  AtomID stub_atom3_scratch_atom_id( 1, 1);
1173  AtomID reference_scratch_atom_id( 1, 1);
1174  AtomID dummy_atom_id( 1, 1);
1175 
1176  pose::Pose const & reference_pose( pose );
1177 
1178  for ( std::map < id::AtomID , id::AtomID >::const_iterator
1179  it=atom_id_map.begin(), it_end = atom_id_map.end(); it != it_end; ++it ) {
1180 
1181  bool verbose( false );
1182 
1183  Size const i = (it->first).rsd(); //Residue index in big pose.
1184  Size const j = (it->first).atomno(); //Atom-number index in big pose.
1185 
1186  // if ( i == 34 || i == 35 ) {
1187  // verbose = true;
1188  // }
1189 
1190  core::kinematics::tree::AtomCOP current_atom ( & reference_pose.atom_tree().atom_dont_do_update( AtomID(j,i) ) );
1191 
1192  if ( !get_scratch_atom_id( current_atom_scratch_atom_id, atom_id_map, current_atom ) ) {
1193  if ( verbose ){ std::cout << "No current atom id? " << " skipping " << pose.residue( i ).name1() << i << " " << pose.residue( i ).atom_name( j ) << std::endl;}
1194  continue;
1195  }
1196 
1197  //////////////////////////////////
1198  // JUMP
1199  if ( current_atom->is_jump() ) {
1200  //Special case.
1201 
1202  // Root?
1203  if ( !current_atom->parent() ) {
1204  if ( verbose ){ std::cout << "No parent " << " skipping " << pose.residue( i ).name1() << i << " " << pose.residue( i ).atom_name( j ) << std::endl;}
1205  continue;
1206  }
1207 
1208  core::kinematics::tree::AtomCOP input_stub_atom1( current_atom->input_stub_atom1() );
1209  core::kinematics::tree::AtomCOP input_stub_atom2( current_atom->input_stub_atom2() );
1210  core::kinematics::tree::AtomCOP input_stub_atom3( current_atom->input_stub_atom3() );
1211  if ( !get_scratch_atom_id( input_stub_atom1_scratch_atom_id, atom_id_map, input_stub_atom1 ) ) {
1212  if ( verbose ){ std::cout << "No JUMP input_stub_atom1? " << " skipping " << pose.residue( i ).name1() << i << " " << pose.residue( i ).atom_name( j ) << std::endl;}
1213  continue;
1214  }
1215  if ( !get_scratch_atom_id( input_stub_atom2_scratch_atom_id, atom_id_map, input_stub_atom2 ) ) {
1216  if ( verbose ){ std::cout << "No JUMP input_stub_atom2? " << " skipping " << pose.residue( i ).name1() << i << " " << pose.residue( i ).atom_name( j ) << std::endl;}
1217  continue;
1218  }
1219  if ( !get_scratch_atom_id( input_stub_atom3_scratch_atom_id, atom_id_map, input_stub_atom3 ) ) {
1220  if ( verbose ){ std::cout << "No JUMP input_stub_atom3? " << " skipping " << pose.residue( i ).name1() << i << " " << pose.residue( i ).atom_name( j ) << std::endl;}
1221  continue;
1222  }
1223  Stub const input_stub( scratch_pose.xyz( input_stub_atom1_scratch_atom_id ),
1224  scratch_pose.xyz( input_stub_atom2_scratch_atom_id ),
1225  scratch_pose.xyz( input_stub_atom3_scratch_atom_id ) );
1226 
1227  core::kinematics::tree::AtomCOP stub_atom1( current_atom->stub_atom1() );
1228  core::kinematics::tree::AtomCOP stub_atom2( current_atom->stub_atom2() );
1229  core::kinematics::tree::AtomCOP stub_atom3( current_atom->stub_atom3() );
1230  if ( !get_scratch_atom_id( stub_atom1_scratch_atom_id, atom_id_map, stub_atom1 ) ) {
1231  if ( verbose ){ std::cout << "No JUMP stub_atom1? " << " skipping " << pose.residue( i ).name1() << i << " " << pose.residue( i ).atom_name( j ) << std::endl;}
1232  continue;
1233  }
1234  if ( !get_scratch_atom_id( stub_atom2_scratch_atom_id, atom_id_map, stub_atom2 ) ) {
1235  if ( verbose ){ std::cout << "No JUMP stub_atom2? " << " skipping " << pose.residue( i ).name1() << i << " " << pose.residue( i ).atom_name( j ) << std::endl; }
1236  continue;
1237  }
1238  if ( !get_scratch_atom_id( stub_atom3_scratch_atom_id, atom_id_map, stub_atom3 ) ) {
1239  Size const stub3_rsd = stub_atom3->id().rsd();
1240  Size const stub3_atmno = stub_atom3->id().atomno();
1241  if ( verbose ){ std::cout << "No JUMP stub_atom3? " << " skipping " << pose.residue( i ).name1() << i << " " << pose.residue( i ).atom_name( j ) <<
1242  " stub_atom3 " << pose.residue( stub3_rsd ).name() << stub3_rsd << " " << pose.residue( stub3_rsd ).atom_name( stub3_atmno ) <<
1243  std::endl;
1244  }
1245  continue;
1246  }
1247  Stub const stub( scratch_pose.xyz( stub_atom1_scratch_atom_id ),
1248  scratch_pose.xyz( stub_atom2_scratch_atom_id ),
1249  scratch_pose.xyz( stub_atom3_scratch_atom_id ) );
1250 
1251  Jump const jump( input_stub, stub );
1252 
1253  if ( verbose ) {
1254  std::cout << "copy_dofs set jump --> " << pose.residue( i ).name1() << i << " " << pose.residue( i ).atom_name( j ) << " " << jump << std::endl;
1255 
1256  std::cout << "input_stub defined by: " << std::endl;
1257  std::cout << " " << input_stub_atom1->id().rsd() << " " << pose.residue( input_stub_atom1->id().rsd() ).atom_name( input_stub_atom1->id().atomno() ) << std::endl;
1258  std::cout << " " << input_stub_atom2->id().rsd() << " " << pose.residue( input_stub_atom2->id().rsd() ).atom_name( input_stub_atom2->id().atomno() ) << std::endl;
1259  std::cout << " " << input_stub_atom3->id().rsd() << " " << pose.residue( input_stub_atom3->id().rsd() ).atom_name( input_stub_atom3->id().atomno() ) << std::endl;
1260  std::cout << " should match --> " << std::endl;
1261  // std::cout << " " << input_stub_atom1_scratch_atom_id.rsd() << " " << scratch_pose.residue( input_stub_atom1_scratch_atom_id.rsd() ).atom_name( input_stub_atom1_scratch_atom_id.atomno() ) << std::endl;
1262  // std::cout << " " << input_stub_atom2_scratch_atom_id.rsd() << " " << scratch_pose.residue( input_stub_atom2_scratch_atom_id.rsd() ).atom_name( input_stub_atom2_scratch_atom_id.atomno() ) << std::endl;
1263  // std::cout << " " << input_stub_atom3_scratch_atom_id.rsd() << " " << scratch_pose.residue( input_stub_atom3_scratch_atom_id.rsd() ).atom_name( input_stub_atom3_scratch_atom_id.atomno() ) << std::endl;
1264 
1265  std::cout << "stub defined by: " << std::endl;
1266  std::cout << " " << stub_atom1->id().rsd() << " " << pose.residue( stub_atom1->id().rsd() ).atom_name( stub_atom1->id().atomno() ) << std::endl;
1267  std::cout << " " << stub_atom2->id().rsd() << " " << pose.residue( stub_atom2->id().rsd() ).atom_name( stub_atom2->id().atomno() ) << std::endl;
1268  std::cout << " " << stub_atom3->id().rsd() << " " << pose.residue( stub_atom3->id().rsd() ).atom_name( stub_atom3->id().atomno() ) << std::endl;
1269  std::cout << " should match --> " << std::endl;
1270  // std::cout << " " << stub_atom1_scratch_atom_id.rsd() << " " << scratch_pose.residue( stub_atom1_scratch_atom_id.rsd() ).atom_name( stub_atom1_scratch_atom_id.atomno() ) << std::endl;
1271  // std::cout << " " << stub_atom2_scratch_atom_id.rsd() << " " << scratch_pose.residue( stub_atom2_scratch_atom_id.rsd() ).atom_name( stub_atom2_scratch_atom_id.atomno() ) << std::endl;
1272  // std::cout << " " << stub_atom3_scratch_atom_id.rsd() << " " << scratch_pose.residue( stub_atom3_scratch_atom_id.rsd() ).atom_name( stub_atom3_scratch_atom_id.atomno() ) << std::endl;
1273  std::cout << "OLD " << pose.jump( AtomID( j, i ) ) << std::endl;
1274  }
1275 
1276  //////////////////////////////////////////////////////////////
1277  //////////////////////////////////////////////////////////////
1278  // WARNING: NOT COMPLETE YET.
1279  // Need to check atom_id_domain_map to make sure this is jump
1280  // is OK
1281  //////////////////////////////////////////////////////////////
1282  //////////////////////////////////////////////////////////////
1283  pose.set_jump( AtomID( j, i ), jump );
1284 
1285  if ( verbose ) std::cout << "NEW " << pose.jump( AtomID( j, i ) ) << std::endl;
1286 
1287  // pose.dump_pdb( "after_jump_change.pdb" );
1288  continue;
1289  }
1290 
1291  //////////////////////////////////
1292  // D
1293  core::kinematics::tree::AtomCOP input_stub_atom1( current_atom->input_stub_atom1() );
1294  if ( !get_scratch_atom_id( input_stub_atom1_scratch_atom_id, atom_id_map, input_stub_atom1 ) ) {
1295  if ( verbose ) { std::cout << "No D input_stub_atom1? " << " skipping " << pose.residue( i ).name1() << i << " " << pose.residue( i ).atom_name( j ) << std::endl; }
1296  continue;
1297  }
1298 
1299  if ( check_domain_map( atom_id_domain_map, current_atom->id(), input_stub_atom1->id() ) ){
1300 
1301  Real const d = ( scratch_pose.xyz( current_atom_scratch_atom_id ) -
1302  scratch_pose.xyz( input_stub_atom1_scratch_atom_id ) ).length();
1303 
1304  pose.set_dof( DOF_ID( AtomID( j, i), D), d );
1305 
1306  } else {
1307  if ( verbose ) { std::cout << "D not OK to change? " << pose.residue( i ).name1() << i << " " << pose.residue( i ).atom_name( j ) << std::endl; }
1308  }
1309 
1310 
1311  //////////////////////////////////
1312  // THETA
1313 
1314  // Following does not generally work..
1315  // if ( input_stub_atom1->is_jump() && input_stub_atom1->parent() /* root is special case */ ) {
1316  // if ( verbose ) std::cout << "input_stub_atom1 is jump... skipping THETA,PHI --> " << pose.residue( i ).name1() << i << " " << pose.residue( i ).atom_name( j ) << std::endl;
1317  // continue;
1318  // }
1319 
1320  // There's one more case ... if this atom is at a junction between the copied pose and the rest of the structure, that could be bad news.
1321  // happens with o1p, o2p at junctions.
1322  if ( false ){
1323 
1324  bool problem_with_sister( false );
1325  for ( Size n = 0; n < input_stub_atom1->n_children(); n++ ) {
1326  core::kinematics::tree::AtomCOP child_atom( input_stub_atom1->child( n ) );
1327  if (!get_scratch_atom_id( dummy_atom_id, atom_id_map, child_atom ) ) {
1328  if ( verbose ) { std::cout << "No THETA ... Sister atom outside region of interest? " << " skipping " << pose.residue( i ).name1() << i << " " << pose.residue( i ).atom_name( j ) << std::endl; }
1329  problem_with_sister = true;
1330  break;
1331  }
1332  }
1333 
1334  ////////////////////////////////////////////////////////////////////////////////////////////////
1335  if (problem_with_sister) continue;
1336  }
1337 
1338  core::kinematics::tree::AtomCOP input_stub_atom2( current_atom->input_stub_atom2() );
1339  if ( !get_scratch_atom_id( input_stub_atom2_scratch_atom_id, atom_id_map, input_stub_atom2 ) ) {
1340  if ( verbose ) std::cout << "No THETA input_stub_atom2? " << " skipping " << pose.residue( i ).name1() << i << " " << pose.residue( i ).atom_name( j ) << std::endl;
1341  continue;
1342  }
1343 
1344  if ( input_stub_atom2_scratch_atom_id == current_atom_scratch_atom_id /* part of a jump triumvirate*/ ) {
1345  if ( verbose ) { std::cout << "Part of jump triumvirate, No THETA " << " skipping " << pose.residue( i ).name1() << i << " " << pose.residue( i ).atom_name( j ) << std::endl; }
1346  continue;
1347  }
1348 
1349  // To check domain movement, need to compare to grandparent *and* all sisters!
1350  utility::vector1< AtomID > upstream_atom_ids, downstream_atom_ids;
1351  downstream_atom_ids.push_back( current_atom->id() );
1352  upstream_atom_ids.push_back( input_stub_atom2->id() );
1353  for ( Size n = 0; n < input_stub_atom1->n_children(); n++ ) {
1354  if( input_stub_atom1->child( n ) == current_atom ) continue;
1355  upstream_atom_ids.push_back( input_stub_atom1->child( n )->id() );
1356  }
1357 
1358 
1359  //if ( check_domain_map( atom_id_domain_map, current_atom->id(), input_stub_atom2->id() ) ){
1360  if ( check_domain_map( atom_id_domain_map, upstream_atom_ids, downstream_atom_ids ) ){
1361 
1362  Real const theta = angle_radians(
1363  scratch_pose.xyz( current_atom_scratch_atom_id ),
1364  scratch_pose.xyz( input_stub_atom1_scratch_atom_id ),
1365  scratch_pose.xyz( input_stub_atom2_scratch_atom_id ) );
1366 
1367  pose.set_dof( DOF_ID( AtomID( j, i), THETA), numeric::constants::d::pi - theta );
1368 
1369  if ( verbose ) {
1370  AtomID const & granny = input_stub_atom2->id();
1371  std::cout << "Good job, change THETA! " << pose.residue( i ).name1() << i << " " << pose.residue( i ).atom_name( j ) << " " << ( atom_id_domain_map.find( current_atom->id() ) )->second << "; stub_atom2: " << pose.residue( granny.rsd() ).name1() << granny.rsd()<< " " << pose.residue( granny.rsd() ).atom_name( granny.atomno() ) << " " << ( atom_id_domain_map.find( input_stub_atom2->id() ) )->second << std::endl;
1372  }
1373 
1374  } else {
1375  if ( verbose ) { std::cout << "THETA not OK to change? " << pose.residue( i ).name1() << i << " " << pose.residue( i ).atom_name( j ) << ( atom_id_domain_map.find( current_atom->id() ) )->second << std::endl; }
1376  }
1377 
1378  //////////////////////////////////
1379  // PHI
1380  // if ( input_stub_atom2->is_jump() && input_stub_atom2->parent() /* root is special case*/ ) {
1381  // if ( verbose ) std::cout << "input_stub_atom2 is jump... skipping PHI --> " << pose.residue( i ).name1() << i << " " << pose.residue( i ).atom_name( j ) << std::endl;
1382  // continue;
1383  // }
1384  /////////////////////////////////////////////////////////////////
1385 
1386  bool stub3_is_external_sister( false );
1387  bool stub3_is_external_granny( false );
1388 
1389  core::kinematics::tree::AtomCOP input_stub_atom3( current_atom->input_stub_atom3() ); // the real great-grandparent, not some phi_offset garbage.
1390  core::kinematics::tree::AtomCOP reference_atom( current_atom->input_stub_atom3() );
1391  core::kinematics::tree::AtomCOP atom_to_move( current_atom );
1392 
1393  if ( input_stub_atom3 == current_atom ) {
1394  if ( verbose ) { std::cout << "Part of jump triumvirate, No PHI " << " skipping " << pose.residue( i ).name1() << i << " " << pose.residue( i ).atom_name( j ) << std::endl; }
1395  continue;
1396  }
1397 
1398  if ( !get_scratch_atom_id( input_stub_atom3_scratch_atom_id, atom_id_map, input_stub_atom3 ) ||
1399  ( input_stub_atom3_scratch_atom_id == current_atom_scratch_atom_id ) /* part of a jump triumvirate*/
1400  ) {
1401 
1402  // There are still a couple ways to save this atom.
1403  // one way: perhaps its stub3 atom is a "sister" lying outside the region of interest,
1404  // whose PHI still depends on what's happening *inside* the region of interest
1405  // An example is the backbone H after protein chainbreaks -- the new pose thinks its PHI is
1406  // an offset of the C of the previous residue, but it can also be positioned based on
1407  // the location of C of the next residue.
1408 
1409  if ( !input_stub_atom1->is_jump() &&
1410  !input_stub_atom3->is_jump() &&
1411  input_stub_atom3->input_stub_atom3() == input_stub_atom1->input_stub_atom2() &&
1412  get_scratch_atom_id( reference_scratch_atom_id, atom_id_map,
1413  input_stub_atom1->input_stub_atom2() ) ){
1414 
1415  reference_atom = input_stub_atom1->input_stub_atom2();
1416 
1417  stub3_is_external_sister = true;
1418  atom_to_move = input_stub_atom3; // move the current atom by moving the atom from which there's an offset.
1419 
1420  if ( verbose ) { std::cout << "SPECIAL CASE input_stub_atom3 is external sister! " << pose.residue( i ).name1() << i << " " << pose.residue( i ).atom_name( j ) << std::endl; }
1421 
1422  } else { // check for an "aunt" that lives inside the pose
1423 
1424  // Second way. This happened to me for coarse-grained RNA...
1425  for ( Size n = 0; n < input_stub_atom2->n_children(); n++ ) {
1426  reference_atom = input_stub_atom2->child( n );
1427  if( reference_atom == input_stub_atom1 ) continue;
1428  if ( get_scratch_atom_id( reference_scratch_atom_id, atom_id_map, reference_atom ) ){
1429  stub3_is_external_granny = true;
1430  atom_to_move = current_atom;
1431  break;
1432  }
1433  }
1434 
1435  if ( !stub3_is_external_granny ) {
1436  // OK, could not salvage this atom's dihedral.
1437  if ( verbose ) {std::cout << "No PHI input_stub_atom3? " << " skipping " << pose.residue( i ).name1() << i << " " << pose.residue( i ).atom_name( j ) << std::endl; }
1438  continue;
1439  // }
1440  } else {
1441  if ( verbose ) { std::cout << "SPECIAL CASE input_stub_atom3 is external granny! " << pose.residue( i ).name1() << i << " " << pose.residue( i ).atom_name( j ) << std::endl; }
1442  }
1443 
1444  }
1445 
1446  }
1447 
1448  // What are that atoms whose relative positions would be changed by changing PHI?
1449  // Downstream: current atom and sisters.
1450  upstream_atom_ids.clear();
1451  downstream_atom_ids.clear();
1452  for ( Size n = 0; n < input_stub_atom1->n_children(); n++ ) {
1453  if( input_stub_atom1->child( n ) == input_stub_atom3 ) continue;
1454  downstream_atom_ids.push_back( input_stub_atom1->child( n )->id() );
1455  }
1456  if ( stub3_is_external_sister ) downstream_atom_ids.push_back( input_stub_atom3->id() );
1457 
1458  // Upstream: great-grandparent and aunts.
1459  if ( input_stub_atom2->parent() ) upstream_atom_ids.push_back( input_stub_atom2->parent()->id() );
1460  // upstream_atom_ids.push_back( input_stub_atom3->id() ); // this might actually be a sister, but it will move. right?
1461  for ( Size n = 0; n < input_stub_atom2->n_children(); n++ ) {
1462  if( input_stub_atom2->child( n ) == input_stub_atom1 ) continue;
1463  upstream_atom_ids.push_back( input_stub_atom2->child( n )->id() );
1464  }
1465 
1466 
1467  if ( check_domain_map( atom_id_domain_map, upstream_atom_ids, downstream_atom_ids ) ) {
1468 
1469  if ( stub3_is_external_sister || stub3_is_external_granny ) {
1470 
1471  Real const phi = dihedral_radians(
1472  scratch_pose.xyz( current_atom_scratch_atom_id ),
1473  scratch_pose.xyz( input_stub_atom1_scratch_atom_id ),
1474  scratch_pose.xyz( input_stub_atom2_scratch_atom_id ),
1475  scratch_pose.xyz( reference_scratch_atom_id ) );
1476 
1477  Real const reference_phi = dihedral_radians(
1478  reference_pose.xyz( current_atom->id() ),
1479  reference_pose.xyz( input_stub_atom1->id() ),
1480  reference_pose.xyz( input_stub_atom2->id() ),
1481  reference_pose.xyz( reference_atom->id() ) );
1482 
1483  pose.set_dof( DOF_ID( atom_to_move->id(), PHI), phi - reference_phi + reference_pose.dof( DOF_ID( atom_to_move->id(), PHI ) ) );
1484 
1485  if ( verbose ) std::cout << "Good JOB, CHANGED PHI THROUGH OFFSET! " << pose.residue( i ).name1() << i << " " << pose.residue( i ).atom_name( j ) << std::endl;
1486 
1487  } else if ( check_domain_map( atom_id_domain_map, current_atom->id(), input_stub_atom3->id() ) ){
1488 
1489  Real const phi = dihedral_radians(
1490  scratch_pose.xyz( current_atom_scratch_atom_id ),
1491  scratch_pose.xyz( input_stub_atom1_scratch_atom_id ),
1492  scratch_pose.xyz( input_stub_atom2_scratch_atom_id ),
1493  scratch_pose.xyz( input_stub_atom3_scratch_atom_id ) );
1494 
1495  pose.set_dof( DOF_ID( AtomID( j, i ), PHI), phi );
1496 
1497  if ( verbose ) std::cout << "Good JOB, CHANGED PHI! " << pose.residue( i ).name1() << i << " " << pose.residue( i ).atom_name( j ) << std::endl;
1498 
1499  } else {
1500  if ( verbose ) {
1501  AtomID const & great_granny = input_stub_atom3->id();
1502  std::cout << "special case but current and input_stub_atom3 in same domain? "
1503  << pose.residue( i ).name1() << i << " " << pose.residue( i ).atom_name( j )
1504  << " " << ( atom_id_domain_map.find( current_atom->id() ) )->second
1505  << " in map? " << ( atom_id_domain_map.find( current_atom->id() ) != atom_id_domain_map.end() )
1506  << "; stub_atom3: " << pose.residue( great_granny.rsd() ).name1()
1507  << great_granny.rsd()<< " " << pose.residue( great_granny.rsd() ).atom_name( great_granny.atomno() )
1508  << " " << ( atom_id_domain_map.find( great_granny ) )->second
1509  << " in map? " << ( atom_id_domain_map.find( great_granny ) != atom_id_domain_map.end() )
1510  << std::endl;
1511  }
1512  }
1513 
1514  } else {
1515  if ( verbose ) {
1516  std::cout << "PHI not OK to change? " << pose.residue( i ).name1() << i << " " << pose.residue( i ).atom_name( j ) << std::endl;
1517  }
1518  }
1519 
1520  } // loop over AtomIDs
1521 
1522  // pose.dump_pdb( "after_res"+ ObjexxFCL::string_of( i )+".pdb" );
1523 
1524 
1525 }
1526 
1527 ///////////////////////////////////////////////////////////////////
1528 bool
1529 get_scratch_atom_id( id::AtomID & other_scratch_atom_id,
1530  std::map< core::id::AtomID, core::id::AtomID> const & atom_id_map,
1531  core::kinematics::tree::AtomCOP other_atom )
1532 {
1533 
1534  using namespace core::id;
1535 
1536  if ( !other_atom ) return false;
1537 
1538  std::map< AtomID, AtomID >::const_iterator iter( atom_id_map.find( other_atom->id() ) );
1539  if ( iter == atom_id_map.end() ) return false; // atom not present in scratch pose!
1540 
1541  other_scratch_atom_id = iter->second;
1542 
1543  return true;
1544 }
1545 
1546 
1547 ///////////////////////////////////////////////////////////////////
1548 void
1550  std::map < core::id::AtomID , core::id::AtomID > & atom_id_map,
1551  ResMap const & res_map,
1552  core::pose::Pose const & pose )
1553 {
1554  using namespace core::id;
1555 
1556  for ( ResMap::const_iterator
1557  it=res_map.begin(), it_end = res_map.end(); it != it_end; ++it ) {
1558 
1559  Size const i = it->first; //Index in big pose.
1560  Size const i_scratch_pose = it->second; // Index in the little "chunk" or "scratch" pose
1561 
1562  // std::cout << "setting up atom_id map " << i << " " << i_scratch_pose << std::endl;
1563  chemical::ResidueType const & rsd_type( pose.residue_type( i ) );
1564  Size count( 0 );
1565 
1566  /////////////////////////////////////////////////////////////////////////
1567  // Might be better to figure out correspondence based on atom name!
1568  // Current code assumes numbering is similar -- not as robust but fast.
1569  /////////////////////////////////////////////////////////////////////////
1570  for ( Size j = 1; j <= rsd_type.natoms(); j++ ) {
1571  // HEY NEED TO FIX THIS LATER. DO WE NEED TO BE CAREFUL ABOUT VIRT?
1572  // MUCH BETTER TO MAKE VARIANTS MATCH *BEFORE* CALLING COPY_DOFS();
1573  // if ( rsd_type.is_virtual( j ) ) continue;
1574  count++;
1575  atom_id_map[ AtomID( j, i ) ] = AtomID( count, i_scratch_pose );
1576  }
1577 
1578  }
1579 }
1580 
1581 
1582 
1583 ///////////////////////////////////////////////////////////////////
1584 void
1586  std::map < core::id::AtomID , core::id::AtomID > & atom_id_map,
1587  ResMap const & res_map,
1588  core::pose::Pose const & pose,
1589  core::pose::Pose const & reference_pose,
1590  bool const backbone_only /* = false */,
1591  bool const ignore_virtual /* = true */ )
1592 {
1593  using namespace core::id;
1594 
1595  for ( ResMap::const_iterator
1596  it=res_map.begin(), it_end = res_map.end(); it != it_end; ++it ) {
1597 
1598  Size const i1 = it->first; //Index in big pose.
1599  Size const i2 = it->second; // Index in the little "chunk" or "scratch" pose
1600 
1601  chemical::ResidueType const & rsd_type1( pose.residue_type( i1 ) );
1602  chemical::ResidueType const & rsd_type2( reference_pose.residue_type( i2 ) );
1603 
1604  for ( Size j1 = 1; j1 <= rsd_type1.natoms(); j1++ ) {
1605 
1606  // Hey do we need this?
1607  if ( ignore_virtual && rsd_type1.is_virtual( j1 ) ) continue;
1608 
1609  std::string const & atom_name1 = rsd_type1.atom_name( j1 );
1610 
1611  if ( ! rsd_type2.has( atom_name1 ) ) continue;
1612 
1613  // protein backbone atoms -- for homology modeling. Good to copy H, O, CB (just off of the mainchain) since they encode information on phi, psi, omega.
1614  // if ( backbone_only &&
1615  // !( atom_name1 == " N " || atom_name1 == " CA " || atom_name1 == " C " || atom_name1 == " H " || atom_name1 == " O " || atom_name1 == " CB " ) &&
1616  // !( atom_name1 == " P " || atom_name1 == " O1P" || atom_name1 == " O2P" || atom_name1 == " O5*" || atom_name1 == " C5*" || atom_name1 == " C4*" || atom_name1 == " O4*" || atom_name1 == " C3*" || atom_name1 == " O3*" || atom_name1 == " C1*" || atom_name1 == " C2*" || atom_name1 == " O2*" || atom_name1 == "1H5*" || atom_name1 == "2H5*" || atom_name1 == " H4*" || atom_name1 == " H3*" || atom_name1 == "1H2*" || atom_name1 == "2HO*" ) ) continue;
1617 
1618  // Following is generic...
1619  if ( backbone_only &&
1620  !( j1 <= rsd_type1.last_backbone_atom() ) &&
1621  !( j1 > rsd_type1.nheavyatoms() && j1 < rsd_type1.first_sidechain_hydrogen() ) ) continue;
1622 
1623 
1624  Size const j2 = rsd_type2.atom_index( atom_name1 );
1625 
1626  // Hey do we need this?
1627  if ( ignore_virtual && rsd_type2.is_virtual( j2 ) ) continue;
1628 
1629  // this is new (Dec. 2010) -- be careful!
1630  // if ( rsd_type1.is_virtual( j1 ) && ! rsd_type2.is_virtual( j2 ) ) continue;
1631  // if ( ! rsd_type1.is_virtual( j1 ) && rsd_type2.is_virtual( j2 ) ) continue;
1632 
1633  atom_id_map[ AtomID( j1, i1 ) ] = AtomID( j2, i2 );
1634  }
1635 
1636  }
1637 }
1638 
1639 ////////////////////////////////////////////////////////////////////////////////////////////////
1640 
1641 void
1642 setup_atom_id_map_match_atom_names( //June 16, 2011 Parin Sripakdeevong
1643  std::map < core::id::AtomID , core::id::AtomID > & atom_id_map,
1644  ResMap const & res_map,
1645  core::pose::Pose const & pose,
1646  MiniPose const & chunk_pose ){
1647  using namespace core::id;
1648 
1649  for ( ResMap::const_iterator it=res_map.begin(), it_end = res_map.end(); it != it_end; ++it ) {
1650 
1651  Size const full_seq_num = it->first; //Index in full pose.
1652  Size const chunk_seq_num = it->second; // Index in the little "chunk" or "scratch" pose
1653 
1654  chemical::ResidueType const & rsd_type1( pose.residue_type( full_seq_num ) );
1655 
1656  utility::vector1< utility::vector1< std::string > > const & chunk_atom_names_list = chunk_pose.atom_names_list();
1657 
1658  for(Size j1 = 1; j1 <= rsd_type1.natoms(); j1++ ) {
1659  for(Size j2=1; j2<=chunk_atom_names_list[chunk_seq_num].size(); j2++){
1660 
1661  std::string const & atom_name1 = rsd_type1.atom_name( j1 );
1662  std::string const & atom_name2 = chunk_atom_names_list[chunk_seq_num][j2];
1663 
1664  if(atom_name1==atom_name2){ //found matching atom_name!
1665  atom_id_map[ AtomID( j1, full_seq_num ) ] = AtomID( j2, chunk_seq_num );
1666  break;
1667  }
1668  }
1669  }
1670 
1671  }
1672 }
1673 
1674 ////////////////////////////////////////////////////////////////////////////////////////////////
1675 
1678  core::id::AtomID const & atom_id,
1679  Pose const & pose
1680 ) {
1681  conformation::Residue const& rsd( pose.residue( atom_id.rsd() ) );
1682  return core::id::NamedAtomID( rsd.atom_name( atom_id.atomno() ), atom_id.rsd() );
1683 }
1684 
1685 ///@detail returns an AtomID corresponding to your NamedAtomID
1686 /// check for a valid AtomID after this.
1687 /// following conditions return invalid ID :
1688 /// rsd > total_residue
1689 /// atom not present in residue ( e.g., no CB in GLY )
1690 id::AtomID
1692  core::id::NamedAtomID const & named_atom_id,
1693  Pose const & pose,
1694  bool raise_exception /*default true*/
1695 ) {
1696  using namespace core::id;
1697  // work out the stubID
1698  if ( named_atom_id.valid() ) {
1699  if ( named_atom_id.rsd() <= pose.total_residue() ) { //if in range, ... otherwise leave atomno_ on 0 --> valid() == false
1700  chemical::ResidueType const& rt ( pose.residue_type ( named_atom_id.rsd() ) );
1701  if ( rt.has( named_atom_id.atom() ) ) {
1702  return AtomID( rt.atom_index( named_atom_id.atom() ), named_atom_id.rsd() );
1703  } else {
1704  // tr.Error << "Error: can't find atom " << named_atom_id.atom() << " in residue "
1705 // << rt.name() << ", residue has " << rt.nheavyatoms() << " heavy atoms." << std::endl;
1706 // tr.Error << "atom names are: " << std::endl;
1707  //rt.show_all_atom_names( tr.Error );
1708  if ( raise_exception ) throw id::EXCN_AtomNotFound( named_atom_id );
1709  return id::BOGUS_ATOM_ID;
1710  }
1711  } else {
1712 // tr.Error << "Error: can't find residue " << named_atom_id.rsd()
1713 // << " in pose (pose.total_residue() = ) "
1714 // << pose.total_residue() << std::endl;
1715  if ( raise_exception ) throw id::EXCN_AtomNotFound( named_atom_id );
1716  return id::BOGUS_ATOM_ID;
1717  }
1718  } else {
1719  if ( raise_exception ) throw id::EXCN_AtomNotFound( named_atom_id );
1720  return id::BOGUS_ATOM_ID;
1721  }
1722 }
1723 
1724 
1726 stub_id_to_named_stub_id( id::StubID const& stub_id, core::pose::Pose const& pose ) {
1727  using namespace core::id;
1728  if ( stub_id.center().valid() ) {
1729  return NamedStubID(
1730  NamedAtomID( atom_id_to_named_atom_id( stub_id.center() , pose ) ),
1731  NamedAtomID( atom_id_to_named_atom_id( stub_id.atom( 1 ), pose ) ),
1732  NamedAtomID( atom_id_to_named_atom_id( stub_id.atom( 2 ), pose ) ),
1733  NamedAtomID( atom_id_to_named_atom_id( stub_id.atom( 3 ), pose ) )
1734  );
1735  } else {
1736  return NamedStubID( // TODO does this make sense? if input stub is bad, what should be done?
1737  NamedAtomID( atom_id_to_named_atom_id( stub_id.atom( 1 ), pose ) ),
1738  NamedAtomID( atom_id_to_named_atom_id( stub_id.atom( 2 ), pose ) ),
1739  NamedAtomID( atom_id_to_named_atom_id( stub_id.atom( 3 ), pose ) )
1740  );
1741  }
1742 }
1743 
1744 id::StubID
1745 named_stub_id_to_stub_id( id::NamedStubID const& named_stub_id, core::pose::Pose const& pose ) {
1746  using namespace core::id;
1747  if ( named_stub_id.center().valid() ) {
1748  return StubID(
1749  AtomID( named_atom_id_to_atom_id( named_stub_id.center() , pose ) ),
1750  AtomID( named_atom_id_to_atom_id( named_stub_id.atom( 1 ), pose ) ),
1751  AtomID( named_atom_id_to_atom_id( named_stub_id.atom( 2 ), pose ) ),
1752  AtomID( named_atom_id_to_atom_id( named_stub_id.atom( 3 ), pose ) )
1753  );
1754  } else {
1755  return StubID( // TODO does this make sense? if input stub is bad, what should be done?
1756  AtomID( named_atom_id_to_atom_id( named_stub_id.atom( 1 ), pose ) ),
1757  AtomID( named_atom_id_to_atom_id( named_stub_id.atom( 1 ), pose ) ),
1758  AtomID( named_atom_id_to_atom_id( named_stub_id.atom( 2 ), pose ) ),
1759  AtomID( named_atom_id_to_atom_id( named_stub_id.atom( 3 ), pose ) )
1760  );
1761  }
1762 }
1763 
1764 
1765 ///////////////////////////////////////////////////////////////
1767  //using core::pose::datacache::CacheableDataType::JOBDIST_OUTPUT_TAG;
1768 
1769  std::string tag( "empty_tag" );
1771  tag =
1772  static_cast< basic::datacache::CacheableString const & >
1774  }
1775 
1776  return tag;
1777 }
1778 
1779 void tag_into_pose( core::pose::Pose & pose, std::string const & tag ) {
1780  //using core::pose::datacache::CacheableDataType::JOBDIST_OUTPUT_TAG;
1781  using basic::datacache::CacheableString;
1782  pose.data().set( core::pose::datacache::CacheableDataType::JOBDIST_OUTPUT_TAG, new CacheableString(tag) );
1783 }
1784 
1786  core::pose::Pose & pose, core::scoring::ScoreType const & sc_type
1787 ) {
1788  return pose.energies().total_energies()[ sc_type ];
1789 }
1790 
1792  core::pose::Pose & pose, std::string const & sc_type
1793 ) {
1794  return pose.energies().total_energies()[ core::scoring::score_type_from_name( sc_type ) ];
1795 }
1796 
1798  return pose.energies().total_energy();
1799 }
1800 
1801 void
1803 {
1804  core::Size tgtlength = tgtpose.total_residue();
1805  core::Size srclength = srcpose.total_residue();
1806  for( core::Size ires = ir; ires <= std::min( srclength, std::min( tgtlength, jr)) ; ires++){
1807  if (!srcpose.residue_type( ires ).is_protein() || !tgtpose.residue_type( ires ).is_protein()) continue;
1808  tgtpose.set_phi( ires, srcpose.phi(ires) );
1809  tgtpose.set_psi( ires, srcpose.psi(ires) );
1810  tgtpose.set_omega( ires, srcpose.omega(ires) );
1811  }
1812 }
1813 
1814 void
1816  transfer_phi_psi( srcpose, tgtpose, 1, std::min( tgtpose.total_residue(), srcpose.total_residue() ) );
1817 }
1818 
1819 //fpd transfer the RB geometry from one pose to another
1820 void
1822 {
1823  core::kinematics::FoldTree f_tgt=tgtpose.fold_tree(), f_src=srcpose.fold_tree();
1824 
1825  // project fold tree
1826  core::Size srcjmps = srcpose.num_jump();
1827  for( core::Size ijmp = 1; ijmp <= srcjmps ; ijmp++){
1828  core::kinematics::Edge srcedge_i = srcpose.fold_tree().jump_edge(ijmp);
1829  core::Size jjmp = tgtpose.fold_tree().jump_nr( srcedge_i.start(), srcedge_i.stop() );
1830  if (jjmp != 0)
1831  tgtpose.set_jump( jjmp, srcpose.jump(ijmp) );
1832  else
1833  TR.Debug << "In transfer_jumps() unable to map jump: " << srcedge_i.start() << " , " << srcedge_i.stop() << std::endl;
1834  }
1835 }
1836 
1837 
1838 /// helper function for residue replacement/residuetype switching
1839 /// these functions should probably move to pose/util.cc
1840 /// @note Will call new_rsd->fill_missing_atoms if the new residue has atoms
1841 /// that the old one doesn't
1842 void
1844  pose::Pose & pose,
1845  Size const seqpos,
1846  core::chemical::ResidueType const & new_rsd_type
1847  )
1848 {
1849 
1850  core::conformation::Residue const & old_rsd( pose.residue( seqpos ) );
1853  pose.replace_residue( seqpos, *new_rsd, false );
1854 
1855 }
1856 
1857 ///////////////////////////////////////////////////////////////////////////////
1858 /// @brief removes variant from an existing residue
1859 /// @details
1860 /// @note
1863  core::conformation::Residue const & old_rsd,
1864  core::chemical::VariantType const & variant_type,
1865  pose::Pose const & pose
1866  )
1867 {
1868  // the type of the desired variant residue
1869  core::chemical::ResidueTypeSet const & rsd_set( old_rsd.residue_type_set() );
1870  core::chemical::ResidueType const & new_rsd_type( rsd_set.get_residue_type_with_variant_removed( old_rsd.type(), variant_type ) );
1873  if ( old_rsd.nchi() == new_rsd_type.nchi() ) {
1874  for ( Size chino=1; chino <= old_rsd.nchi(); ++chino ) {
1875  new_rsd->set_chi( chino, old_rsd.chi( chino ) );
1876  }
1877  } else {
1878  TR << "The chi angles will not be updated and your dunbrack score for this rotamer will be huge; this function is only meant to add a variant type to a residue of the same type" << std::endl;
1879  }
1880 
1881  return new_rsd;
1882 }
1883 
1884 ///////////////////////////////////////////////////////////////////////////////
1885 /// @brief construct a variant of an existing residue
1886 /// @details
1887 /// @note
1890  conformation::Residue const & old_rsd,
1891  chemical::VariantType const & variant_type,
1892  pose::Pose const & pose
1893  ) {
1894  // the type of the desired variant residue
1895  chemical::ResidueTypeSet const & rsd_set( old_rsd.residue_type_set() );
1896  chemical::ResidueType const & new_rsd_type( rsd_set.get_residue_type_with_variant_added( old_rsd.type(), variant_type ) );
1897  conformation::ResidueOP new_rsd( conformation::ResidueFactory::create_residue( new_rsd_type, old_rsd, pose.conformation() ) );
1899  if ( old_rsd.nchi() == new_rsd_type.nchi() ) {
1900  for ( Size chino=1; chino <= old_rsd.nchi(); ++chino ) {
1901  new_rsd->set_chi( chino, old_rsd.chi( chino ) );
1902  }
1903  } else {
1904  TR << "The chi angles will not be updated and your dunbrack score for this rotamer will be huge; this function is only meant to add a variant type to a residue of the same type" << std::endl;
1905  }
1906 
1907  return new_rsd;
1908 }
1909 
1910 ///////////////////////////////////////////////////////////////////////////////
1911 /// @brief construct a variant of an existing pose residue
1912 /// @details eg make a terminus variant, and replace the orignal in pose.
1913 /// @note this copies any atoms in common between old and new residues, rebuild the others
1914 void
1916  pose::Pose & pose,
1917  chemical::VariantType const & variant_type,
1918  Size const seqpos
1919  )
1920 {
1921  runtime_assert( seqpos != 0 );
1922  conformation::Residue const & old_rsd( pose.residue( seqpos ) );
1923 
1924  // the type of the desired variant residue
1925  chemical::ResidueTypeSet const & rsd_set( old_rsd.residue_type_set() );
1926  chemical::ResidueType const & new_rsd_type( rsd_set.get_residue_type_with_variant_added( old_rsd.type(), variant_type ) );
1927 
1929 
1930 }
1931 
1932 ///////////////////////////////////////////////////////////////////////////////
1933 /// @brief construct a non-variant of an existing pose residue
1934 /// @details eg remove a terminus variant, and replace the orignal in pose.
1935 /// @note this copies any atoms in common between old and new residues, rebuild the others
1936 void
1938  pose::Pose & pose,
1939  chemical::VariantType const & variant_type,
1940  Size const seqpos
1941  )
1942 {
1943  conformation::Residue const & old_rsd( pose.residue( seqpos ) );
1944 
1945  // the type of the desired variant residue
1946  chemical::ResidueTypeSet const & rsd_set( old_rsd.residue_type_set() );
1947  chemical::ResidueType const & new_rsd_type( rsd_set.get_residue_type_with_variant_removed( old_rsd.type(), variant_type ) );
1948 
1950 }
1951 
1952 void
1954  pose::Pose & pose,
1955  Size const seqpos
1956  )
1957 {
1959 }
1960 
1961 void
1963  pose::Pose & pose,
1964  Size const seqpos
1965  )
1966 {
1968 }
1969 
1970 void
1972  pose::Pose & pose,
1973  Size const seqpos
1974  )
1975 {
1977 }
1978 
1979 void
1981  pose::Pose & pose,
1982  Size const seqpos
1983  )
1984 {
1986 }
1987 
1988 ///@brief returns a Distance
1989 core::Real
1990 pose_max_nbr_radius( Pose const & pose )
1991 {
1992  core::Real maxrad( 0.0 );
1993  for ( core::Size ii = 1; ii <= pose.total_residue(); ++ii ) {
1994  if ( pose.residue( ii ).nbr_radius() > maxrad ) maxrad = pose.residue_type(ii).nbr_radius();
1995  }
1996  return maxrad;
1997 }
1998 
1999 ///////////////////////////////////////////////////////////////////////////////
2000 void
2002  pose::Pose const & pose,
2004  )
2005 {
2006  Size const n_res( pose.n_residue() );
2007 
2008  // Set DOF mask size and initialize to an invalid TorsionID
2010 
2011  for ( Size i = 1; i <= n_res; ++i ) {
2012  conformation::Residue const & rsd( pose.residue(i) );
2013 
2014  // first the backbone torsion angles
2015  {
2016  // PHIL note the Residue-based helper functions you need for this
2017  // PHIL also note the pose.conformation() interface
2018  int const n_torsions( rsd.mainchain_atoms().size() );
2019  for ( int j=1; j<= n_torsions; ++j ) {
2020  id::TorsionID const tor_id( i, id::BB, j );
2021  id::DOF_ID const & id( pose.conformation().dof_id_from_torsion_id( tor_id ) );
2022  if ( id.valid() ) {
2023  dof_map[ id ] = tor_id;
2024  }
2025  }
2026  }
2027 
2028  {
2029  // PHIL note the Residue-based helper functions you need for this
2030  // PHIL also note the pose.conformation() interface
2031  int const n_torsions( rsd.nchi() );
2032  for ( int j=1; j<= n_torsions; ++j ) {
2033  id::TorsionID const tor_id( i, id::CHI, j );
2034  id::DOF_ID const & id( pose.conformation().dof_id_from_torsion_id( tor_id ) );
2035  if ( id.valid() ) {
2036  dof_map[ id ] = tor_id;
2037  }
2038  } // j=1,chi-torsions
2039  } // scope
2040 
2041 
2042  } // i=1,n_res
2043 
2044  for ( Size i = 1; i <= pose.num_jump(); ++i ) {
2045  for ( int j=1; j<= 6; ++j ) {
2046  id::TorsionID const tor_id(i,id::JUMP,j);
2047  id::DOF_ID const & id( pose.conformation().dof_id_from_torsion_id( tor_id ) );
2048  dof_map[ id ] =tor_id;
2049  }
2050  } // i=1.num_jump
2051 }
2052 
2053 
2054 ///////////////////////////////////////////////////////////////////////////////
2055 ///
2056 void
2058  kinematics::MoveMap const & mm,
2059  pose::Pose const & pose,
2060  id::DOF_ID_Mask & dof_mask
2061 )
2062 {
2063  Size const n_res( pose.n_residue() );
2064 
2065  // Set DOF mask size and initialize to false
2066  core::pose::initialize_dof_id_map( dof_mask, pose, false );
2067 
2068  // DOF_Type defaults
2069  // could/should do this with a loop over types?
2070  // currently ignoring rb types, set these individually
2071  // of by jump number
2072  dof_mask.set( id::PHI , mm.get( id::PHI ) );
2073  dof_mask.set( id::THETA, mm.get( id::THETA ) );
2074  dof_mask.set( id::D , mm.get( id::D ) );
2075 
2076  // bb & chi
2077  bool const PHI_default( mm.get( id::PHI ) );
2078  //bool const vary_omega( mm.vary_omega() );
2079 
2080  for ( Size i = 1; i <= n_res; ++i ) {
2081  conformation::Residue const & rsd( pose.residue(i));
2082 
2083  // first the backbone torsion angles
2084  //bool const bb_move( mm.get_bb(i) );
2085  //if ( bb_move && !PHI_default ) {
2086  {
2087  // PHIL note the Residue-based helper functions you need for this
2088  // PHIL also note the pose.conformation() interface
2089  int const n_torsions( rsd.mainchain_atoms().size() );
2090  for ( int j=1; j<= n_torsions; ++j ) {
2091  bool const mm_setting( mm.get( id::TorsionID(i,id::BB,j) ) );
2092  if ( mm_setting == PHI_default ) continue;
2093  id::DOF_ID const & id
2095  if ( id.valid() ) {
2096  //if ( rsd.is_protein() ) {
2097  // assert( n_torsions == 3 );
2098  // if ( j == 3 && !vary_omega ) continue; // MAGIC NUMBER
2099  //}
2100  dof_mask[ id ] = mm_setting;
2101  } else {
2102  // probably just a terminal/chainbreak torsion
2103  //std::cout << "WARNING: Unable to find atom_tree atom for this " <<
2104  //" Rosetta torsion angle: " << i << ' ' << j << std::endl;
2105  }
2106  } // j=1,bb-torsions
2107  } // if ( bb_move )
2108 
2109  //bool const chi_move( mm.get_chi(i) );
2110  //if ( chi_move && !PHI_default ) {
2111  {
2112  // PHIL note the Residue-based helper functions you need for this
2113  // PHIL also note the pose.conformation() interface
2114  int const n_torsions( rsd.nchi() );
2115  for ( int j=1; j<= n_torsions; ++j ) {
2116  bool const mm_setting( mm.get( id::TorsionID(i,id::CHI,j) ) );
2117  if ( mm_setting == PHI_default ) continue;
2118  id::DOF_ID const & id
2120  if ( id.valid() ) {
2121  dof_mask[ id ] = mm_setting;
2122  } else {
2123  TR.Warning << "WARNING: Unable to find atom_tree atom for this " <<
2124  " Rosetta chi angle: " << i << ' ' << j << std::endl;
2125  }
2126  } // j=1,chi-torsions
2127  } // if ( chi_move )
2128 
2129 
2130  } // i=1,n_res
2131 
2132  for ( core::Size i=1; i<= pose.num_jump(); ++i ) {
2133  if ( mm.get_jump(i) ) {
2134  for ( int j=1; j<= 6; ++j ) {
2135  id::DOF_ID const & id
2137  dof_mask[ id ] = true;
2138  }
2139  }
2140  } // i=1.num_jump
2141 
2142 
2143  /////////////////////////
2144  // DOF's set individually
2145  for ( kinematics::MoveMap::DOF_ID_Map::const_iterator it=mm.dof_id_begin(), it_end=mm.dof_id_end();
2146  it != it_end; ++it ) {
2147  dof_mask[ it->first ] = it->second;
2148  }
2149 
2150 
2151 } // setup_dof_mask_from_move_map
2152 
2153 bool
2154 has_chain(std::string const & chain, core::pose::Pose const & pose){
2155  assert(chain.size()==1);// chain is one char
2156  char chain_char= chain[0];
2157  return has_chain(chain_char, pose);
2158 }
2159 
2160 bool
2161 has_chain(char const & chain, core::pose::Pose const & pose){
2162  for(core::Size i=1; i <= pose.conformation().num_chains(); i++){
2163  char this_char= get_chain_from_chain_id(i, pose);
2164  if(this_char == chain){
2165  return true;
2166  }
2167  }
2168  return false;
2169 }
2170 
2171 std::set<core::Size>
2172 get_jump_ids_from_chain_ids(std::set<core::Size> const chain_ids, core::pose::Pose const & pose){
2173  std::set<core::Size> jump_ids;
2174  std::set<core::Size>::const_iterator chain_id= chain_ids.begin();
2175  for(; chain_id != chain_ids.end(); ++chain_id){
2176  core::Size jump_id= get_jump_id_from_chain_id(*chain_id, pose);
2177  jump_ids.insert(jump_id);
2178  }
2179  return jump_ids;
2180 }
2181 
2182 core::Size
2184  for(core::Size jump_id=1; jump_id <= pose.num_jump(); jump_id++){
2185  core::Size ligand_residue_id= (core::Size) pose.fold_tree().downstream_jump_residue(jump_id);
2186  core::Size ligand_chain_id= pose.chain(ligand_residue_id);
2187  if(chain_id==ligand_chain_id){
2188  return jump_id;
2189  }
2190  }
2191  utility_exit();
2192  return 0;// this will never happen
2193 }
2194 
2195 core::Size
2197  assert(chain.size()==1);// chain is one char
2198  if( chain.size() > 1) utility_exit_with_message("Multiple chain_ids per chain! Are you using '-treat_residues_in_these_chains_as_separate_chemical_entities', and not using compatible movers?" );
2199  char chain_char= chain[0];
2200  return get_chain_id_from_chain(chain_char, pose);
2201 }
2202 
2203 core::Size
2204 get_chain_id_from_chain(char const & chain, core::pose::Pose const & pose){
2205  utility::vector1<core::Size> chain_ids = get_chain_ids_from_chain(chain, pose);
2206  assert(chain_ids.size() == 1);
2207  return chain_ids[1];
2208 }
2209 
2212  assert(chain.size()==1);// chain is one char
2213  char chain_char= chain[0];
2214  return get_chain_ids_from_chain(chain_char, pose);
2215 
2216 }
2217 
2219 get_chain_ids_from_chain(char const & chain, core::pose::Pose const & pose){
2220  utility::vector1<core::Size> chain_ids;
2221  for(core::Size i=1; i <= pose.conformation().num_chains(); i++){
2222  char this_char= get_chain_from_chain_id(i, pose);
2223  if(this_char == chain){
2224  chain_ids.push_back(i);
2225  }
2226  }
2227  return chain_ids;
2228 }
2229 
2230 core::Size
2232  core::Size chain_id= get_chain_id_from_chain(chain, pose);
2233  return get_jump_id_from_chain_id(chain_id, pose);
2234 }
2235 
2236 core::Size
2237 get_jump_id_from_chain(char const & chain, core::pose::Pose const & pose){
2238  core::Size chain_id= get_chain_id_from_chain(chain, pose);
2239  return get_jump_id_from_chain_id(chain_id, pose);
2240 }
2241 
2243 get_jump_ids_from_chain(char const & chain, core::pose::Pose const & pose){
2245  utility::vector1<core::Size> chain_ids = get_chain_ids_from_chain(chain, pose);
2246  foreach(core::Size chain_id, chain_ids){
2247  jump_ids.push_back( get_jump_id_from_chain_id(chain_id, pose));
2248  }
2249  return jump_ids;
2250 }
2251 
2254  assert(chain.size()==1);// chain is one char
2255  char chain_char= chain[0];
2256  return get_jump_ids_from_chain(chain_char, pose);
2257 }
2258 
2260  core::Size ligand_residue_id= (core::Size) pose.fold_tree().downstream_jump_residue(jump_id);
2261  return pose.chain(ligand_residue_id);
2262 }
2263 
2264 char
2265 get_chain_from_jump_id(core::Size const & jump_id, core::pose::Pose const & pose){
2266  core::Size chain_id= get_chain_id_from_jump_id(jump_id, pose);
2267  return get_chain_from_chain_id(chain_id, pose);
2268 }
2269 
2271 get_chain_residues(core::pose::Pose const & pose, core::Size const chain_id){
2272  core::Size begin= pose.conformation().chain_begin(chain_id);
2273  core::Size const end= pose.conformation().chain_end(chain_id);
2275  for(; begin <= end; ++begin){
2276  residues.push_back( new core::conformation::Residue(pose.residue(begin)) );
2277  }
2278  return residues;
2279 }
2280 
2281 char
2282 get_chain_from_chain_id(core::Size const & chain_id, core::pose::Pose const & pose){
2283  core::Size first_chain_residue= pose.conformation().chain_begin( chain_id );
2284  return pose.pdb_info()->chain(first_chain_residue);
2285 }
2286 
2288  core::Size begin,
2289  core::Size const end,
2290  core::pose::Pose const & pose
2291 ) {
2292  core::Size total_heavy_atoms = 0;
2293  for (; begin <= end; ++begin) {
2294  total_heavy_atoms += pose.residue(begin).nheavyatoms();
2295  }
2296  TR.Debug << "# of heavy atoms: "<< total_heavy_atoms << std::endl;
2297  return total_heavy_atoms;
2298 }
2299 
2301  core::Size begin,
2302  core::Size const end,
2303  core::pose::Pose const & pose
2304 ) {
2305  core::Size total_atoms = 0;
2306  for (; begin <= end; ++begin) {
2307  total_atoms += pose.residue(begin).natoms();
2308  }
2309  TR.Debug << "# of heavy atoms: "<< total_atoms << std::endl;
2310  return total_atoms;
2311 }
2312 
2314  core::Size begin,
2315  core::Size const end,
2316  core::pose::Pose const & pose
2317 ) {
2318  core::Size total_hbond_acceptors = 0;
2319  for (; begin <= end; ++begin) {
2320  total_hbond_acceptors += pose.residue(begin).n_hbond_acceptors();
2321  }
2322  TR.Debug << "# of heavy atoms: "<< total_hbond_acceptors << std::endl;
2323  return total_hbond_acceptors;
2324 }
2325 
2327  core::Size begin,
2328  core::Size const end,
2329  core::pose::Pose const & pose
2330 ) {
2331  core::Size total_hbond_donors = 0;
2332  for (; begin <= end; ++begin) {
2333  total_hbond_donors += pose.residue(begin).n_hbond_donors();
2334  }
2335  TR.Debug << "# of heavy atoms: "<< total_hbond_donors << std::endl;
2336  return total_hbond_donors;
2337 }
2338 
2340  core::Size begin,
2341  core::Size const end,
2342  core::pose::Pose const & pose
2343 ) {
2344  core::Size total_chi_angles = 0;
2345  for (; begin <= end; ++begin) {
2346  total_chi_angles += pose.residue(begin).nchi();
2347  }
2348  return total_chi_angles;
2349 }
2350 
2351 core::Real
2353  core::Size begin,
2354  core::Size const end,
2355  core::pose::Pose const & pose
2356 ){
2357  core::Real mass = 0;
2358  for (; begin <= end; ++begin) {
2359  mass += pose.residue(begin).type().molecular_mass();
2360  }
2361  return mass;
2362 }
2363 
2364 core::Real
2366  core::Size begin,
2367  core::Size const end,
2368  core::pose::Pose const & pose
2369 ){
2370  core::Real mass = 0;
2371  for (; begin <= end; ++begin) {
2372  mass += pose.residue(begin).type().molar_mass();
2373  }
2374  return mass;
2375 }
2376 
2377 
2378 core::Size get_hash_from_chain(char const & chain, core::pose::Pose const & pose)
2379 {
2380  core::Size hash = 0;
2381 
2382  core::Size chain_id = get_chain_id_from_chain(chain,pose);
2383  core::Size chain_begin = pose.conformation().chain_begin(chain_id);
2384  core::Size chain_end = pose.conformation().chain_end(chain_id);
2385  for(core::Size res_num = chain_begin; res_num <= chain_end; ++res_num)
2386  {
2387  core::Size natoms = pose.conformation().residue(res_num).natoms();
2388  for(core::Size atom_num = 1; atom_num <= natoms; ++atom_num)
2389  {
2390  id::AtomID atom_id(atom_num,res_num);
2391  PointPosition current_xyz = pose.conformation().xyz(atom_id);
2392  boost::hash_combine(hash,current_xyz);
2393  }
2394  }
2395 
2396  return hash;
2397 }
2398 
2399 core::Size get_hash_excluding_chain(char const & chain, core::pose::Pose const & pose)
2400 {
2401  core::Size hash = 0;
2402 
2403  core::Size chain_id = get_chain_id_from_chain(chain,pose);
2404 
2405  for(core::Size res_num = 1; res_num <= pose.n_residue(); ++res_num)
2406  {
2407  if((int)chain_id == pose.chain(res_num))
2408  {
2409  continue;
2410  }
2411  core::Size natoms = pose.conformation().residue(res_num).natoms();
2412  for(core::Size atom_num = 1; atom_num <= natoms; ++atom_num)
2413  {
2414  id::AtomID atom_id(atom_num,res_num);
2415  PointPosition current_xyz = pose.conformation().xyz(atom_id);
2416  boost::hash_combine(hash,current_xyz);
2417  }
2418  }
2419 
2420  return hash;
2421 }
2422 
2424 {
2425 
2426  std::stringstream coord_stream;
2427 
2428  core::Size chain_id = get_chain_id_from_chain(chain,pose);
2429 
2430  for(core::Size res_num = 1; res_num <= pose.n_residue(); ++res_num)
2431  {
2432  if((int)chain_id == pose.chain(res_num))
2433  {
2434  continue;
2435  }
2436 
2437  core::Size natoms = pose.conformation().residue(res_num).natoms();
2438  for(core::Size atom_num = 1; atom_num <= natoms; ++atom_num)
2439  {
2440  id::AtomID atom_id(atom_num,res_num);
2441  PointPosition current_xyz = pose.conformation().xyz(atom_id);
2442  coord_stream << numeric::truncate_and_serialize_xyz_vector(current_xyz,5);
2443  }
2444  }
2445  return utility::string_to_sha1(coord_stream.str());
2446 }
2447 
2448 void
2450  Pose & pose
2451 ) {
2452 
2453  // disulfides
2454  using basic::options::option;
2455  using namespace basic::options::OptionKeys;
2456  // Fix disulfides if a file is given
2457  if ( basic::options::option[ basic::options::OptionKeys::in::fix_disulf ].user() ) {
2458  core::io::raw_data::DisulfideFile ds_file( basic::options::option[ basic::options::OptionKeys::in::fix_disulf ]() );
2460  ds_file.disulfides(disulfides, pose);
2461  pose.conformation().fix_disulfides( disulfides );
2462  } else {
2463  if ( option[ in::detect_disulf ].user() ?
2464  option[ in::detect_disulf ]() : // detect_disulf true
2465  pose.is_fullatom() // detect_disulf default but fa pose
2466  ) {
2468  }
2469  }
2470 }
2471 
2473 {
2474  //using core::pose::datacache::CacheableDataType::JOBDIST_OUTPUT_TAG;
2475  using basic::datacache::CacheableString;
2476  using basic::datacache::CacheableStringOP;
2477 
2479  CacheableStringOP data = dynamic_cast< CacheableString* > ( (pose.data().get_raw_ptr( ( core::pose::datacache::CacheableDataType::JOBDIST_OUTPUT_TAG )) ));
2480  if( data.get() == NULL ) return std::string("UnknownTag");
2481  else return data->str();
2482  }
2483 
2484  return std::string("UnknownTag");
2485 }
2486 
2488  core::id::SequenceMapping retval(first.total_residue(), second.total_residue());
2489  core::pose::PDBInfoCOP first_pdbinfo = first.pdb_info();
2490  core::pose::PDBInfoCOP second_pdbinfo = second.pdb_info();
2491 
2492  if ( first_pdbinfo && !first_pdbinfo->obsolete() && second_pdbinfo && !second_pdbinfo->obsolete() ) {
2493  for ( core::Size ii(1); ii<= first.total_residue(); ++ii ) {
2494  // pdb2pose returns 0 for "not found" - 0 is also used for "not found" for SequenceMapping.
2495  retval[ii] = second_pdbinfo->pdb2pose( first_pdbinfo->chain(ii), first_pdbinfo->number(ii), first_pdbinfo->icode(ii) );
2496  }
2497  } else {
2498  TR << "One or both poses do not have usable PDBInfo, using sequence alignment instead." << std::endl;
2500  }
2501 
2502  return retval;
2503 }
2504 
2506 {
2507  core::Size count = 0;
2508  for(core::Size i = 1; i <= pose.total_residue();++i)
2509  {
2510  core::conformation::Residue const & resi(pose.residue(i));
2511  if(resi.aa() <= core::chemical::num_canonical_aas)
2512  {
2513  ++count;
2514  }
2515  }
2516  return count;
2517 }
2518 
2520 {
2521  core::Size count = 0;
2522  for(core::Size i = 1; i <= pose.total_residue();++i)
2523  {
2524  core::conformation::Residue const & resi(pose.residue(i));
2525  if(resi.aa() > core::chemical::num_canonical_aas)
2526  {
2527  ++count;
2528  }
2529  }
2530  return count;
2531 }
2532 
2534 {
2535  core::Size count = 0;
2536  for(core::Size i = 1; i <= pose.total_residue();++i)
2537  {
2538  core::conformation::Residue const & resi(pose.residue(i));
2539  if(resi.aa() <= core::chemical::num_canonical_aas)
2540  {
2541  count += resi.natoms();
2542  }
2543  }
2544  return count;
2545 }
2546 
2548 {
2549  core::Size count = 0;
2550  for(core::Size i = 1; i <= pose.total_residue();++i)
2551  {
2552  core::conformation::Residue const & resi(pose.residue(i));
2553  if(resi.aa() > core::chemical::num_canonical_aas)
2554  {
2555  count += resi.natoms();
2556  }
2557  }
2558  return count;
2559 }
2560 
2562 {
2563  core::Size count = 0;
2564  for(core::Size i = 1; i <= pose.total_residue();++i)
2565  {
2566  core::conformation::Residue const & resi(pose.residue(i));
2567  if(resi.aa() > core::chemical::num_canonical_aas)
2568  {
2569  count += resi.nchi();
2570  }
2571  }
2572  return count;
2573 }
2574 #ifdef USELUA
2575 void lregister_util( lua_State * lstate ) {
2576  luabind::module(lstate, "core")
2577  [
2578  luabind::namespace_("pose")
2579  [
2580  luabind::def("getExtraScore", &getPoseExtraScores, luabind::pure_out_value(_3)),
2581  luabind::def("setExtraScore", &setPoseExtraScores),
2582  luabind::def("get_comment", &get_comment, luabind::pure_out_value(_3)),
2583  luabind::def("add_comment", &add_comment),
2584  luabind::def("getScore", (core::Real (*) (core::pose::Pose &, std::string const & ) ) &energy_from_pose),
2585  luabind::def("getTotalScore", (core::Real (*) (core::pose::Pose & ) ) &total_energy_from_pose)
2586  ]
2587  ];
2588 }
2589 #endif
2590 
2591 } // pose
2592 } // core