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 // This file is part of the Rosetta software suite and is made available under license.
5 // The Rosetta software is developed by the contributing members of the Rosetta Commons consortium.
6 // (C) 199x-2009 Rosetta Commons participating institutions and developers.
7 // For more information, see http://www.rosettacommons.org/.
8 
9 /// @file core/conformation/symmetry/util.hh
10 /// @brief utility functions for handling of symmetric conformations
11 /// @author Ingemar Andre
12 
13 // Unit headers
15 
16 // Package headers
21 //#include <core/scoring/symmetry/SymmetricScoreFunction.hh>
24 
25 //#include <core/pose/Pose.hh>
26 #include <core/kinematics/util.hh>
28 #include <core/chemical/AA.hh>
30 // AUTO-REMOVED #include <core/chemical/VariantType.hh>
31 // AUTO-REMOVED #include <core/kinematics/MoveMap.hh>
32 #include <core/kinematics/Edge.hh>
33 #include <core/id/AtomID.hh>
34 
35 // Basic Headers
36 #include <basic/Tracer.hh>
37 // AUTO-REMOVED #include <basic/options/option.hh>
38 // AUTO-REMOVED #include <basic/options/keys/symmetry.OptionKeys.gen.hh>
39 // AUTO-REMOVED #include <basic/options/keys/fold_and_dock.OptionKeys.gen.hh>
40 
41 // Numeric headers
42 #include <numeric/random/random.hh>
43 #include <numeric/xyzMatrix.hh>
44 #include <numeric/xyzVector.hh>
45 #include <numeric/xyz.functions.hh>
46 // AUTO-REMOVED #include <numeric/xyzTriple.hh>
47 // AUTO-REMOVED #include <numeric/xyzVector.io.hh>
48 
49 // ObjexxFCL Headers
50 #include <ObjexxFCL/FArray1D.hh>
51 #include <ObjexxFCL/FArray2D.hh>
52 #include <ObjexxFCL/format.hh>
53 
54 #include <utility/vector1.hh>
55 
56 
57 
58 namespace core {
59 namespace conformation {
60 namespace symmetry {
61 
62 static basic::Tracer TR("core.conformation.symmetry.util");
63 static numeric::random::RandomGenerator RG(408529); // <- Magic number, do not change it!!!
64 
65 Size fold_tree_entry_point(core::kinematics::FoldTree const & ft, Size lb_resi=0, Size ub_resi=0) {
66  int resi = -1;
67  if(lb_resi==0) lb_resi = 1;
68  if(ub_resi==0) ub_resi = ft.nres();
69  for(int i = 1; i <= (int)ft.num_jump(); ++i) {
70  Size up = ft.upstream_jump_residue(i);
71  Size dn = ft.downstream_jump_residue(i);
72  if( lb_resi <= dn && dn <= ub_resi && ( up < lb_resi || ub_resi < up ) ) resi = dn; // dn in bounds, up out
73  }
74  if( (int)lb_resi <= resi && resi <= (int)ub_resi ) return resi; // if resi good, return it
75  resi = ft.root();
76  if( (int)lb_resi <= resi && resi <= (int)ub_resi ) return resi; // try fold_tree root
77  utility_exit_with_message("can'd get fold_tree root in range!!!");
78  return 0; // this will never happen
79 }
80 
81 // sheffler
82 /// @details get residue index
83 Size process_residue_request(conformation::Conformation const & src_conf, std::string input, Size lb_resi=0, Size ub_resi=0) {
84  int resi = -1;
85  if(lb_resi==0) lb_resi = 1;
86  if(ub_resi==0) ub_resi = src_conf.size();
87  if(input=="FT" || input=="KEEP_FOLDTREE_ANCHOR") resi = fold_tree_entry_point( src_conf.fold_tree(), lb_resi, ub_resi );
88  if(input=="COM" || input=="CENTER_OF_MASS" ) resi = residue_center_of_mass( src_conf, lb_resi, ub_resi );
89  if(input=="FIRST" || input=="FIRST_RESIDUE" ) resi = lb_resi;
90  if(input=="LAST" || input=="LAST_RESIDUE" ) resi = ub_resi;
91  if(input=="") resi = 0;
92  if(resi == -1) resi = utility::string2int(input);
93  if(resi < 0) utility_exit_with_message("error in process_residue_request: '"+input+"'");
94  // TR << "process_residue_request: '" << input << "' to " << resi << std::endl;
95  return resi;
96 }
97 
98 bool is_jump_intracomponent(std::map<char,std::pair<Size,Size> > chain2range, Size up, Size dn) {
99  for(std::map<char,std::pair<Size,Size> >::const_iterator it = chain2range.begin(); it != chain2range.end(); ++it) {
100  Size const lb = it->second.first, ub = it->second.second;
101  if( lb <= up && up <= ub && lb <= dn && dn <= ub ) return true;
102  }
103  return false;
104 }
105 
106 char which_component(std::map<char,std::pair<Size,Size> > chain2range, Size resi) {
107  for(std::map<char,std::pair<Size,Size> >::const_iterator it = chain2range.begin(); it != chain2range.end(); ++it) {
108  Size const lb = it->second.first, ub = it->second.second;
109  if( lb <= resi && resi <= ub ) return it->first;
110  }
111  utility_exit_with_message("resi not in any component!");
112  return (char)NULL; // this will never happen
113 }
114 
117  core::kinematics::FoldTree const & f_orig,
118  std::map<char,std::pair<Size,Size> > const & /*chain2range*/ // maybe use later
119 ) {
120  if( f_orig.num_cutpoint() != (int)f_orig.num_jump() ) utility_exit_with_message("FoldTree ISANITY!!!!!!!");
121  ObjexxFCL::FArray1D_int cuts( f_orig.num_cutpoint() );
122  ObjexxFCL::FArray2D_int jumps( 2, f_orig.num_jump() );
123  // utility::vector1<std::string> upatom(f_orig.num_jump() );
124  utility::vector1<std::string> dnatom(f_orig.num_jump() );
125 
126  utility::vector1<int> cutpoints(f_orig.num_cutpoint());
127  for(int i = 1; i <= f_orig.num_cutpoint(); ++i) {
128  cutpoints[i] = f_orig.cutpoint(i);
129  }
130  std::sort(cutpoints.begin(),cutpoints.end());
131  cutpoints.push_back(f_orig.nres());
132 
133  // simple way for now
134  for(Size i = 1; i < cutpoints.size(); ++i) {
135  cuts(i) = cutpoints[i];
136  jumps(1,i) = cutpoints[i];
137  jumps(2,i) = fold_tree_entry_point(f_orig, cutpoints[i]+1,cutpoints[i+1]);
138  // upatom[i] = f_orig.upstream_atom(i);
139  dnatom[i] = f_orig.downstream_atom(i);
140  }
142  f_contig.tree_from_jumps_and_cuts(f_orig.nres(),f_orig.num_jump(),jumps,cuts);
143  for(Size i = 1; i < cutpoints.size(); ++i) {
144  if(dnatom[i]!="") f_contig.set_jump_atoms(i,"N",dnatom[i]);
145  }
146  f_contig.reorder(1);
147 
148  // complicated way....
149  // int jcount = 0;
150  // utility::vector1<Size> intercomp_up,intercomp_dn;
151  // for(int i = 1; i <= f_orig.num_jump(); ++i) {
152  // Size up = f_orig.upstream_jump_residue(i);
153  // Size dn = f_orig.downstream_jump_residue(i);
154  // if( is_jump_intracomponent(chain2range,up,dn) ) {
155  // jump(1,++jcount) = up;
156  // jump(1, jcount) = dn;
157  // } else {
158  // intercomp_up.push_back(up);
159  // intercomp_dn.push_back(dn);
160  // }
161  // }
162  // for(int i = 1; i <= intercomp_dn.size(); ++i){
163  // int lb = f_orig.boundary_left(intercomp_dn[i]);
164  // }
165 
166  // //test output
167  // std::map<Size,std::string> labels;
168  // for(std::map<char,std::pair<Size,Size> >::const_iterator i = chain2range.begin(); i != chain2range.end(); ++i) {
169  // for(Size ir = i->second.first; ir <= i->second.second; ++ir) {
170  // labels[ir] = std::string("Chain") + i->first;
171  // }
172  // }
173  // TR << "get_component_contiguous_foldtree" << std::endl;
174  // TR << "ORIG " << f_orig << std::endl;
175  // TR << "CONTIG " << f_contig << std::endl;
176  // TR << "ORIG:\n" << core::kinematics::visualize_fold_tree(f_orig,labels) << std::endl;
177  // TR << "CONTIG:\n" << core::kinematics::visualize_fold_tree(f_contig,labels) << std::endl;
178  // utility_exit_with_message("SETNETRINT");
179  return f_contig;
180 }
181 
182 
183 // sheffler
184 /// @details get a mapping of chain chars to resi ranges
185 std::map<char,std::pair<Size,Size> >
186 get_chain2range( Conformation const & src_conf, std::map< int, char > src_conf2pdb_chain ) {
187  // TR << src_conf.num_chains() << endl;
188  // for(Size i = 1; i <= src_conf.num_chains(); ++i){
189  // TR << "src_conf chain " << i << " " << src_conf.chain_begin(i) << "-" << src_conf.chain_end (i) << endl;
190  // }
191  // TR << "PDBINFO CHAIN MAP" << endl;
192  // for(map< int, char >::const_iterator i = src_conf2pdb_chain.begin(); i != src_conf2pdb_chain.end(); ++i) {
193  // TR << i->first << " " << i->second << endl;
194  // }
195  // TR << "END PDBINFO CHAIN MAP" << endl;
196  std::map<char,std::pair<Size,Size> > crange;
197  std::string const nullchain = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
198  for(Size i = 1; i <= src_conf.num_chains(); ++i) {
199  char chain = src_conf2pdb_chain.count(i)==0 ? nullchain[i-1] : src_conf2pdb_chain[i];
200  if(crange.count(chain)==0) crange[chain] = std::make_pair(99999999,0);
201  crange[chain].first = std::min( src_conf.chain_begin(i), crange[chain].first );
202  crange[chain].second = std::max( src_conf.chain_end (i), crange[chain].second );
203  }
204  // sanity check
205  for(std::map<char,std::pair<Size,Size> >::const_iterator i = crange.begin(); i != crange.end(); ++i) {
206  // TR << "get_chain2range " << i->first << " " << i->second.first << "-" << i->second.second << std::endl;
207  if( i->second.first > i->second.second ) utility_exit_with_message("THIS SHOULD NEVER HAPPEN!");
208  for(std::map<char,std::pair<Size,Size> >::const_iterator j = crange.begin(); j != crange.end(); ++j) {
209  if( i->second.first==j->second.first && i->second.second==j->second.second ) continue; // same
210  if( i->second.first > j->second.first && i->second.first > j->second.second ) continue; // disjoint, i < j
211  if( j->second.first > i->second.first && j->second.first > i->second.second ) continue; // disjoint, j > i
212  utility_exit_with_message("[ERROR] overlapping chain ranges in pose!!!!!!!!");
213  }
214  }
215  return crange;
216 }
217 
218 /// @details Attempt to detect whether a conformation is symmetric
219 bool
221 {
222  return ( dynamic_cast< conformation::symmetry::SymmetricConformation const * >( &conf ) );
223 }
224 
225 bool
227 {
228  return symminfo.get_use_symmetry();
229 }
230 
231 // utility::vector1<numeric::xyzVector<core::Real> >
232 // conf_coords(conformation::Conformation & conf, Size lb=1, Size ub=0) {
233 // if(ub==0) ub = conf.size();
234 // utility::vector1<numeric::xyzVector<core::Real> > coords;
235 // for(int ir = lb; ir <= ub; ++ir){
236 // coords.push_back(conf.residue(ir).xyz(1));
237 // }
238 // return coords;
239 // }
240 
241 // bool check_coords(
242 // utility::vector1<numeric::xyzVector<core::Real> > const & a,
243 // utility::vector1<numeric::xyzVector<core::Real> > const & b
244 // ){
245 // if(a.size() != b.size()) utility_exit_with_message("ERROR");
246 // bool err = false;
247 // for(int ir = 1; ir <= a.size(); ++ir) {
248 // if( a[ir].distance(b[ir]) > 0.00001 ) {
249 // std::cerr << "different at " << ir << std::endl;
250 // err = true;
251 // }
252 // }
253 // return err;
254 // }
255 
256 /// @details Generate a symmetric conformation from a monomeric pose and symmetry information
257 /// stored in the SymmData object
260  conformation::Conformation & src_conformation,
262  std::map< int, char > src_conf2pdb_chain
263 )
264 {
265  // utility::vector1<numeric::xyzVector<core::Real> > orig_coords = conf_coords(src_conformation);
266 
267  if( symmdata.get_num_components() > 1 ) {
268  // TR << "\n========== BEG orig fold tree ===========" << std::endl;
269  // TR << src_conformation.fold_tree() << std::endl;
270  // TR << "\n" << core::kinematics::visualize_fold_tree(src_conformation.fold_tree()) << std::endl;
271  // TR << "\n========== END orig_fold_tree ===========" << std::endl;
272  std::map<char,std::pair<Size,Size> > const chain2range = get_chain2range(src_conformation,src_conf2pdb_chain);
273  core::kinematics::FoldTree newft = get_component_contiguous_foldtree(src_conformation.fold_tree(),chain2range);
274  // utility::vector1<numeric::xyzVector<core::Real> > before = conf_coords(src_conformation);
275  src_conformation.fold_tree( newft );
276  // utility::vector1<numeric::xyzVector<core::Real> > after = conf_coords(src_conformation);
277  // if(check_coords(before,after)) utility_exit_with_message("error");
278  // TR << "\n========== BEG component_contiguous_foldtree ===========" << std::endl;
279  // TR << src_conformation.fold_tree() << std::endl;
280  // TR << "\n" << core::kinematics::visualize_fold_tree(src_conformation.fold_tree()) << std::endl;
281  // TR << "\n========== END component_contiguous_foldtree ===========" << std::endl;
282  }
283 
284  Size njump_orig = src_conformation.fold_tree().num_jump();
285 
286  // maybe a little inefficient: first build a standard conformation, then construct symmetric conformation at the end
287  conformation::Conformation conf( src_conformation );
288 
289  // recenter the pose to the origin?
290  if ( symmdata.get_recenter() ) {
291  core::conformation::symmetry::recenter( conf, symmdata );
292  }
293 
294  // Setup temporary variables
295  Size const nres_monomer( conf.size() );
296  Size const njump_monomer( conf.fold_tree().num_jump() );
297 
298  // setup the pseudo residues
299  std::map< std::string, conformation::symmetry::VirtualCoordinate > coords ( symmdata.get_virtual_coordinates() );
300  std::map< std::string, std::pair< std::string, std::string > > virtual_connects( symmdata.get_virtual_connects() );
301  std::map< Size, std::string > virtual_num_to_id (symmdata.get_virtual_num_to_id() );
302 
303  // Setup virtual residues
304  {
305  // create the new residue
306  chemical::ResidueTypeSet const & rsd_set( src_conformation.residue(1).residue_type_set() );
307  conformation::ResidueOP rsd( conformation::ResidueFactory::create_residue( rsd_set.name_map( "VRT" ) ) );
308 
309  // root the fold_tree at this pseudo residue
310 // {
311 // kinematics::FoldTree f( conf.fold_tree() );
312 // f.reorder( conf.size() );
313 // conf.fold_tree( f );
314 // }
315 
316  for ( Size i =1; i <= virtual_num_to_id.size(); ++i ) {
317  if ( virtual_num_to_id.find( i ) == virtual_num_to_id.end() ) {
318  utility_exit_with_message( "[ERROR] Cannot find jump number..." );
319  }
320  std::string tag ( virtual_num_to_id.find( i )->second );
321  if ( coords.find( tag ) == coords.end() ) {
322  utility_exit_with_message( "[ERROR] Cannot find tag " + tag );
323  }
324  conformation::symmetry::VirtualCoordinate virt_coord( coords.find( tag )->second );
325  rsd->set_xyz( "ORIG", virt_coord.get_origin() );
326  rsd->set_xyz( "X", virt_coord.get_x().normalized() + virt_coord.get_origin() );
327  rsd->set_xyz( "Y", virt_coord.get_y().normalized() + virt_coord.get_origin() );
328  conf.append_residue_by_jump( *rsd, conf.size() ); //append it to the end of the monomeri
329  }
330  }
331 
332  // now insert the other conformations. This step will create a fold_tree that will be discarded at a later stage.
333  // Optimally we want to set the fold tree directly but that turns out to be difficult. TODO change
334  // kinematics::Jump const monomer_jump( conf.jump( njump_monomer+1 ) );
335  for ( Size i=1; i< symmdata.get_subunits(); ++i ) {
336  Size const insert_seqpos( nres_monomer * i + 1 ); // desired sequence position of residue 1 in inserted conformation
337  Size const insert_jumppos( njump_monomer * i + 1 ); // desired jump number of 1st jump in inserted conformation
338  Size const anchor_pseudo( nres_monomer * i + i + 1 ); // in current numbering
339  Size const new_jump_number( njump_monomer*( i + 1 ) + i + 1 );
340  conf.insert_conformation_by_jump( src_conformation, insert_seqpos, insert_jumppos, anchor_pseudo, new_jump_number);
341 // conf.set_jump( new_jump_number, monomer_jump );
342  }
343 
345 
346  // Now generate the fold_tree from the symmdata and set it into the conformation. In the future we want to be able to use a
347  // atom tree for this.
348  kinematics::FoldTree f ( core::conformation::symmetry::set_fold_tree_from_symm_data( src_conformation, symmdata, src_conf2pdb_chain ) );
349  // set the root of the fold tree
350  Size new_root ( conf.size() - coords.size() + symmdata.get_root() );
351  f.reorder( new_root );
352  TR.Debug << f << std::endl;
353  conf.fold_tree( f );
354 
355  // if(check_coords(orig_coords, conf_coords(conf,1,orig_coords.size()) )) utility_exit_with_message("error");
356 
357  // now build the symmetry info object
358  conformation::symmetry::SymmetryInfo symm_info_raw( symmdata, nres_monomer, njump_monomer+1-symmdata.get_num_components() );
359  std::map<char,std::pair<Size,Size> > component_bounds;
360  for(Size ic = 1; ic <= src_conformation.num_chains(); ++ic){
361  char chain = src_conf2pdb_chain[ic];
362  component_bounds[chain].first = src_conformation.chain_begin(ic);
363  component_bounds[chain].second = src_conformation.chain_end(ic);
364  }
365  symm_info_raw.set_multicomponent_info(
366  symmdata.get_components(),
367  component_bounds,
369  symmdata.get_jump_name_to_components(),
370  symmdata.get_jump_name_to_subunits()
371  );
372  conformation::symmetry::SymmetryInfo const & symm_info(symm_info_raw);
373 
374  if( symmdata.get_num_components() > 1 ){
375  for(std::map< Size, SymDof >::const_iterator j = symm_info.get_dofs().begin(); j != symm_info.get_dofs().end(); ++j){
376  std::string const & dofname( symm_info.get_jump_name(j->first) );
377  utility::vector1<char> compchild = symmdata.components_moved_by_jump(dofname);
378  utility::vector1<Size> subchild = symmdata.subunits_moved_by_jump(dofname);
379  TR << "MULTICOMPONENT " << "DOF " << dofname << std::endl;
380  TR << "MULTICOMPONENT " << " moves these components:";
381  for(utility::vector1<char>::const_iterator i = compchild.begin(); i != compchild.end(); ++i){
382  TR << " " << *i;
383  }
384  TR << std::endl;
385  TR << "MULTICOMPONENT " << " moves these subunits:";
386  for(utility::vector1<Size>::const_iterator i = subchild.begin(); i != subchild.end(); ++i){
387  TR << " " << *i;
388  }
389  TR << std::endl;
390  }
391  for(utility::vector1<char>::const_iterator i = symm_info.get_components().begin(); i != symm_info.get_components().end(); ++i){
392  TR << "MULTICOMPONENT " << *i << " " << symm_info.get_component_bounds().find(*i)->second.first << "-" << symm_info.get_component_bounds().find(*i)->second.second << std::endl;
393  TR << "MULTICOMPONENT " << " moved by dofs:";
394  for(std::map< Size, SymDof >::const_iterator j = symm_info.get_dofs().begin(); j != symm_info.get_dofs().end(); ++j){
395  std::string const & dofname( symm_info.get_jump_name(j->first) );
396  // if( symm_info.get_jump_name_to_components().find(dofname) == symm_info.get_jump_name_to_components().end() ){
397  // utility_exit_with_message("jump name not in component map: "+dofname);
398  // }
399  utility::vector1<char> compchild = symmdata.components_moved_by_jump(dofname);
400  if( std::find(compchild.begin(),compchild.end(),*i) == compchild.end() ) continue;
401  TR << " " << dofname;
402  }
403  TR << std::endl << "MULTICOMPONENT " << " contains virtuals:";
404  for(std::map<std::string,char>::const_iterator j = symm_info.get_subunit_name_to_component().begin(); j != symm_info.get_subunit_name_to_component().end(); ++j){
405  if(j->second != *i) continue;
406  TR << " " << j->first;
407  }
408  TR << std::endl;
409  }
410 
411  // for(std::map< Size, SymDof >::const_iterator j = symm_info.get_dofs().begin(); j != symm_info.get_dofs().end(); ++j){
412  // std::string const & dofname( symm_info.get_jump_name(j->first) );
413  // if( symm_info.get_jump_name_to_components().find(dofname) == symm_info.get_jump_name_to_components().end() ){
414  // utility_exit_with_message("jump name not in component map: "+dofname);
415  // }
416  // if( symm_info.get_jump_name_to_components().find(dofname)->second != *i ) continue;
417  // TR << "MULTICOMPONENT " << dofname << std::endl;
418  // }
419  }
420 
421  // now create the symmetric conformation
423 
424  // if(check_coords(orig_coords, conf_coords(*symm_conf,1,orig_coords.size()) ));// utility_exit_with_message("error");
425 
426  // apply independent jumps so the structure is created symmetrically
427  for ( Size i=1; i<= f.num_jump(); ++i ) {
428  if ( symm_info.jump_is_independent( i ) ) {
429  symm_conf->set_jump( i, conf.jump( i ) );
430  }
431  }
432 
433  // if(check_coords(orig_coords, conf_coords(*symm_conf,1,orig_coords.size()) ));// utility_exit_with_message("error");
434 
435  // renumber the dof information to take the internal jumps into consideration
436  core::conformation::symmetry::shift_jump_numbers_in_dofs( *symm_conf, (njump_orig+1-symmdata.get_num_components()) * symmdata.get_subunits() );
437 
438  // if( symmdata.get_num_components() > 1 ) {
439  // TR << "=================== SYM FOLD TREE ========================" << std::endl;
440  // TR << symm_conf->fold_tree() << std::endl;
441  TR << "=================== SYM FOLD TREE, jump notation: =symfixed= *indep* #symdof# jump[=follows] ========================\n"
442  << show_foldtree(*symm_conf,symmdata,get_chain2range(src_conformation,src_conf2pdb_chain)) << std::endl;
443  // }
444 
445  return symm_conf;
446 }
447 
448 // @details Make a fold tree from data stored in the SymmData object. This would have to make sense.
449 // this function would probably enjoy more checks...
452  conformation::Conformation & src_conformation,
454  std::map< int, char > src_conf2pdb_chain
455 )
456 {
457  std::map<char,std::pair<Size,Size> > const chain2range = get_chain2range(src_conformation,src_conf2pdb_chain);
458 
459  using namespace kinematics;
460  FoldTree f, f_orig = src_conformation.fold_tree();
461  f.clear();
462 
463  // Save number of monomer residues, subunits and virtuals
464  Size num_res_subunit( src_conformation.size() );
465  Size subunits( symmdata.get_subunits() );
466  Size num_cuts_subunit( f_orig.num_cutpoint() );
467  Size num_virtuals( symmdata.get_virtual_coordinates().size() );
468  Size num_virtual_connects ( symmdata.get_virtual_connects().size() );
469  Size num_res_real( num_res_subunit*subunits );
470  Size anchor ( process_residue_request(src_conformation,symmdata.get_anchor_residue() ) );
471 
472  // Check that input data makes sense
473  if ( anchor > num_res_subunit ) {
474  utility_exit_with_message( "Anchor outside the subunit..." );
475  }
476 
477  if( symmdata.get_num_components() == 1 ) {
478 
479 
480  Size num_jumps_subunit( f_orig.num_jump() );
481 
482  // Store number of jumps and cuts
483  Size njumps( 0 );
484  Size total_num_cuts( num_cuts_subunit*subunits + subunits + num_virtuals - 1 );
485  Size total_num_jumps( num_jumps_subunit*subunits + num_virtual_connects );
486 
487  // store information from subunit foldtree
488  utility::vector1< int > cuts_subunit( f_orig.cutpoints() );
489  ObjexxFCL::FArray1D_int cuts( total_num_cuts );
490  ObjexxFCL::FArray2D_int jump_points_subunit( 2, num_jumps_subunit ),
491  jumps( 2, total_num_jumps );
492 
493  for ( Size i = 1; i<= f_orig.num_jump(); ++i ) {
494  jump_points_subunit(1,i) = f_orig.upstream_jump_residue(i);
495  jump_points_subunit(2,i) = f_orig.downstream_jump_residue(i);
496  }
497 
498  // Now add jumps and cuts for the other subunits
499  for ( Size i = 0; i < subunits; ++i ) {
500  for ( Size j = 1; j <= num_jumps_subunit; ++j ) {
501  ++njumps;
502  int new_cut_pos( i*num_res_subunit + cuts_subunit.at( j ) );
503  cuts( njumps ) = new_cut_pos;
504  int new_jump_pos1( i*num_res_subunit + jump_points_subunit(1,j) );
505  int new_jump_pos2( i*num_res_subunit + jump_points_subunit(2,j) );
506  jumps(1, njumps ) = std::min(new_jump_pos1,new_jump_pos2);
507  jumps(2, njumps ) = std::max(new_jump_pos1,new_jump_pos2);
508  }
509  }
510 
511  // why copy the maps?
512  std::map< std::string, std::pair< std::string, std::string > > const virtual_connect( symmdata.get_virtual_connects() );
513  std::map< std::string, Size > virtual_id_to_num (symmdata.get_virtual_id_to_num() );
514  std::map< Size, std::string > virtual_num_to_id (symmdata.get_virtual_num_to_id() );
515  std::map< std::string, Size > virtual_id_to_subunit (symmdata.get_virt_id_to_subunit_num() );
516 
517  std::map< std::string, std::pair< std::string, std::string > >::const_iterator it_start = virtual_connect.begin();
518  std::map< std::string, std::pair< std::string, std::string > >::const_iterator it_end = virtual_connect.end();
519  for ( std::map< std::string, std::pair< std::string, std::string > >::const_iterator it = it_start; it != it_end; ++it ) {
520  std::pair< std::string, std::string > connect( it->second );
521  std::string pos_id1( connect.first );
522  std::string pos_id2( connect.second );
523  if ( pos_id2 == "SUBUNIT" ) {
524  int subunit = virtual_id_to_subunit.find( pos_id1 )->second;
525  ++njumps;
526  cuts( njumps ) = num_res_subunit*subunit;
527  int jump_pos1( ( subunit-1 )*num_res_subunit + anchor );
528  int jump_pos2( num_res_real + virtual_id_to_num.find( pos_id1 )->second );
529  jumps(1, njumps ) = std::min(jump_pos1,jump_pos2);
530  jumps(2, njumps ) = std::max(jump_pos1,jump_pos2);
531  }
532  }
533 
534  // Read jump structure from symmdata
535 
536  // Read the virtual connect data and add the new connections. They are stored in virtual_connects. We also need to
537  // know the mapping between mapping between name of virtual residues and the jump number
538  Size pos( 0 );
539  for ( std::map< std::string, std::pair< std::string, std::string > >::const_iterator it = it_start; it != it_end; ++it ) {
540  std::pair< std::string, std::string > connect( it->second );
541  std::string pos_id1( connect.first );
542  std::string pos_id2( connect.second );
543  // We have already added the jumps from virtual residues to their corresponding subunits
544  if ( pos_id2 == "SUBUNIT" ) continue;
545  ++njumps;
546  ++pos;
547  assert( virtual_id_to_num.find( pos_id1 ) != virtual_id_to_num.end() && virtual_id_to_num.find( pos_id2 ) != virtual_id_to_num.end() );
548  Size pos1 ( virtual_id_to_num.find( pos_id1 )->second );
549  Size pos2 ( virtual_id_to_num.find( pos_id2 )->second );
550  cuts( njumps ) = num_res_real + pos;
551  jumps(1, njumps ) = num_res_real + std::min(pos1,pos2);
552  jumps(2, njumps ) = num_res_real + std::max(pos1,pos2);
553  }
554 
555  // Now create foldtree
556  f.tree_from_jumps_and_cuts( num_res_real + num_virtuals, njumps, jumps, cuts );
557  f.reorder( num_res_real + 1 );
558 
559  // now set jump atoms from f_orig
560  {
561  std::map<int,std::string> downstream_res_to_jump_atom;
562  for(Size i = 1; i <= f_orig.num_jump(); ++i){
563  downstream_res_to_jump_atom[f_orig.downstream_jump_residue(i)] = f_orig.downstream_atom(i);
564  }
565  for(Size i = 1; i <= f.num_jump(); ++i){
566  int upres = f.upstream_jump_residue(i);
567  int dnres = f.downstream_jump_residue(i);
568  int upres1 = (upres-1) % num_res_subunit + 1;
569  int dnres1 = (dnres-1) % num_res_subunit + 1;
570  if( dnres > (int)num_res_real ) continue;
571  if( downstream_res_to_jump_atom.find(dnres1) == downstream_res_to_jump_atom.end() ) continue;
572  if( downstream_res_to_jump_atom[dnres1] == "" ) continue;
573  std::string upatom = upres > (int)num_res_real ? "X" : src_conformation.residue(upres1).atom_name(1);
574  std::string dnatom = downstream_res_to_jump_atom[dnres1];
575  TR << "set SYM jump atoms: " << upres << ":" << upatom << " " << dnres << ":" << dnatom << std::endl;
576  f.set_jump_atoms(i, upatom, dnatom );
577  }
578  }
579 
580  return f;
581 
582 
583 
584  } else if( symmdata.get_num_components() > 1 ) {
585  using std::map;
586  using std::endl;
587  using std::string;
588  using std::pair;
589  using std::make_pair;
590  using ObjexxFCL::fmt::I;
591 
592  Size num_jumps_subunit( f_orig.num_jump() + 1 - symmdata.get_num_components() );
593 
594  // Store number of jumps and cuts
595  Size njumps( 0 ), ncuts(0);
596  Size total_num_cuts( num_cuts_subunit*subunits + subunits + num_virtuals - 1 );
597  Size total_num_jumps( num_jumps_subunit*subunits + num_virtual_connects );
598  utility::vector1< int > cuts_subunit( f_orig.cutpoints() );
599  ObjexxFCL::FArray2D_int jumps( 2, total_num_jumps );
600 
601  // TR << "NUM COMPONENTS: " << symmdata.get_num_components() << std::endl;
602  ObjexxFCL::FArray2D_int jump_points_subunit( 2, num_jumps_subunit );
603  Size nsubjump = 0;
604  for ( Size i = 1; i<= f_orig.num_jump(); ++i ) {
605  Size const up = f_orig.upstream_jump_residue(i);
606  Size const dn = f_orig.downstream_jump_residue(i);
607  bool up_and_dn_within_component = is_jump_intracomponent(chain2range,up,dn);
608  if(!up_and_dn_within_component) {
609  TR << "this intrasub jump will be replaced with a SUBUNIT jump " << up << " " << dn << endl;
610  continue;
611  }
612  nsubjump++;
613  jump_points_subunit(1,nsubjump) = up;
614  jump_points_subunit(2,nsubjump) = dn;
615  }
616  if(nsubjump != num_jumps_subunit){
617  // TR << "f_orig.num_jump() " << f_orig.num_jump() << std::endl;
618  // TR << "symmdata.get_num_components() " << symmdata.get_num_components() << std::endl;
619  // TR << "nsubjump " << nsubjump << std::endl;
620  utility_exit_with_message("intra-subunit jump mismatch!");
621  }
622 
623  // Now add jumps and cuts for the other subunits
624  for ( Size i = 0; i < subunits; ++i ) {
625  for ( Size j = 1; j <= nsubjump; ++j ) {
626  ++njumps;
627  int new_jump_pos1( i*num_res_subunit + jump_points_subunit(1,j) );
628  int new_jump_pos2( i*num_res_subunit + jump_points_subunit(2,j) );
629  jumps(1, njumps ) = std::min(new_jump_pos1,new_jump_pos2);
630  jumps(2, njumps ) = std::max(new_jump_pos1,new_jump_pos2);
631  }
632  }
633 
634 
635  std::map< std::string, std::pair< std::string, std::string > > const & virtual_connect( symmdata.get_virtual_connects() );
636  std::map< std::string, Size > const & virtual_id_to_num (symmdata.get_virtual_id_to_num() );
637  // std::map< Size, std::string > const & virtual_num_to_id (symmdata.get_virtual_num_to_id() );
638  std::map< std::string, Size > const & virtual_id_to_subunit (symmdata.get_virt_id_to_subunit_num() );
639  // for(map<string,Size>::const_iterator it = virtual_id_to_subunit.begin(); it != virtual_id_to_subunit.end(); ++it) {
640  // TR << "virtual_id_to_subunit " << it->first << " " << it->second << endl;
641  // }
642  map< string, char > const & virtual_id_to_subunit_chain(symmdata.get_virt_id_to_subunit_chain() );
643  map< string, string > const & virtual_id_to_subunit_residue(symmdata.get_virt_id_to_subunit_residue() );
644  // sanity check for SUBUNIT chain / residue
645  // for(map<char,pair<Size,Size> >::const_iterator i = chain2range.begin(); i != chain2range.end(); ++i) {
646  // TR << "get_chain2range " << i->first << " " << i->second.first << "-" << i->second.second << endl;
647  // }
648  for(map<string,char>::const_iterator it = virtual_id_to_subunit_chain.begin(); it != virtual_id_to_subunit_chain.end(); ++it) {
649  string virt = it->first;
650  char chain = it->second;
651  if( chain == (char)0 ) chain = src_conf2pdb_chain.count(1) ? src_conf2pdb_chain[1] : 'A';
652  if(chain2range.find(chain)==chain2range.end()){
653  std::cerr << "missing chain in pdb: " << chain << std::endl;
654  utility_exit_with_message("missing chain in symfile/pdb");
655  }
656  Size beg = chain2range.find(chain)->second.first;
657  Size end = chain2range.find(chain)->second.second;
658  Size resi = process_residue_request( src_conformation, virtual_id_to_subunit_residue.find(virt)->second, beg, end );
659  if( !( beg <= resi && resi <= end ) ) {
660  TR << "SUBUNIT chain " << chain << " assertion fail: " << beg << " <= " << resi << " <= " << end << endl;
661  utility_exit_with_message("requested residue out of bounds: "+virtual_id_to_subunit_residue.find(virt)->second);
662  }
663  // TR << "SUBUNIT chain: " << virt << " " << chain << " " << resi << endl;
664  }
665 
666  std::map< std::string, std::pair< std::string, std::string > >::const_iterator it_start = virtual_connect.begin();
667  std::map< std::string, std::pair< std::string, std::string > >::const_iterator it_end = virtual_connect.end();
668  for ( std::map< std::string, std::pair< std::string, std::string > >::const_iterator it = it_start; it != it_end; ++it ) {
669  std::pair< std::string, std::string > connect( it->second );
670  std::string pos_id1( connect.first );
671  std::string pos_id2( connect.second );
672  if ( pos_id2 == "SUBUNIT" ) {
673  char chain = virtual_id_to_subunit_chain.find(pos_id1)->second;
674  if( chain == (char)0 ) chain = src_conf2pdb_chain.count(1) ? src_conf2pdb_chain[1] : 'A';
675  Size beg = chain2range.find(chain)->second.first;
676  Size end = chain2range.find(chain)->second.second;
677  Size resi = process_residue_request( src_conformation, virtual_id_to_subunit_residue.find(pos_id1)->second, beg, end );
678  // TR << "set SUBUNIT jumps " << pos_id1 << " chain: " << chain << " anchor: " << resi << " range: " << beg << "-" << end << endl;
679  int subunit = virtual_id_to_subunit.find( pos_id1 )->second;
680  ++njumps;
681  Size this_anchor = resi ? resi : anchor;
682  if( this_anchor < beg || end < this_anchor) utility_exit_with_message("bad anchor "+virtual_id_to_subunit_residue.find(pos_id1)->second);
683  // cuts from subunit already
684  // cuts(njumps) = (subunit-1)*num_res_subunit + end;
685  int jump_pos1( (subunit-1)*num_res_subunit + this_anchor );
686  int jump_pos2( num_res_real + virtual_id_to_num.find( pos_id1 )->second );
687  jumps(1, njumps ) = std::min(jump_pos1,jump_pos2);
688  jumps(2, njumps ) = std::max(jump_pos1,jump_pos2);
689  }
690  }
691 
692  // Read jump structure from symmdata
693 
694  // Read the virtual connect data and add the new connections. They are stored in virtual_connects. We also need to
695  // know the mapping between mapping between name of virtual residues and the jump number
696  Size pos( 0 );
697  for ( std::map< std::string, std::pair< std::string, std::string > >::const_iterator it = it_start; it != it_end; ++it ) {
698  std::pair< std::string, std::string > connect( it->second );
699  std::string pos_id1( connect.first );
700  std::string pos_id2( connect.second );
701  // We have already added the jumps from virtual residues to their corresponding subunits
702  if ( pos_id2 == "SUBUNIT" ) continue;
703  ++njumps;
704  ++pos;
705  assert( virtual_id_to_num.find( pos_id1 ) != virtual_id_to_num.end() && virtual_id_to_num.find( pos_id2 ) != virtual_id_to_num.end() );
706  Size pos1 ( virtual_id_to_num.find( pos_id1 )->second );
707  Size pos2 ( virtual_id_to_num.find( pos_id2 )->second );
708  jumps(1, njumps ) = num_res_real + std::min(pos1,pos2);
709  jumps(2, njumps ) = num_res_real + std::max(pos1,pos2);
710  }
711 
712  ObjexxFCL::FArray1D_int cuts( total_num_cuts );
713  for ( Size i = 0; i < subunits; ++i ) {
714  for(Size j = 1; j <= f_orig.num_jump(); ++j) {
715  cuts( ++ncuts ) = i*num_res_subunit + cuts_subunit.at(j);
716  }
717  cuts(++ncuts) = num_res_subunit*(i+1);
718  }
719  for(Size i = 1; i < num_virtuals; ++i) {
720  cuts(++ncuts) = i+num_res_real;
721  }
722 
723 
724  // // Now create foldtree
725  // TR << "create new fold tree, oldnjump " << f.num_jump() << " newnjump " << njumps << std::endl;
726  // for(int i = 1; i <= total_num_cuts; ++i){
727  // TR << i << " " << cuts(i) << std::endl;
728  // }
729  f.tree_from_jumps_and_cuts( num_res_real + num_virtuals, njumps, jumps, cuts, num_res_real+1 );
730  f.reorder( num_res_real + 1 );
731 
732  // now set jump atoms from f_orig
733  {
734  std::map<int,std::string> downstream_res_to_jump_atom;
735  for(Size i = 1; i <= f_orig.num_jump(); ++i){
736  downstream_res_to_jump_atom[f_orig.downstream_jump_residue(i)] = f_orig.downstream_atom(i);
737  }
738  for(Size i = 1; i <= f.num_jump(); ++i){
739  int upres = f.upstream_jump_residue(i);
740  int dnres = f.downstream_jump_residue(i);
741  int upres1 = (upres-1) % num_res_subunit + 1;
742  int dnres1 = (dnres-1) % num_res_subunit + 1;
743  if( dnres > (int)num_res_real ) continue;
744  if( downstream_res_to_jump_atom.find(dnres1) == downstream_res_to_jump_atom.end() ) continue;
745  if( downstream_res_to_jump_atom[dnres1] == "" ) continue;
746  std::string upatom = upres > (int)num_res_real ? "X" : src_conformation.residue(upres1).atom_name(1);
747  std::string dnatom = downstream_res_to_jump_atom[dnres1];
748  TR << "set SYM jump atoms: " << upres << ":" << upatom << " " << dnres << ":" << dnatom << std::endl;
749  f.set_jump_atoms(i, upatom, dnatom );
750  }
751  }
752 
753  return f;
754 
755  } else {
756  TR << "num_componints: " << symmdata.get_num_components() << std::endl;
757  utility_exit_with_message("BAD num_componints");
758  }
759 
760  return FoldTree(0); // this will never happen
761 }
762 
763 // this function is STILL under construction...
766  kinematics::FoldTree symm_f,
768  kinematics::FoldTree monomer_f
769 )
770 {
771  using namespace kinematics;
772  FoldTree f=symm_f, f_new=monomer_f;
773 
774  // Save number of monomer residues, subunits and virtuals
775  Size num_res_subunit( symmetry_info.num_independent_residues() );
776  Size subunits( symmetry_info.subunits() );
777  //Size anchor ( symmdata.get_anchor_residue() );
778 
779 
780  // Now add jumps and cuts for the other subunits
781  for ( Size i = 0; i < subunits; ++i ) {
782  int begin ( i*num_res_subunit+1 );
783  int end ( (i+1)*num_res_subunit );
784  f.delete_segment( begin, end );
785  //f.insert_fold_tree_by_jump(f, insert_seqpos, insert_jumppos, anchor_pos, anchor_jump_number, anchor_atom, root_atom);
786 
787  }
788 
789  return f;
790 }
791 
792 
793 // @details center the pose at the origin. Use the CA of the anchor residue
794 // as the anchor point
795 void
797  conformation::Conformation & src_conformation,
799 )
800 {
801  conformation::Residue anchor ( src_conformation.residue( process_residue_request(src_conformation,symmdata.get_anchor_residue()) ) );
802  Vector trans( anchor.xyz( "CA" ) );
803  for ( Size i = 1; i <= src_conformation.size(); ++i ) {
804  for ( Size j = 1; j <= src_conformation.residue_type(i).natoms(); ++j ) {
805  id::AtomID id( j, i );
806  src_conformation.set_xyz( id, src_conformation.xyz(id) - trans );
807  }
808  }
809 }
810 
811 // @details shift jump numbers in dof
812 void
814  conformation::Conformation & conformation,
815  Size shift
816 )
817 {
818  using namespace core::conformation::symmetry;
819 
820  runtime_assert( is_symmetric( conformation ) );
821  SymmetricConformation & symm_conf (
822  dynamic_cast<SymmetricConformation & > ( conformation ) );
823  SymmetryInfoOP symm_info( symm_conf.Symmetry_Info() );
824 
825  std::map< Size, SymDof > dofs ( symm_conf.Symmetry_Info()->get_dofs() );
826  std::map< Size, SymDof > dofs_shifted;
827  std::map< Size, SymDof >::iterator it;
828  std::map< Size, SymDof >::iterator it_begin = dofs.begin();
829  std::map< Size, SymDof >::iterator it_end = dofs.end();
830 
831  for ( it = it_begin; it != it_end; ++it ) {
832  int jump_nbr ( (*it).first + shift );
833  dofs_shifted.insert( std::make_pair( jump_nbr, (*it).second ) );
834  }
835  symm_info->set_dofs( dofs_shifted );
836 }
837 
838 
841  if( !is_symmetric( conf ) ) {
842  return conf.fold_tree();
843  }
844 
845  // basic idea: only take edges with at least one end in the 1st subunit
846  kinematics::FoldTree const &f = conf.fold_tree();
847  kinematics::FoldTree f_new;
848 
849  conformation::symmetry::SymmetricConformation const & symm_conf ( dynamic_cast<conformation::symmetry::SymmetricConformation const & > ( conf ) );
851  Size nres_subunit ( symm_info->num_independent_residues() );
852 
853  for ( core::kinematics::FoldTree::const_iterator it=f.begin(), eit=f.end(); it != eit; ++it) {
854  if ( it->start() <= (int)nres_subunit && it->stop() <=(int)nres_subunit ) {
855  f_new.add_edge( *it );
856  } else if ( it->stop() <= (int)nres_subunit ) { // this is the jump to the subunit
857  core::kinematics::Edge e_new = *it;
858  e_new.start() = nres_subunit + 1;
859  f_new.add_edge( e_new );
860  }
861  }
862  f_new.renumber_jumps();
863 
864  //TR.Error << "get_asymm_unit_fold_tree() called with " << f << std::endl;
865  //TR.Error << "get_asymm_unit_fold_tree() returning " << f_new << std::endl;
866  return f_new;
867 }
868 
869 void
873 ) {
874 
875  if( !is_symmetric( conf ) ) {
876  return;
877  }
878 
879  // basic idea: grabs jumps and cuts from monomer, symmetrize them,
880  // retain VRT jumps and cuts, generate a new fold tree
881  kinematics::FoldTree f_orig = f;
882  //TR.Error << "symmetrize_fold_tree() called with " << f << std::endl;
883  //TR.Error << "reference fold tree = " << p.fold_tree() << std::endl;
884 
886  dynamic_cast<conformation::symmetry::SymmetricConformation const & > ( conf ) );
888  Size nres_subunit ( symm_info->num_independent_residues() );
889  Size nsubunits ( symm_info->subunits() );
890  Size num_nonvrt = symm_info->num_total_residues_without_pseudo();
891 
892  // 1 - Get monomer jumps, cuts, and anchor
893  Size new_anchor = 0;
894  utility::vector1< Size > new_cuts;
896 
897  for ( Size i = 1; i<= f_orig.num_jump(); ++i ) {
898  Size down ( f_orig.downstream_jump_residue(i) );
899  Size up ( f_orig.upstream_jump_residue(i) );
900  if ( up > nres_subunit ) {
901  new_anchor = down;
902  TR << "symmetrize_fold_tree(): setting anchor to " << new_anchor << std::endl;
903  } else {
904  // add this jump in each subunit
905  for ( Size j=0; j<nsubunits; ++j) {
906  // dont worry about order, they get sorted later
907  new_jumps.push_back( std::pair<int,int>( j*nres_subunit+down, j*nres_subunit+up ) );
908  }
909  }
910  }
911  utility::vector1< int > cuts_vector( f_orig.cutpoints() );
912 
913  // 1A - symmetrize
914  for ( Size i = 0; i<nsubunits; ++i) {
915  for ( Size j = 1; j<=cuts_vector.size(); ++j ) {
916  if (i*nres_subunit + cuts_vector[j] != num_nonvrt)
917  new_cuts.push_back( i*nres_subunit + cuts_vector[j] );
918  }
919  }
920 
921  // 2 - Get symmetic jumps cuts and anchor
922  // inter-VRT jumps
923  kinematics::FoldTree const & f_pose = conf.fold_tree();
924  for ( Size i = 1; i<= f_pose.num_jump(); ++i ) {
925  Size down ( f_pose.downstream_jump_residue(i) );
926  Size up ( f_pose.upstream_jump_residue(i) );
927  // connections between VRTs are unchanged
928  if ( up > num_nonvrt && down > num_nonvrt) {
929  new_jumps.push_back( std::pair<Size,Size>(up,down) );
930  }
931  // jumps to new anchor
932  if ( up > num_nonvrt && down <= num_nonvrt) {
933  int subunit_i = symm_info->subunit_index(down);
934  new_jumps.push_back( std::pair<Size,Size>( up, (subunit_i-1)*nres_subunit + new_anchor ) );
935  }
936  // jumps from new anchor
937  if ( up <= num_nonvrt && down > num_nonvrt) {
938  int subunit_i = symm_info->subunit_index(up);
939  new_jumps.push_back( std::pair<Size,Size>( (subunit_i-1)*nres_subunit + new_anchor , down ) );
940  }
941  }
942 
943  // cuts
944  cuts_vector = f_pose.cutpoints();
945  for ( Size i = 1; i<=cuts_vector.size(); ++i ) {
946  if ( cuts_vector[i] >= (int) num_nonvrt)
947  new_cuts.push_back( cuts_vector[i] );
948  }
949 
950  // 3 - combine
951  ObjexxFCL::FArray1D_int cuts( new_cuts.size() );
952  ObjexxFCL::FArray2D_int jumps( 2, new_jumps.size() );
953  // Initialize jumps
954  for ( Size i = 1; i<= new_jumps.size(); ++i ) {
955  jumps(1,i) = std::min( (int)new_jumps[i].first, (int)new_jumps[i].second);
956  jumps(2,i) = std::max( (int)new_jumps[i].first, (int)new_jumps[i].second);
957  // DEBUG -- PRINT JUMPS AND CUTS
958  //TR.Error << " jump " << i << " : " << jumps(1,i) << " , " << jumps(2,i) << std::endl;
959  }
960  for ( Size i = 1; i<= new_cuts.size(); ++i ) {
961  cuts(i) = (int)new_cuts[i];
962  //TR.Error << " cut " << i << " : " << cuts(i) << std::endl;
963  }
964 
965  // 4 make the foldtree
966  f.clear();
967  f.tree_from_jumps_and_cuts( conf.size(), new_jumps.size(), jumps, cuts, f_pose.root(), false ); // true );
968  //TR.Error << "symmetrize_fold_tree() before reorder " << f << std::endl;
969  //f.reorder( f_pose.root() );
970  //TR.Error << "symmetrize_fold_tree() returning with " << f << std::endl;
971 }
972 
973 
974 void
976  if( !is_symmetric( conf ) ) {
977  conf.fold_tree( f );
978  }
979 
980  kinematics::FoldTree f_new = f;
981  symmetrize_fold_tree( conf, f_new );
982 
983  conf.fold_tree( f_new );
984 }
985 
986 // this function is directly stolen from the docking code in protocols. The code duplication is introduced
987 // to avoid dependencies of core functionality from protocols
988 int
990  conformation::Conformation const & conformation,
991  int const start,
992  int const stop
993 )
994 {
995  Vector center( 0.0 );
996  for ( int i=start; i<=stop; ++i ) {
997  //if( !pose.residue( i ).is_protein() ) continue;
998  if( !conformation.residue( i ).is_protein()) {
999  Vector ca_pos( conformation.residue( i ).nbr_atom_xyz() );
1000  center += ca_pos;
1001  } else {
1002  Vector ca_pos( conformation.residue( i ).atom( "CA" ).xyz() );
1003  center += ca_pos;
1004  }
1005  }
1006  center /= (stop-start+1);
1007 
1008  return core::conformation::symmetry::return_nearest_residue( conformation, start, stop, center );
1009 }
1010 
1011 // this function is directly stolen from the docking code in protocols. The code duplication is introduced
1012 // to avoid dependencies of protocols on core functionality
1013 int
1015  conformation::Conformation const & conformation,
1016  int const begin,
1017  int const end,
1018  Vector center
1019 )
1020 {
1021  Real min_dist = 9999.9;
1022  int res = 0;
1023  for ( int i=begin; i<=end; ++i )
1024  {
1025  Vector ca_pos;
1026  if( !conformation.residue( i ).is_protein() ){
1027  ca_pos = conformation.residue( i ).nbr_atom_xyz();
1028  } else {
1029  ca_pos = conformation.residue( i ).atom( "CA" ).xyz() ;
1030  }
1031 
1032  ca_pos -= center;
1033  Real tmp_dist( ca_pos.length_squared() );
1034  if ( tmp_dist < min_dist ) {
1035  res = i;
1036  min_dist = tmp_dist;
1037  }
1038  }
1039  return res;
1040 }
1041 
1045  SymmData const & symmdata,
1046  std::map<char,std::pair<Size,Size> > const & chain2range
1047 ){
1048  Size nsub = symm_conf.Symmetry_Info()->subunits();
1049  Size nres_monomer = symm_conf.Symmetry_Info()->num_independent_residues();
1050  Size nreal = nsub * nres_monomer;
1051 
1052  // label real res by chain
1053  std::map<Size,std::string> labels;
1054  for(std::map<char,std::pair<Size,Size> >::const_iterator i = chain2range.begin(); i != chain2range.end(); ++i) {
1055  for(Size is = 1; is <= nsub; ++is) {
1056  for(Size ir = i->second.first; ir <= i->second.second; ++ir) {
1057  labels[(is-1)*nres_monomer+ir] = std::string("Sub") + ObjexxFCL::string_of(is) + std::string("") + i->first;
1058  }
1059  }
1060  }
1061  // label virtuals by name in symdef
1062  Size Nreal = symm_conf.Symmetry_Info()->num_total_residues_without_pseudo();
1063  for(std::map<Size,std::string>::const_iterator i = symmdata.get_virtual_num_to_id().begin(); i != symmdata.get_virtual_num_to_id().end(); ++i) {
1064  labels[i->first+Nreal] = i->second;
1065  }
1066  std::map<Size,char> mark_jump_to_res;
1067  for(Size i = 1; i <= symm_conf.fold_tree().num_jump(); ++i) {
1068  if( symm_conf.Symmetry_Info()->jump_is_independent(i) ) {
1069  mark_jump_to_res[symm_conf.fold_tree().downstream_jump_residue(i)] = '*';
1070  }
1071  }
1072  for(Size i = 1; i <= symm_conf.fold_tree().num_jump(); ++i) {
1073  Size up = symm_conf.fold_tree().upstream_jump_residue(i);
1074  Size dn = symm_conf.fold_tree().downstream_jump_residue(i);
1075  if( symm_conf.Symmetry_Info()->jump_is_independent(i) && up > nreal && dn > nreal ) {
1076  mark_jump_to_res[symm_conf.fold_tree().downstream_jump_residue(i)] = '=';
1077  }
1078  }
1079  std::map<Size,SymDof> dofs( symm_conf.Symmetry_Info()->get_dofs() );
1080  for(std::map<Size,SymDof>::const_iterator i = dofs.begin(); i != dofs.end(); ++i) {
1081  // TR << "SymDOF " << i->first << " " << i->second << std::endl;
1082  mark_jump_to_res[symm_conf.fold_tree().downstream_jump_residue(i->first)] = '#';
1083  }
1084  std::map<Size,Size> jump_follows;
1085  for(Size i = 1; i <= symm_conf.fold_tree().num_jump(); ++i){
1086  if(symm_conf.Symmetry_Info()->jump_follows(i)!=(Size)0) {
1087  jump_follows[i] = symm_conf.Symmetry_Info()->jump_follows(i);
1088  }
1089  }
1090 
1091  // for(Size i = 1; i <= symm_conf.fold_tree().num_jump(); ++i){
1092  // using ObjexxFCL::fmt::I;
1093  // Size up = symm_conf.fold_tree().upstream_jump_residue(i);
1094  // Size dn = symm_conf.fold_tree().downstream_jump_residue(i);
1095  // TR << "JUMP " << I(3,i) << " " << I(4,up) << " -> " << I(4,dn)
1096  // << " " << (symm_conf.Symmetry_Info()->jump_is_independent(i) ? "I" : " ")
1097  // << " " << I(3,symm_conf.Symmetry_Info()->jump_follows(i))
1098  // << " " << labels[up] << " " << labels[dn]
1099  // << " " << (dofs.find(i)!=dofs.end() ? "DOF" : "" )
1100  // << std::endl;
1101  // }
1102 
1103  return core::kinematics::visualize_fold_tree(symm_conf.fold_tree(),labels,mark_jump_to_res,jump_follows);
1104 
1105 }
1106 
1107 
1108 } // symmetry
1109 } // pose
1110 } // core