Rosetta 3.5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
ClassicMatchAlgorithm.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 // :noTabs=false:tabSize=4:indentSize=4:
4 //
5 // (c) Copyright Rosetta Commons Member Institutions.
6 // (c) This file is part of the Rosetta software suite and is made available under license.
7 // (c) The Rosetta software is developed by the contributing members of the Rosetta Commons.
8 // (c) For more information, see http://www.rosettacommons.org. Questions about this can be
9 // (c) addressed to University of Washington UW TechTransfer, email: license@u.washington.edu.
10 
11 /// @file protocols/match/downstream/ClassicMatchAlgorithm.cc
12 /// @brief
13 /// @author Alex Zanghellini (zanghell@u.washington.edu)
14 /// @author Andrew Leaver-Fay (aleaverfay@gmail.com), porting to mini
15 
16 // Unit headers
18 
19 // Package headers
24 // AUTO-REMOVED #include <protocols/match/upstream/UpstreamBuilder.hh>
25 // AUTO-REMOVED #include <protocols/match/upstream/ScaffoldBuildPoint.hh>
27 
28 // Project headers
31 #include <basic/Tracer.hh>
32 
33 // Utility headers
34 #include <utility/pointer/ReferenceCount.hh>
35 
36 // C++ headers
37 #include <list>
38 
39 #include <protocols/match/Hit.hh>
40 #include <utility/vector1.hh>
41 #include <utility/options/StringVectorOption.hh>
42 
43 
44 namespace protocols {
45 namespace match {
46 namespace downstream {
47 
48 static basic::Tracer TR( "protocols.match.downstream.ClassicMatchAlgorithm" );
49 
51  parent( geom_cst_id ),
52  occspace_rev_id_at_last_update_( 0 )
53 {}
54 
56 
57 
60  return new ClassicMatchAlgorithm( *this );
61 }
62 
63 std::list< Hit >
65  Matcher & matcher
66 )
67 {
68  /// First, make sure that all downstream builders for this geometric constraint
69  /// are pointing at the matcher's occupied space grid.
70  std::list< DownstreamBuilderOP > const & dsbuilders(
71  matcher.downstream_builders( geom_cst_id() ));
72  for ( std::list< DownstreamBuilderOP >::const_iterator
73  iter = dsbuilders.begin(),
74  iter_end = dsbuilders.end();
75  iter != iter_end; ++iter ) {
76  (*iter)->set_occupied_space_hash( matcher.occ_space_hash() );
77  }
78 
79  /// Later, we'll have code right here that looks at the occspace hash and figures out which
80  /// regions of 3D each sidechain atom of the upstream residues would have to be in to produce
81  /// a viable hit, and then we'll adjust the usptream builder for this residue to filter out
82  /// atoms early on in hit generation... so exciting. For now, we do not.
83 
85 }
86 
87 /// @details Reset the occupied space hash that the matcher uses so that
88 /// it reflects the hits generated this round; this will cause the invalidation
89 /// of hits generated in previous rounds. These invalidated hits will be deleted
90 /// in calls to respond_to_peripheral_hitlist_change.
91 void
93  Matcher & matcher,
94  Size round_just_completed
95 )
96 {
97  OccupiedSpaceHashOP occspace = matcher.occ_space_hash();
98 
99  if ( geom_cst_id() == round_just_completed ) {
100  TR << "Finished round " << geom_cst_id() << " with " << matcher.hits( geom_cst_id() ).size();
101  TR << " hits." << std::endl;
102  }
103 
104  if ( geom_cst_id() == 1 && round_just_completed == 1 ) {
105  /// The first geometric constraint inserts hits into the occupied space grid;
106  /// the later geometric constraints merely mark voxels already present in the
107  /// occupied space grid with 1.
109  iter = matcher.hits( geom_cst_id() ).begin(),
110  iter_end = matcher.hits( geom_cst_id() ).end();
111  iter != iter_end; ++iter ) {
112  occspace->insert_hit_geometry( iter->second() );
113  }
114 
115  } else {
116 
117  if ( geom_cst_id() != round_just_completed ) {
118  TR << "Updating the occupied space grid with " << matcher.hits( geom_cst_id() ).size();
119  TR << " hits from geometric constraint # " << geom_cst_id() << std::endl;
120  }
121 
122  occspace->prepare_to_note_hits_for_completed_round();
123 
124  /// Prepare to clear the cobwebs. Note which voxels in the occ_space_hash_
125  /// could lead to matches, and which voxels could not possibly lead to matches.
127  iter = matcher.hits( geom_cst_id() ).begin(),
128  iter_end = matcher.hits( geom_cst_id() ).end();
129  iter != iter_end; ++iter ) {
130  occspace->note_hit_geometry( iter->second() );
131  }
132 
133  occspace->drop_unsatisfied_voxels();
134  }
135 
136  occspace_rev_id_at_last_update_ = occspace->revision_id();
137 }
138 
139 /// @details Drop hits that had previously seemed viable after another round completed;
140 /// during that round, certain previously occupied regions of 6D were not filled
141 /// with new hits. Any previously-generated hit that falls into a region of 6D which is
142 /// no longer occupied should be elminated since it could not ever result in a match;
143 /// it is inviable.
144 void
146 {
147  OccupiedSpaceHashOP occspace = matcher.occ_space_hash();
148  if ( occspace_rev_id_at_last_update_ == occspace->revision_id() ) {
149  /// Nothing about the occupied space hash has changed since I last pruned
150  /// my non-viable hits. There are no more non-viable hits that need pruning.
151  return;
152  }
153 
155  Matcher::HitListIterator iter_end = matcher.hit_list_end( geom_cst_id() );
156 
157  Size drop_count( 0 );
158 
159  while ( iter != iter_end ) {
160  Matcher::HitListIterator iter_next = iter;
161  ++iter_next;
162  if ( ! occspace->previous_round_geometry_still_matchable( iter->second() ) ) {
163  matcher.erase_hit( *this, geom_cst_id(), iter );
164  ++drop_count;
165  }
166  iter = iter_next;
167  }
168 
169  TR << "Erased " << drop_count << " round " << geom_cst_id();
170  TR << " hits with ";
171  TR << matcher.hits( geom_cst_id() ).size() << " hits remaining." << std::endl;
172 
173  occspace_rev_id_at_last_update_ = occspace->revision_id();
174 }
175 
176 
177 std::list< Hit >
179  Size const scaffold_build_point_id,
180  Size const upstream_conf_id,
181  core::conformation::Residue const & upstream_residue
182 ) const
183 {
184  std::list< Hit > local_hit_list;
185 
186  /// Sanity check: the input residue must match the residue type this MatchAlgorithm is expecting.
187  if ( & upstream_residue.type() != restype_.get() ) {
188  utility_exit_with_message( "ERROR: Classic Match Algorithm was expecting restype: " + restype_->name() + " but was given " + upstream_residue.name() + ". Cannot continue" );
189  }
190 
191  /// Sanity check: all transforms must have been precomputed before reaching this stage.
192  for ( Size ii = 1; ii <= n_external_samplers(); ++ii ) {
193  if ( ! external_samplers_[ ii ].transforms_uptodate() ) {
194  utility_exit_with_message( "CRITICAL ERROR in ClassicMatchAlgorithm::build. ExternalGeomSampler transforms are not up-to-date" );
195  }
196  }
197 
198  for ( Size ii = 1; ii <= n_external_samplers(); ++ii ) {
199  std::list< Hit > hits = build_from_three_coords(
200  ii,
201  scaffold_build_point_id,
202  upstream_conf_id,
203  upstream_residue );
204  local_hit_list.splice( local_hit_list.end(), hits );
205  }
206 
207  return local_hit_list;
208 }
209 
210 bool
212 {
213  return false;
214 }
215 
216 bool
218 {
219  return true;
220 }
221 
222 
223 /// @details If this function is causing an exit, then there is a bug within the Matcher's
224 /// match-enumeration logic. There is no meaningful way forward after this function is invoked.
225 /// It should not be invoked.
228 {
229  HitPtrListCOP empty;
230  utility_exit_with_message( "Cannot invoke ClassicMatchAlgorithm::hits_to_include_with_partial_match()" );
231  return empty;
232 }
233 
234 
237 {
238  Size total = 0;
239  for ( Size ii = 1; ii <= n_external_samplers(); ++ii ) {
240  Size iitotal = 1;
242 
243  iitotal *= exsampler.n_tor_U3D1_samples();
244  iitotal *= exsampler.n_ang_U2D1_samples();
245  iitotal *= exsampler.n_dis_U1D1_samples();
246  iitotal *= exsampler.n_tor_U2D2_samples();
247  iitotal *= exsampler.n_ang_U1D2_samples();
248  iitotal *= exsampler.n_tor_U1D3_samples();
249 
250  iitotal *= dsbuilders_[ ii ]->n_possible_hits_per_at3frame();
251 
252  total += iitotal;
253  }
254  return total;
255 }
256 
257 
258 std::list< Hit >
260  Size const which_external_sampler,
261  Size const scaffold_build_point_id,
262  Size const upstream_conf_id,
263  core::conformation::Residue const & upstream_residue
264 ) const
265 {
266  using namespace toolbox::match_enzdes_util;
267  Vector coord1( upstream_residue.xyz( launch_atom( which_external_sampler, 1 )));
268  Vector coord2( upstream_residue.xyz( launch_atom( which_external_sampler, 2 )));
269  Vector coord3( upstream_residue.xyz( launch_atom( which_external_sampler, 3 )));
270 
271  toolbox::match_enzdes_util::ExternalGeomSampler const & exsampler( external_samplers_[ which_external_sampler ] );
272 
273  DownstreamBuilderCOP dsbuilder( dsbuilders_[ which_external_sampler ] );
274 
275  std::list< Hit > hitlist;
276 
277  ProbeRadius const
278  radD1( dsbuilder->atom1_radius() ),
279  radD2( dsbuilder->atom2_radius()),
280  radD3( dsbuilder->atom3_radius() );
281 
282  bool active_site_check_D1( active_site_grid_set() && dsbuilder->atom1_belongs_in_active_site() );
283  bool active_site_check_D2( active_site_grid_set() && dsbuilder->atom2_belongs_in_active_site() );
284  bool active_site_check_D3( active_site_grid_set() && dsbuilder->atom3_belongs_in_active_site() );
285 
286 
287  /// 1. Define a coordinate frame from the three coordinates of atoms 1 2 and 3 in the
288  /// canonical form such that the point is at coord1, z lies along the coord1-coord2 vector,
289  /// y lies in the plane of coord1, 2, & 3, and x is the cross product of y and z.
290  HTReal ht_start( coord3, coord2, coord1 );
291 
292 
293  /// Six nested for loops to iterate across all the specified geometries that describe how to
294  /// build the downstream target from the upstream conformation. No transcendental function evaulations
295  /// necessary here, as the coordinate transformations have already been computed! Just good old
296  /// addition and multiplication.
297  for ( Size ii = 1; ii <= exsampler.n_tor_U3D1_samples(); ++ii ) {
298  HTReal ht_ii = ht_start * exsampler.transform( HT_tor_U3D1, ii );
299 
300  for ( Size jj = 1; jj <= exsampler.n_ang_U2D1_samples(); ++jj ) {
301  HTReal ht_jj = ht_ii * exsampler.transform( HT_ang_U2D1, jj );
302 
303  for ( Size kk = 1; kk <= exsampler.n_dis_U1D1_samples(); ++kk ) {
304  HTReal ht_kk = ht_jj;
305  ht_kk.walk_along_z( exsampler.dis_U1D1_samples()[ kk ] );
306  Vector pD1 = ht_kk.point();
307  if ( radD1 > ZERO && bbgrid().occupied( radD1, pD1 )) continue; /// Collision check atom D1
308  if ( active_site_check_D1 && ! active_site_grid().occupied( pD1 ) ) continue;
309 
310  for ( Size ll = 1; ll <= exsampler.n_tor_U2D2_samples(); ++ll ) {
311  HTReal ht_ll = ht_kk * exsampler.transform( HT_tor_U2D2, ll );
312 
313  for ( Size mm = 1; mm <= exsampler.n_ang_U1D2_samples(); ++mm ) {
314  HTReal ht_mm = ht_ll * exsampler.transform( HT_ang_U1D2, mm );
315  Vector pD2 = ht_mm.point();
316  if ( radD2 > ZERO && bbgrid().occupied( radD2, pD2 )) continue; /// Collision check atom D2
317  if ( active_site_check_D2 && ! active_site_grid().occupied( pD2 ) ) continue;
318 
319  for ( Size nn = 1; nn <= exsampler.n_tor_U1D3_samples(); ++nn ) {
320  HTReal ht_nn = ht_mm * exsampler.transform( HT_tor_U1D3, nn );
321  Vector pD3 = ht_nn.point();
322  if ( radD3 > ZERO && bbgrid().occupied( radD3, pD3 )) continue; /// Collision check atom D3
323  if ( active_site_check_D3 && ! active_site_grid().occupied( pD3 ) ) continue;
324 
325  std::list< Hit > nn_hits = dsbuilder->build(
326  ht_nn,
327  scaffold_build_point_id,
328  upstream_conf_id,
329  exgeom_ids_[ which_external_sampler ],
330  upstream_residue );
331  hitlist.splice( hitlist.end(), nn_hits );
332  }
333  }
334  }
335  }
336  }
337  }
338 
339  return hitlist;
340 
341 }
342 
343 ////// Debugging code below -- insert this after atom 6's collision check.
344 /*
345  std::cout << "Collision free placement of atoms 4 5 and 6: ";
346  std::cout << "p4: ";
347  for ( Size oo = 1; oo <= 3; ++oo ) std::cout << p4( oo ) << " ";
348  std::cout << "p5: ";
349  for ( Size oo = 1; oo <= 3; ++oo ) std::cout << p5( oo ) << " ";
350  std::cout << "p6: ";
351  for ( Size oo = 1; oo <= 3; ++oo ) std::cout << p6( oo ) << " ";
352  std::cout << std::endl;
353 
354  std::cout << "tor_U3D1: expected: " << exsampler.tor_U3D1_samples()[ ii ] << " real: "
355  << numeric::constants::d::radians_to_degrees * numeric::dihedral_radians(
356  coord1, coord2, coord3, p4 ) << std::endl;
357 
358  std::cout << "ang_U2D1: expected: " << exsampler.ang_U2D1_samples()[ jj ] << " real: "
359  << numeric::constants::d::radians_to_degrees * numeric::angle_radians(
360  coord2, coord3, p4 ) << std::endl;
361 
362  std::cout << "dis_U1D1: expected: " << exsampler.dis_U1D1_samples()[ kk ] << " real: "
363  << p4.distance( coord3 ) << std::endl;
364 
365  std::cout << "tor_U2D2: expected: " << exsampler.tor_U2D2_samples()[ ll ] << " real: "
366  << numeric::constants::d::radians_to_degrees * numeric::dihedral_radians(
367  coord2, coord3, p4, p5 ) << std::endl;
368 
369  std::cout << "ang_U1D2: expected: " << exsampler.ang_U1D2_samples()[ mm ] << " real: "
370  << numeric::constants::d::radians_to_degrees * numeric::angle_radians(
371  coord3, p4, p5 ) << std::endl;
372 
373  std::cout << "tor_U1D3: expected: " << exsampler.tor_U1D3_samples()[ nn ] << " real: "
374  << numeric::constants::d::radians_to_degrees * numeric::dihedral_radians(
375  coord3, p4, p5, p6 ) << std::endl;
376 
377  std::cout << "EXGEOM SAMPLE tor_U3D1: " << exsampler.tor_U3D1_samples()[ ii ];
378  std::cout << " ang_U2D1: " << exsampler.ang_U2D1_samples()[ jj ];
379  std::cout << " dis_U1D1: " << exsampler.dis_U1D1_samples()[ kk ];
380  std::cout << " tor_U2D2: " << exsampler.tor_U2D2_samples()[ ll ];
381  std::cout << " ang_U1D2: " << exsampler.ang_U1D2_samples()[ mm ];
382  std::cout << " tor_U1D3: " << exsampler.tor_U1D3_samples()[ nn ] << std::endl;
383 
384 
385 */
386 
387 
389 {
390  restype_ = restype;
391  external_samplers_.clear();
392  launch_points_.clear();
393 }
394 
395 
396 /// @details Precompute transforms for the external geom sampler as it is added
397 /// so that the transforms are ready when build() is called.
400  Size const exgeom_id,
401  std::string const & atom1,
402  std::string const & atom2,
403  std::string const & atom3,
404  DownstreamBuilderCOP dsbuilder
405 )
406 {
407 
408  Size id1( restype().has( atom1 ) ? restype().atom_index( atom1 ) : 0 );
409  Size id2( restype().has( atom2 ) ? restype().atom_index( atom2 ) : 0 );
410  Size id3( restype().has( atom3 ) ? restype().atom_index( atom3 ) : 0 );
411 
412  if ( id1 == 0 ) {
413  utility_exit_with_message( "ERROR in adding external geom sampler to ClassicMatchAlgorithm: " + restype().name() + " does not contain requested atom " + atom1 );
414  }
415  if ( id2 == 0 ) {
416  utility_exit_with_message( "ERROR in adding external geom sampler to ClassicMatchAlgorithm: " + restype().name() + " does not contain requested atom " + atom2 );
417  }
418  if ( id3 == 0 ) {
419  utility_exit_with_message( "ERROR in adding external geom sampler to ClassicMatchAlgorithm: " + restype().name() + " does not contain requested atom " + atom3 );
420  }
421 
422  utility::fixedsizearray1< Size, 3 > atids;
423  atids[ 1 ] = id1;
424  atids[ 2 ] = id2;
425  atids[ 3 ] = id3;
426 
427  external_samplers_.push_back( sampler );
428  launch_points_.push_back( atids );
429  dsbuilders_.push_back( dsbuilder );
430  exgeom_ids_.push_back( exgeom_id );
431 
432  /// initialize the external sampler transforms
434  samp.set_dis_D1D2( dsbuilder->atom1_atom2_distance() );
435  samp.set_dis_D2D3( dsbuilder->atom2_atom3_distance() );
436  samp.set_ang_D1D2D3( dsbuilder->atom1_atom2_atom3_angle() );
437  samp.precompute_transforms();
438 }
439 
440 void
442 {
443  external_samplers_.clear();
444  launch_points_.clear();
445  dsbuilders_.clear();
446 }
447 
448 }
449 }
450 }