Rosetta 3.5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
RestrictDesignToProteinDNAInterface.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 RestrictDesignToProteinDNAInterface.cc
11 /// @brief
12 /// @author ashworth
13 
18 #include <protocols/dna/util.hh> // find_basepairs
20 
21 #include <core/chemical/AA.hh>
25 #include <basic/options/option.hh>
27 #include <core/pose/Pose.hh>
28 #include <core/pose/PDBInfo.hh>
29 #include <core/pose/PDBPoseMap.hh>
31 
32 #include <basic/Tracer.hh>
33 #include <utility/tag/Tag.hh>
34 #include <utility/exit.hh>
35 #include <utility/vector1.hh>
36 using utility::vector1;
37 #include <utility/string_util.hh>
38 using utility::string_split;
39 
40 #include <ObjexxFCL/format.hh>
41 
42 // option key includes
43 
44 #include <basic/options/keys/dna.OptionKeys.gen.hh>
45 
46 #include <utility/vector0.hh>
47 
48 
49 using namespace ObjexxFCL::fmt;
50 
51 namespace protocols {
52 namespace dna {
53 
54 using namespace core;
55  using namespace chemical;
56  using namespace conformation;
57  using namespace basic::options;
58  using namespace pack;
59  using namespace task;
60  using namespace operation;
61  using namespace pose;
62  using namespace scoring;
63  using namespace constraints;
64 
65 using basic::t_info;
66 using basic::t_debug;
67 using basic::t_trace;
68 static basic::Tracer TR("protocols.dna.RestrictDesignToProteinDNAInterface",t_info);
69 
70 TaskOperationOP RestrictDesignToProteinDNAInterfaceCreator::create_task_operation() const
71 {
73 }
74 
75 RestrictDesignToProteinDNAInterface::RestrictDesignToProteinDNAInterface()
76  : parent(),
77  dna_chains_(0),
78  interface_(0),
79  reference_pose_(0),
80  base_only_( true ),
81  forget_chains_and_interface_( true ),
82  z_cutoff_( 0.0 ),
83  close_threshold_( 10. * 10. ),
84  contact_threshold_( 3.7 * 3.7 )
85 {}
86 
88 
90 {
91  return new RestrictDesignToProteinDNAInterface( *this );
92 }
93 
94 void
96 {
97  dna_chains_ = new DnaChains( *dna_chains );
98 }
99 
102 
103 void
105 {
107 }
108 
109 DnaDesignDefOPs const &
111 
112 void
114 {
115  interface_ = new DnaInterfaceFinder( *interface );
116 }
117 
120 
121 void
123 {
124  reference_pose_ = pose;
125 }
126 
127 PoseCOP
129 
130 void
132 {
134  if ( tag->hasOption("dna_defs") ) {
135  //targeted_dna_.clear() // pros/cons?
136  std::string const defs( tag->getOption< std::string >("dna_defs") );
137  if ( defs == "COMMANDLINE" ) {
138  TR(t_debug) << " parsing dna definitions from command line" << std::endl;
140  } else {
141  TR(t_debug) << " parsing dna definitions: " << defs << std::endl;
142  Strings const str_defs( string_split( defs, ',' ) );
144  }
145  TR(t_debug) << "targeted DNA is: " << targeted_dna_ << std::endl;
146  }
147  if ( tag->hasOption("base_only") ) base_only_ = tag->getOption< bool >("base_only");
148  if ( tag->hasOption("z_cutoff") ) z_cutoff_ = tag->getOption< Real >("z_cutoff");
149  if ( tag->hasOption("close_threshold") )
150  close_threshold_ = tag->getOption< Real >("close_threshold");
151  if ( tag->hasOption("contact_threshold") )
152  close_threshold_ = tag->getOption< Real >("contact_threshold");
153  if ( tag->hasOption("forget_chains_and_interface") )
154  forget_chains_and_interface_ = tag->getOption< bool >("forget_chains_and_interface");
155 }
156 
157 /// @begin RestrictDesignToProteinDNAInterface::apply
158 /// @brief determines the DNA interface residues and informs a PackerTask of their appropriate packing behavior
159 /// @details
160 /// Step 2: get info about DNA chains and set up DNA packing behavior
161 /// Step 3: Determine protein-DNA interface
162 /// Step 4: apply any new restrictions to resfile pack/design settings, and any existing constraints
163 /// Step 5: report
164 void
166  Pose const & pose,
167  PackerTask & ptask
168 ) const
169 {
170  using namespace task;
171 
172  if ( z_cutoff_ == 0.0 ) z_cutoff_ = option[ OptionKeys::dna::design::z_cutoff ]();
173 
174 // This class does not try to automatically configure residues whose corresponding ResidueLevelTask do not have the behavior "AUTO". This behavior should be set for protein residues, either manually or by using another kind of TaskOperation.
175 
176 /*
177  // if no resfile was specified,
178  // assume all protein positions are "AUTO" positions (behavior automated)
179  if ( ! option[ OptionKeys::packing::resfile ].user() ) {
180  for ( Size i(1), end( ptask.total_residue() ); i <= end; ++i ) {
181  ResidueLevelTask & rtask( ptask.nonconst_residue_task(i) );
182  if ( pose.residue_type(i).is_protein() ) rtask.add_behavior("AUTO");
183  }
184  }
185 */
186 
187  Size const nres( pose.total_residue() );
188  runtime_assert( nres == ptask.total_residue() );
189 
190 
191 /// Step 2: get info about DNA chains and set up DNA packing behavior
192 
193  // get basepairing info unless supplied by user
194  if ( !dna_chains_ ) {
195  dna_chains_ = new DnaChains;
196  find_basepairs( pose, *dna_chains_ );
197  }
198 
199  // configure the packer task for any specified targeted top-stranded DNA basepair positions
200  if ( ! targeted_dna_.empty() ) {
201  // (by default, targeted_dna_ is an empty vector, so none of the following applies)
202  for ( DnaDesignDefOPs::const_iterator def( targeted_dna_.begin() );
203  def != targeted_dna_.end(); ++def ) {
204  Size index( (*def)->pdbpos );
205  if ( pose.pdb_info() ) {
206  // if pose has PDB numbering and chain info, assume DNA defs refer to them
207  PDBPoseMap const & pdb_pose_map( pose.pdb_info()->pdb2pose() );
208  index = pdb_pose_map.find( (*def)->chain, (*def)->pdbpos );
209  }
210  if ( ! pose.residue_type( index ).is_DNA() ) {
211  std::cerr << "ERROR: DNA design def " << **def << " indicates a non-DNA position"
212  << std::endl; utility_exit();
213  } else if ( ! dna_chains_->is_top( index ) ) {
214  std::cerr << "ERROR: DNA design def " << **def << " is DNA but is not in the 'top' strand"
215  << std::endl; utility_exit();
216  }
217  DnaPosition const & pos( (*dna_chains_)[ index ] );
218  runtime_assert( index == pos.top() );
219  ResidueLevelTask & toptask( ptask.nonconst_residue_task( pos.top() ) );
220  toptask.add_behavior("TARGET");
221  if ( pos.paired() ) ptask.nonconst_residue_task( pos.bottom() ).add_behavior("TARGET");
222 
223  if ( ! (*def)->name3.empty() ) {
224  // specifying the appropriate ResidueType here is tricky, because there are multiple possible 'name3's for the nucleotides, AND because we must make sure to indicate a ResidueType that is already represented in the ResidueLevelTask
225  ResidueTypeSet const & rts( pose.residue(1).residue_type_set() );
226  // a list of all existing residue types that match the input name3
227  ResidueTypeCOPs const & name3map( rts.name3_map( (*def)->name3 ) );
228  // use the first ResidueType represented in the ResidueLevelTask that corresponds to one in the name3 map
230  allowed_type( toptask.allowed_residue_types_begin() ),
231  end( toptask.allowed_residue_types_end() ); allowed_type != end; ++allowed_type ) {
232  if ( std::find( name3map.begin(), name3map.end(), *allowed_type ) != name3map.end() ) {
233  toptask.target_type( *allowed_type ); break;
234  TR(t_info) << "Setting target type " << (*def)->name3
235  << " at position " << pos.top() << std::endl;
236  }
237  }
238  if ( ! toptask.target_type() ) {
239  TR(t_info) << "Error: target type " << (*def)->name3
240  << " does not correspond to an allowed type at position " << pos.top()
241  << std::endl; utility_exit();
242  }
243  if ( pos.paired() ) {
244  std::string const comp_name3( dna_comp_name_str( (*def)->name3 ) );
245  ResidueTypeCOPs const & name3map_comp( rts.name3_map( comp_name3 ) );
246  ResidueLevelTask & bottask( ptask.nonconst_residue_task( pos.bottom() ) );
248  allowed_type( bottask.allowed_residue_types_begin() ),
249  end( bottask.allowed_residue_types_end() ); allowed_type != end; ++allowed_type ) {
250  if ( std::find( name3map_comp.begin(), name3map_comp.end(), *allowed_type ) !=
251  name3map_comp.end() ) {
252  bottask.target_type( *allowed_type ); break;
253  TR(t_info) << "Setting target type " << comp_name3 << " at position " << pos.bottom()
254  << std::endl;
255  }
256  }
257  if ( ! bottask.target_type() ) {
258  TR(t_info) << "Error: target type " << comp_name3
259  << " does not correspond to an allowed type at position " << pos.bottom()
260  << std::endl; utility_exit();
261  }
262  }
263  }
264  }
265 
266  // when targeting particular basepair positions, packing for all non-specified DNAs is disabled
267  for ( Size i(1); i <= ptask.total_residue(); ++i ) {
268  ResidueLevelTask & rtask( ptask.nonconst_residue_task(i) );
269  if ( pose.residue_type(i).is_DNA() && !rtask.has_behavior("TARGET") ) {
270  rtask.prevent_repacking();
271  }
272  }
273  }
274 
275 /// Step 3: Determine protein-DNA interface
276 
277  // find protein-dna interface (unless user supplied one)
278  if ( !interface_ ) {
279 
280  vector1< Size > dna_design_positions;
281  bool limit_by_DNA(false);
282  for ( Size i(1); i <= nres; ++i ) {
283  if ( !pose.residue_type(i).is_DNA() ) continue;
284  ResidueLevelTask const & rtask( ptask.residue_task(i) );
285  // scan positions count as targeted
286  if ( rtask.has_behavior("TARGET") || rtask.has_behavior("SCAN") ) {
287  limit_by_DNA = true;
288  break;
289  }
290  }
291  if ( !limit_by_DNA ) {
292  // there are no specifically targeted dna positions: use entire DNA interface
293  for ( Size dpos(1); dpos <= nres; ++dpos ) {
294  if ( !pose.residue_type(dpos).is_DNA() ) continue;
295  dna_design_positions.push_back( dpos );
296  // turn off all DNA repacking (...?)
297  //ptask.temporarily_set_pack_residue( dpos, false );
298  }
299  } else {
300  // targeted dna design positions exist: limit interface to within the vicinity of these
301  for ( DnaPositions::iterator it( dna_chains_->begin() ); it != dna_chains_->end(); ++it ) {
302  Size resid( it->first ); DnaPosition & dnapos( it->second );
303  ResidueLevelTask & toptask( ptask.nonconst_residue_task( resid ) );
304  if ( !toptask.has_behavior("TARGET") && !toptask.has_behavior("SCAN") ) continue;
305  dna_design_positions.push_back( resid );
306  // verbose/debug
307  TR(t_info) << "\nTargeting DNA at position ";
308  if ( pose.pdb_info() ) {
309  TR << pose.pdb_info()->chain( dnapos.top() ) << "."
310  << pose.pdb_info()->number( dnapos.top() ) << '\n';
311  } else {
312  TR << pose.chain( dnapos.top() ) << "." << dnapos.top() << '\n';
313  }
314  TR(t_debug) << "Allowed types:\n"; toptask.print_allowed_types( TR(t_debug) );
315 
316  if ( !dnapos.paired() ) continue;
317  dna_design_positions.push_back( dnapos.bottom() );
318  ResidueLevelTask & bottask( ptask.nonconst_residue_task( dnapos.bottom() ) );
319  // verbose/debug
320  TR(t_info) << "\nTargeting DNA at position ";
321  if ( pose.pdb_info() ) {
322  TR << pose.pdb_info()->chain( dnapos.bottom() ) << "."
323  << pose.pdb_info()->number( dnapos.bottom() ) << '\n';
324  } else {
325  TR << pose.chain( dnapos.bottom() ) << "." << dnapos.bottom() << '\n';
326  }
327  TR(t_debug) << "Allowed types:\n"; bottask.print_allowed_types( TR(t_debug) );
328  }
329  }
330 
331  vector1< Size > protein_positions;
332  for ( Size p_index(1); p_index <= nres; ++p_index ) {
333  if ( ! ptask.pack_residue( p_index ) ) continue; // already disabled
334  if ( pose.residue_type( p_index ).is_DNA() ) continue; // ignore DNA
335  if ( ! pose.residue_type( p_index ).is_protein() ) {
336  ptask.nonconst_residue_task( p_index ).prevent_repacking(); // not protein, disable
337  } else if ( ptask.residue_task( p_index ).has_behavior("AUTO") ) {
338  protein_positions.push_back(p_index); // decide how to pack/design this position below
339  }
340  }
341 
342  interface_ =
344  // perform arginine rotamer sweep to decide wether or not to pack/design protein residues
345  interface_->determine_protein_interface( pose, protein_positions, dna_design_positions );
346  }
347 
348 /// Step 4: apply any new restrictions to resfile pack/design settings, and any existing constraints
349  bool const repack_only( option[ OptionKeys::dna::design::repack_only ]() );
350  ConstraintSetCOP constraint_set( pose.constraint_set() );
351  for ( DnaNeighbors::const_iterator itr( interface_->protein_neighbors().begin() ),
352  end( interface_->protein_neighbors().end() ); itr != end; ++itr ) {
353  Size const index( itr->first );
354  DnaNeighbor const & neighbor( itr->second );
355 
356  ResidueLevelTask & restask( ptask.nonconst_residue_task( index ) );
357  // residues with constraints will not be designed
358  bool const cst( constraint_set && constraint_set->residue_pair_constraints_exists( index ) );
359  if ( neighbor.contact() && !cst && !repack_only ) continue; // designable, no restriction
360  // restriction to current and/or original amino acid type
361  vector1< bool > aas( num_canonical_aas, false );
362  AA current_aa( pose.residue_type(index).aa() );
363  if ( neighbor.close() ) aas[ current_aa ] = true;
364  if ( reference_pose_ ) {
365  // intended to reflect the true native type, if desired/necessary
366  // such as for 'reversion to [original] wildtype' during iterative design
367  AA orig_aa( reference_pose_->residue_type(index).aa() );
368  if ( current_aa != orig_aa ) aas[ orig_aa ] = true;
369  }
370  // aas.empty() returns true if all of its values are false
371  if ( !aas.empty() ) restask.restrict_absent_canonical_aas( aas );
372  else restask.prevent_repacking();
373  }
374 
375 /// Step 5: report
376  for ( Size i(1), end( ptask.total_residue() ); i <= end; ++i ) {
377  ResidueLevelTask const & rlt( ptask.residue_task(i) );
378  if ( pose.residue_type(i).is_DNA() ) {
379  if ( ! rlt.being_packed() ) continue;
380  TR(t_info) << "DNA types allowed at ";
381  if ( pose.pdb_info() ) {
382  TR << pose.pdb_info()->number(i) << " "
383  << pose.pdb_info()->chain(i);
384  }
385  else TR << i << " " << pose.chain(i);
386  TR << ":";
387  // set used here to avoid redundant name3's from extra adduct variant allowed_types
388  std::set< std::string > name3set;
390  allowed_type( rlt.allowed_residue_types_begin() ),
391  typesend( rlt.allowed_residue_types_end() ); allowed_type != typesend; ++allowed_type ) {
392  name3set.insert( (*allowed_type)->name3() );
393  }
394  for ( std::set< std::string >::const_iterator n3( name3set.begin() ), n3end( name3set.end() );
395  n3 != n3end; ++n3 ) {
396  TR << *n3 << ",";
397  }
398  TR << '\n';
399  continue;
400  }
401  if ( ! rlt.being_packed() ) continue;
402  if ( pose.pdb_info() ) {
403  TR(t_info) << pose.pdb_info()->chain(i) << "." << pose.pdb_info()->number(i) << ".";
404  } else {
405  TR(t_info) << pose.chain(i) << "." << i << ".";
406  }
407  TR << pose.residue(i).name3();
408  if ( rlt.being_designed() ) TR(t_info) << " is DESIGNABLE";
409  else TR(t_info) << " is packable";
410  TR(t_info) << '\n';
411  }
412  TR(t_info) << std::endl;
414  // abandon exisiting dna chains and interface info to prevent accumulation of state
415  TR.Debug << "forgetting chains and interface" << std::endl;
416  dna_chains_ = 0;
417  interface_ = 0;
418  }
419 }
420 
421 } // namespace dna
422 } // namespace protocols
423