Rosetta 3.5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
PointMutationCalculator.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 sw=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 /// @author Chris King (chrisk1@uw.edu)
11 //#include <algorithm >
14 #include <core/pose/PDBInfo.hh>
15 #include <fstream>
16 // AUTO-REMOVED #include <utility/file/FileName.hh>
17 #include <iostream>
18 #include <numeric/random/random.hh>
20 #include <core/pose/Pose.hh>
24 #include <utility/tag/Tag.hh>
26 // AUTO-REMOVED #include <protocols/moves/DataMap.hh>
27 #include <basic/Tracer.hh>
35 #include <utility/vector1.hh>
36 #include <utility/vector0.hh>
37 #include <utility/string_util.hh>
38 #include <protocols/moves/Mover.hh>
39 #include <protocols/jd2/util.hh>
40 #include <boost/foreach.hpp>
41 #define foreach BOOST_FOREACH
48 
49 //Auto Headers
50 #include <basic/options/option.hh>
51 #include <basic/options/keys/OptionKeys.hh>
52 #include <basic/options/keys/packing.OptionKeys.gen.hh>
53 
54 #ifdef USEMPI
55 #include <mpi.h>
56 #include <utility/mpi_util.hh>
59 #include <basic/options/keys/out.OptionKeys.gen.hh>
60 #include <basic/options/keys/run.OptionKeys.gen.hh>
61 #endif
62 
63 namespace protocols {
64 namespace design_opt {
65 
66 static basic::Tracer TR( "protocols.design_opt.PointMutationCalculator" );
67 static numeric::random::RandomGenerator RG( 54 );
68 using namespace core;
69 using namespace chemical;
70 using utility::vector1;
71 using utility::vector0;
72 using std::pair;
73 
74 ///@brief default ctor
76  task_factory_( NULL ),
77  scorefxn_( NULL ),
78  relax_mover_( NULL ),
79 // filters_( NULL ), /*TODO: this throws a warning!*/
80 // sample_type_( "low" )
81  dump_pdb_( false ),
82  rtmin_( false ),
83  parallel_( false ),
84  design_shell_( -1.0),
85  repack_shell_( 8.0 )
86 {}
87 
88 //full ctor
92  protocols::moves::MoverOP relax_mover,
95  bool dump_pdb,
96  bool rtmin,
97  bool parallel,
98  core::Real design_shell,
99  core::Real repack_shell
100 )
101 {
103  filters_ = filters;
107  rtmin_ = rtmin;
110  design_shell_ = design_shell;
111  repack_shell_ = repack_shell;
112 
113  for( Size isamp = 1; isamp <= sample_types.size(); ++isamp ){
114  if( sample_types_[ isamp ] != "high" && sample_types_[ isamp ] != "low" ){
115  TR << "WARNING: the sample type, " << sample_types_[ isamp ] << ", is not defined. Use \'high\' or \'low\'." << std::endl;
116  runtime_assert( false );
117  }
118  }
119 }
120 
121 //backcompatible; single-filter convenience ctor
123  core::pack::task::TaskFactoryOP task_factory,
125  protocols::moves::MoverOP relax_mover,
127  std::string sample_type,
128  bool dump_pdb,
129  bool rtmin,
130  bool parallel,
131  core::Real design_shell,
132  core::Real repack_shell
133 
134 )
135 {
137  filters.push_back( filter );
139  sample_types.push_back( sample_type );
141  filters_ = filters;
145  rtmin_ = rtmin;
148  design_shell_ = design_shell;
149  repack_shell_ = repack_shell;
150 
151  for( Size isamp = 1; isamp <= sample_types.size(); ++isamp ){
152  if( sample_types_[ isamp ] != "high" && sample_types_[ isamp ] != "low" ){
153  TR << "WARNING: the sample type, " << sample_types_[ isamp ] << ", is not defined. Use \'high\' or \'low\'." << std::endl;
154  runtime_assert( false );
155  }
156  }
157 }
158 
159 //destruction!
161 
162 //creators
165  return new PointMutationCalculator( *this );
166 }
167 
168 // setter - getter pairs
169 void
171  relax_mover_ = mover;
172 }
173 
176  return relax_mover_;
177 }
178 
179 void
181  filters_ = filters;
182 }
183 
185  return filters_;
186 }
187 
188 void
190 {
192 }
193 
196 {
197  return task_factory_;
198 }
199 
200 void
203 }
204 
205 bool
207  return dump_pdb_;
208 }
209 
210 void
213 }
214 
217  return sample_types_;
218 }
219 
220 void
223 }
224 
227  return scorefxn_;
228 }
229 
230 void
232  design_shell_ = dz_shell;
233 }
234 
235 void
237  repack_shell_ = rp_shell;
238 }
239 
240 bool
242  return rtmin_;
243 }
244 
245 void
247 
248 bool
250  return parallel_;
251 }
252 
253 void
255 
256 /*
257 //utility funxns for comparing values in sort
258 bool
259 cmp_pair_by_second(
260  pair< AA, Real > const pair1,
261  pair< AA, Real > const pair2 )
262 {
263  return pair1.second < pair2.second;
264 }
265 
266 bool
267 cmp_triple_by_third(
268  pair< Size, pair< AA, Real > > const pair1,
269  pair< Size, pair< AA, Real > > const pair2 )
270 {
271  return pair1.second.second < pair2.second.second;
272 }
273 
274 bool
275 cmp_pair_vec_by_first_vec_val(
276  pair< Size, vector1< pair< AA, Real > > > const pair1,
277  pair< Size, vector1< pair< AA, Real > > > const pair2 )
278 {
279  return pair1.second[ 1 ].second < pair2.second[ 1 ].second;
280 }
281 */
282 
283 #ifdef USEMPI
284 Size
285 get_nstruct(){
286  using namespace basic::options;
287  using namespace basic::options::OptionKeys;
288 
289  if ( option[ run::shuffle ]() ) {
290  return option[ out::shuffle_nstruct ]();
291  } else {
292  return option[ out::nstruct ]();
293  }
294 }
295 #endif
296 
297 void
299  pose::Pose & pose,
300  Size const & resi,
301  AA const & target_aa
302 ){
303  using namespace core::pack::task;
304  using namespace core::pack::task::operation;
305  using namespace core::chemical;
306 
307  //make bool vector of allowed aa's [1,20], all false except for target_aa
308  vector1< bool > allowed_aas;
309  allowed_aas.clear();
310  allowed_aas.assign( num_canonical_aas, false );
311  allowed_aas[ target_aa ] = true;
312  //make mut_res task factory by copying input task_factory,
313  //then restrict to mutates resi to target_aa and repack 8A shell
314  core::pack::task::TaskFactoryOP mut_res = new core::pack::task::TaskFactory( *task_factory() );
317  repack_around_op->design_shell( design_shell_ ); //neg radius insures no designing nbrs, positive will do so!
318  repack_around_op->repack_shell( repack_shell_ );
319  repack_around_op->allow_design( true ); //because we still want to design resi
320  repack_around_op->include_residue( resi );
321  mut_res->push_back( repack_around_op );
322  //make mutate_residue packer task, mutate target res, repack all others
323  PackerTaskOP mutate_residue = mut_res->create_task_and_apply_taskoperations( pose );
324  mutate_residue->initialize_from_command_line().or_include_current( true );
325  mutate_residue->nonconst_residue_task( resi ).restrict_absent_canonical_aas( allowed_aas );
326  TR<<"Mutating residue "<<pose.residue( resi ).name3()<<resi<<" to ";
327  //run PackRotamers with mutate_residue task
330  if( core::pose::symmetry::is_symmetric( pose ) ) {
331  mutate_residue->request_symmetrize_by_union();
332  pack = new protocols::simple_moves::symmetry::SymPackRotamersMover( scorefxn(), mutate_residue );
333  } else {
334  pack = new protocols::simple_moves::PackRotamersMover( scorefxn(), mutate_residue );
335  }
336  pack->apply( pose );
337  if( rtmin() ){
338  // definition/allocation of RTmin mover must flag dependant, as some scoreterms are incompatable with RTmin initilization
339  if( core::pose::symmetry::is_symmetric( pose ) ) {
340  utility_exit_with_message("Cannot currently use PointMutationCalculator (GreedyOptMutation/ParetoOptMutation) with rtmin on a symmetric pose!");
341  }
342  rtmin = new protocols::simple_moves::RotamerTrialsMinMover( scorefxn(), *mutate_residue );
343  rtmin->apply( pose );
344  TR<<"Finished rtmin"<<std::endl;
345  }
346  TR<<pose.residue( resi ).name3()<<". Now relaxing..."<<std::endl;
347  //then run input relax mover
348  if( relax_mover() ) {
349  relax_mover()->apply( pose );
350  }
351 }
352 
353 void
355  pose::Pose & pose,
356  Size const & resi,
357  AA const & target_aa,
359 ){
360  using namespace core::pack::task;
361  using namespace core::pack::task::operation;
362  using namespace core::chemical;
363 
364  //make bool vector of allowed aa's [1,20], all false except for target_aa
365  vector1< bool > allowed_aas;
366  allowed_aas.clear();
367  allowed_aas.assign( num_canonical_aas, false );
368  allowed_aas[ target_aa ] = true;
369  //make mut_res task factory by copying input task_factory,
370  //then restrict to mutates resi to target_aa and repack 8A shell
371  core::pack::task::TaskFactoryOP mut_res = new core::pack::task::TaskFactory( *task_factory() );
374  repack_around_op->design_shell( design_shell_ ); //neg radius insures no designing nbrs
375  repack_around_op->repack_shell( repack_shell_ );
376  repack_around_op->allow_design( true ); //because we still want to design resi
377  repack_around_op->include_residue( resi );
380  restrict_to_aa_op->include_residue( resi );
381  restrict_to_aa_op->keep_aas( allowed_aas );
386  mut_res->push_back( repack_around_op );
387  mut_res->push_back( restrict_to_aa_op );
388  mut_res->push_back( init_from_cmd_op );
389  mut_res->push_back( incl_curr_op );
390  TR << "Mutation " << pose.residue( resi ).name1() << "_" << resi;
391  //only use green packer if not symmetric!
392  assert( !core::pose::symmetry::is_symmetric( pose ) );
393  green_packer->set_task_factory( mut_res );
394  green_packer->apply( pose );
395  TR << "_" << pose.residue( resi ).name1();
396  //then run input relax mover
397  relax_mover()->apply( pose );
398 }
399 
400 void
402  pose::Pose & pose,
403  bool & filter_pass,
404  vector1< Real > & vals
405 ){
406  //now run filters
407  filter_pass = true;
408  vals.clear();
409  for( Size ifilt = 1; ifilt <= filters_.size(); ++ifilt ){
410  //check if this filter passes, AND it with current value of pass/fail
411  bool this_filter_pass( ( filters_[ ifilt ] )->apply( pose ) );
412  filter_pass = filter_pass && this_filter_pass;
413  //val sign is switched if type is high
414  Real const flip_sign( sample_types_[ ifilt ] == "high" ? -1 : 1 );
415  Real const val( flip_sign * ( filters_[ ifilt ] )->report_sm( pose ) );
416  //TODO: option to bail at first fail??
417  TR<< " :: Filter " << ifilt;
418  if( !this_filter_pass ) TR << " fail, ";
419  else TR << " pass, ";
420  TR << " value "<< val << " ::";
421  vals.push_back( val );
422  }
423  TR << std::endl;
424 }
425 
426 void
428  Size const seqpos,
429  chemical::AA const aa,
430  vector1< Real > const vals,
431  vector1< pair< Size, vector1< pair< AA, vector1< Real > > > > > & seqpos_aa_vals_vec
432 )
433 {
434  using namespace core::chemical;
435  //create the aa,vals pair
436  pair< AA, vector1< Real > > aa_vals_pair( pair< AA, vector1< Real > >( aa, vals ) );
437  //first check if we've assigned anything for seqpos
438  //if we have, just append this aa,vals pair onto that seqpos' data
439  bool new_pos( true ); // It's a new position unless we find it
440  for( Size iseq = 1; iseq <= seqpos_aa_vals_vec.size(); ++iseq ){
441  if( seqpos == seqpos_aa_vals_vec[ iseq ].first ){
442  new_pos = false;
443  bool replaced( false );
444  //we need to check if we already have vals for this seqpos,aa in our data
445  for( core::Size iaa = 1; iaa <= seqpos_aa_vals_vec[ iseq ].second.size(); ++iaa ){
446  char this_aa_char( chemical::oneletter_code_from_aa( seqpos_aa_vals_vec[ iseq ].second[ iaa ].first ) );
447  if( this_aa_char == chemical::oneletter_code_from_aa( aa ) ){
448  seqpos_aa_vals_vec[ iseq ].second[ iaa ].second = vals;
449  replaced = true;
450  }
451  }
452  //dont append new data if we're just replacing
453  if( replaced ) break;
454  seqpos_aa_vals_vec[ iseq ].second.push_back( aa_vals_pair );
455  break;
456  }
457  }
458  //if this is the first instance of data at seqpos,
459  //create a 1-element vector and add to the ptmut data
460  if( new_pos ){
461  vector1< pair< AA, vector1< Real > > > aa_vals_vec( 1, aa_vals_pair );
462  seqpos_aa_vals_vec.push_back( pair< Size, vector1< pair< AA, vector1< Real > > > >( seqpos, aa_vals_vec ) );
463  }
464 }
465 
466 //backcompatibility; overloaded interface that allows the same data struct but wth one val/aa instead of a vector
467 void
469  pose::Pose const & pose,
470  vector1< pair< Size, vector1< pair< AA, Real > > > > & seqpos_aa_val_vec
471 )
472 {
473  //call the default with a new tmp container
475  calc_point_mut_filters( pose, seqpos_aa_vals_vec );
476  //iter thru tmp container and use vals to populate input container
477  for( vector1< pair< core::Size, vector1< pair< AA, vector1< Real > > > > >::iterator seqpos_aa_vals = seqpos_aa_vals_vec.begin();
478  seqpos_aa_vals != seqpos_aa_vals_vec.end(); ++seqpos_aa_vals ){
479  Size seqpos( seqpos_aa_vals->first );
480  //seqpos_aa_vals->second is a seqpos' vector of aa/vals pairs
481  assert( !seqpos_aa_vals->second.empty() );
483  for( vector1< pair< AA, vector1< Real > > >::iterator aa_vals = seqpos_aa_vals->second.begin();
484  aa_vals != seqpos_aa_vals->second.end(); ++aa_vals ){
485  //aa_vals->second is an aa's vector of vals
486  assert( !aa_vals->second.empty() );
487  aa_val.push_back( pair< AA, Real >( aa_vals->first, aa_vals->second[ 1 ] ) );
488  }
489  seqpos_aa_val_vec.push_back( pair< Size, vector1< pair< AA, Real > > >( seqpos, aa_val ) );
490  }
491 }
492 
493 void
495  pose::Pose const & start_pose,
496  vector1< pair< Size, vector1< pair< AA, vector1< Real > > > > > & seqpos_aa_vals_vec
497 )
498 {
499  using namespace core::pack::task;
500  using namespace core::pack::task::operation;
501  using namespace core::chemical;
502 
503  //create vec of pairs of seqpos, vector of AA/vals pairs that pass input filter
504  //clear the input first!
505  seqpos_aa_vals_vec.clear();
506  //apply input task factory to pose
507 // PackerTaskCOP task = task_factory()->create_task_and_apply_taskoperations( start_pose );
508  PackerTaskOP tmptask = task_factory_->create_task_and_apply_taskoperations( start_pose );
509  if(core::pose::symmetry::is_symmetric(start_pose)) {
510  tmptask->request_symmetrize_by_union();
512  }
513  PackerTaskCOP task = tmptask;
514  //get vector< Size > of protein seqpos being designed and group id mask for green packer (0 is designed, 1 is rp only)
515  vector1< core::Size > being_designed;
516  utility::vector1< Size > group_ids;
517  being_designed.clear();
518  for( core::Size resi = 1; resi <= start_pose.total_residue(); ++resi ){
519  if(core::pose::symmetry::is_symmetric(start_pose)) {
520  if( resi > core::pose::symmetry::symmetry_info(start_pose)->num_independent_residues() ) {
521  break;
522  }
523  }
524  if( task->residue_task( resi ).being_designed() && start_pose.residue(resi).is_protein() ){
525  being_designed.push_back( resi );
526  group_ids.push_back( 0 );
527  } else{
528  group_ids.push_back( 1 );
529  }
530  }
531  if( being_designed.empty() ) {
532  TR.Warning << "WARNING: No residues are listed as designable." << std::endl;
533  }
534 
535  //GreenPacker stuff, precompute non-designable residues' interaxn graph
536  //dont use green packer if symmetric (symm not supported for green packer)
537  //dont use green packer if user specifies linmem interaxn graph (is calc on the fly)
538  bool use_precomp_rot_pair_nrgs( true );
539  if( basic::options::option[ basic::options::OptionKeys::packing::linmem_ig ].user() ){
540  TR << "Note: you are using linmem_ig in your options: " <<
541  "packing will be slower because GreedyOpt can't use GreenPacker precomputed rotamer pair energies" << std::endl;
542  use_precomp_rot_pair_nrgs = false;
543  }
544  if( core::pose::symmetry::is_symmetric( start_pose ) ){
545  TR << "Note: you are using symmetry: " <<
546  "packing will be slower because GreedyOpt can't use GreenPacker precomputed rotamer pair energies" << std::endl;
547  use_precomp_rot_pair_nrgs = false;
548  }
549  protocols::simple_moves::UserDefinedGroupDiscriminatorOP user_defined_group_discriminator(
551  user_defined_group_discriminator->set_group_ids( group_ids );
553  green_packer->set_group_discriminator( user_defined_group_discriminator );
554  green_packer->set_scorefunction( *scorefxn() );
555  green_packer->set_reference_round_task_factory( task_factory() );
556 
557 #ifdef USEMPI
558  int mpi_rank( 0 ), mpi_nprocs( 1 ), mpi_rank_low( 0 );
559  if( parallel() ){
560  MPI_Comm_rank(MPI_COMM_WORLD, &mpi_rank);
561  MPI_Comm_size(MPI_COMM_WORLD, &mpi_nprocs);
562  //Get the lowest rank proc that's running this mover
563  if( dynamic_cast< protocols::jd2::MPIWorkPoolJobDistributor* >( protocols::jd2::JobDistributor::get_instance() ) ){
564  //!!WARNING!! We're assuming we have one head node (0) and nprocs-1 workers !!WARNING!!
565  TR << "Detected jd2::MPIWorkPoolJobDistributor... excluding proc 0 from calculations" << std::endl;
566  mpi_rank_low = 1;
567  //We must have one job( nstruct ) for each worker in pool or we'll freeze later because nodes w/ no job will get killed by jd2
568  if( get_nstruct() < mpi_nprocs - mpi_rank_low ) utility_exit_with_message(
569  "You must specify nstruct >= " + utility::to_string( mpi_nprocs - mpi_rank_low ) +
570  " when using " + utility::to_string( mpi_nprocs ) + " processors for MPI PointMutationCalculator" +
571  " when called from rosetta_scripts or any other app using jd2::MPIWorkPoolJobDistributor!" );
572  }
573  else if( dynamic_cast< protocols::jd2::MPIFileBufJobDistributor* >(protocols::jd2::JobDistributor::get_instance() ) ){
576  mpi_rank_low = jd2->min_client_rank();
577  TR << "Detected jd2::MPIFileBufJobDistributor... excluding procs 0-" << ( mpi_rank_low - 1 ) << " from calculations" << std::endl;
578  //We must have one job( nstruct ) for each worker in pool or we'll freeze later because nodes w/ no job will get killed by jd2
579  if( get_nstruct() < mpi_nprocs - mpi_rank_low ) utility_exit_with_message(
580  "You must specify nstruct >= " + utility::to_string( mpi_nprocs - mpi_rank_low ) +
581  " when using " + utility::to_string( mpi_nprocs ) + " processors for MPI PointMutationCalculator" +
582  " when called from rosetta_scripts or any other app using jd2::MPIFileBufJobDistributor!" );
583  }
584  /*
585  //create a group of worker nodes and then a communicator
586  MPI_Group mpi_pool_group, mpi_all_group;
587  MPI_Comm MPI_COMM_POOL;
588  int returnval;
589  //create mpi_all_group group
590  returnval = MPI_Comm_group( MPI_COMM_WORLD, &mpi_all_group);
591  if ( returnval != MPI_SUCCESS ) utility_exit_with_message("failed in creating a new communicator!");
592  //create the pool group
593  // ranks is node ranks to include in your new group
594  int const mpi_pool_nprocs( mpi_nprocs - mpi_rank_low );
595  int ranks[ mpi_pool_nprocs ];
596  for( int irank = 0; irank < mpi_pool_nprocs; ++irank ){
597  ranks[ irank ] = mpi_rank_low + irank;
598  TR << "MPI group incl Proc " << mpi_rank_low + irank << std::endl;
599  }
600  TR << "Creating pool group..." << std::endl;
601  returnval = MPI_Group_incl( mpi_all_group, mpi_pool_nprocs, ranks, &mpi_pool_group );
602  if ( returnval != MPI_SUCCESS ) utility_exit_with_message("failed in creating a new communicator!");
603  TR << "Creating comm group..." << std::endl;
604  returnval = MPI_Comm_create( MPI_COMM_WORLD, mpi_pool_group, &MPI_COMM_POOL );
605  if ( returnval != MPI_SUCCESS ) utility_exit_with_message("failed in creating a new communicator!");
606  TR << "MPI Comm created!" << std::endl;
607  */
608  }
609 #endif
610 
611  //make a single list of seqpos,aa pairs
612  vector1< pair< Size, AA > > all_muts;
613  for( Size iresi = 1; iresi <= being_designed.size(); ++iresi ){
614  Size const resi( being_designed[ iresi ] );
615  //create vector< AA > of allowed residue types at seqpos
616  typedef std::list< ResidueTypeCOP > ResidueTypeCOPList;
617  ResidueTypeCOPList const & allowed( task->residue_task( resi ).allowed_residue_types() );
618  vector1< AA > allow_temp;
619  foreach( ResidueTypeCOP const t, allowed ){
620  if(std::find(allow_temp.begin(),allow_temp.end(),t->aa())!=allow_temp.end()) continue;
621  allow_temp.push_back( t->aa() );
622  }
623  //for each allowed AA
624  foreach( AA const target_aa, allow_temp ){
625  all_muts.push_back( pair< Size, AA >( resi, target_aa ) );
626  }
627  }
628 
629  vector1< pair< Size, AA > > my_muts( all_muts );
630  if( parallel() ){
631 #ifdef USEMPI
632  //split up my_muts into smaller sublists for diff procs
633  my_muts.clear();
634  //asign muts to each proc
635  for( Size imut = 1; imut <= all_muts.size(); ++imut ){
636  //e.g. for 4 procs, hand out muts like 1,2,3,1,2,3,etc (nothing given to proc 0)
637  Size this_mpi_rank( ( imut - 1 ) % ( mpi_nprocs - mpi_rank_low ) + mpi_rank_low );
638  if( this_mpi_rank == mpi_rank ){
639  my_muts.push_back( all_muts[ imut ] );
640  }
641  }
642  //TR << "Proc " << mpi_rank << " takes mutations: ";
643  //for( Size imut = 1; imut <= my_muts.size(); ++imut ) TR << my_muts[ imut ].first << my_muts[ imut ].second << " ";
644  //TR << std::endl;
645 #endif
646  }
647 
648  for( Size imut = 1; imut <= my_muts.size(); ++imut ){
649  Size seqpos( my_muts[ imut ].first );
650  AA target_aa( my_muts[ imut ].second );
651  //make copy of original
652  pose::Pose pose( start_pose );
653  //make the mutation and relax
654  //then check if passes input filter, bail out if it doesn't
655  bool filter_pass;
656  vector1< Real > vals;
657  if( use_precomp_rot_pair_nrgs ) mutate_and_relax( pose, seqpos, target_aa, green_packer );
658  else mutate_and_relax( pose, seqpos, target_aa );
659 // mutate_and_relax( pose, seqpos, target_aa );
660  eval_filters( pose, filter_pass, vals );
661 
662  //don't store this aa/val if any filter failed
663  if( !filter_pass ) continue;
664  assert( !vals.empty() );
665  //dump pdb? (only if filter passes)
666  if( dump_pdb() ){
667  std::stringstream fname;
668  fname << protocols::jd2::current_output_name() << start_pose.residue( seqpos ).name3() << seqpos << pose.residue( seqpos ).name3()<<".pdb";
669  TR<<"Saving pose "<<fname.str() << std::endl;
670  pose.dump_scored_pdb( fname.str(), *scorefxn() );
671  }
672  TR.flush();
673  insert_point_mut_filter_vals( seqpos, target_aa, vals, seqpos_aa_vals_vec );
674  }//for mut
675 
676  if( parallel() ){
677 #ifdef USEMPI
678  //MPI_Barrier( MPI_COMM_POOL );
679  //sync everybody's mutation filter data
680  //worker sends ptmut data to pool leader
681  if( mpi_rank > mpi_rank_low ){
682  utility::send_integer_to_node( mpi_rank_low, seqpos_aa_vals_vec.size() ); //send int
683  for( Size iseq = 1; iseq <= seqpos_aa_vals_vec.size(); ++iseq ){
684  utility::send_integer_to_node( mpi_rank_low, seqpos_aa_vals_vec[ iseq ].first ); //send int
685  utility::vector1< std::pair< core::chemical::AA, vector1< core::Real > > > const & aa_pairs( seqpos_aa_vals_vec[ iseq ].second );
686  utility::send_integer_to_node( mpi_rank_low, aa_pairs.size() ); //send int
687  for( core::Size iaa = 1; iaa <= aa_pairs.size(); ++iaa ){
688  utility::send_char_to_node( mpi_rank_low, chemical::oneletter_code_from_aa( aa_pairs[ iaa ].first ) ); //send char
689  //TR << "Proc " << mpi_rank << " sending seqpos,aa: " << seqpos_aa_vals_vec[ iseq ].first << aa_pairs[ iaa ].first
690  // << ": " << aa_pairs[ iaa ].second[ 1 ] << " to Proc 0" << std::endl;
691  for( Size ival = 1; ival <= ( filters() ).size(); ++ival ){
692  utility::send_double_to_node( mpi_rank_low, aa_pairs[ iaa ].second[ ival ] ); //send Real
693  }
694  }
695  }
696  }
697  //pool leader receives ptmut data from workers and combines with its own
698  else if( mpi_rank == mpi_rank_low ){
699  for( Size iproc = mpi_rank_low + 1; iproc < mpi_nprocs; ++iproc ){
700  //get data for one mut (seqpos, AA, and filter vals )
701  //need to know how many seqpos
702  Size n_seqpos( utility::receive_integer_from_node( iproc ) ); //rec int
703  for( Size imut = 1; imut <= n_seqpos; ++imut ){
704  Size seqpos( utility::receive_integer_from_node( iproc ) ); //rec int
705  //need to know how many muts at this seqpos
706  Size n_aas( utility::receive_integer_from_node( iproc ) ); //rec int
707  for( Size iaa = 1; iaa <= n_aas; ++iaa ){
708  char aa_char( utility::receive_char_from_node( iproc ) ); //rec char
710  vector1< Real > vals( ( filters() ).size(), 0. );
711  for( Size ival = 1; ival <= vals.size(); ++ival ){
712  vals[ ival ] = utility::receive_double_from_node( iproc ); //rec Real
713  }
714  //TR << "Proc " << mpi_rank << " received seqpos,aa: " << seqpos << aa << ": "
715  // << vals[ 1 ] << " from Proc " << iproc << std::endl;
716  insert_point_mut_filter_vals( seqpos, aa, vals, seqpos_aa_vals_vec );
717  }
718  }
719  }
720  }
721  //MPI_Barrier( MPI_COMM_POOL );
722  //then pool leader sends combined ptmut data back to workers
723  if( mpi_rank == mpi_rank_low ){
724  for( Size iproc = mpi_rank_low + 1; iproc < mpi_nprocs; ++iproc ){
725  utility::send_integer_to_node( iproc, seqpos_aa_vals_vec.size() ); //send int
726  for( Size iseq = 1; iseq <= seqpos_aa_vals_vec.size(); ++iseq ){
727  utility::send_integer_to_node( iproc, seqpos_aa_vals_vec[ iseq ].first ); //send int
728  utility::vector1< std::pair< core::chemical::AA, vector1< core::Real > > > const & aa_pairs( seqpos_aa_vals_vec[ iseq ].second );
729  utility::send_integer_to_node( iproc, aa_pairs.size() ); //send int
730  for( core::Size iaa = 1; iaa <= aa_pairs.size(); ++iaa ){
731  utility::send_char_to_node( iproc, chemical::oneletter_code_from_aa( aa_pairs[ iaa ].first ) ); //send char
732  //TR << "Proc " << mpi_rank << " sending seqpos,aa: " << seqpos_aa_vals_vec[ iseq ].first << aa_pairs[ iaa ].first << std::endl;
733  for( Size ival = 1; ival <= ( filters() ).size(); ++ival ){
734  utility::send_double_to_node( iproc, aa_pairs[ iaa ].second[ ival ] ); //send Real
735  }
736  }
737  }
738  }
739  }
740  //workers receive combined ptmut data from pool leader
741  else if( mpi_rank > mpi_rank_low ){
742  //need to know how many seqpos
743  Size n_seqpos( utility::receive_integer_from_node( mpi_rank_low ) ); //rec int
744  for( Size imut = 1; imut <= n_seqpos; ++imut ){
745  Size seqpos( utility::receive_integer_from_node( mpi_rank_low ) ); //rec int
746  //need to know how many muts at this seqpos
747  Size n_aas( utility::receive_integer_from_node( mpi_rank_low ) ); //rec int
748  for( Size iaa = 1; iaa <= n_aas; ++iaa ){
749  char aa_char( utility::receive_char_from_node( mpi_rank_low ) ); //rec char
751  //TR << "Proc " << mpi_rank << " received seqpos,aa: " << seqpos << aa << std::endl;
752  vector1< Real > vals( ( filters() ).size(), 0. );
753  for( Size ival = 1; ival <= vals.size(); ++ival ){
754  vals[ ival ] = utility::receive_double_from_node( mpi_rank_low ); //rec Real
755  }
756  insert_point_mut_filter_vals( seqpos, aa, vals, seqpos_aa_vals_vec );
757  }
758  }
759  }
760  // MPI_Finalize();
761 #endif
762  }
763 
764 /*
765  //this part sorts the seqpos/aa/val data
766  //first over each seqpos by aa val, then over all seqpos by best aa val
767  for( vector1< pair< core::Size, vector1< pair< AA, Real > > > >::iterator aa_vals = seqpos_aa_vals_vec.begin();
768  aa_vals != seqpos_aa_vals_vec.end(); ++aa_vals ){
769  //skip if aa_vals vector is empty
770  if( aa_vals->second.empty() ) continue;
771  //sort aa_vals in incr val order
772  std::sort( aa_vals->second.begin(), aa_vals->second.end(), cmp_pair_by_second );
773  //best val is lowest, store all in sorted_seqpos_aa_vals_vec
774 // pair< AA, Real > best_resid_val( aa_vals->second[ 1 ] );
775  //create the pair of seqpos and sorted AA/val pairs
776  pair< Size, vector1< pair< AA, Real > > > sorted_aa_vals( aa_vals->first, aa_vals->second );
777  seqpos_aa_vals_vec.push_back( sorted_aa_vals );
778  }
779 
780  //now sort seqpos_aa_vals_vec by *first* (lowest) val in each seqpos vector, low to high
781  //uses cmp_pair_vec_by_first_vec_val to sort based on second val in
782  //first pair element of pair( size, vec( pair ) )
783  std::sort( seqpos_aa_vals_vec.begin(), seqpos_aa_vals_vec.end(), cmp_pair_vec_by_first_vec_val );
784 */
785 
786 }
787 
788 
789 
790 } // design_opt
791 } // protocols