Rosetta 3.5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
Translator.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/chemical/ChemicalManager.cc
11 /// @brief Chemical manager class
12 /// @author Oliver Lange (olange@u.washington.edu)
13 
15 // AUTO-REMOVED #include <core/coarse/TranslatorSet.hh>
16 
17 #include <core/pose/Pose.hh>
23 // AUTO-REMOVED #include <core/scoring/ScoreFunction.hh>
24 
25 #include <ObjexxFCL/string.functions.hh>
26 
27 //Auto Headers
29 #include <core/id/DOF_ID.hh>
30 
31 #include <numeric/NumericTraits.hh>
32 
33 using namespace core;
34 using namespace coarse;
35 using namespace std;
36 using namespace conformation;
37 using namespace chemical;
38 using namespace ObjexxFCL;
39 
40 using namespace pack::dunbrack;
41 
42 /// must be a better place for this, already exists in ResidueType.cc!
43 inline
46 {
47  std::string trimmed_name( name );
48  left_justify( trimmed_name ); trim( trimmed_name ); // simpler way to dothis?
49  return trimmed_name;
50 }
51 
52 void Translator::pretty_print(std::ostream& os) const {
53  int bead_nr=0;
54  os << "==============================" << endl;
55  os << "Coarse-Graining for residue " << fine_res_type_->name() << endl;
56  os << "-------------------------------" << endl;
57  for (BeadList::const_iterator it=beads_.begin(), eit=beads_.end(); it!=eit;++it,++bead_nr) {
58  os << bead_names_[bead_nr] << endl;
59  for (AtomList::const_iterator ait=it->begin(), eait=it->end(); ait!=eait; ++ait) {
60  os << ait->name_ << " ";
61  };
62  os << endl;
63  };
64  os << "==============================" << endl;
65 }
66 int
68  return coarse_res_type_->nchi();
69 }
70 
71 std::string const &
73  return coarse_res_type_->name();
74 }
75 
76 
77 void
78 Translator::add_atom(AtomList &list, const ResidueType &res, int pos) {
79  add_atom(list,res,res.atom_name(pos));
80 }
81 
82 void
83 Translator::add_atom(AtomList &list, const ResidueType &res, const Rule::AtomToken &atom) {
84  /* careful: although the ResidueType understands atomnames like "CB" its function atom_name yields " CB ",
85  so we store only the "stripped" version of atom_names in our list */
86  int pos = -1;
87  if (res.has(atom)) {
88  pos=res.atom_index(atom);
89  if (map_atom_to_bead(atom)<0) {
90  list.push_back(BeadAtom(strip_whitespace(atom),1.0));
91  for (uint na=res.attached_H_begin(pos);na<=res.attached_H_end(pos);na++) {
92  if (map_atom_to_bead(res.atom_name(na))<0) {
93  list.push_back(BeadAtom(strip_whitespace(res.atom_name(na)),0.0));
94  }
95  };
96  };
97  }
98 }
99 
100 
102  // returns bead-position of atom at pos in full_atom
103  // returns -1 if atom not found
104  bool bfound=false;
105  AtomList::const_iterator ait;
106  int bead_nr=0;
107  //WEIGHT: Find will not work anymore
108  for (BeadList::const_iterator it=beads_.begin(), eit=beads_.end(); it!=eit && !bfound;++it,bead_nr++) {
109  bfound=((ait=find(it->begin(),it->end(),strip_whitespace(atom)))!=it->end());
110  };
111 
112  return bfound ? bead_nr : -1;
113 }
114 
115 
116 void
118  for (uint pos=res.first_sidechain_atom(); pos<=res.nheavyatoms(); ++pos) {
119  add_atom(list,res,pos);
120  };
121 }
122 
123 void
125  for (uint pos=1; pos<=res.nheavyatoms(); ++pos) {
126  add_atom(list,res,pos);
127  };
128 }
129 
130 Translator::Translator(const RuleSet &rules, ResidueTypeCOP fine_res_ptr, ResidueTypeAP coarse_res_ptr) {
131  coarse_res_type_=coarse_res_ptr;
132  coarse_res_type_->set_translator(TranslatorCAP(this));
133  fine_res_type_=fine_res_ptr;
134  ResidueType const &fine_res=(*fine_res_ptr);
135  ResidueType const &coarse_res=(*coarse_res_ptr);
136  assert( coarse_res.name() == fine_res.name() );
137 
138  chemical::AA aa = fine_res.aa();
139  beads_.clear();
140  beads_.resize(1); //make space for "full_atom" at pos 0;
141  bead_names_.clear(); bead_names_.push_back(Rule::FULL_ATOM);
142 
143  RuleCOP rule = rules[aa];
144  for (Rule::ConstBeadIterator it=rule->begin(), eit=rule->end(); it!=eit; ++it) {
145  AtomList *pal;
146  if (it->first==Rule::FULL_ATOM) {
147  pal=&beads_.front();
148  } else {
149  // start "ingredient list" for the current coarse-bead
150  beads_.push_back(AtomList());
151 
152  // put bead name into bead_names_ Full-Atom is already at position 0
153  bead_names_.push_back(it->first);
154  pal=&beads_.back();
155  }
156 
157 
158  cerr << "add bead " << it->first << endl;
159 
160  AtomList &al=*pal;
161  for (Rule::ConstTokenIterator ait=it->second.begin(), eait=it->second.end(); ait!=eait; ++ait) {
162  Rule::AtomToken token=*ait;
163  if (token==Rule::REST_SIDECHAIN) {
164  add_remaining_sidechain(al,fine_res);
165  } else if (token==Rule::REST_ALL) {
166  add_all_remaining(al,fine_res);
167  } else
168  add_atom(al,fine_res,token);
169  }
170  }
171 
172  // check for FULL_ATOM that both residues contain the atom name
173  AtomList &full_atom=beads_.front();
174  for (AtomList::const_iterator ait=full_atom.begin(),eait=full_atom.end(); ait!=eait; ++ait) {
175  cerr << ait->name_ << endl;
176  assert( fine_res.has(ait->name_) && coarse_res.has(ait->name_) );
177  };
178 
179  //fix bond lengths, angles, etc.
180  // ResidueType const * ptr = &(*coarse_res_ptr);
181  // ResidueType *non_cons = const_cast< ResidueType* > (ptr);
182  //fix_coarsetype_geometry(ResidueTypeOP( non_cons ));
183  fix_coarsetype_geometry( coarse_res_ptr );
184 }
185 
187  //creates fine-residue instance, coarse grains it and reads out the coarse-geometry
188 
189  //create fine residue instance
190  ResidueOP frsd = ResidueFactory::create_residue(*fine_res_type_);
191 
192  //coarse grain
193  ResidueOP crsd = coarsify(*frsd);
194 
195  for (Size ai=1;ai<=crsd->natoms();ai++) {
196  // c_type->atom(ai).xyz( crsd->atom(ai).xyz() );
197  // change in interface of residuetype
198  c_type->set_xyz( ai, crsd->atom(ai).xyz() );
199  }
200 }
201 
202 
203 ResidueOP Translator::coarsify(const Residue &fine) const {
204  ResidueOP new_rsd( ResidueFactory::create_residue( *coarse_res_type_ ) );
205  int bead_nr=0;
206  for (BeadList::const_iterator it=beads_.begin(), eit=beads_.end(); it!=eit;++it,++bead_nr) {
207  core::Vector cen(0.0,0.0,0.0);
208  Real sum_weight=0;
209  for (AtomList::const_iterator ait=it->begin(), eait=it->end(); ait!=eait; ++ait) {
210  if (bead_nr==0) {
211  //full_atom copy them
212  // cerr << "copy atom " << *ait << fine.atom(*ait).xyz()[1] << endl;
213  new_rsd->atom(ait->name_).xyz(fine.atom(ait->name_).xyz());
214  // cout << "atom type of bead " << bead_names_[bead_nr] << " " << ait->name_ << " is " << new_rsd->atom(ait->name_).type() << endl;
215  } else {
216  //coarse_grain compute mean
217  cen+=fine.atom(ait->name_).xyz()*ait->weight_;
218  sum_weight+=ait->weight_;
219  // Vector tmp=cen/natom;
220  // cerr << "add bead atom " << *ait << fine.atom(*ait).xyz()[1] <<' ';
221  // cerr << tmp[1] << endl;
222 
223  };
224  };
225  if (bead_nr>0) {
226  // coarse grained set bead coordinates
227  if (sum_weight>0.0) {
228  new_rsd->atom(bead_names_[bead_nr]).xyz(cen/sum_weight);
229  // cout << "atom type of bead " << bead_names_[bead_nr] << " is " << new_rsd->atom(bead_names_[bead_nr]).type() << endl;
230  } else {
231  cerr << "WARNING: empty bead " << bead_names_[bead_nr] << " in residue " << coarse_res_type_->name() << endl;
232  };
233  }
234  }
235  return new_rsd;
236 }
237 
238 // some helper functions for the coarsification of SingleResidueDunbrackLibraries
239 
240 bool match_mask(RotVector const& mask, int nchi, DunbrackRotamer< FOUR, Real > const & rotamer );
241 
242 bool update_mask(RotVector& mask,int nchi,RotVector const &max_bins);
243 
245  Translator const& map,
246  ResidueTypeCOP fine_res_type,
247  DunbrackRotamer< FOUR, Real > const& rotamer
248 );
249 
251  utility::vector1< DunbrackRotamer< FOUR > > const & fine_rotamers,
252  RotVector const& mask,
253  Size nchi,
254  Real &pnew
255 );
256 
257 void coarse_rotamer(
258  Translator const& map,
259  ResidueTypeCOP fine_res_type,
260  ResidueTypeCOP coarse_res_type,
261  DunbrackRotamer< FOUR, Real > const& rotamer,
262  Size nchi,
263  ChiVector &chi,
264  AngleVector &angle
265 );
266 
267 void average_rotamers(
268  Translator const& map,
269  ResidueTypeCOP fine_res_type,
270  ResidueTypeCOP coarse_res_type,
271  utility::vector1< DunbrackRotamer< FOUR > > const & fine_rotamers,
272  RotVector const& mask,
273  Size nchi,
274  ChiVector &chi_mean,
275  ChiVector &chi_std,
276  AngleVector &angle_mean,
277  AngleVector &angle_std
278 );
279 
280 
283  utility::vector1< DunbrackRotamer< FOUR > > const & fine_rotamers
284 ) const
285 {
286 
287  using namespace scoring;
288  using namespace pack::dunbrack;
289  using namespace conformation;
290  using namespace std;
291  bool bAverage( false ); //use most frequent chi/angle for coarse rotamer
292 
293  CoarseRotamerSetOP coarse_rotset = new CoarseRotamerSet;
294  assert(coarse_rotset);
295  //coarse_rotset->tag="coarse";
296  Size nchi=coarse_res_type_->nchi();
297  assert(nchi==1); //this is only correct in the current version... a debuggin' assert
298 
299  RotVector mask(4);
300  RotVector max_bins(nchi);
301 
302  { //set mask to first rotamer_id
303  for (Size chi=1;chi<=nchi; chi++) {
304  mask[chi]=1;
305  max_bins[chi]=3; // is that always so ?
306  };
307  for (Size chi=nchi+1;chi<=4; chi++) {
308  mask[chi]=0;
309  };
310  }
311 
312  do { //while( update_mask(...) )
313  Real pnew;
314  int rot_freq = find_most_frequent_rotamer( fine_rotamers, mask, nchi, pnew );
315  //assert ( nchi == fine_rotamers[ rot_freq ].nchi_aa() ); //case of inequality might occur and then we need to think about it...
316  ChiVector new_chi( 4, 0.0 ); //initialize with 0
317  AngleVector new_angle( 4, 0.0 );
318  DunbrackRotamer< FOUR, Real > fine_high_res = increase_rotamer_precision( fine_rotamers[ rot_freq ] );
319  coarse_rotamer( *this, fine_res_type_, coarse_res_type_, fine_high_res, nchi, new_chi, new_angle );
320 
321  ChiVector chi_mean( 4, 0.0 ); //initialize with 0
322  ChiVector chi_std( 4, 0.0 );
323  AngleVector angle_mean( 4, 0.0 );
324  AngleVector angle_std( 4, 0.0 );
325  average_rotamers( *this, fine_res_type_, coarse_res_type_, fine_rotamers, mask, nchi, chi_mean, chi_std, angle_mean, angle_std );
326 
327  CoarseRotamerOP coarse_rot;
328  if ( bAverage ) {
329  coarse_rot = new CoarseRotamer( pnew, nchi, mask, chi_mean, chi_std, angle_mean, angle_std );
330  } else {
331  coarse_rot = new CoarseRotamer( pnew, nchi, mask, new_chi, chi_std, new_angle, angle_std );
332  }
333  coarse_rotset->push_back(coarse_rot);
334 
335  } while ( update_mask( mask, nchi, max_bins ) );
336  // You could use a lexicographical iterator here...
337 
338  return coarse_rotset;
339 }
340 
343  std::cerr << "Translator::get_RotamerLibrary() for " << name() << std::endl;
344  //SingleResidueRotamerLibraryCAP rotlib (fine_res_type_->get_RotamerLibrary());
345  //if (rotlib) return rotlib->coarsify(*this);
346  //else
347  return NULL;
348 }
349 
350 
351 bool update_mask(RotVector& mask,int nchi,RotVector const &max_bins) {
352  int chi=1;
353  while (++mask[chi]>max_bins[chi]) {
354  mask[chi++]=1;
355  if (chi>nchi) return false;
356  }
357  return true;
358 }
359 
360 // does a coarse rotamer 13xx match to the fine grain 1332 ?
361 // mask: 13xx
362 // nchi: length of mask (e.g, 2)
363 // rotid: 1321
364 bool match_mask(RotVector const& mask, int nchi, DunbrackRotamer< FOUR, Real > const & rotamer ) {
365  int chi=1;
366  while ( mask[chi] == rotamer.rotwell(chi) ) {
367  chi++;
368  if ( chi>nchi ) return true;
369  };
370  return false;
371 }
372 
373 inline Real sqr ( Real x ) {
374  return x*x;
375 }
376 inline Real sqr3 ( Real x ) {
377  return x*x*x;
378 }
379 
382  Translator const& map,
383  ResidueTypeCOP fine_res_type,
384  DunbrackRotamer< FOUR, Real > const & rotamer
385 )
386 {
387  ResidueOP fine_res = ResidueFactory::create_residue( *fine_res_type );
388  //real-world representation of rotamer
389  for ( Size jj = 1; jj <= std::min( Size( 4 ), fine_res_type->nchi()); ++jj ) { // apl needs info from DunLib
390  fine_res->set_chi( jj, rotamer.chi_mean( jj ) );
391  }
392 
393  //coarse representation of rotamer
394  ResidueOP coarse_res = map.coarsify(*fine_res);
395  pose::PoseOP pose = new pose::Pose;
396  pose->clear();
397  pose->append_residue_by_bond(*coarse_res);
398  pose->fold_tree( kinematics::FoldTree( pose->total_residue() ) );
399  // @phil: might be nice to have a method update_internals() in Residue
400  // other thing: I think it is counter-intuitive that pose clones the residue
401  // that is passed in.
402  // might have good reasons -- might be a remnant of the old design, where you
403  // had to make clones from the "ideal" residues.
404  return pose;
405 }
406 
407 
409  Translator const& map,
410  ResidueTypeCOP fine_res_type,
411  ResidueTypeCOP coarse_res_type,
412  DunbrackRotamer< FOUR, Real > const & rotamer,
413  Size nchi,
414  ChiVector &chi,
415  AngleVector &angle
416 ) {
417  const Real Pi = numeric::NumericTraits<Real>::pi();
418 
419  pose::PoseOP pose ( create_rotamer(map, fine_res_type, rotamer) );
420  for ( Size jj = 1; jj<=nchi; ++jj) {
421  chemical::AtomIndices chi_atoms = coarse_res_type->chi_atoms( jj );
422  const Size seqpos ( 1 ); //only one residue in artifical pose
423  chi[jj] = pose->chi( jj, seqpos);
424  angle[jj] = 180.0/Pi*pose->dof( id::DOF_ID( id::AtomID( chi_atoms[4], seqpos ),id::THETA) );
425  }
426 }
427 
428 
430  Translator const& map,
431  ResidueTypeCOP fine_res_type,
432  ResidueTypeCOP coarse_res_type,
433  utility::vector1< DunbrackRotamer< FOUR > > const & fine_rotamers,
434  RotVector const& mask,
435  Size nchi,
436  ChiVector &chi_mean,
437  ChiVector &chi_std,
438  AngleVector &angle_mean,
439  AngleVector &angle_std
440 )
441 {
442  const Real Pi = numeric::NumericTraits<Real>::pi();
443  //run thru all rotamers to get sdev's
444 
445  Real pnew( 0.0 );
446  FArray2D< Real > xy_mean_chi( nchi, 2, 0.0 );
447  FArray2D< Real > xy_mean_angle( nchi, 2, 0.0 );
448 
449  for ( Size i=1; i<=fine_rotamers.size(); i++) {
450  DunbrackRotamer< FOUR, Real > const rotamer = increase_rotamer_precision( fine_rotamers[i] );
451  if ( match_mask( mask, nchi, rotamer ) ) {
452 
453  Real p = rotamer.rotamer_probability();
454  ChiVector newChi( 4, 0.0 );
455  ChiVector newAngle( 4, 0.0 );
456  coarse_rotamer( map, fine_res_type, coarse_res_type, rotamer, nchi, newChi, newAngle );
457  for ( Size jj = 1; jj <= nchi; ++jj) {
458  Real r_chi = 1-sqr3(rotamer.chi_sd(jj)/180.0*Pi)/2.0;
459  xy_mean_chi( jj, 1)+= p * std::sin( newChi[jj] ) * r_chi;
460  xy_mean_chi( jj, 2)+= p * std::cos( newChi[jj] ) * r_chi;
461 
462  xy_mean_angle( jj, 1)+= p * std::sin( newAngle[jj] );
463  xy_mean_angle( jj, 2)+= p * std::cos( newAngle[jj] );
464  };
465  pnew+=p;
466  } //match mask
467  } // for loop
468 
469  for ( Size jj = 1; jj<=nchi; ++jj) {
470  chi_mean[jj]=std::atan2( xy_mean_chi(jj,1), xy_mean_chi(jj,2) ) * 180/Pi;
471  angle_mean[jj]=std::atan2( xy_mean_angle(jj,1), xy_mean_angle(jj,2) ) * 180/Pi;
472  if (pnew>1e-7) {
473  Real r_chi = std::sqrt( sqr( xy_mean_chi( jj, 1 ) )+sqr( xy_mean_chi( jj, 2) ) )/pnew;
474  chi_std[jj] = pow( 2.0 * ( 1.0-r_chi ), 1/3.0 ) * 180 / Pi;
475  Real r_ang = std::sqrt( sqr( xy_mean_angle( jj, 1 ) )+sqr( xy_mean_angle( jj, 2) ) )/pnew;
476  angle_std[jj] = pow( 2.0 * (1.0 - r_ang), 1/3.0 ) * 180 / Pi;
477  } else {
478  chi_std[jj]=10; // it doesn't matter just avoid a nan...
479  angle_std[jj]=10;
480  }
481  }
482 }
483 
485  utility::vector1< DunbrackRotamer< FOUR > > const & fine_rotamers,
486  RotVector const& mask,
487  Size nchi,
488  Real & pnew
489 )
490 { // find most frequent rotamer
491  using namespace pack::dunbrack;
492 
493  int rot_freq ( -1 );
494  Real pmax ( -1.0 );
495  pnew = 0.0;
496  for (Size i=1; i<=fine_rotamers.size(); i++) {
497  DunbrackRotamer< FOUR, Real > const rotamer = increase_rotamer_precision( fine_rotamers[i] );
498  if ( match_mask( mask, nchi, rotamer ) ) {
499  Real p = rotamer.rotamer_probability();
500  if ( p > pmax ) {
501  pmax = p;
502  rot_freq=i;
503  pnew+=p;
504  }
505  }
506  }
507  return rot_freq;
508 }
509