28 #include <basic/database/open.hh>
35 #include <basic/options/option.hh>
51 #include <basic/Tracer.hh>
58 #include <ObjexxFCL/FArray1D.hh>
61 #include <numeric/random/random.hh>
69 #include <basic/options/keys/docking.OptionKeys.gen.hh>
70 #include <basic/options/keys/enzdes.OptionKeys.gen.hh>
71 #include <basic/options/keys/score.OptionKeys.gen.hh>
75 #include <utility/vector1.hh>
85 namespace ligand_docking {
88 using namespace ObjexxFCL;
91 static basic::Tracer
TR(
"protocols.ligand_docking.LigandBaseProtocol");
92 static numeric::random::RandomGenerator
my_RG(810323);
97 sc_interface_padding_(0),
98 bb_interface_cutoff_(0)
100 Mover::type(
"LigandBaseProtocol" );
105 using namespace basic::options;
106 use_soft_rep_ = option[ OptionKeys::docking::ligand::soft_rep ];
107 bool const rosetta_electrostatics = option[ OptionKeys::docking::ligand::old_estat ];
108 bool const hbonds_downweight =
true;
114 if ( option[ OptionKeys::docking::ligand::tweak_sxfn ] ) {
115 TR.Debug <<
"Using regular tweaked scorefunctions" << std::endl;
121 if ( option[ OptionKeys::score::weights ].user() || option[ OptionKeys::score::patch ].user() ) {
122 TR.Debug <<
"Using untweaked command-line specified (hard) scorefunction. " << std::endl;
125 TR.Debug <<
"Using untweaked ligand.wts hard scorefunction." << std::endl;
128 if ( option[ OptionKeys::score::soft_wts ].user() ) {
129 TR.Debug <<
"Using untweaked -score:soft_wts specified soft scorefunction." << std::endl;
132 TR.Debug <<
"Using untweaked ligand_soft_rep.wts soft scorefunction." << std::endl;
156 return "LigandBaseProtocol";
162 bool estat_exclude_protein,
164 bool hbonds_downweight
167 using namespace core::scoring;
175 sfxn->set_energy_method_options( options );
177 sfxn->add_weights_from_file( basic::database::full_name(
"scoring/weights/"+weights_tag+
".wts" ) );
191 if( estat_upweight ) sfxn->set_weight(
hack_elec, (10./6.) * sfxn->get_weight(
hack_elec ) );
193 if( hbonds_downweight ) {
206 if( sfxn->has_zero_weight(
omega ) ) sfxn->set_weight(
omega, 0.5 );
207 if( sfxn->has_zero_weight(
rama ) ) sfxn->set_weight(
rama, 0.2 );
224 for(
core::Size ii = 1; ii <= scores_in.size(); ++ii) {
227 if( scores.find(
"ligand_is_touching") == scores.end()
228 || scores[
"ligand_is_touching"] != 0 ) {
229 scores_out.push_back( scores_in[ii] );
235 if( to_keep <= 1.0 && to_keep >= 0.0 ) {
236 scores_out.resize( (
core::Size) std::ceil(to_keep * scores_out.size()) );
237 }
else if ( to_keep > 1.0 && scores_out.size() > to_keep ){
238 scores_out.resize( (
core::Size) std::ceil(to_keep) );
240 utility_exit_with_message(
"Cannot select a negative quantity of poses.");
261 std::set< std::string > & tags_out
265 scores_list2.reserve( atdiff.
scores().size() );
267 for(
core::Size ii = 1; ii <= scores_list2.size(); ++ii) {
268 tags_out.insert( scores_list2[ii].first );
280 using namespace core;
281 using namespace core::chemical;
282 using namespace core::conformation;
284 if( rsd1.
type().
name3() != rsd2.
type().
name3() ) utility_exit_with_message(
"Residue type name3 mismatch");
285 if( rsd1.
nheavyatoms() != rsd2.
nheavyatoms() ) utility_exit_with_message(
"Residue number-of-heavy-atoms mismatch");
286 fractions_out.resize(cutoffs.size(), 0);
293 while( old2new.size() > 0 ) {
305 for(
core::Size i = 1; i <= cutoffs.size(); ++i) {
306 core::Real const cutoff2 = cutoffs[i] * cutoffs[i];
315 if( diff.length_squared() <= cutoff2 ) nwithin += 1;
318 core::Real fracwithin = (natoms > 0 ? nwithin / natoms : 0);
319 if( fracwithin > fractions_out[i] ) {
321 fractions_out[i] = fracwithin;
334 if ( jump_id == 0 ) {
335 utility_exit_with_message(
"Pose has no jumps!");
368 utility_exit_with_message(
"Expected ligand to be last residue in pose and only one downstream of the jump");
381 if( !start_from_pts.empty() ) {
383 desired_centroid = start_from_pts[ which_triple ];
389 return desired_centroid;
407 core::Vector const trans_vec = desired_centroid - ligand_centroid;
408 core::Real const trans_len = trans_vec.length();
409 if(trans_len > 1e-3) {
423 bool include_all_rsds,
424 bool include_backbone,
425 bool include_ligands,
431 movemap->set_jump(jump_id,
true);
437 if ( !include_all_rsds ) {
439 if( include_backbone ) {
443 if ( !include_ligands ) {
449 if ( allow_min(i) ) {
451 movemap->set_chi(i,
true);
452 if ( include_backbone && allow_min_bb[i] ) movemap->set_bb(i,
true);
455 if( include_water ) {
460 movemap->set_jump( e.
label(), true );
461 TR <<
"Minimize water jump " << e.
label() <<
" to residue " << i <<
" " << pose.
residue_type(i).
name3() << std::endl;
477 FArray1D_bool
const & allow_repack,
478 bool ligand_protonation
481 using namespace core::pack::task;
482 PackerTaskOP pack_task = TaskFactory::create_packer_task(pose);
483 pack_task->initialize_from_command_line();
484 pack_task->append_rotamerset_operation(
unboundrot_ );
493 if( !this_rsd.
is_polymer() && ligand_protonation ) {
494 using namespace core::chemical;
497 for(
core::Size j = 1; j <= allowed_types.size(); ++j ) {
498 if( allowed_types[j]->
name() == this_rsd.
name() )
continue;
499 pack_task->nonconst_residue_task( i ).allow_noncanonical_aa( allowed_types[j]->
name() );
501 TR <<
"Allowed residues at position " << i <<
":" << std::endl;
503 rt != pack_task->nonconst_residue_task( i ).allowed_residue_types_end(); ++rt) {
504 TR <<
" " << (*rt)->name() << std::endl;
507 pack_task->nonconst_residue_task( i ).restrict_to_repacking();
509 if ( !allow_repack(i) )
510 pack_task->nonconst_residue_task( i ).prevent_repacking();
521 bool include_all_rsds,
522 bool ligand_protonation
535 bool ligand_protonation
550 FArray1D_bool & is_interface
565 int num_in_interface = 0;
571 if ( ! is_upstream(i) ) {
572 is_interface(i) =
true;
573 num_in_interface += 1;
579 if ( is_upstream(j) )
continue;
582 double dist2 = lig_rsd.
xyz(k).distance_squared( prot_rsd.
xyz(prot_rsd.
nbr_atom()) );
583 double cutoff = prot_rsd.
nbr_radius() + 6.0 + padding;
584 if ( dist2 <= cutoff * cutoff ) {
585 is_interface(i) =
true;
586 num_in_interface += 1;
587 goto END_LIGRES_LOOP;
593 TR <<
"Interface is " << num_in_interface <<
" / " << pose.
total_residue()
594 <<
" residues (" << 100*(double(num_in_interface) / double(pose.
total_residue())) <<
"%)" << std::endl;
610 runtime_assert( cutoff_dist > 0 );
611 double const cutoff2 = cutoff_dist * cutoff_dist;
613 int num_in_interface = 0;
621 if ( ! is_upstream(i) ) {
622 is_interface[i] =
true;
623 num_in_interface += 1;
630 if( prot_rsd.
has(
"CB") ) prot_cb = prot_rsd.
xyz(
"CB");
631 else if( prot_rsd.
has(
"CA") ) prot_cb = prot_rsd.
xyz(
"CA");
633 TR <<
"Can't find CA/CB for residue " << i << std::endl;
637 if ( is_upstream(j) )
continue;
640 double dist2 = lig_rsd.
xyz(k).distance_squared( prot_cb );
641 if ( dist2 <= cutoff2 ) {
642 is_interface[i] =
true;
645 num_in_interface += 1;
646 goto END_LIGRES_LOOP;
652 TR <<
"Backbone interface is " << num_in_interface <<
" / " << pose.
total_residue()
653 <<
" residues (" << 100*(double(num_in_interface) / double(pose.
total_residue())) <<
"%)" << std::endl;
655 int const window = 3;
659 for(
Size j = i; j >=
Size(std::max(1,
int(i)-window)); --j) {
661 is_around_interface[i] = is_around_interface[i] | is_interface[j];
665 for(
Size j = i; j <= std::min(nres,i+window); ++j) {
667 is_around_interface[i] = is_around_interface[i] | is_interface[j];
684 using namespace core::scoring::constraints;
707 TR.Debug <<
"Restraining C-alpha of residue " << i << std::endl;
727 using namespace core::scoring::constraints;
741 AtomID(rsd.nbr_atom(), lig_id),
746 TR <<
"Restraining ligand residue " << lig_id << std::endl;
786 allow_move_bb[i] = mobile_bb[i];
811 using namespace core::kinematics;
816 if(mobile_bb.size() != nres){
817 std::cerr <<
"Error: vector containing mobile residue information doesn't have the same number of residues as the pose." << std::endl;
818 utility::exit( EXIT_FAILURE, __FILE__, __LINE__);
829 if( i == lig_id )
continue;
831 if( mobile_bb[i] )
continue;
833 if( new_dist2 < shortest_dist2 ) {
834 shortest_dist2 = new_dist2;
838 Size old_nres = f.nres(), old_njump = f.num_jump();
844 bool contains_attach_pt = (( e->start() <
int(attach_pt) &&
int(attach_pt) < e->stop() )
845 || ( e->stop() <
int(attach_pt) &&
int(attach_pt) < e->start() ));
846 if( e->label() == (
int) jump_id ) {
847 f_new.
add_edge( attach_pt, lig_id, jump_id );
848 }
else if( e->label() == Edge::PEPTIDE && contains_attach_pt ) {
849 f_new.
add_edge( e->start(), attach_pt, Edge::PEPTIDE );
850 f_new.
add_edge( attach_pt, e->stop(), Edge::PEPTIDE );
852 f_new.
add_edge( e->start(), e->stop(), e->label() );
856 TR <<
"Moved ligand " << f << std::endl;
857 if( !f.connected() ) utility_exit_with_message(
"Fold tree not connected?!");
858 if( !f.check_fold_tree() ) utility_exit_with_message(
"Fold tree did not pass check!");
859 if( old_njump != f.num_jump() ) utility_exit_with_message(
"Number of jumps changed?!");
860 if( old_nres != f.nres() ) utility_exit_with_message(
"Number of residues changed?!");
861 if( lig_id != (
Size) f.downstream_jump_residue(jump_id) ) utility_exit_with_message(
"Ligand no longer at end of last jump!");
872 Size const e_start = edge_itr->start();
873 Size const e_stop = edge_itr->stop();
874 if( e_stop < e_start ) utility_exit_with_message(
"Not prepared to deal with backwards fold tree edges!");
876 if( !edge_itr->is_polymer() ) {
881 using std::max;
using std::min;
882 using namespace protocols::loops;
884 for(
Size i = e_start; i <= e_stop; ++i) {
885 while( i <= e_stop && !mobile_bb[i] ) ++i;
886 if( i > e_stop )
break;
889 while( i <= e_stop && mobile_bb[i] ) ++i;
890 if( i > e_stop ) i = e_stop;
891 if( !mobile_bb[i] ) --i;
895 if( (stop-start+1) < 4 ){
898 TR.Warning <<
"WARNING: for backbone minimization to work properly, a stretch of at least 4 residues needs to be allowed to move. Stretch between " << start <<
" and " << stop <<
" is too short." << std::endl;
908 runtime_assert( cut_start <= cut_end );
913 loops.push_back(
Loop( start, stop, cutpt ) );
918 int last_rigid = e_start;
919 for(
Size i = 1; i <= loops.size(); ++i) {
920 Loop const & l = loops[i];
921 int first = max(
int(e_start),
int(l.
start()-1) );
922 int last = min(
int(e_stop),
int(l.
stop()+1) );
923 if( first != last_rigid ) {
924 f_new.
add_edge( last_rigid, first, Edge::PEPTIDE );
929 f_new.
add_edge(
Edge( first, last, ++new_jump,
"CA",
"CA",
false ) );
933 if( last_rigid !=
int(e_stop) ) {
934 f_new.
add_edge( last_rigid, e_stop, Edge::PEPTIDE );
942 for(
Size i = 1; i <= nres; ++i ) {
949 TR <<
"Final loops foldtree " << f << std::endl;
950 if( !f.check_fold_tree() ) {
951 utility_exit_with_message(
"Invalid fold tree after trying to set up for minimization!");
959 if( lig_id != 0 ) runtime_assert( lig_id ==
get_ligand_id(pose, jump_id) );
974 using namespace core;
978 Real bb_bump_cutoff = basic::options::option[ basic::options::OptionKeys::enzdes::bb_bump_cutoff ];
982 if( i == seqpos ) help_task->nonconst_residue_task( i ).restrict_to_repacking();
983 else help_task->nonconst_residue_task( i ).prevent_repacking();
998 rotlib->fill_rotamer_vector( pose, *scofx, *help_task, neighbor_graph, res_type, existing_residue, extra_chi_steps,
true , suggested_rotamers );
1017 int const neighbor_id( (*ir)->get_other_ind( seqpos ) );
1020 scofx->bump_check_backbone( **rot_it, neighbor, pose, emap );
1022 core::Real thisrotE = scofx->weights().dot( emap ) ;
1024 if( thisrotE < bb_bump_cutoff ){
1025 temp_accepted_rotamers.push_back( *rot_it );
1026 if( thisrotE < bestE ){
1037 if( temp_accepted_rotamers.size() > 0 ){
1038 accepted_rotamers.push_back( best_rot );
1041 if( *rot_it != best_rot ) accepted_rotamers.push_back( *rot_it );