Rosetta 3.5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
WriteUpstreamCoordinateKineamge.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 // :noTabs=false:tabSize=4:indentSize=4:
4 //
5 // (c) Copyright Rosetta Commons Member Institutions.
6 // (c) This file is part of the Rosetta software suite and is made available under license.
7 // (c) The Rosetta software is developed by the contributing members of the Rosetta Commons.
8 // (c) For more information, see http://www.rosettacommons.org. Questions about this can be
9 // (c) addressed to University of Washington UW TechTransfer, email: license@u.washington.edu.
10 
11 /// @file protocols/match/DownstreamAlgorithm.cc
12 /// @brief
13 /// @author Alex Zanghellini (zanghell@u.washington.edu)
14 /// @author Andrew Leaver-Fay (aleaverfay@gmail.com), porting to mini
15 
16 // Unit headers
18 
19 // Package headers
20 // AUTO-REMOVED #include <protocols/match/BumpGrid.hh>
23 
24 // Project headers
27 
28 // Utility headers
29 #include <utility/pointer/ReferenceCount.hh>
30 #include <utility/string_util.hh>
31 
32 // C++ headers
33 #include <list>
34 
36 #include <core/id/AtomID.hh>
37 #include <protocols/match/Hit.hh>
38 #include <utility/vector1.hh>
39 
40 
41 namespace protocols {
42 namespace match {
43 namespace output {
44 
45 /// TWO FUNCTIONS STOLEN FROM IAN: and slightly modified.
47  std::ostream & out,
48  int residue_num,
49  int atom_num,
50  core::Vector const & atom_xyz,
51  core::chemical::ResidueType const & res,
52  std::string extras = "" //< P for points, color, width/radius, etc.
53 )
54 {
55  // atom_num is often 0 in fold tree, means no specific atom.
56  // might as well use the first() one:
57  if (atom_num == 0) atom_num = 1;
58  core::chemical::AtomType const & atom_type = res.atom_type(atom_num);
59  // This info appears when you click on the point
60  out << "{" << res.name3() << " " << residue_num
61  << " " << res.atom_name(atom_num) << " (" << atom_type.name() << ")"
62  << "}";
63  // Color, width, etc. followed by coordinates
64  //out << "col" << residue_num << " ";
65  out << extras;
66  out << " " << atom_xyz.x() << " " << atom_xyz.y() << " " << atom_xyz.z() << "\n";
67 }
68 
70  std::ostream & out,
71  int residue_num,
72  int atom_num,
73  core::conformation::Residue const & res,
74  std::string extras = "" //< P for points, color, width/radius, etc.
75 )
76 {
77  print_node( out, residue_num, atom_num, res.xyz( atom_num ), res.type(), extras );
78 }
79 
80 
82  std::ostream & out,
83  int residue_num,
84  std::string atom_name,
85  core::conformation::Residue const & res,
86  std::string extras = "" //< P for points, color, width/radius, etc.
87 )
88 {
89  // atom_num is often 0 in fold tree, means no specific atom.
90  // might as well use the first one:
91 
92  int atom_num;
93  if (atom_name == "") {
94  atom_num = 1;
95  } else {
96  atom_num = res.atom_index( atom_name );
97  }
98  print_node( out, residue_num, atom_num, res, extras );
99 }
100 
102  master_( "" ),
103  dominant_( true ),
104  animate_( true ),
105  group_( true ),
106  write_virtual_atoms_( false )
107 {}
108 
109 /// @details Don't write out multiple copies of the upstream coordinates if you're
110 /// drawing multiple instances of the downstream partner from a single rotamer. Instead,
111 /// use the kinemage "instance" flag to point to the coordinates already written out
112 /// in this file. This creates a smaller output file.
113 void
115  std::ostream & ostr,
116  Size const scaffold_build_point_id,
117  Size const upstream_conf_id,
118  core::conformation::Residue const & rsd,
119  bool is_instance /* = false */
120 ) const
121 {
122 
123  // intra-residue connections
124  // do residues in different (~random) colors to help distinguish them
125  //int const num_colors = 6;
126  //std::string colors[num_colors] = {"pinktint", "peachtint", "yellowtint", "greentint", "bluetint", "lilactint"};
127  //std::string color = colors[ rsd.seqpos() % num_colors ];
128  std::string color = "bluetint";
129 
130  std::string tag = "";
131 
132  ostr << "@" << ( group_ ? "group" : "subgroup" ) << " { rot" << upstream_conf_id << " }";
133  if ( animate_ ) ostr << " animate";
134  if ( dominant_ ) ostr << " dominant";
135  ostr << "\n";
136  ostr << "@vectorlist {";
137  if ( is_instance ) {
138  ostr << rsd.name() << " " << scaffold_build_point_id << " " << upstream_conf_id;
139  } else {
140  ostr << rsd.name() << " " << scaffold_build_point_id;
141  }
142  ostr << "} color= " << color;
143  if ( master_ != "" ) ostr << " master= {" << master_ << "}";
144  if ( is_instance ) {
145  ostr << " instance= {" << rsd.name() << " " << scaffold_build_point_id << "}";
146  }
147  ostr << "\n";
148 
149  if ( ! is_instance ) {
150  for( core::Size atom_i = 1; atom_i <= rsd.natoms(); ++atom_i) {
151  core::conformation::Residue::AtomIndices const & nbrs = rsd.nbrs(atom_i);
152  for(core::conformation::Residue::AtomIndices::const_iterator j = nbrs.begin(), end_j = nbrs.end(); j != end_j; ++j) {
153  core::Size atom_j = *j;
154  if(atom_j <= atom_i) continue; // so we draw each bond just once, not twice
155  bool const is_H = rsd.atom_is_hydrogen(atom_j) || rsd.atom_is_hydrogen(atom_i);
156 
157  if ( ! write_virtual_atoms_ && ( rsd.atom_type( atom_i ).element() == "X" || rsd.atom_type( atom_j ).element() == "X" )) continue;
158 
159  /// no backbone hydrogens...
160  if ( rsd.atom_is_backbone( atom_i ) && rsd.atom_is_hydrogen( atom_i ) ) continue;
161  if ( rsd.atom_is_backbone( atom_j ) && rsd.atom_is_hydrogen( atom_j ) ) continue;
162  std::string const ptmaster = ( is_H ? " 'h'" : "" );
163  print_node( ostr, rsd.seqpos(), atom_i, rsd, tag+"P"+ptmaster);
164  print_node( ostr, rsd.seqpos(), atom_j, rsd, tag+ptmaster);
165  }
166  }
167  }
168 }
169 
170 
171 void ResidueKinemageWriter::dominant( bool setting ) { dominant_ = setting; }
172 void ResidueKinemageWriter::animate( bool setting ) { animate_ = setting; }
173 void ResidueKinemageWriter::group( bool setting ) { group_ = setting; }
174 void ResidueKinemageWriter::master( std::string const & setting ) { master_ = setting; }
176 
178 ) :
179  DownstreamAlgorithm( 1 ), // our geom_cst_id is irrelevant
180  kinemage_file_name_( "NO_FILE" ),
181  file_out_(),
182  ostr_( file_out_ ),
183  last_scaffold_build_point_( 0 ),
184  nkins_( 0 ),
185  n_downstream_to_output_( 0 ),
186  return_pseudo_hits_( false )
187 {
188 }
189 
190 
192  std::string const & fname
193 ) :
194  DownstreamAlgorithm( 1 ), // our geom_cst_id is irrelevant
195  kinemage_file_name_( fname ),
196  file_out_(),
197  ostr_( file_out_ ),
198  last_scaffold_build_point_( 0 ),
199  nkins_( 0 ),
200  n_downstream_to_output_( 0 ),
201  return_pseudo_hits_( false )
202 {
203  file_out_.open( kinemage_file_name_.c_str() );
204 }
205 
206 
208  std::ostream & ostr
209 ) :
210  DownstreamAlgorithm( 1 ), // our geom_cst_id is irrelevant
211  kinemage_file_name_( "OSTREAM_MODE" ),
212  file_out_(),
213  ostr_( ostr ),
214  last_scaffold_build_point_( 0 ),
215  nkins_( 0 ),
216  n_downstream_to_output_( 0 ),
217  return_pseudo_hits_( false )
218 {
219 }
220 
222 {
223  if ( file_out_.is_open() ) file_out_.close();
224 }
225 
228 {
230 }
231 
232 /// @brief To be invoked by derived classes, this function completes the building of
233 /// the downstream conformation once the coordinates of the upstream conformation
234 /// are known (and deemed non-colliding or, generally, pass any filter the upstream
235 /// builder would use).
236 std::list< Hit >
238  Size const scaffold_build_point_id,
239  Size const upstream_conf_id,
240  core::conformation::Residue const & rsd
241 ) const
242 {
243  std::list< Hit > empty_list;
244  ResidueKinemageWriter writer;
245  writer.master( "rotamers" );
246 
247  if ( last_scaffold_build_point_ != scaffold_build_point_id ) {
248  ostr_ << "@kinemage {" << ++nkins_ << "}\n";
249  ostr_ << "@title { matcher }\n";
250  core::Vector const & ctr( rsd.has( "CB" ) ? rsd.xyz( "CB" ) : rsd.xyz("CA") );
251  ostr_ << "@1center " << ctr.x() << " " << ctr.y() << " " << ctr.z() << "\n";
252  ostr_ << "@1span 25\n";
253  n_output_so_far_ = 0;
254  }
255 
256  last_scaffold_build_point_ = scaffold_build_point_id;
257 
258  if ( match_algorithm_ ) {
259  std::list< Hit > downstream_hits = match_algorithm_->build( scaffold_build_point_id, upstream_conf_id, rsd );
260  if ( n_downstream_to_output_ != 0 && n_output_so_far_ >= n_downstream_to_output_ ) return downstream_hits;
261 
262  if ( dswriter_ ) {
263 
264  /// Write out the upstream residue coord once for each downstream hit so when we're
265  /// animating we'll see the various downstream hits individually with their upstream residue.
266  /// Take advantage of the kinemage "instance" flag so that the coordinates for the
267  /// upstream residue are only written to the file once.
268  for ( std::list< Hit >::const_iterator
269  iter = downstream_hits.begin(), iter_begin = downstream_hits.begin(),
270  iter_end = downstream_hits.end();
271  iter != iter_end; ++iter ) {
272  writer.write_rsd_coords( ostr_, scaffold_build_point_id, upstream_conf_id, rsd, (iter != iter_begin) );
273  dswriter_->write_downstream_coordinates( *iter, ostr_ );
274 
276  if ( n_downstream_to_output_ != 0 && n_output_so_far_ >= n_downstream_to_output_ ) return downstream_hits;
277 
278  }
279  } else {
280  if ( n_downstream_to_output_ != 0 && n_output_so_far_ >= n_downstream_to_output_ ) return downstream_hits;
281 
282  /// write out the conformation if it generates at least one hit, but exclude it otherwise.
283  if ( ! downstream_hits.empty() ) {
284  writer.write_rsd_coords( ostr_, scaffold_build_point_id, upstream_conf_id, rsd );
286  if ( n_downstream_to_output_ != 0 && n_output_so_far_ >= n_downstream_to_output_ ) return downstream_hits;
287  }
288  }
289  return downstream_hits; // return the set of found hits -- maybe someone listening wants them.
290  } else {
291  if ( n_downstream_to_output_ != 0 && n_output_so_far_ >= n_downstream_to_output_ ) return empty_list;
292 
293  writer.write_rsd_coords( ostr_, scaffold_build_point_id, upstream_conf_id, rsd );
295  }
296 
297  if ( return_pseudo_hits_ ) {
298  Hit hit;
299  hit.first()[ 1 ] = scaffold_build_point_id;
300  hit.first()[ 2 ] = upstream_conf_id;
301  empty_list.push_back( hit );
302  }
303 
304  return empty_list;
305 }
306 
307 /// @details This is an acceptalbe return value for this debugging-purposed class.
308 bool
310 {
311  return false;
312 }
313 
314 bool
316 {
317  return true;
318 }
319 
320 
321 /// @details If this function is causing an exit, then there is a bug within the Matcher's
322 /// match-enumeration logic. There is no meaningful way forward after this function is invoked.
323 /// It should not be invoked. Truely, this class should not be used in match enumeration.
326 {
327  HitPtrListCOP empty;
328  utility_exit_with_message( "Cannot invoke WriteUpstreamCoordinateKinemage::hits_to_include_with_partial_match()" );
329  return empty;
330 }
331 
334 {
335  if ( match_algorithm_ ) {
336  return match_algorithm_->n_possible_hits_per_upstream_conformation();
337  } else {
338  return 0;
339  }
340 }
341 
342 
343 void
345 {
346  if ( kinemage_file_name_ == "OSTREAM_MODE" ) {
347  utility_exit_with_message( "ERROR: Cannot set kinemage file name when in ostream mode" );
348  }
350  if ( file_out_.is_open() ) file_out_.close();
351  file_out_.open( kinemage_file_name_.c_str() );
352 
353 }
354 
355 void
357 {
358  match_algorithm_ = algorithm;
359 }
360 
361 void
363 {
364  dswriter_ = dswriter;
365 }
366 
367 void
369 {
370  n_downstream_to_output_ = n_downstream_to_output;
371 }
372 
374  :
375  matches_output_count_( 0 ),
376  use_default_master_( true ),
377  animate_( false ),
378  dominant_( false ),
379  group_( false ),
380  write_virtual_atoms_( false ),
381  geom_id_( 0 ),
382  kinemage_file_name_( "NO_FILE" ),
383  file_out_(),
384  ostr_( file_out_ )
385 {}
386 
388  std::string const & fname
389 ) :
390  matches_output_count_( 0 ),
391  use_default_master_( true ),
392  animate_( false ),
393  dominant_( false ),
394  group_( false ),
395  write_virtual_atoms_( false ),
396  geom_id_( 0 ),
397  kinemage_file_name_( fname ),
398  file_out_(),
399  ostr_( file_out_ )
400 {
401  file_out_.open( kinemage_file_name_.c_str() );
402 }
403 
404 
406  matches_output_count_( 0 ),
407  use_default_master_( true ),
408  animate_( false ),
409  dominant_( false ),
410  group_( false ),
411  write_virtual_atoms_( false ),
412  geom_id_( 0 ),
413  kinemage_file_name_( "OSTREAM_MODE" ),
414  file_out_(),
415  ostr_( ostr )
416 {}
417 
419 {
420  if ( file_out_.is_open() ) file_out_.close();
421 }
422 
423 void
425  Hit const & hit,
426  core::conformation::Residue const & upstream_conformation
427 )
428 {
429  output_hit( hit, upstream_conformation );
430 }
431 
432 void
434  Hit const & hit,
435  core::conformation::Residue const & upstream_conformation
436 )
437 {
438  output_upstream_coordinates( hit, upstream_conformation );
439  if ( dswriter_ ) {
440  dswriter_->write_downstream_coordinates( hit, ostr_ );
441  }
442 }
443 
444 void
446  upstream_hit const & hit,
447  core::conformation::Residue const & upstream_conformation
448 )
449 {
450  ResidueKinemageWriter writer;
451  writer.dominant( dominant_ ); writer.animate( animate_ ); writer.group( group_ );
452 
453  /// set the master
454  if ( use_default_master_ ) {
455  writer.master( "geom" + utility::to_string( geom_id_ ) );
456  } else if ( master_ != "" ) {
457  writer.master( master_ );
458  }
459 
460  writer.write_rsd_coords( ostr_, hit.scaffold_build_id(), hit.upstream_conf_id(), upstream_conformation, false );
461 
462 }
463 
464 
465 void
467 {
468  if ( matches_output_count_ == 0 ) {
469  ostr_ << "@kinemage 1\n";
470  }
472  ostr_ << "@group { match " << matches_output_count_ << " } dominant animate\n";
473 }
474 
475 
476 void
478 {
479  if ( kinemage_file_name_ == "OSTREAM_MODE" ) {
480  utility_exit_with_message( "ERROR: Cannot set kinemage file name when in ostream mode" );
481  }
482  kinemage_file_name_ = fname;
483  if ( file_out_.is_open() ) file_out_.close();
484  file_out_.open( kinemage_file_name_.c_str() );
485 }
486 
487 void
489 {
490  dswriter_ = dswriter;
491 }
492 
494 {
495  geom_id_ = setting;
496  if ( dswriter_ ) {
497  std::string master( "geom" + utility::to_string( geom_id_ ));
498  dswriter_->set_downstream_master( master );
499  }
500 }
501 
502 void
504 {
505  master_ = master;
506  use_default_master_ = false;
507 }
508 
509 void
511 {
512  use_default_master_ = setting;
513 }
514 
515 /// @brief Returns whether or not the default master is being used.
516 bool
518 {
519  return use_default_master_;
520 }
521 
523 {
524  animate_ = setting;
525 }
526 
528 {
529  dominant_ = setting;
530 }
531 
533 {
534  group_ = setting;
535 }
536 
538 {
539  write_virtual_atoms_ = setting;
540 }
541 
542 
545 
546 
548 
550 
551 
552 void
554  Hit const & hit,
555  std::ostream & ostr
556 ) const
557 {
558  //std::cout << "outputting hit: ";
559  //for ( Size ii = 1; ii <= 6; ++ii ) {
560  // std::cout << hit.second[ ii ] << " ";
561  //}
562  //std::cout << std::endl;
563 
564  if ( ! restype_ ) {
565  utility_exit_with_message( "ERROR: SingleDownstreamResidueWriter must have its residue type initialized!" );
566  }
567 
568  utility::vector1< core::Vector > coords( restype_->natoms() );
569  dsbuilder_->coordinates_from_hit( hit, all_atom_inds_, coords );
570 
571  // intra-residue connections
572  // do residues in different (~random) colors to help distinguish them
573  //int const num_colors = 6;
574  //std::string colors[num_colors] = {"pinktint", "peachtint", "yellowtint", "greentint", "bluetint", "lilactint"};
575  //std::string color = colors[ rsd.seqpos() % num_colors ];
576  std::string color = "greentint";
577 
578  std::string tag = "";
579 
580  ostr << "@vectorlist {" << restype_->name() << " " << hit.first()[ 1 ] << " " << hit.first()[ 2 ] << " " << hit.first()[ 3 ];
581  ostr << "} color= " << color << " master= {rotamers}";
582  if ( master_ != "" ) {
583  ostr << " master= {" << master_ << "}";
584  }
585  ostr << "\n";
586 
587  for ( core::Size atom_i = 1; atom_i <= restype_->natoms(); ++atom_i) {
588  core::chemical::AtomIndices const & nbrs = restype_->nbrs(atom_i);
589  for(core::chemical::AtomIndices::const_iterator j = nbrs.begin(), end_j = nbrs.end(); j != end_j; ++j) {
590  core::Size atom_j = *j;
591  if ( atom_j <= atom_i ) continue; // so we draw each bond just once, not twice
592  bool const is_H = restype_->atom_is_hydrogen(atom_j) || restype_->atom_is_hydrogen(atom_i);
593  /// no backbone hydrogens...
594 
595  /// Don't write virtual atoms.
596  if ( restype_->atom_type( atom_i ).element() == "X" || restype_->atom_type( atom_j ).element() == "X" ) continue;
597 
598  ///if ( restype_->atom_is_backbone( atom_i ) && restype_->atom_is_hydrogen( atom_i ) ) continue;
599  ///if ( restype_->atom_is_backbone( atom_j ) && restype_->atom_is_hydrogen( atom_j ) ) continue;
600  std::string const ptmaster = ( is_H ? " 'h'" : "" );
601  print_node( ostr, hit.first()[ 1 ], atom_i, coords[ atom_i ], *restype_, tag+"P"+ptmaster);
602  print_node( ostr, hit.first()[ 1 ], atom_j, coords[ atom_j ], *restype_, tag+ptmaster);
603  }
604  }
605 
606 }
607 
608 void
610 {
611  restype_ = restype;
612  all_atom_inds_.resize( restype_->natoms() );
613  for ( Size ii = 1; ii <= all_atom_inds_.size(); ++ii ) all_atom_inds_[ ii ] = core::id::AtomID( ii, 1 );
614 }
615 
616 void
618 {
619  dsbuilder_ = dsbuilder;
620 }
621 
622 void
624 {
625  master_ = master;
626 }
627 
628 }
629 }
630 }