18 #include <basic/MetricValue.hh>
19 #include <basic/Tracer.hh>
20 #include <basic/options/util.hh>
58 #include <utility/file/FileName.hh>
63 #include <ObjexxFCL/format.hh>
76 #include <basic/options/keys/run.OptionKeys.gen.hh>
81 #include <utility/vector0.hh>
82 #include <utility/vector1.hh>
85 using namespace basic::options;
86 using namespace basic::options::OptionKeys;
89 using namespace core::pack::task::operation;
90 using namespace core::pack::task;
92 using namespace protocols;
93 using namespace ObjexxFCL::fmt;
94 using namespace utility;
101 static basic::Tracer
TR(
"protocols.pmut_scan.PointMutScanDriver");
111 double_mutant_scan_( double_mutant_scan ),
112 mutants_list_file_( list_file ),
113 output_mutant_structures_( output_mutant_structures ),
114 pdb_file_names_( pdb_file_names ),
125 MPI_Comm_rank( MPI_COMM_WORLD, &
mpi_rank );
126 MPI_Comm_size( MPI_COMM_WORLD, &mpi_nprocs );
142 scorefxn_->set_energy_method_options( energymethodoptions );
169 clock_t entire_starttime(0);
172 entire_starttime = clock();
191 clock_t entire_stoptime = clock();
192 TR <<
"main(): whole protocol took " << ((double)entire_stoptime-entire_starttime) / CLOCKS_PER_SEC <<
" seconds" << std::endl;
193 TR <<
"go(): DONE with pmut scan." << std::endl;
204 return "master node";
207 r <<
"slave node " << rank;
220 MPI_Barrier( MPI_COMM_WORLD );
312 Size no_double_mutants_possible = 0;
313 Size no_double_mutants_excluded_for_distance = 0;
314 Size no_double_mutants_excluded_otherwise = 0;
315 Size no_single_mutants_excluded_otherwise = 0;
326 for (
Size resid1 = 1; resid1 <= n_residue; ++resid1 ) {
349 ++no_single_mutants_excluded_otherwise;
359 for (
Size resid2 = resid1 + 1; resid2 <= n_residue; ++resid2 ) {
363 if ( neighbors[ resid1 ][ resid2 ] ==
false ) {
364 no_double_mutants_possible += 19;
365 no_double_mutants_excluded_for_distance += 19;
376 no_double_mutants_possible++;
389 m.add_mutation( md2 );
391 ++no_double_mutants_excluded_otherwise;
403 Size const single_possible = 19 * n_residue;
404 TR <<
"fill_mutations_list(): number single mutants possible: " << single_possible << std::endl;
405 TR <<
"fill_mutations_list(): number single mutants excluded otherwise: " << no_single_mutants_excluded_otherwise << std::endl;
407 TR <<
"fill_mutations_list(): number double mutants possible: " << no_double_mutants_possible << std::endl;
408 TR <<
"fill_mutations_list(): number double mutants excluded for distance: " << no_double_mutants_excluded_for_distance << std::endl;
409 TR <<
"fill_mutations_list(): number double mutants excluded otherwise: " << no_double_mutants_excluded_otherwise << std::endl;
426 std::ifstream data( list_file.c_str() );
427 if ( !data.good() ) {
428 utility_exit_with_message(
"Unable to open mutations file: " + list_file +
'\n' );
434 while ( getline( data, line ) ) {
435 if ( line.size() < 1 || line[0] ==
'#' )
continue;
436 mutant_file_lines.push_back( line );
442 for (
Size ii=1; ii <= mutant_file_lines.size(); ++ii ) {
443 std::string const & line( mutant_file_lines[ ii ] );
444 std::istringstream iss( line );
446 char wt_residue, mut_residue, chain;
452 while ( iss.peek() && !iss.eof() ) {
454 iss >> chain >> wt_residue >> position_code >> mut_residue;
458 Size pdb_resnum;
char icode =
' ';
459 std::stringstream ss;
461 if ( position_code.find_first_not_of(
"0123456789") == std::string::npos ) {
467 for ( std::string::iterator it = position_code.begin(); it < position_code.end(); ++it ) {
468 if ( isdigit(*it) ) {
479 Size pose_resnum = (pose.
pdb_info())->pdb2pose( chain, pdb_resnum, icode );
481 if ( pose.
residue( pose_resnum ).
name1() != wt_residue ) {
482 TR <<
"wt_residue: " << wt_residue <<
", pdb resnum: " << pdb_resnum <<
", pose resnum: " << pose_resnum
483 <<
", residue at pose resnum: " << pose.
residue( pose_resnum ).
name1() << std::endl;
484 utility_exit_with_message(
"Error. Wild-type residue given in mutatons_list file does not match input structure. Please try again.");
489 MutationData md( wt_residue, mut_residue, pose_resnum, pdb_resnum, icode, chain );
523 edge_end_iter = pg->get_vertex(r).upper_edge_list_end(); edge_iter != edge_end_iter; ++edge_iter ) {
524 neighbor_graph.
add_edge(r, edge_iter->upper_vertex());
534 Size nb_resnum = (*eli)->get_other_ind( ii );
535 if ( nb_resnum < ii ) {
continue; }
541 for (
Size jja = jj_rsd.first_sidechain_atom(); jja <= jj_rsd.nheavyatoms(); ++jja ) {
543 Vector const & jja_atom_xyz = jja_atom.xyz();
545 for (
Size iia = ii_rsd.first_sidechain_atom(); iia <= ii_rsd.nheavyatoms(); ++iia ) {
547 Vector const & iia_atom_xyz = iia_atom.xyz();
549 if ( iia_atom_xyz.distance( jja_atom_xyz ) < 4.5 ) {
550 neighbors[ ii ][ nb_resnum ] =
true;
556 if ( neighbors[ ii ][ nb_resnum ] ) {
584 Size my_njobs = ( nextra >= 1 ? 1 : 0 ) + num_mutants_per_cpu;
585 for (
Size ii = 1; ii <= my_njobs; ++ii ) {
591 Size mutant_offset = my_njobs;
595 Size node_njobs = ( nextra > node_index ? 1 : 0 ) + num_mutants_per_cpu;
596 MPI_Send( & node_njobs, 1, MPI_UNSIGNED_LONG, node_index, tag_, MPI_COMM_WORLD );
598 for (
Size mutant_index = mutant_offset + 1; mutant_index <= mutant_offset + node_njobs; ++mutant_index ) {
599 send_mutant_data_to_node( node_index,
all_mutants_[ mutant_index ] );
601 mutant_offset += node_njobs;
607 MPI_Recv( & my_njobs, 1, MPI_UNSIGNED_LONG, 0, tag_, MPI_COMM_WORLD, & stat_ );
611 for (
Size ii = 1; ii <= my_njobs; ++ii ) {
612 mutants_list_.push_back( receive_mutant_data_from_node( 0 ) );
621 gethostname(hostname,
sizeof(hostname));
622 TR <<
"divide_up_pdbs(): mutation '" <<
mutants_list_[ ii ] <<
"' assigned to " << hostname <<
" (rank = " <<
MPI_rank_ <<
")" << std::endl;
643 MPI_Send( & mutant_num_mutations, 1, MPI_UNSIGNED_LONG, destination, tag, MPI_COMM_WORLD );
647 char wt_residue = iter->wt_residue_;
648 char mut_residue = iter->mut_residue_;
650 MPI_Send( & wt_residue, 1, MPI_CHAR, destination, tag, MPI_COMM_WORLD );
651 MPI_Send( & mut_residue, 1, MPI_CHAR, destination, tag, MPI_COMM_WORLD );
653 Size pose_resnum = iter->pose_resnum_;
654 Size pdb_resnum = iter->pdb_resnum_;
655 MPI_Send( & pose_resnum, 1, MPI_UNSIGNED_LONG, destination, tag, MPI_COMM_WORLD );
656 MPI_Send( & pdb_resnum, 1, MPI_UNSIGNED_LONG, destination, tag, MPI_COMM_WORLD );
658 char icode = iter->icode_;
659 char chain = iter->chain_;
661 MPI_Send( & icode, 1, MPI_CHAR, destination, tag, MPI_COMM_WORLD );
662 MPI_Send( & chain, 1, MPI_CHAR, destination, tag, MPI_COMM_WORLD );
675 Mutant PointMutScanDriver::receive_mutant_data_from_node(
int source ) {
681 MPI_Recv( & num_mutations, 1, MPI_UNSIGNED_LONG, source, tag, MPI_COMM_WORLD, & stat );
685 for (
Size ii = 1; ii <= num_mutations; ++ii ) {
687 char wt_residue, mut_residue;
688 MPI_Recv( & wt_residue, 1, MPI_CHAR, source, tag, MPI_COMM_WORLD, & stat );
689 MPI_Recv( & mut_residue, 1, MPI_CHAR, source, tag, MPI_COMM_WORLD, & stat );
692 Size pose_resnum = 1, pdb_resnum = 1;
693 MPI_Recv( & pose_resnum, 1, MPI_UNSIGNED_LONG, source, tag, MPI_COMM_WORLD, & stat );
694 MPI_Recv( & pdb_resnum, 1, MPI_UNSIGNED_LONG, source, tag, MPI_COMM_WORLD, & stat );
697 MPI_Recv( & icode, 1, MPI_CHAR, source, tag, MPI_COMM_WORLD, & stat );
698 MPI_Recv( & chain, 1, MPI_CHAR, source, tag, MPI_COMM_WORLD, & stat );
701 MutationData md( wt_residue, mut_residue, pose_resnum, pdb_resnum, icode, chain );
702 m.add_mutation( md );
727 TR <<
A(
"mutation" ) <<
X(3) <<
A(
"mutation_PDB_numbering" ) <<
X(3) <<
A(
"average_ddG" ) <<
X(3) <<
A(
"average_total_energy" ) << std::endl;
772 for (
Size ii = 1; ii <= native_poses.size(); ++ii ) {
779 std::stringstream out;
780 out << mutation_string;
781 if ( mutation_string !=
"" ) { out <<
","; }
786 out << mutation_string_PDB_numbering;
787 if ( mutation_string_PDB_numbering !=
"" ) { out <<
","; }
789 std::string updated_mutation_string_PDB_numbering = out.str();
792 make_specific_mutant( mutant_poses, native_poses, m, updated_mutation_string, updated_mutation_string_PDB_numbering );
800 Energy sum_mutant_scores = 0.0;
801 Energy average_mutant_score = 0.0;
803 Energy sum_native_scores = 0.0;
804 Energy average_native_score = 0.0;
809 for (
Size ii=1; ii <= native_poses.size(); ++ii ) {
816 pose::Pose & mutant_pose = mutant_poses[ ii ];
818 mutant_poses_total_energies[ ii ] = mutant_score;
819 sum_mutant_scores += mutant_score;
822 pose::Pose & native_pose = native_poses[ ii ];
824 native_poses_total_energies[ ii ] = native_score;
825 sum_native_scores += native_score;
828 std::stringstream out;
829 out << mutation_string;
830 if ( mutation_string !=
"" ) { out <<
", "; }
833 std::string mutant_filename = fn.base() +
"." + out.str() +
".pdb";
839 average_mutant_score = sum_mutant_scores / mutant_poses.size();
840 average_native_score = sum_native_scores / native_poses.size();
842 Real ddG_mutation = average_mutant_score - average_native_score;
847 std::stringstream out;
848 out << mutation_string;
849 if ( mutation_string !=
"" ) { out <<
","; }
854 out << mutation_string_PDB_numbering;
855 if ( mutation_string_PDB_numbering !=
"" ) { out <<
","; }
857 std::string final_mutation_string_PDB_numbering = out.str();
860 TR << final_mutation_string <<
X(3) << final_mutation_string_PDB_numbering <<
X(3) << F( 9,3,ddG_mutation ) <<
X(3) << F( 9,2,average_mutant_score ) << std::endl;
873 TR.flush_all_channels();
894 std::stringstream out;
899 pose::metrics::CalculatorFactory::Instance().register_calculator( calculator_name, mutant_nb_calculator );
901 basic::MetricValue< std::set< Size > > mv_neighbors;
902 mutant_pose.
metric( calculator_name,
"neighbors", mv_neighbors );
903 std::set< Size >
const neighbor_set( mv_neighbors.value() );
918 native_tf->push_back( nb_op ); mutant_tf->push_back( nb_op );
923 native_tf->push_back( init_op ); mutant_tf->push_back( init_op );
926 native_tf->push_back( ic_op ); mutant_tf->push_back( ic_op );
935 keep_canonical_aas[ mut_aa ] =
true;
937 mutant_tf->push_back( restrict_op );
938 wt_repack_op->include_residue( ii );
942 mutant_repack_op->include_residue( ii );
943 wt_repack_op->include_residue( ii );
946 native_tf->push_back( wt_repack_op );
947 mutant_tf->push_back( mutant_repack_op );
952 std::set< core::Size >::const_iterator iter;
953 for ( iter = neighbor_set.begin(); iter != neighbor_set.end(); iter++ ) {
955 movemap->set_chi( *iter,
true );
971 seq_mover->add_mover( mutant_repacker_mover );
972 seq_mover->add_mover( task_aware_min_mover );
974 seq_mover->apply( mutant_pose );
986 seq_mover->add_mover( native_pack_mover );
987 seq_mover->add_mover( task_aware_min_mover );
989 seq_mover->apply( native_pose );
992 pose::metrics::CalculatorFactory::Instance().remove_calculator( calculator_name );
993 mutant_nb_calculator = NULL;