Rosetta 3.5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
PDBWriter.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/output/PDBWriter.cc
12 /// @brief Forward declaration of class to write output matches that have (presumably) passed the output filters.
13 /// @author Florian Richter (floric@u.washington.edu), june 09
14 
15 // Unit headers
17 
18 // Package Headers
19 #include <protocols/match/Hit.hh>
24 
25 // Project Headers
27 #include <core/io/pdb/pose_io.hh>
28 #include <core/io/pdb/file_data.hh>
29 #include <core/pose/Remarks.hh>
30 #include <core/pose/Pose.hh>
31 #include <core/pose/PDBInfo.hh>
33 #include <basic/Tracer.hh>
34 
38 
39 // Utility headers
40 #include <utility/string_util.hh>
41 #include <utility/pointer/ReferenceCount.hh>
42 
43 //numeric headers
44 #include <numeric/random/random.hh>
45 
46 #include <fstream>
47 
49 #include <utility/vector1.hh>
50 
51 
52 namespace protocols {
53 namespace match {
54 namespace output {
55 
56 static basic::Tracer TR( "protocols.match.output.PDBWriter" );
57 
59  coordinate_cacher_(NULL),
60  write_matchres_only_(false),
61  scaf_name_(""),
62  cstfile_name_(""),
63  prefix_("UM"),
64  num_written_(0),
65  num_geom_cst_(0)
66 {
67  signature_map_.clear();
69 }
70 
72 
73 
74 void
76 {
77  signature_map_.clear();
78  num_written_ = 0;
79 }
80 
81 
82 void
84 {
87  utility::vector1< core::Size > ex_geom_ids_for_upstream_res;
88 
89  //TR << "NPW recording match w/ hits ";
90  //for( core::Size ii =1; ii <= m.size(); ++ii) TR << &(m[ii]) << ", ";
91  //TR << std::endl;
92 
93 
94  std::map< core::Size, core::Size > redundant_upstream_res;
95  determine_redundant_upstream_matchres( match_dspos1( m, 1 ), redundant_upstream_res );
96 
97  for ( Size ii = 1; ii <= m.size(); ++ii ) {
99  coordinate_cacher_->upstream_conformation_for_hit( ii, m[ ii ] );
100  upstream_matchres.push_back( conf );
101  ex_geom_ids_for_upstream_res.push_back( m[ ii ].external_geom_id() );
102  if ( ! output_dsgeom_for_geomcst_[ ii ] ) continue;
103  if ( dsbuilders_[ ii ] ) {
104  downstream_poses.push_back( dsbuilders_[ ii ]->downstream_pose_from_hit( m[ii] ) );
105  } else {
106  utility_exit_with_message( "Cannot output downstream pose for geomcst id " +
107  utility::to_string( ii ) + " which does not have a downstream builder!" );
108  }
109  }
110 
111  //utility::vector1< core::Size > matchres_seqpos;
113  upstream_matchres, redundant_upstream_res, ex_geom_ids_for_upstream_res );
114  std::string outtag = assemble_outtag( upstream_matchres );
115  core::Size outcounter(1);
116 
117  for ( Size ii = 1; ii <= m.size(); ++ii ) {
118  if ( ! output_dsgeom_for_geomcst_[ ii ] ) continue;
119  std::string this_tag = outtag + "_" + utility::to_string( ii ) + ".pdb";
120 
121  //every match in it's own file for now
122  std::ofstream file_out( this_tag.c_str() );
123  //Size atom_counter(0);
124 
125  up_outpose->dump_pdb( file_out );
126 
127  downstream_poses[ outcounter ]->dump_pdb( file_out );
128  file_out.close();
129  outcounter++;
130  }
131 
132  num_written_++;
133 
134  //if( num_written_ % 100 == 0 ) std::cout << "recored match function called " << num_written_ << "times" <<std::endl;
135 }
136 
137 void
139 {
140 
141  //TR << "NPW recording dspos1 match w/ upstream hits ";
142  //for( core::Size ii =1; ii <= m.upstream_hits.size(); ++ii) TR << &(m.upstream_hits[ii]) << ", ";
143  //TR << std::endl;
144 
145 
146  /// What are we doing here? The Matcher should never have sent us this match.
148 
150  utility_exit_with_message( "Cannot output downstream pose for geomcst id " +
151  utility::to_string( m.originating_geom_cst_for_dspos ) +
152  " which does not have a downstream builder!" );
153  }
154 
156  utility::vector1< core::Size > ex_geom_ids_for_upstream_res;
157 
158  Hit fullhit = full_hit( m );
159 
161  downstream_pose_from_hit( fullhit );
162 
163  /// Does any single residue do double-duty? e.g. is there a residue whose
164  /// sidechain is used in satisfying one geometric constraint, while it's
165  /// backbone is used in another?
166  std::map< core::Size, core::Size > redundant_upstream_res;
167  determine_redundant_upstream_matchres( m, redundant_upstream_res );
168 
169  for ( Size ii = 1; ii <= m.upstream_hits.size(); ++ii ) {
171  coordinate_cacher_->upstream_conformation_for_hit( ii, fake_hit( m.upstream_hits[ ii ] ) );
172  upstream_matchres.push_back( conf );
173  ex_geom_ids_for_upstream_res.push_back( fullhit.external_geom_id() );
174  }
175 
176  //utility::vector1< core::Size > matchres_seqpos;
177 
179  upstream_matchres, redundant_upstream_res, ex_geom_ids_for_upstream_res );
180 
181  std::string outtag = assemble_outtag( upstream_matchres );
182 
183  std::string this_tag = outtag + "_" + utility::to_string( m.originating_geom_cst_for_dspos ) + ".pdb";
184  std::ofstream file_out( this_tag.c_str() );
185  up_outpose->dump_pdb( file_out );
186  downstream_pose->dump_pdb( file_out );
187 
188  num_written_++;
189 
190 }
191 
192 //void
193 //PDBWriter::create_output_pose_from_dspos1_match(
194 // match_dspos1 const & m )
195 //{
196 //}
197 
198 void
200 {
201  coordinate_cacher_ = cacher;
202 }
203 
204 void
206 {
207  prefix_ = prefix;
208 }
209 
210 void
212  MatcherTaskCOP mtask
213 ){
215 
216  orig_upstream_pose_ = mtask->upstream_pose();
217  downstream_pose_from_task_ = mtask->downstream_pose();
218  write_matchres_only_ = mtask->output_matchres_only();
219  num_geom_cst_ = mtask->enz_input_data()->mcfi_lists_size();
221  std::fill( output_dsgeom_for_geomcst_.begin(), output_dsgeom_for_geomcst_.end(), false );
222  dsbuilders_.resize( num_geom_cst_ );
223  for ( core::Size i = 1; i <= mtask->geom_csts_downstream_output().size(); ++i ) {
224  output_dsgeom_for_geomcst_[ mtask->geom_csts_downstream_output()[i] ] = true;
225  }
226  scaf_name_ = mtask->upstream_pose_name();
227  utility::vector1< std::string > cst_path = utility::string_split( mtask->cstfile_name(), '/' );
228  cstfile_name_ = (utility::string_split( cst_path[ cst_path.size() ] , '.' ) )[1];
229  upstream_only_geom_cst_ = mtask->upstream_only_geom_cst();
230 }
231 
232 void
234  Size geomcst_id,
236 ){
237  dsbuilders_[ geomcst_id ] = dsbuilder;
238 }
239 
240 
241 void
243  core::pose::Pose & outpose,
244  utility::vector1< core::conformation::ResidueCOP > const & upstream_matchres,
245  std::map< core::Size, core::Size > const & redundant_upstream_res,
246  utility::vector1< core::Size > const & ex_geom_ids_for_upstream_res
247 ) const
248 {
249 
250  using namespace core::io::pdb;
251 
252  core::pose::Remarks rems;
253 
254  std::string ds_resname = downstream_pose_from_task_->residue(1).name3();
255 
256  for ( core::Size i = 1; i <= upstream_matchres.size(); ++i ) {
257 
259  ri.num = 666; /// really now?
260  std::string upname3( upstream_matchres[ i ]->name3() );
261  std::map< core::Size, core::Size >::const_iterator red_it = redundant_upstream_res.find( i );
262  if( red_it != redundant_upstream_res.end() ){
263  upname3 = upstream_matchres[ red_it->second ]->name3();
264  }
265  std::string upres_chain( utility::to_string( orig_upstream_pose_->pdb_info()->chain( upstream_matchres[ i ]->seqpos() ) ) );
266 
267  std::string targ_resname( ds_resname );
268  std::string targ_chain("X");
269  int targ_seqpos(0);
270  std::map< core::Size, core::Size >::const_iterator upstream_only_it(upstream_only_geom_cst_.find( i ) );
271  if( upstream_only_it != upstream_only_geom_cst_.end() ){
272  targ_resname = upstream_matchres[ upstream_only_it->second ]->name3();
273  targ_chain = utility::to_string( orig_upstream_pose_->pdb_info()->chain( upstream_matchres[ upstream_only_it->second ]->seqpos() ) );
274  targ_seqpos = orig_upstream_pose_->pdb_info()->number( upstream_matchres[ upstream_only_it->second ]->seqpos() );
275  }
277  targ_chain, targ_resname, targ_seqpos, upres_chain, upname3, orig_upstream_pose_->pdb_info()->number( upstream_matchres[ i ]->seqpos() ), i , ex_geom_ids_for_upstream_res[ i ] );
278  rems.push_back( ri );
279 
280  }
281 
282  outpose.pdb_info()->remarks( rems );
283 
284 }
285 
286 
289  utility::vector1< core::conformation::ResidueCOP > const & upstream_matchres,
290  std::map< core::Size, core::Size > const & redundant_upstream_res,
291  utility::vector1< core::Size > const & ex_geom_ids_for_upstream_res
292 )
293 {
294  runtime_assert( ex_geom_ids_for_upstream_res.size() == upstream_matchres.size() );
295  //matchres_seqpos.clear();
296 
297  core::pose::PoseOP outpose;
298 
299  if( write_matchres_only_ ){
300  outpose = new core::pose::Pose();
301 
302  core::pose::PDBInfoOP pdbinf = new core::pose::PDBInfo( *outpose );
303  outpose->pdb_info( pdbinf );
304  }
305 
306  else outpose = new core::pose::Pose( *orig_upstream_pose_ );
307 
308  for ( core::Size i = 1; i <= upstream_matchres.size(); ++i ) {
309  if( redundant_upstream_res.find( i ) != redundant_upstream_res.end() ) continue;
310  //matchres_seqpos.push_back( upstream_matchres[i]->seqpos() );
311  if( write_matchres_only_ ){
312  if( i == 1 ) {
313  outpose->append_residue_by_jump( *(upstream_matchres[i]), 1 );
314  } else {
315  outpose->append_residue_by_bond( *(upstream_matchres[i]) );
316  }
317  outpose->pdb_info()->chain( i, orig_upstream_pose_->pdb_info()->chain( upstream_matchres[i]->seqpos() ) );
318  outpose->pdb_info()->number( i, orig_upstream_pose_->pdb_info()->number( upstream_matchres[i]->seqpos() ) );
319  } else {
320  outpose->replace_residue( upstream_matchres[i]->seqpos(), *(upstream_matchres[i]), false );
321  }
322 
323  }
324 
325  assemble_remark_lines( *outpose, upstream_matchres, redundant_upstream_res, ex_geom_ids_for_upstream_res );
326 
327  //looks like we have to set the pdbinfo obsolete to false
328  outpose->pdb_info()->obsolete( false );
329 
330  return outpose;
331 }
332 
336 ) const
337 {
338  std::string signature("");
339  for ( core::Size i =1; i <= upstream_matchres.size(); ++i ){
340  signature = signature + upstream_matchres[i]->name1() +
341  utility::to_string( orig_upstream_pose_->pdb_info()->number( upstream_matchres[i]->seqpos() ) );
342  }
343  return signature;
344 }
345 
348 {
349  return num_geom_cst_;
350 }
351 
354 {
355  return scaf_name_;
356 }
357 
360 {
361  return cstfile_name_;
362 }
363 
366 {
367  return prefix_;
368 }
369 
370 
373 {
374  return coordinate_cacher_;
375 }
376 
379 {
380  return dsbuilders_;
381 }
382 
383 
387 )
388 {
389 
390  std::string signature( signature_string( upstream_matchres ));
391  //for ( core::Size i =1; i <= upstream_matchres.size(); ++i ){
392  // signature = signature + upstream_matchres[i]->name1() +
393  // utility::to_string( upstream_matchres[i]->seqpos() );
394  //}
395 
396  std::map< std::string, SizePair >::iterator map_it = signature_map_.find( signature );
397  if ( map_it == signature_map_.end() ) {
398  core::Size num_this_um = signature_map_.size() + 1;
399  signature_map_[ signature ] = SizePair( num_this_um, 1 );
400  map_it = signature_map_.find( signature );
401  } else {
402  map_it->second.second++;
403  }
404 
405  std::string unique_string( utility::to_string( map_it->second.first ) + "_" +
406  signature + "_" + utility::to_string( map_it->second.second ) );
407 
408  return prefix_ + "_" + unique_string + "_" + scaf_name_ + "_" + cstfile_name_;
409 }
410 
411 
413  PDBWriter(),
414  grouper_(grouper)
415 {
417 }
418 
420 
421 void
423 {
426  grouper_->reset();
427 }
428 
429 
430 /// @details this class writes output in a form that has no link
431 /// between a downstream conformation and the upstream conf that
432 /// it came from.
433 void
435 {
436  TR << "CloudPDBWriter beginning to output matches for " << match_groups_ushits_.size() << " match groups." << std::endl;
437  core::Size total_ushit_count(0), total_dshit_count(0);
438  for( core::Size ii = 1; ii <= match_groups_ushits_.size(); ++ii){
439  for( core::Size jj =1; jj <= num_geom_cst(); ++jj){
440  total_ushit_count += match_groups_ushits_[ii][jj].size();
441  total_dshit_count += match_groups_dshits_[ii][jj].size();
442  }
443  }
444  TR << "A total of " << total_ushit_count << " upstream hits and " << total_dshit_count << " downstream hits were recorded." << std::endl;
446 
447  //let's save some memory
449 }
450 
451 void
453 {
454  runtime_assert( m.size() == num_geom_cst() );
455  core::Size mgroup( grouper_->assign_group_for_match( m ) );
456  //TR << "CPW recording match for assigned group " << mgroup << " ... " << std::endl;
457 
458  // check if this is a new unqiue match
459  if( mgroup > match_groups_ushits_.size() ){
460  runtime_assert( mgroup == match_groups_ushits_.size() + 1 );
463  representative_group_matches_.push_back( match_dspos1( m, 1 ) );
464  //TR << "CPW pushed back first match for group " << mgroup << " match_group_ushits_.size is " << match_groups_ushits_.size() << ", ex geom id for hit2 is " << m[2].external_geom_id() << std::endl;
465 
467  for ( Size ii = 1; ii <= m.size(); ++ii ) {
468  core::conformation::ResidueCOP conf = coordinate_cacher()->upstream_conformation_for_hit( ii, m[ ii ] );
469  upstream_matchres.push_back( conf );
470 
471  //note the special case here: we don't push back the first because
472  //that will be written out separately
473  if( (ii != 1) && (dsbuilders()[ii]) ){
474  match_groups_dshits_[mgroup][ii].insert( downstream_hit( m[ii] ) );
475  }
476  }
477  unique_match_names_.push_back( prefix() + "_" + utility::to_string( mgroup ) + "_" + signature_string( upstream_matchres ) + "_" + scaf_name() + "_" + cstfile_name() );
478 
479  }
480  else{
481  //TR << "CPW group " << mgroup << " has been previously encountered.. ";
482  for( core::Size ii = 1; ii <= num_geom_cst(); ++ii ){
483  upstream_hit uhit( m[ii] );
484  if( match_groups_ushits_[mgroup][ii].find( uhit ) == match_groups_ushits_[mgroup][ii].end() ){
485  match_groups_ushits_[mgroup][ii].insert( uhit );
486  //TR << " got new uphit for geomcst " << ii << "; ";
487  }
488  if( dsbuilders()[ii] ){
489  downstream_hit dhit( m[ii] );
490  if( match_groups_dshits_[mgroup][ii].find( dhit ) == match_groups_dshits_[mgroup][ii].end() ){
491  match_groups_dshits_[mgroup][ii].insert( dhit );
492  //TR << " got new downhit for geomcst " << ii << "; ";
493  }
494  }
495  }
496  //TR << std::endl;
497  }
498 }
499 
500 
501 void
503 {
504  utility_exit_with_message( "not implemented yet");
505 }
506 
507 void
509 {
510  runtime_assert( match_groups_ushits_.size() == unique_match_names_.size() );
511  for( core::Size ii = 1; ii <= match_groups_ushits_.size(); ++ii){
512 
513  TR << "beginning writing cloud for group " << ii << std::endl;
514  for( core::Size jj =1; jj <= num_geom_cst(); ++jj){
515  TR << match_groups_ushits_[ii][jj].size() << " upstream hits and " << match_groups_dshits_[ii][jj].size() << " downstream hits " << " for geom cst " << jj << std::endl;
516  }
517  TR.flush();
518 
519  //1. for each group, we have to write out the whole pose once
520  std::map< core::Size, core::Size > redundant_upstream_res;
522  utility::vector1< core::Size > ex_geom_ids_for_upstream_res;
523  match_dspos1 const & rep_match( representative_group_matches_[ii] );
524 
525  determine_redundant_upstream_matchres( rep_match, redundant_upstream_res );
527 
528  for ( Size jj = 1; jj <= rep_match.upstream_hits.size(); ++jj ) {
530  coordinate_cacher()->upstream_conformation_for_hit( jj, fake_hit( rep_match.upstream_hits[ jj ] ) );
531  upstream_matchres.push_back( conf );
532  ex_geom_ids_for_upstream_res.push_back( rep_match.upstream_hits[jj].external_geom_id() );
533 
534  if( redundant_upstream_res.find( jj ) != redundant_upstream_res.end() ){
536  }
537  }
539  upstream_matchres, redundant_upstream_res, ex_geom_ids_for_upstream_res );
540  core::pose::PoseCOP downstream_pose = dsbuilders()[ rep_match.originating_geom_cst_for_dspos ]->downstream_pose_from_hit( full_hit( rep_match ) );
541 
542  std::ofstream file_out( (unique_match_names_[ii] + "_1.pdb").c_str() );
543  if( !file_out.is_open() ) utility_exit_with_message("Could not open file with name " + unique_match_names_[ii] + "_1.pdb for outputting matches.");
544 
545  file_out << "MODEL 1\n";
546  up_outpose->dump_pdb( file_out );
547  downstream_pose->dump_pdb( file_out );
548  file_out << "ENDMDL \n";
549 
550  //now spit out the remaining hits in this group
551  core::Size allmodelcount(0), num_files_this_group(1), modelcount(2), atomcounter(0);
552  bool all_hitset_iterators_at_end( false );
553  //UpstreamHitSets const & us_hitset_ref( match_groups_ushits_[ ii ] );
554  while( ! all_hitset_iterators_at_end ){
555  all_hitset_iterators_at_end = true;
556  bool modeltag_written( false );
557 
558  for( core::Size jj = 1; jj <= num_geom_cst(); ++jj ){
559  if( us_hitset_its_[jj] == us_hitset_end_its_[jj] ) continue;
560  all_hitset_iterators_at_end = false;
561 
562  if( !modeltag_written ){
563  file_out << "MODEL "+utility::to_string( modelcount++ )+"\n";
564  modeltag_written = true;
565  }
566  core::conformation::ResidueCOP conf = coordinate_cacher()->upstream_conformation_for_hit( jj, fake_hit(*us_hitset_its_[jj] ) );
567  core::io::pdb::dump_pdb_residue( *conf, atomcounter, file_out );
568  //TR <<"nm upstream res for cstid " << jj << "; ";
569  us_hitset_its_[jj]++;
570  } //jj loop over all geom csts
571 
572  //write out one ds pose
573  for( core::Size jj = 1; jj <= num_geom_cst(); ++jj ){
574  if( ds_hitset_its_[jj] == ds_hitset_end_its_[jj]) continue;
575  all_hitset_iterators_at_end = false;
576  if( !modeltag_written ){
577  file_out << "MODEL "+utility::to_string( modelcount++ )+"\n";
578  modeltag_written = true;
579  }
580  dsbuilders()[jj]->downstream_pose_from_hit( fake_hit(*(ds_hitset_its_[jj])) )->dump_pdb( file_out );
581  //TR <<"nm downstream res for cstid " << jj << "; ";
582  ds_hitset_its_[jj]++;
583  break;
584  }
585  if( modeltag_written ) file_out << "ENDMDL \n";
586 
587  //note: we don't want to go overboard w/ the number of different models,
588  //bc the packer can only handle so much. so if there are more than 100,
589  //let's open a new file
590  if( modelcount == 101 && (! all_hitset_iterators_at_end ) ){
591  file_out.close();
592  atomcounter = 0;
593  allmodelcount += (modelcount - 2);
594  modelcount = 2;
595  num_files_this_group++;
596  file_out.open( (unique_match_names_[ii] + "_"+utility::to_string( num_files_this_group ) +".pdb").c_str() );
597  file_out << "MODEL 1\n";
598  up_outpose->dump_pdb( file_out );
599  downstream_pose->dump_pdb( file_out );
600  file_out << "ENDMDL \n";
601  }
602 
603  } //while there are still hits
604  allmodelcount += modelcount;
605  TR << "A total of " << allmodelcount - 1 << " models were written for " << " match group " << ii << " in " << num_files_this_group << " files." << std::endl;
606  file_out.close();
607 
608  //at the end, let's clear the stuff of this group to relieve some memory
609  match_groups_ushits_[ ii ].clear();
610  match_groups_dshits_[ ii ].clear();
611  } //loop over all match groups
612 } //write_match_groups
613 
614 
617 {
618  return match_groups_ushits_;
619 }
620 
623 {
624  return match_groups_dshits_;
625 }
626 
629 {
631 }
632 
635 {
636  return ds_hitset_its_;
637 }
638 
641 {
642  return ds_hitset_end_its_;
643 }
644 
645 void
647 {
648  match_groups_ushits_.clear();
649  match_groups_dshits_.clear();
650  unique_match_names_.clear();
652  us_hitset_its_.clear();
653  us_hitset_end_its_.clear();
654  ds_hitset_its_.clear();
655  ds_hitset_end_its_.clear();
656 }
657 
658 void
660  core::Size const group )
661 {
662  us_hitset_its_.clear();
663  us_hitset_end_its_.clear();
664  ds_hitset_its_.clear();
665  ds_hitset_end_its_.clear();
666 
667  UpstreamHitSets const & us_hitset_ref( match_groups_ushits_[ group ] );
668  DownstreamHitSets const & ds_hitset_ref( match_groups_dshits_[ group ] );
669  runtime_assert( us_hitset_ref.size() == ds_hitset_ref.size() );
670  for( core::Size ii = 1; ii <= us_hitset_ref.size(); ++ii ){
671  //runtime_assert( us_hitset_ref[ii].size() > 0 );
672  us_hitset_its_.push_back( us_hitset_ref[ ii ].begin() );
673  us_hitset_end_its_.push_back( us_hitset_ref[ii].end() );
674  ds_hitset_its_.push_back( ds_hitset_ref[ ii ].begin() );
675  ds_hitset_end_its_.push_back( ds_hitset_ref[ii].end() );
676  }
677 }
678 
679 
681  : parent( grouper )
682 {}
683 
685 
686 /// @brief this function doesn't do anything, but needs
687 /// to exist to suppress the unwanted call to the base
688 /// class function
689 void
691 
692 void
694  core::pose::Pose & pose,
695  core::Size match_group
696 )
697 {
698 
699  std::map< core::Size, core::Size > redundant_upstream_res;
701  utility::vector1< core::Size > ex_geom_ids_for_upstream_res;
702  match_dspos1 const & rep_match( representative_group_matches()[match_group] );
703 
704  determine_redundant_upstream_matchres( rep_match, redundant_upstream_res );
705  //setup_hitset_iterators_for_group( match_group );
706 
707  //first put in the upstream residues
708  for ( Size jj = 1; jj <= rep_match.upstream_hits.size(); ++jj ) {
710  coordinate_cacher()->upstream_conformation_for_hit( jj, fake_hit( rep_match.upstream_hits[ jj ] ) );
711  upstream_matchres.push_back( conf );
712  ex_geom_ids_for_upstream_res.push_back( full_hit( rep_match).external_geom_id() );
713  if( redundant_upstream_res.find( jj ) == redundant_upstream_res.end() ){
714  pose.replace_residue( conf->seqpos(), *conf, false );
715  }
716  }
717 
718  //assemble remarks
719  assemble_remark_lines( pose, upstream_matchres, redundant_upstream_res, ex_geom_ids_for_upstream_res );
720 
721  //then the downstream pose
722  core::pose::PoseCOP downstream_pose = dsbuilders()[ rep_match.originating_geom_cst_for_dspos ]->downstream_pose_from_hit( full_hit( rep_match ) );
723 
724  if( downstream_pose->total_residue() == 1 ){
725  pose.append_residue_by_jump( downstream_pose->residue(1), 1, "", "", true );
726  pose.pdb_info()->chain( pose.total_residue(), 'X' );
727  pose.pdb_info()->number( pose.total_residue(), 1 );
728  pose.pdb_info()->obsolete( false );
729  //pose.append_residue_by_jump( downstream_pose->residue(1), pose.total_residue(), "CA", downstream_pose->residue(1).atom_name(1), true );
730 
732  for( core::Size i = 1; i <= num_geom_cst(); ++i ){
733  for( std::set< downstream_hit >::const_iterator ds_hits_it( match_groups_dshits()[match_group][i].begin()), ds_hits_end( match_groups_dshits()[match_group][i].end() ); ds_hits_it != ds_hits_end; ++ds_hits_it){
734  additional_lig_confs.push_back( &(dsbuilders()[i]->downstream_pose_from_hit( fake_hit(*(ds_hits_it)) )->residue(1) ) );
735  if( additional_lig_confs.size() > 99 ) break;
736  }
737  if( additional_lig_confs.size() > 99 ) break;
738  }
739  if( additional_lig_confs.size() > 1 ){
740  protocols::toolbox::match_enzdes_util::get_enzdes_observer( pose )->set_rigid_body_confs_for_lig( pose.total_residue(), additional_lig_confs );
741  }
742  }
743  else utility_exit_with_message("PoseMatchOutputWriter not set up to put a downstream pose containing more than one ligand into the upstream pose");
744 }
745 
746 void
748  core::pose::Pose & pose
749 )
750 {
751  core::Size num_match_groups( match_groups_ushits().size() );
752  if( num_match_groups > 1 ){
753  core::Size mgroup( numeric::random::random_range( 1, num_match_groups ) );
754  TR << "WARNING: Matcher produced " << num_match_groups << " unique match groups, randomly picked " << mgroup << " to be inserted into the pose." << std::endl;
755  insert_match_into_pose( pose, mgroup );
756  }
757  else if( num_match_groups == 1 ) insert_match_into_pose( pose, 1 );
758  else{
759  TR << "Apparently no matches were found, so it's impossible to insert a match into the pose." << std::endl;
760  }
761 }
762 
763 
764 }
765 }
766 }