Rosetta 3.5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
MotifSearch.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 //
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 /// @file protocols/motifs/MotifSearch.cc
11 /// @brief Motif searching protocol
12 /// @author sthyme (sthyme@gmail.com)
13 
14 // Unit Headers
16 
17 // Package Headers
23 
24 // Project Headers (protocols)
27 // AUTO-REMOVED #include <protocols/dna/RestrictDesignToProteinDNAInterface.hh>
28 #include <protocols/dna/util.hh>
30 
31 // Project Headers
39 // AUTO-REMOVED #include <core/pack/task/PackerTask.hh>
40 // AUTO-REMOVED #include <core/pack/task/TaskFactory.hh>
41 #include <core/io/pdb/pose_io.hh>
43 // AUTO-REMOVED #include <core/kinematics/FoldTree.hh>
44 #include <core/pose/PDBInfo.hh>
45 #include <core/pose/Pose.hh>
46 // AUTO-REMOVED #include <core/scoring/constraints/CoordinateConstraint.hh>
48 // AUTO-REMOVED #include <core/scoring/dna/setup.hh>
49 #include <core/scoring/Energies.hh>
51 #include <core/scoring/rms_util.hh>
55 #include <basic/Tracer.hh>
56 
57 // Utility Headers
58 #include <utility/io/ozstream.hh>
59 // AUTO-REMOVED #include <utility/string_util.hh>
60 
61 #include <numeric/xyzVector.hh>
62 
63 // C++ Headers
64 #include <iostream>
65 
66 // Option Key Includes
67 #include <basic/options/option.hh>
68 // AUTO-REMOVED #include <basic/options/util.hh>
69 // AUTO-REMOVED #include <basic/options/keys/dna.OptionKeys.gen.hh>
70 #include <basic/options/keys/motifs.OptionKeys.gen.hh>
71 
72 #include <utility/vector1.hh>
73 
74 
75 namespace protocols {
76 namespace motifs {
77 
78 static basic::Tracer ms_tr( "protocols.motifs.MotifSearch", basic::t_info );
79 
81 {}
82 
84  : motif_library_(),
85  target_positions_(),
86  build_positionOPs_(0),
87  target_conformers_map_(),
88  // Option flags/parameters: default to command line options
89  ztest_cutoff_1_( basic::options::option[ basic::options::OptionKeys::motifs::z1 ]() ),
90  ztest_cutoff_2_( basic::options::option[ basic::options::OptionKeys::motifs::z2 ]() ),
91  rmsd_cutoff_1_( basic::options::option[ basic::options::OptionKeys::motifs::r1 ]() ),
92  rmsd_cutoff_2_( basic::options::option[ basic::options::OptionKeys::motifs::r2 ]() ),
93  dtest_cutoff_( basic::options::option[ basic::options::OptionKeys::motifs::dtest ]() ),
94  rot_level_( basic::options::option[ basic::options::OptionKeys::motifs::rotlevel ]() ),
95  minimize_( basic::options::option[ basic::options::OptionKeys::motifs::minimize ]() )
96 {
97  init_options();
98 }
99 
101 utility::pointer::ReferenceCount( src )
102 {
103  (*this) = src;
104 }
105 
106 MotifSearch const &
108 {
109  if( this != &src ) {
119  rot_level_ = src.rot_level_ ;
120  minimize_ = src.minimize_;
121  bpdata_ = src.bpdata_;
123  output_ = src.output_;
125  data_ = src.data_;
130  rots2add_ = src.rots2add_;
133  bump_check_ = src.bump_check_;
134  }
135  return *this;
136 }
137 
138 void
140  Pose & pose,
141  utility::vector1< Size > & input_BPs
142 )
143 {
144  initialize( pose, input_BPs );
145  incorporate_motifs( pose );
146 }
147 
148 void
150  Pose & pose,
151  utility::vector1< Size > & input_BPs
152 )
153 {
154 
155  // Obtain all necessary user input
156  if( motif_library_.empty() ) {
158  MotifCOPs motifcops = motifs.library();
159  motif_library_ = motifcops;
160  } // if it's not empty that means that the app must have filled the motif_library_
163  if( input_BPs.empty() ) {
165  }
166 
167  // This section is only relevant if you are using defs to get amino acid build positions (unlikely)
168  // Temporary container for build positions until I can associate with targets
169  DnaDesignDefOPs build_position_defs;
170  build_position_defs = get_motif_build_position_defs_user();
171  position_vector_setup( pose );
172 
173  // If there are no input target positions wild-type DNA is assumed
174  // I am not sure if the interface finder is the best way to get positions,
175  // I am worried that it is restrictive? change parameter?
176  if( build_position_defs.empty() && target_positions_.empty() ) {
177  ms_tr << "No input build or target positions, will be doing a motif search using every protein position in the interface as a build position." << std::endl;
179  it != end; ++it ) {
180  std::set< std::string > names;
181  names.insert( protocols::dna::dna_full_name3( (pose.residue( (*it) ).name3() ) ) );
182  target_positions_[*it] = names;
183  }
184  if( ! input_BPs.empty() ) {
185  for( Size i(1); i <= input_BPs.size(); ++i ) {
186  BuildPosition_from_Size( pose, input_BPs[i] );
187  }
188  } else {
190  }
191  } else if( build_position_defs.empty() ) {
192  ms_tr << "Identifying build positions based on input target positions (or they're from DnaInterfacePacker)." << std::endl;
193  if ( ! input_BPs.empty() ) {
194  for( Size i(1); i <= input_BPs.size(); ++i ) {
195  BuildPosition_from_Size( pose, input_BPs[i] );
196  }
197  } else {
199  }
200  // If the BuildPosition vector remains empty then you're allowed to use any positions
201  // If statement below (in search fxn itself) would be if( contains name3 of current motif || .empty );
202  } else if ( target_positions_.empty() ) {
203  ms_tr << "No target positions given, will be using closest position to placed motif." << std::endl;
205  it != end; ++it ) {
206  std::set< std::string > names;
207  names.insert( protocols::dna::dna_full_name3( (pose.residue( (*it) ).name3() ) ) );
208  target_positions_[*it] = names;
209  }
210  defs2BuildPositions_findts( pose, build_position_defs );
211  } else {
212  defs2BuildPositions( pose, build_position_defs );
213  // When there is both an input for build positions and target positions,
214  // the input is forced (each build position uses all input target sites)
215  }
216  if( bpdata_ ) {
217  for( BuildPositionOPs::const_iterator ir( build_positionOPs_.begin() ), end_ir( build_positionOPs_.end() );
218  ir != end_ir; ++ir ) {
220  if( clear_bprots_ ) {
221  // I could avoid adding them in the first place, but that loading function is more complicated than just clearing and I might want them later
222  (*ir)->clear_rots();
223  }
224  }
225  if( ! motif_library_.empty() ) {
226  ms_tr << "WARNING!! Loading BPData, but also loaded a MotifLibrary of all motifs" << std::endl;
227  }
228  }
229 }
230 
231 void
233  Pose const & pose
234 )
235 {
236  core::pose::Pose posecopy( pose );
237  core::pose::Pose posecopy2( pose );
238 
239  // Setup output files for motifs and rotamers
240  utility::io::ozstream motif_output_file;
241  utility::io::ozstream data_output_file;
242  utility::io::ozstream qd_output_file;
243  if( output_ ) {
244  motif_output_file.open_append( output_filename_ );
245  }
246  if( data_ ) {
247  data_output_file.open_append( data_filename_ );
248  }
249  if( quick_and_dirty_ ) {
250  std::string motif_filename( pose.pdb_info()->name() );
251  motif_filename.erase( motif_filename.end()-4, motif_filename.end() );
252  std::string qd_output_filename = motif_filename + ".qd_motifs";
253  qd_output_file.open_append( qd_output_filename );
254  }
255 
256  // for every protein backbone position (motif build position)
257  for( BuildPositionOPs::const_iterator ir( build_positionOPs_.begin() ), end_ir( build_positionOPs_.end() );
258  ir != end_ir; ++ir ) {
259  // Map of all of the very best residues for each amino acid type, to make sure I don't add 2,000 Args and only 2 Tyrs
260  std::map< std::string, std::map< Real, MotifHitOP > > best_mhits_all;
261 
262  // If we have rotamers coming in from files and they weren't cleared in initialization, then the search won't happen on this BuildPosition
263  if ( ( ! ((*ir)->best_rotamers()).empty() ) && ( ! rerun_motifsearch_ ) ) continue;
264  ms_tr << "WORKING ON PROTEIN POSITION " << (*ir)->seqpos() << std::endl;
265  MotifCOPs bp_best_motifs( (*ir)->best_motifs() );
266  core::pack::rotamer_set::Rotamers bp_best_rotamers( (*ir)->best_rotamers() );
267  // Need to clear the best_rotamers and best_motifs before I collect new ones
268  (*ir)->clear_data();
269 
270  Size seqpos( (*ir)->seqpos() );
271  std::stringstream firstline;
272  firstline << "POSITION " << seqpos;
273  if( output_ ) {
274  motif_output_file << firstline.str() << "\n";
275  }
276  if( data_ ) {
277  data_output_file << firstline.str() << "\n";
278  }
279  if( quick_and_dirty_ ) {
280  qd_output_file << firstline.str() << "\n";
281  }
282 
284  // If the BP has motifs in it at this point then they came from an input file from the cmd line
285  if( ! bp_best_motifs.empty() ) {
286  motif_library = bp_best_motifs;
287  } else {
288  motif_library = motif_library_;
289  }
290 
291  std::map< core::Size, core::pack::rotamer_set::RotamerSetOP > rotamer_sets;
292  if( bp_best_rotamers.empty() ) {
293  for( Size i(1); i <= core::chemical::num_canonical_aas; ++i ) {
295  aa_info[i] = true;
297  rotamer_sets[i] = rotset;
298  }
299  } else {
300  Size bp_rots( bp_best_rotamers.size() );
301  for( Size i(1); i <= core::chemical::num_canonical_aas; ++i ) {
303  core::pack::rotamer_set::RotamerSetOP rotset = rsf.create_rotamer_set( posecopy.residue((*ir)->seqpos()) );
304  for( Size r(1); r <= bp_rots; ++r ) {
305  if( bp_best_rotamers[r]->name3() == core::chemical::name_from_aa(core::chemical::AA(i)) ) {
306  rotset->add_rotamer( *((bp_best_rotamers)[r]) );
307  }
308  }
309  rotamer_sets[i] = rotset;
310  }
311  }
312 
313  // For every motif in the motif_library_
314  Real dtest_cutoff_sq = ( dtest_cutoff_ * dtest_cutoff_ );
315  for( protocols::motifs::MotifCOPs::const_iterator motifcop_itr = motif_library.begin(), end_itr = motif_library.end();
316  motifcop_itr != end_itr; ++motifcop_itr ) {
317  // WARNING: everything in this code assumes that residue 1 in the motif is the protein position and residue 2 is the dna
318  bool passed_quick_and_dirty(false);
319  protocols::motifs::MotifCOP motifcop( *motifcop_itr );
320  //ms_tr << "WORKING ON MOTIF: " << motifcop->remark() << std::endl;
321 
322  // The BuildPosition may at some point have the ability to restrict ahead of time
323  // currently I am not sure how to get restrictions from resfiles and so on . . .
324  // it may not be an issue because there are ways other than resfiles, such as the defs for protein positions
325  // and the main reason I would want this functionality is for homology models and theoretically the input pose
326  // should already have all of the position types set as wild-type and be relaxed and minimized
327  std::set< std::string > allowedtypes( (*ir)->allowed_types() );
328 
329  // Tighter cutoffs for residues with 3 and 4 chi angles
334  Real dtest_cutoff = dtest_cutoff_sq;
335  if( (motifcop->restype_name1() == "ARG") && ( ! quick_and_dirty_ ) ) {
336  rmsd_cutoff_1 = (rmsd_cutoff_1 / 2.0 );
337  rmsd_cutoff_2 = (rmsd_cutoff_2 / 2.0 );
338  dtest_cutoff = (dtest_cutoff / 2.0 );
339  }
340  if( ( (motifcop->restype_name1() == "MET") || (motifcop->restype_name1() == "LYS") || (motifcop->restype_name1() == "GLU") || (motifcop->restype_name1() == "GLN") ) && ( ! quick_and_dirty_ ) ) {
341  rmsd_cutoff_1 = (rmsd_cutoff_1 / 1.33 );
342  rmsd_cutoff_2 = (rmsd_cutoff_2 / 1.33 );
343  dtest_cutoff = (dtest_cutoff / 1.33 );
344  }
345 
346  // Atoms required for the parallel base test
347  // maybe these vectors should be stored as a part of this class?
348  // for non-DNA motif searches I won't be using the z-test at all
350  if( protocols::dna::dna_full_name3( motifcop->restype_name2() ) == "GUA" || protocols::dna::dna_full_name3( motifcop->restype_name2() ) == "ADE" ) {
351  atoms.push_back("C5");
352  atoms.push_back("C6");
353  atoms.push_back("N3");
354  atoms.push_back("C2");
355  atoms.push_back("N1");
356  atoms.push_back("C4");
357  } else if( protocols::dna::dna_full_name3( motifcop->restype_name2() ) == "CYT" || protocols::dna::dna_full_name3( motifcop->restype_name2() ) == "THY" ) {
358  atoms.push_back("C5");
359  atoms.push_back("C4");
360  atoms.push_back("N1");
361  atoms.push_back("C2");
362  atoms.push_back("N3");
363  atoms.push_back("C6");
364  } else {
365  ms_tr << "Residue you are planning to do parallel base test with is not a DNA base!" << std::endl;
366  }
367 
368  bool automorphism(false);
369  bool passed_automorphism(false);
370  if(
371  motifcop->restype_name1() == "ASP" ||
372  motifcop->restype_name1() == "GLU" ||
373  motifcop->restype_name1() == "PHE" ||
374  motifcop->restype_name1() == "LEU" ||
375  motifcop->restype_name1() == "ARG" ||
376  motifcop->restype_name1() == "TYR" ||
377  motifcop->restype_name1() == "VAL"
378  )
379  {
380  automorphism = true;
381  }
382 
383  // Related to only using motifs that include an allowed amino acid at the BuildPosition
384  // At this point the allowedtypes is always going to be empty
385  bool allowed(false);
386  if( allowedtypes.empty() ) {
387  allowed = true;
388  }
389  for( std::set< std::string >::const_iterator ir2(allowedtypes.begin() ), end_ir2( allowedtypes.end() );
390  ir2 != end_ir2; ++ir2 ) {
391  if( (*ir2) == motifcop->restype_name1() ) {
392  allowed = true;
393  }
394  }
395  if( ! allowed ) continue;
396 
397  // Create a standard dna base of type in motif
398  // For ligand motifs we will need to create a residue of the type we are trying to target
399  // Since there won't be a second residue in the motif
400  // restype_name2() will need to be set to something in the motif?
401  std::string basetype( motifcop->restype_name2() );
402  // If there are conformers
403  core::conformation::ResidueOPs DNAResidueOPs( target_conformers_map_[basetype] );
404  bool noconformers( false );
405  if( DNAResidueOPs.empty() ) {
406  noconformers = true;
407  }
409  // Get the rotamer set with type matching motif at the motif build position
410  core::pack::rotamer_set::RotamerSetOP rotset = rotamer_sets[ core::chemical::aa_from_name(motifcop->restype_name1()) ];
411 
412  Real final(100);
413  std::pair< core::conformation::ResidueOP, core::conformation::ResidueOP > bestpair;
414  bool b_bestpair( false );
415  Size rs1( rotset->num_rotamers() );
416 
417  // For every rotamer in the rotamer set
418  for( Size ir2(1); ir2 <= rs1; ++ir2 ) {
419  Real ztest_ir2(0.0);
420  Real rmsdtest_ir2(100.0);
421 
422  // This atom type is only C1* because that atom is common
423  // to all DNA bases and it is basically in the plane of the base
424  core::conformation::Atom atm( baseres2->atom("C1*") );
425  core::conformation::Atom auto_atm( baseres2->atom("C1*") );
426  motifcop->place_atom( *(rotset->nonconst_rotamer(ir2)), *baseres2, atm );
427  if( automorphism ) {
428  motifcop->place_atom( *(rotset->nonconst_rotamer(ir2)), *baseres2, auto_atm, false );
429  }
430 
431  // Important in case of the very strange situation where more than one
432  // target_position is close enough to pass the tests
433  bool tftest(false);
434  Size bestpos(0);
435  Real test(1000);
436 
437  Sizes target_positions( (*ir)->target_positions() );
438  for( Sizes::const_iterator bpos( target_positions.begin() ), end( target_positions.end() );
439  bpos != end; ++bpos ) {
440  std::set< std::string > allowed_types( target_positions_[*bpos] );
441  for( std::set< std::string >::const_iterator type( allowed_types.begin()), atend( allowed_types.end() );
442  type != atend; ++type ) {
443  if( basetype == *type ) {
444  // Should have a test to ensure that it has the atom types I'll be using?
445  Real dtest1( atm.xyz().distance_squared( posecopy.residue( *bpos ).xyz( "C1*" ) ) );
446  Real dtest1_auto(100);
447  if( automorphism ) {
448  dtest1_auto = ( auto_atm.xyz().distance_squared( posecopy.residue( *bpos ).xyz( "C1*" ) ) );
449  }
450 
451  if( ! automorphism ) {
452  if( dtest1 > dtest_cutoff ) continue;
453  } else {
454  if( dtest1 > dtest_cutoff && dtest1_auto > dtest_cutoff ) continue;
455  if( dtest1 < dtest_cutoff && dtest1_auto < dtest_cutoff ) {
456  if( dtest1_auto < dtest1 ) {
457  passed_automorphism = true;
458  } else {
459  passed_automorphism = false;
460  }
461  } else if( dtest1_auto < dtest_cutoff ) {
462  passed_automorphism = true;
463  } else {
464  passed_automorphism = false;
465  }
466  }
467  core::conformation::ResidueOP posebase = new core::conformation::Residue( posecopy.residue( *bpos ) );
468  if( passed_automorphism ) {
469  motifcop->place_atoms( *(rotset->nonconst_rotamer(ir2)), *posebase, atoms, false );
470  } else {
471  motifcop->place_atoms( *(rotset->nonconst_rotamer(ir2)), *posebase, atoms );
472  }
473  Real ztest = protocols::motifs::parallel_base_test( *posebase, posecopy.residue( *bpos ) );
474 
475  if( ztest < ztest_cutoff_1 ) continue;
476  ztest_ir2 = ztest;
477  if( quick_and_dirty_ ) {
478  qd_output_file << *motifcop;
479  passed_quick_and_dirty = true;
480  break;
481  }
482  if( protocols::dna::dna_full_name3( posecopy.residue(*bpos).name3() ) != basetype ) {
483  make_base_pair_mutation( posecopy, *bpos , core::chemical::aa_from_name( basetype ) );
484  }
485  Real rmsdtest = atom_specific_rms( *posebase, posecopy.residue(*bpos), atoms );
486 
487  if( rmsdtest > rmsd_cutoff_1 ) continue;
488  rmsdtest_ir2 = rmsdtest;
489  if( rmsdtest < test ) {
490  test = rmsdtest;
491  bestpos = *bpos;
492  posecopy2 = posecopy;
493  tftest = true;
494  } // if( rmsdtest < test )
495  }
496  } // loop over allowed_types for the allowed DNA types
497  if( passed_quick_and_dirty ) break;
498  } // loop over potential target DNA positions
499 
500  if( passed_quick_and_dirty ) break;
501  if( ! tftest ) continue;
502 
503  MotifHitOP motifhit = new MotifHit( *motifcop, bestpos, passed_automorphism );
504 
505  // If there are no conformers will use the base from the pose, so rmsd can be 0 theoretically
506  if( noconformers ) {
507  core::conformation::ResidueOP posebase2 = new core::conformation::Residue( posecopy2.residue( bestpos) );
508  if( passed_automorphism ) {
509  motifcop->place_residue(*(rotset->nonconst_rotamer(ir2)), *posebase2, false );
510  } else {
511  motifcop->place_residue(*(rotset->nonconst_rotamer(ir2)), *posebase2 );
512  }
513  // The RMSD is def different if you do the entire base instead of the few atoms as above
514  //Real ztest2 = parallel_base_test( *posebase2, posecopy2.residue(bestpos) );
515  //Real rmsdtest2 = core::scoring::automorphic_rmsd( *posebase2, posecopy2.residue(bestpos), false );
516  //Real finaltest2 = ( ( rmsdtest2 * 100 ) / ( ztest2 * 100 ) );
517  Real finaltest = ( ( rmsdtest_ir2 * 100 ) / ( ztest_ir2 * 100 ) );
518  //NOTE: Do I want to keep any statistics about percentages of passing certain cutoffs??
519  if( (rmsdtest_ir2 < rmsd_cutoff_2) && (ztest_ir2 > ztest_cutoff_2) ) {
520  ms_tr << "Passed! RMSD between DNA resi (rosetta #), no conformers " << bestpos << " and motif DNA = " << rmsdtest_ir2 << " and Z-test = " << ztest_ir2 << " and combined score = " << finaltest << " for residue type " << motifcop->restype_name1() << ", rotamer # " << ir2 << ", motif named " << motifcop->remark() << std::endl;
521  //ms_tr << "Passed! RMSD between DNA resi (rosetta #) " << bestpos << " and motif DNA = " << rmsdtest2 << " and Z-test = " << ztest2 << " and combined score = " << finaltest2 << " for residue type " << motifcop->restype_name1() << ", rotamer # " << ir2 << ", motif named " << motifcop->remark() << std::endl;
522  if( data_ ) {
523  data_output_file << "Passed! RMSD between DNA resi (rosetta #), no conformers " << bestpos << " and motif DNA = " << rmsdtest_ir2 << " and Z-test = " << ztest_ir2 << " and combined score = " << finaltest << " for residue type " << motifcop->restype_name1() << ", rotamer # " << ir2 << ", motif named " << motifcop->remark() << std::endl;
524  }
525  // Fix to make it so that rotamers with different hydrogen positions are added, even though they are not part of the motif and thus have the same finaltest value
526  if ( ( motifcop->restype_name1() == "SER" ) || ( motifcop->restype_name1() == "THR" ) || ( motifcop->restype_name1() == "TYR" ) || ( motifcop->restype_name1() == "ILE" ) || ( motifcop->restype_name1() == "CYS" ) ) {
527  finaltest = finaltest + ( 0.00001 * ir2 );
528  }
529  motifhit->final_test( finaltest );
530  motifhit->build_rotamer( *(rotset->nonconst_rotamer(ir2) ) );
531  motifhit->target_conformer( *posebase2 );
532  best_mhits_all[motifcop->restype_name1()][finaltest] = motifhit->clone();
533  if ( finaltest < final ) {
534  b_bestpair = true;
535  bestpair = std::make_pair( (rotset->nonconst_rotamer(ir2))->clone(), posebase2->clone() );
536  final = finaltest;
537  }
538  } // if passed the second round of tests
539  } else {
540  for( core::conformation::ResidueOPs::const_iterator resop( DNAResidueOPs.begin() ), end( DNAResidueOPs.end() );
541  resop != end; ++resop ) {
542  if( passed_automorphism ) {
543  motifcop->place_residue(*(rotset->nonconst_rotamer(ir2)), **resop, false );
544  } else {
545  motifcop->place_residue(*(rotset->nonconst_rotamer(ir2)), **resop );
546  }
547  Real ztest2 = parallel_base_test( **resop, posecopy2.residue(bestpos) );
548  if( ztest2 < ztest_cutoff_2 ) continue;
549  Real rmsdtest2 = core::scoring::automorphic_rmsd( **resop, posecopy2.residue(bestpos), false );
550  if( rmsdtest2 > rmsd_cutoff_2 ) continue;
551  Real finaltest = ( ( rmsdtest2 * 100 ) / ( ztest2 * 100 ) );
552  Real finaltestc = ( ( rmsdtest_ir2 * 100 ) / ( ztest_ir2 * 100 ) );
553  //NOTE: Do I want to keep any statistics about percentages of passing certain cutoffs??
554  if( (rmsdtest2 < rmsd_cutoff_2) && (ztest2 > ztest_cutoff_2) ) {
555  ms_tr << "Passed! RMSD between DNA resi (rosetta #) " << bestpos << " and motif DNA = " << rmsdtest2 << " and Z-test = " << ztest2 << " and combined score = " << finaltest << " for residue type " << motifcop->restype_name1() << ", rotamer # " << ir2 << ", motif named " << motifcop->remark() << std::endl;
556  if( data_ ) {
557  data_output_file << "Passed! RMSD between DNA resi (rosetta #) " << bestpos << " and motif DNA = " << rmsdtest2 << " and Z-test = " << ztest2 << " and combined score = " << finaltest << " for residue type " << motifcop->restype_name1() << ", rotamer # " << ir2 << ", motif named " << motifcop->remark() << std::endl;
558  }
559  // Fix to make it so that rotamers with different hydrogen positions are added, even though they are not part of the motif and thus have the same finaltest value
560  if ( ( motifcop->restype_name1() == "SER" ) || ( motifcop->restype_name1() == "THR" ) || ( motifcop->restype_name1() == "TYR" ) || ( motifcop->restype_name1() == "ILE" ) || ( motifcop->restype_name1() == "CYS" ) ) {
561  finaltest = finaltest + ( 0.00001 * ir2 );
562  }
563  motifhit->final_test( finaltest );
564  motifhit->build_rotamer( *(rotset->nonconst_rotamer(ir2) ) );
565  motifhit->target_conformer( **resop );
566  best_mhits_all[motifcop->restype_name1()][finaltestc] = motifhit->clone();
567  if ( finaltest < final ) {
568  b_bestpair = true;
569  bestpair = std::make_pair( (rotset->nonconst_rotamer(ir2))->clone(), (*resop)->clone() );
570  final = finaltest;
571  }
572  } // if conformer passed the second round of tests
573  } // loop over conformers
574  } // if not noconfomers
575  } // loop over first rotamer set
576 
577  // Dump the best rotamer and conformer pair for each motif, mainly for debugging purposes
578  if( dump_motifs_ ) {
579  if( b_bestpair ) {
580  core::pose::Pose pose_dump2;
581  pose_dump2.append_residue_by_jump( *(bestpair.second), 1);
582  pose_dump2.append_residue_by_jump( *(bestpair.first), 1);
583  std::stringstream pose2_name_full;
584  if( passed_automorphism ) {
585  pose2_name_full << "Test_auto_" << motifcop->restype_name2()[0] << "_" << (*ir)->seqpos() << motifcop->restype_name1() << "_" << motifcop->remark() << ".pdb";
586  } else {
587  pose2_name_full << "Test_" << motifcop->restype_name2()[0] << "_" << (*ir)->seqpos() << motifcop->restype_name1() << "_" << motifcop->remark() << ".pdb";
588  }
589  core::io::pdb::dump_pdb( pose_dump2, pose2_name_full.str() );
590  }
591  }
592  }
593  if( ! best_mhits_all.empty() ) {
594  core::pose::Pose pose_dump( pose );
595  for( std::map< std::string, std::map< Real, MotifHitOP > >::const_iterator bh( best_mhits_all.begin() ),
596  end( best_mhits_all.end() ); bh != end; ++bh ) {
597  Size hits = 0;
598  for( std::map< Real, MotifHitOP >::const_iterator bh2( (bh->second).begin() ),
599  end2( (bh->second).end() ); bh2 != end2; ++bh2 ) {
600  MotifHitOP motifhitop( bh2->second );
601  if( ! minimize_ ) {
602  (*ir)->keep_rotamer( *(motifhitop->build_rotamer()) );
603  (*ir)->keep_motif( *(motifhitop->motifcop()) );
604  (*ir)->keep_motifhit( *(motifhitop) );
605  ++hits;
606  if( output_ ) {
607  motif_output_file << *(motifhitop->motifcop());
608  motif_output_file << "RESIDUE " << (*(motifhitop->build_rotamer()));
609  }
610  if( hits > rots2add_ ) break;
611  } else {
612  using namespace core::scoring;
613  // Need a copy of the pose to generate the constraints
614  // Maybe there's a way to rewrite the constraint making code to avoid this?
615  // No, because the minimize itself needs the residues to be a part of the pose?
616  // Or maybe instead of copying the pose you could save the residue you are replacing and replace it back?
617  //core::pose::Pose pose_dump( pose );
618  core::conformation::ResidueOP build_rotamer = new core::conformation::Residue( *(motifhitop->build_rotamer()) );
619  pose_dump.replace_residue( (*ir)->seqpos(), *build_rotamer, false );
620  // The residue is probably already placed . . .
621  // if( passed_automorphism ) {
622  // motifcop->place_residue( motifhitop->build_rotamer(), motifhitop->target_conformer(), false );
623  // } else {
624  // motifcop->place_residue( motifhitop->build_rotamer(), motifhitop->target_conformer() );
625  // }
626  if ( protocols::dna::dna_full_name3( pose_dump.residue(motifhitop->vbpos()).name3() ) != protocols::dna::dna_full_name3( (motifhitop->target_conformer())->name3() ) ) {
627  make_base_pair_mutation( pose_dump, motifhitop->vbpos(), core::chemical::aa_from_name( protocols::dna::dna_full_name3( motifhitop->target_conformer()->name3() ) ) );
628  }
629  if( motifhitop->passed_automorphism() ) {
630  (motifhitop->motifcop())->place_residue( pose_dump.residue( motifhitop->vbpos() ), *build_rotamer, false );
631  } else {
632  (motifhitop->motifcop())->place_residue( pose_dump.residue( motifhitop->vbpos() ), *build_rotamer );
633  }
634  /*core::pose::Pose pose_dump2( pose );
635  pose_dump2.replace_residue( (*ir)->seqpos(), *build_rotamer, false );
636  std::stringstream pose2_name_full;
637  std::stringstream pose_name_full;
638  std::stringstream pose3_name_full;
639  pose2_name_full << "AfterReplace_" << bh2->first << ".pdb";
640  pose_name_full << "BeforeReplace_" << bh2->first << ".pdb";
641  pose3_name_full << "AfterMinBeforeReplace_" << bh2->first << ".pdb";
642  core::io::pdb::dump_pdb( pose_dump2, pose2_name_full.str() );
643  core::io::pdb::dump_pdb( pose_dump, pose_name_full.str() );*/
644 
646  add_motif_sc_constraints( sc_cst_set, pose_dump, (*ir)->seqpos(), *build_rotamer, motifhitop->motifcop(), false );
647  //add_motif_sc_constraints( sc_cst_set, pose_dump2, (*ir)->seqpos(), *build_rotamer, motifhitop->motifcop(), false );
649  methods::EnergyMethodOptions options( score_fxn->energy_method_options() );
650  score_fxn->set_energy_method_options( options );
651  score_fxn->set_weight( coordinate_constraint, 10.0 );
652  pose_dump.constraint_set( sc_cst_set );
653  //pose_dump2.constraint_set( sc_cst_set );
654  //core::Real pre_sc_constraint_check( pose_dump.energies().total_energies()[ coordinate_constraint ] );
655  //core::Real pre_sc_constraint_check2( pose_dump2.energies().total_energies()[ coordinate_constraint ] );
656  //ms_tr << "Before sidechain refinement constraints score is " << pre_sc_constraint_check << std::endl;
657  //ms_tr << "2Before sidechain refinement constraints score is " << pre_sc_constraint_check2 << std::endl;
658  /*if( data_ ) {
659  data_output_file << "Before sidechain refinement constraints score is " << pre_sc_constraint_check << std::endl;
660  }*/
662  movemap->set_chi( (*ir)->seqpos(), true );
663  protocols::simple_moves::MinMoverOP minmover = new protocols::simple_moves::MinMover( movemap, score_fxn, "dfpmin_armijo_nonmonotone_atol", 0.000001, true );
664  minmover->apply( pose_dump );
665  //core::io::pdb::dump_pdb( pose_dump, pose3_name_full.str() );
666  core::Real sc_constraint_check( pose_dump.energies().total_energies()[ coordinate_constraint ] );
667  ms_tr << "After sidechain refinement constraints score is " << sc_constraint_check << std::endl;
668  /*if( data_ ) {
669  data_output_file << "After sidechain refinement constraints score is " << sc_constraint_check << std::endl;
670  }*/
671  /*if( sc_constraint_check < 10.0 && sc_constraint_check < pre_sc_constraint_check ) {
672  (*ir)->keep_rotamer( (pose_dump.residue((*ir)->seqpos())) );
673  ++hits;
674  if( output_ ) {
675  motif_output_file << *(motifhitop->motifcop());
676  motif_output_file << "RESIDUE " << (pose_dump.residue((*ir)->seqpos()));
677  }
678  } else if( pre_sc_constraint_check < 10.0 && sc_constraint_check > pre_sc_constraint_check ) {
679  pose_dump.replace_residue( (*ir)->seqpos(), *(motifhitop->build_rotamer()), true );
680  (*ir)->keep_rotamer( (pose_dump.residue((*ir)->seqpos())) );
681  ++hits;
682  if( output_ ) {
683  motif_output_file << *(motifhitop->motifcop());
684  motif_output_file << "RESIDUE " << (pose_dump.residue((*ir)->seqpos()));
685  }
686  }*/
687  if( sc_constraint_check < 10.0 ) {
688  (*ir)->keep_rotamer( (pose_dump.residue((*ir)->seqpos())) );
689  (*ir)->keep_motif( *(motifhitop->motifcop()) );
690  (*ir)->keep_motifhit( *(motifhitop) );
691  ++hits;
692  if( output_ ) {
693  motif_output_file << *(motifhitop->motifcop());
694  motif_output_file << "RESIDUE " << (pose_dump.residue((*ir)->seqpos()));
695  }
696  }
697  pose_dump.replace_residue( (*ir)->seqpos(), *(motifhitop->build_rotamer()), true );
698  (*ir)->keep_rotamer( (pose_dump.residue((*ir)->seqpos())) );
699  (*ir)->keep_motif( *(motifhitop->motifcop()) );
700  (*ir)->keep_motifhit( *(motifhitop) );
701  if( output_ ) {
702  motif_output_file << *(motifhitop->motifcop());
703  motif_output_file << "RESIDUE " << (pose_dump.residue((*ir)->seqpos()));
704  }
705  if( hits > rots2add_ ) break;
706  }
707  }
708  }
709  }
710  }
711  if( output_ ) {
712  motif_output_file.close();
713  }
714  if( data_ ) {
715  data_output_file.close();
716  }
717  if( quick_and_dirty_ ) {
718  qd_output_file.close();
719  }
720 }
721 
724  Size const seqpos
725 )
726 {
727  core::pack::rotamer_set::Rotamers best_rotamers;
728  for ( BuildPositionOPs::const_iterator ir( build_positionOPs_.begin() ), end_ir( build_positionOPs_.end() );
729  ir != end_ir; ++ir ) {
730  if( (*ir)->seqpos() != seqpos ) continue;
731  if ( ! ((*ir)->best_rotamers()).empty() ) {
732  std::set< std::string > allowedtypes( (*ir)->allowed_types() );
733  if( allowedtypes.empty() ) {
734  best_rotamers = (*ir)->best_rotamers();
735  }
736  Size rs( ((*ir)->best_rotamers()).size() );
737  for ( Size r(1) ; r <= rs; ++r ) {
738  for( std::set< std::string >::const_iterator ir2(allowedtypes.begin() ), end_ir2( allowedtypes.end() );
739  ir2 != end_ir2; ++ir2 ) {
740  if( (*ir2) == ((*ir)->best_rotamers()[r])->name3() ) {
741  best_rotamers.push_back( (*ir)->best_rotamers()[r] );
742  }
743  }
744  }
745  //best_rotamers = (*ir)->best_rotamers();
746  } else {
747  ms_tr << "There were no rotamers to be included for position " << seqpos << std::endl;
748  }
749  }
750  return best_rotamers;
751 }
752 
755  Size const seqpos
756 )
757 {
758  protocols::motifs::MotifHitCOPs motifhitcops;
759  for ( BuildPositionOPs::const_iterator ir( build_positionOPs_.begin() ), end_ir( build_positionOPs_.end() );
760  ir != end_ir; ++ir ) {
761  if( (*ir)->seqpos() != seqpos ) continue;
762  if ( ! ((*ir)->best_motifhits()).empty() ) {
763  Size rs( ((*ir)->best_motifhits()).size() );
764  for ( Size r(1) ; r <= rs; ++r ) {
765  motifhitcops.push_back( (*ir)->best_motifhits()[r] );
766  }
767  } else {
768  ms_tr << "There were no motif hits for " << seqpos << ". Check to be sure that MotifSearch protocol actually ran. Use flag rerun_motifsearch to ensure that it runs even with input rotamers from BPData flag." << std::endl;
769  }
770  }
771  return motifhitcops;
772 }
773 
774 // Maybe this belongs with Motif.cc or MotifLibrary.cc, or both, but not here
775 bool
777 {
778  using namespace core::chemical;
779  // This function only works for a motif that is made up of only two residues
780  bool protein_dna( false );
781  // motif_library_ has to be filled with the input MotifLibrary before you can call this fxn
782  if ( ! motif_library_.empty() ) {
783  // Check to see if motif has a protein component and a dna component
784  //THIS IS RIDICULOUS, DON'T MAKE RESIDUES, MAKE RESIDUE TYPE FROM NAME3
787  if ( ( res1->is_protein() && res2->is_DNA() ) || ( res2->is_protein() && res1->is_DNA() ) ) {
788  protein_dna = true;
789  }
790  } else {
791  ms_tr << "MotifLibrary has not been initialized yet, cannot yet identify the type of motifs being used, assuming protein-DNA with possible disastrous consequences." << std::endl;
792  protein_dna = true;
793  }
794  return protein_dna;
795 }
796 
797 // Will make this more general! Should keep the chains separate
798 // Maybe make a map of vectors, keeping track of the different chains
799 void
801  Pose const & pose
802 )
803 {
804  for ( Size i(1), end( pose.total_residue() ); i <= end; ++i ) {
805  if ( pose.residue_type(i).is_protein() ) {
806  protein_positions_.push_back(i);
807  }
808  if ( pose.residue_type(i).is_DNA() ) {
809  dna_positions_.push_back(i);
810  }
811  }
812 }
813 
814 void
816  Pose const & pose,
817  utility::vector1< Size > & build_positions
818 )
819 {
820  if ( protein_dna_motif() ) {
821  protein_DNA_motif_build_positions_JA( pose, build_positions, dna_positions_ ); //could easily change this line to take one of Phil's DNA interface fxns that also fills a vector
822  } else {
823  ms_tr << "ERROR! These motifs are not protein-DNA, need to add another else if statement that allows for a different type of interface finding function." << std::endl;
824  }
825 }
826 
827 void
829  Pose const & pose
830 )
831 {
832  Sizes positions(0);
833  if ( protein_dna_motif() ) {
835  protein_DNA_motif_build_positions_JA( pose, positions, target_positions );
836  for ( Sizes::const_iterator pos( positions.begin() ), end( positions.end() );
837  pos != end; ++pos ) {
838  Size seqpos(*pos);
839  Sizes short_target_positions( shorten_target_list( pose, seqpos, target_positions ) );
840  std::set< std::string > allowed_types; // this vector will remain empty in this sitatuation since there is no input Def to limit the types of amino acids allowed
841  if( restrict_to_wt_ ) {
842  allowed_types.insert( pose.residue( seqpos ).name3() );
843  }
844  BuildPositionOP build_position = new BuildPosition( seqpos, short_target_positions, allowed_types );
845  build_positionOPs_.push_back( build_position );
846  }
847  } else {
848  ms_tr << "ERROR! These motifs are not protein-DNA, need to add another else if statement that allows for a different type of interface finding function." << std::endl;
849  }
850 }
851 
852 void
854  Pose const & pose,
855  Size const input_BP
856 )
857 {
859  Sizes short_target_positions( shorten_target_list( pose, input_BP, target_positions ) );
860  std::set< std::string > allowed_types; // this set will remain empty in this sitatuation since there is no input Def to limit the types of amino acids allowed
861  if( restrict_to_wt_ ) {
862  allowed_types.insert( pose.residue( input_BP ).name3() );
863  }
864  BuildPositionOP build_position = new BuildPosition( input_BP, short_target_positions, allowed_types );
865  build_positionOPs_.push_back( build_position );
866 }
867 
868 void
870  Pose const & pose,
871  DnaDesignDefOPs const & defs
872 )
873 {
874  if ( protein_dna_motif() ) {
875  Sizes full_tl( map2keyvector( target_positions_ ) );
876  std::map< Size, std::set< std::string > > mappositions( bpdefs2map( pose, defs ) );
877  for ( std::map<Size, std::set< std::string > >::const_iterator it( mappositions.begin() ),
878  end( mappositions.end() ); it != end; ++it ) {
879  BuildPositionOP build_position = new BuildPosition( it->first, full_tl, it->second );
880  build_positionOPs_.push_back( build_position );
881  }
882  } else {
883  ms_tr << "ERROR! These motifs are not protein-DNA, need to add another else if statement that allows for a different type of interface finding function." << std::endl;
884  }
885 }
886 
887 void
889  Pose const & pose,
890  DnaDesignDefOPs const & defs
891 )
892 {
893  if ( protein_dna_motif() ) {
894  Sizes full_tl( map2keyvector( target_positions_ ) );
895  std::map< Size, std::set< std::string > > mappositions( bpdefs2map( pose, defs ) );
896  for ( std::map<Size, std::set< std::string > >::const_iterator it( mappositions.begin() ),
897  end( mappositions.end() ); it != end; ++it ) {
898  Size test(it->first);
899  Sizes short_tl( shorten_target_list( pose, test, full_tl ) );
900  BuildPositionOP build_position = new BuildPosition( it->first, short_tl, it->second );
901  build_positionOPs_.push_back( build_position );
902  }
903  } else {
904  ms_tr << "ERROR! These motifs are not protein-DNA, need to add another else if statement that allows for a different type of interface finding function." << std::endl;
905  }
906 }
907 
910  std::map< Size, std::set< std::string > > mappositions
911 )
912 {
913  Sizes positions(0);
914  for ( std::map<Size, std::set< std::string > >::const_iterator it( mappositions.begin() ),
915  end( mappositions.end() ); it != end; ++it ) {
916  positions.push_back( it->first );
917  }
918  return positions;
919 }
920 
923  Pose const & pose,
924  Size const bp,
925  Sizes & full_tl
926 )
927 {
928  Sizes short_tl(0);
929  Sizes bps(0);
930  bps.push_back( bp );
931  protein_DNA_motif_target_positions_JA( pose, bps, full_tl, short_tl );
932  return short_tl;
933 }
934 
935 void
937  Pose const & pose,
938  Sizes & build_positions,
940 )
941 {
942  protocols::dna::DnaInterfaceFinderOP interface = new protocols::dna::DnaInterfaceFinder( 10*10, 3.9*3.9, 6., true );
943  if ( ! target_positions.empty() ) { // again, this won't work well if there are multiple target positions in vector
944  interface->determine_protein_interface( pose, protein_positions_, target_positions ); // unless target_positions_ is empty - will actually deal with that later, will fill with all DNA in initialize if no protein pos or dna pos are given
945  protocols::dna::DnaNeighbors protein_neighbors = interface->protein_neighbors();
946  for ( protocols::dna::DnaNeighbors::const_iterator itr( protein_neighbors.begin() ),
947  end( protein_neighbors.end() ); itr != end; ++itr ) {
948  if ( (*itr).second.contact() ) {
949  build_positions.push_back( itr->first );
950  ms_tr << "Positions being targeted for motif design " << itr->first << std::endl;
951  }
952  }
953  ms_tr << "Attempting to identify build positions when there are no target positions." << std::endl;
954  }
955 }
956 
957 void
959  Pose const & pose,
960  Sizes & build_positions,
962  Sizes & short_tl
963 )
964 {
965  // JA used 3.7, I picked 3.9 to access a position I knew was important
966  protocols::dna::DnaInterfaceFinderOP interface = new protocols::dna::DnaInterfaceFinder( 10*10, 3.9*3.9, 6., true );
967  if ( ! build_positions.empty() ) {
968  interface->determine_dna_interface( pose, build_positions, target_positions );
969  protocols::dna::DnaNeighbors dna_neighbors = interface->dna_neighbors();
970  for ( protocols::dna::DnaNeighbors::const_iterator itr( dna_neighbors.begin() ),
971  end( dna_neighbors.end() ); itr != end; ++itr ) {
972  if ( (*itr).second.contact() ) {
973  short_tl.push_back( itr->first );
974  ms_tr << "Positions (DNA) being targeted for motif design " << itr->first << std::endl;
975  }
976  }
977  ms_tr << "Attempting to identify build positions when there are no target positions." << std::endl;
978  }
979 }
980 
981 void
983  Real const & r1,
984  Real const & z1,
985  Real const & r2,
986  Real const & z2,
987  Real const & d1,
988  Size const & rlevel,
989  bool const bpdata,
990  bool const bump_check
991 )
992 {
993  ztest_cutoff_1_ = z1;
994  ztest_cutoff_2_ = z2;
995  rmsd_cutoff_1_ = r1;
996  rmsd_cutoff_2_ = r2;
997  dtest_cutoff_ = d1;
998  rot_level_ = rlevel;
999  bpdata_ = bpdata;
1000  bump_check_ = bump_check;
1001 }
1002 
1003 void
1005 {
1006  ztest_cutoff_1_ = basic::options::option[ basic::options::OptionKeys::motifs::z1 ]();
1007  ztest_cutoff_2_ = basic::options::option[ basic::options::OptionKeys::motifs::z2 ]();
1008  rmsd_cutoff_1_ = basic::options::option[ basic::options::OptionKeys::motifs::r1 ]();
1009  rmsd_cutoff_2_ = basic::options::option[ basic::options::OptionKeys::motifs::r2 ]();
1010  dtest_cutoff_ = basic::options::option[ basic::options::OptionKeys::motifs::dtest ]();
1011  rot_level_ = basic::options::option[ basic::options::OptionKeys::motifs::rotlevel ]();
1012 }
1013 
1014 void
1016  MotifLibrary & motiflibrary
1017 )
1018 {
1019  for( protocols::motifs::MotifCOPs::const_iterator motifcop_itr = motiflibrary.begin(), end_itr = motiflibrary.end();
1020  motifcop_itr != end_itr; ++motifcop_itr ) {
1021  protocols::motifs::MotifCOP motifcop( *motifcop_itr );
1022  motif_library_.push_back( motifcop );
1023  }
1024 }
1025 
1026 // should probably be a private fxn, so should other ones . . . need to organize code
1027 void
1029 {
1030  if( basic::options::option[ basic::options::OptionKeys::motifs::BPData ].user() ) {
1031  bpdata_ = true;
1032  bpdata_filename_ = basic::options::option[ basic::options::OptionKeys::motifs::BPData ]();
1033  } else {
1034  bpdata_ = false;
1035  }
1036  if( basic::options::option[ basic::options::OptionKeys::motifs::output_file ].user() ) {
1037  output_filename_ = basic::options::option[ basic::options::OptionKeys::motifs::output_file ]();
1038  output_ = true;
1039  } else {
1040  output_ = false;
1041  }
1042  if( basic::options::option[ basic::options::OptionKeys::motifs::data_file ].user() ) {
1043  data_filename_ = basic::options::option[ basic::options::OptionKeys::motifs::data_file ]();
1044  data_ = true;
1045  } else {
1046  data_ = false;
1047  }
1048  if( (basic::options::option[ basic::options::OptionKeys::motifs::quick_and_dirty ]).user() ) {
1049  quick_and_dirty_ = true;
1050  } else {
1051  quick_and_dirty_ = false;
1052  }
1053  if( (basic::options::option[ basic::options::OptionKeys::motifs::dump_motifs ]).user() ) {
1054  dump_motifs_ = true;
1055  } else {
1056  dump_motifs_ = false;
1057  }
1058  if( basic::options::option[ basic::options::OptionKeys::motifs::clear_bprots ].user() ) {
1059  clear_bprots_ = true;
1060  } else {
1061  clear_bprots_ = false;
1062  }
1063  if( basic::options::option[ basic::options::OptionKeys::motifs::rots2add ].user() ) {
1064  rots2add_ = basic::options::option[ basic::options::OptionKeys::motifs::rots2add ]();
1065  } else {
1066  rots2add_ = 100;
1067  }
1068  if( (basic::options::option[ basic::options::OptionKeys::motifs::restrict_to_wt ]).user() ) {
1069  restrict_to_wt_ = true;
1070  } else {
1071  restrict_to_wt_ = false;
1072  }
1073  if( (basic::options::option[ basic::options::OptionKeys::motifs::rerun_motifsearch ]).user() ) {
1074  rerun_motifsearch_ = true;
1075  } else {
1076  rerun_motifsearch_ = false;
1077  }
1078  if( (basic::options::option[ basic::options::OptionKeys::motifs::no_rotamer_bump ]).user() ) {
1079  bump_check_ = false;
1080  } else {
1081  bump_check_ = true;
1082  }
1083 
1084 
1085 }
1086 
1087 } // motifs
1088 } // protocols