Rosetta 3.5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
SymmetricMotifFilter.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/protein_interface_design/filters/SymmetricMotifFilter.cc
11 /// @brief position-independent RMS filter evaluating how close a set of interfaces is to symmetric
12 /// @author Frank DiMaio
13 
17 
18 #include <core/types.hh>
19 #include <core/pose/Pose.hh>
22 #include <utility/tag/Tag.hh>
23 #include <protocols/moves/Mover.fwd.hh> //Movers_map
24 #include <core/pose/PDBInfo.hh>
25 
26 #include <core/scoring/rms_util.hh>
29 #include <basic/options/option.hh>
30 #include <basic/options/keys/in.OptionKeys.gen.hh>
32 
33 #include <core/id/AtomID.hh>
34 #include <core/id/AtomID_Map.hh>
35 #include <ObjexxFCL/FArray1D.hh>
36 
37 #include <numeric/random/random.hh>
38 #include <numeric/xyzVector.hh>
39 #include <numeric/xyzMatrix.hh>
40 #include <numeric/xyz.functions.hh>
41 #include <numeric/model_quality/rms.hh>
42 
43 #include <utility/string_util.hh>
44 #include <utility/vector0.hh>
45 #include <utility/vector1.hh>
46 #include <basic/Tracer.hh>
47 
48 // symmetry
52 
53 namespace protocols {
54 namespace simple_filters {
55 
56 // tracer
57 static basic::Tracer TR( "protocols.simple_filters.SymmetricMotifFilter" );
58 
59 // creator
62 
64 SymmetricMotifFilterCreator::keyname() const { return "SymmetricMotif"; }
65 
66 // helper functions
68  core::Real S;
69  if ( R.xx() > R.yy() && R.xx() > R.zz() ) {
70  S = sqrt( 1.0 + R.xx() - R.yy() - R.zz() ) * 2;
71  Q.x = 0.25 * S;
72  Q.y = (R.xy() + R.yx() ) / S;
73  Q.z = (R.zx() + R.xz() ) / S;
74  Q.w = (R.zy() - R.yz() ) / S;
75  } else if ( R.yy() > R.zz() ) {
76  S = sqrt( 1.0 + R.yy() - R.xx() - R.zz() ) * 2;
77  Q.x = (R.yx() + R.xy() ) / S;
78  Q.y = 0.25 * S;
79  Q.z = (R.zy() + R.yz() ) / S;
80  Q.w = (R.xz() - R.zx() ) / S;
81  } else {
82  S = sqrt( 1.0 + R.zz() - R.xx() - R.yy() ) * 2;
83  Q.x = (R.xz() + R.zx() ) / S;
84  Q.y = (R.zy() + R.yz() ) / S;
85  Q.z = 0.25 * S;
86  Q.w = (R.yx() - R.xy()) / S;
87  }
88 }
89 
91  core::Real xx = Q.x*Q.x; core::Real xy = Q.x*Q.y; core::Real xz = Q.x*Q.z;
92  core::Real xw = Q.x*Q.w; core::Real yy = Q.y*Q.y; core::Real yz = Q.y*Q.z;
93  core::Real yw = Q.y*Q.w; core::Real zz = Q.z*Q.z; core::Real zw = Q.z*Q.w;
94 
95  R.xx(1-2*(yy+zz)); R.xy( 2*(xy-zw)); R.xz( 2*(xz+yw));
96  R.yx( 2*(xy+zw)); R.yy(1-2*(xx+zz)); R.yz( 2*(yz-xw));
97  R.zx( 2*(xz-yw)); R.zy( 2*(yz+xw)); R.zz(1-2*(xx+yy));
98 }
99 
100 //rms wrapper
105  core::Size motiflen = std::min( chainA.size(), chainB.size() );
106  ObjexxFCL::FArray2D< core::Real > final_coords( 3, motiflen );
107  ObjexxFCL::FArray2D< core::Real > init_coords( 3, motiflen );
108  ObjexxFCL::FArray1D< numeric::Real > ww( motiflen, 1.0 );
109  ObjexxFCL::FArray2D< numeric::Real > uu( 3, 3, 0.0 );
110 
111  numeric::Real ctx;
112  preT = postT = numeric::xyzVector< core::Real >(0,0,0);
113  for (int j=1; j<=(int)motiflen; ++j) {
114  for (int k=0; k<3; ++k) {
115  init_coords(k+1,j) = chainA[j][k];
116  final_coords(k+1,j) = chainB[j][k];
117  }
118  preT += chainA[j];
119  postT += chainB[j];
120  }
121  preT /= motiflen;
122  postT /= motiflen;
123  for (int j=1; j<=(int)motiflen; ++j) {
124  for (int k=0; k<3; ++k) {
125  init_coords(k+1,j) -= preT[k];
126  final_coords(k+1,j) -= postT[k];
127  }
128  }
129 
130  float rms;
131  numeric::model_quality::findUU( final_coords, init_coords, ww, motiflen, uu, ctx );
132  numeric::model_quality::calc_rms_fast( rms, final_coords, init_coords, ww, motiflen, ctx );
133 
134  R.xx( uu(1,1) ); R.xy( uu(2,1) ); R.xz( uu(3,1) );
135  R.yx( uu(1,2) ); R.yy( uu(2,2) ); R.yz( uu(3,2) );
136  R.zx( uu(1,3) ); R.zy( uu(2,3) ); R.zz( uu(3,3) );
137 
138  return ((core::Real)rms);
139 }
140 
141 //
142 // filter definition
144  protocols::filters::Filter( "SymmetricMotif" )
145 {
146  set_defaults();
147 }
148 
150  : protocols::filters::Filter( "SymmetricMotif" ), symm_type_(symm_type_in)
151 {
152  ref_motifs_ = reference_motifs;
153  process_motifs();
154  set_defaults();
155 }
156 
158 
159 void
161  angle_thresh_ = 5.0;
162  trans_thresh_ = 4.0;
163  rmsd_thresh_ = 2.0;
164  clash_thresh_ = 0;
165 
166  angle_wt_ = 1.0;
167  trans_wt_ = 5.0;
168  rmsd_wt_ = 10.0;
169  clash_wt_ = 100.0;
170 }
171 
172 
175  return new SymmetricMotifFilter( *this );
176 }
177 
178 bool
180  core::Real bestscore;
181  std::string hitLocation;
182  bool found_motif = compute( pose, bestscore, hitLocation );
183  if (found_motif) {
184  TR.Debug << "Motif hit at " << hitLocation << std::endl;
185  }
186  return( found_motif );
187 }
188 
190 {
191  ref_motifs_.push_back( motif );
192 }
193 
194 void
195 SymmetricMotifFilter::report( std::ostream & /*out*/, core::pose::Pose const & pose ) const {
196  core::Real bestscore;
197  std::string hitLocation;
198  bool found_motif = compute( pose, bestscore, hitLocation );
199  if (found_motif) {
200  TR << "Motif hit at " << hitLocation << std::endl;
201  } else {
202  TR << "No motif hits found." << std::endl;
203  }
204  return;
205 }
206 
209  core::Real bestscore = 0.0; // arbitrarily set to zero to silence compiler warning ~Labonte
210  std::string hitLocation;
211  //bool found_motif = compute( pose, bestscore, hitLocation );
212  return bestscore;
213 }
214 
215 
216 //
217 // compute
218 bool
219 SymmetricMotifFilter::compute( core::pose::Pose const & pose, core::Real &best_score, std::string &motifhit ) const {
220  if (symm_type_ == "D2") {
221  return compute_d2( pose, best_score, motifhit );
222  }
223  return false; // added to remove compiler warning; I assume false is warranted here? ~ Labonte
224 }
225 
226 //
227 // compute
228 bool
229 SymmetricMotifFilter::compute_d2( core::pose::Pose const & pose, core::Real &best_score, std::string &motifhit ) const {
230  using numeric::constants::d::pi;
231 
232  // three-stage approach
233  // 1) find backbone segments satisfying each motif (fast)
234  // 2) [symm dependent!] for each backbone hit pair, measure angle error (fast)
235  // 3) for each hit passing these filters, do CA clash check (slow)
236  motifhit = "";
237  bool foundOne = false;
238  best_score = 999;
239  bool noforce = (forced_pos_.size() == 0);
240 
241  // ca trace of pose
243  core::Size nres = pose.total_residue();
247  dynamic_cast<core::conformation::symmetry::SymmetricConformation const &> ( pose.conformation()) );
248  symm_info = SymmConf.Symmetry_Info();
249  nres = symm_info->num_independent_residues();
250  }
251  for (Size i=1; i<=nres; ++i) {
252  if ( !pose.residue_type(i).is_protein() ) continue;
253  cas_pose.push_back( pose.residue(i).atom(" CA ").xyz() );
254  cas_pose.push_back( pose.residue(i).atom(" C ").xyz() );
255  cas_pose.push_back( pose.residue(i).atom(" N ").xyz() );
256  cas_pose.push_back( pose.residue(i).atom(" O ").xyz() );
257  }
258  core::Size nres_prot = cas_pose.size() / 4;
259 
260  // 1) find backbone segments satisfying each motif
261  utility::vector1< utility::vector1< int > > motif_hits1(1), motif_hits2(1);
262  utility::vector1< core::Real > motif_rms1, motif_rms2;
264  utility::vector1< numeric::xyzVector< core::Real > > preTs1, preTs2, postTs1, postTs2;
265 
266  core::Size segmentCounter = 0;
267 
268  for (int i=1; i<=2; ++i) {
269  utility::vector1< utility::vector1< int > > &motif_hits_i = (i==1 ? motif_hits1 : motif_hits2);
270  utility::vector1< core::Real > &motif_rms_i = (i==1 ? motif_rms1 : motif_rms2);
271  utility::vector1< numeric::xyzMatrix< core::Real > > &Rs_i = (i==1 ? Rs1 : Rs2);
272  utility::vector1< numeric::xyzVector< core::Real > > &preTs_i = (i==1 ? preTs1 : preTs2);
273  utility::vector1< numeric::xyzVector< core::Real > > &postTs_i = (i==1 ? postTs1 : postTs2);
275  utility::vector1< core::Size > const &motif_cuts_i = motif_cuts[i];
276 
277  utility::vector1< utility::vector1< int > > prev_Is; // intermediate hits
278  motif_hits_i[1].push_back( -1 );
279 
280 
281  // build up multi-segment motifs one segment at a time
282  for (Size j=2; j<=motif_cuts_i.size(); ++j) {
283  prev_Is = motif_hits_i;
284  motif_hits_i.clear();
285  segmentCounter++;
286 
287  for (Size k=1; k<=prev_Is.size(); ++k) {
289  utility::vector1< bool > elim(nres_prot, false);
290 
291  // load prev hits' CA coords
292  for (Size j_prev = 2; j_prev<j; ++j_prev) {
293  core::Size segstart_x = prev_Is[k][j_prev-1];
294  core::Size seglen_x = motif_cuts_i[j_prev] - motif_cuts_i[j_prev-1] - 1;
295  for (Size l=segstart_x; l<=segstart_x+seglen_x; ++l) {
296  prevCAs.push_back( cas_pose[4*l-3] );
297  prevCAs.push_back( cas_pose[4*l-2] );
298  prevCAs.push_back( cas_pose[4*l-1] );
299  prevCAs.push_back( cas_pose[4*l] );
300  elim[l] = true;
301  }
302  }
303 
304  // scan through all possible placements of this motif
305  int lstart=1, lstop=nres_prot;
306  if (!noforce && forced_pos_[segmentCounter]!=-1) {
307  lstart=lstop=forced_pos_[segmentCounter];
308  }
309 
310  for (int l=lstart; l<=lstop; ++l) {
311  core::Size segstart_l = l;
312  core::Size seglen_l = motif_cuts_i[j] - motif_cuts_i[j-1] - 1;
313  bool overlap=false;
314  if (segstart_l+seglen_l > nres_prot) continue;
315  for (Size m=segstart_l; m<=segstart_l+seglen_l && !overlap; ++m) {
316  overlap |= elim[m];
317  }
318  if (overlap) continue;
319 
320  utility::vector1< numeric::xyzVector< core::Real > > ca_chunk_pose = prevCAs;
321  for (Size m=segstart_l; m<=segstart_l+seglen_l; ++m) {
322  ca_chunk_pose.push_back( cas_pose[4*m-3] );
323  ca_chunk_pose.push_back( cas_pose[4*m-2] );
324  ca_chunk_pose.push_back( cas_pose[4*m-1] );
325  ca_chunk_pose.push_back( cas_pose[4*m ] );
326  }
327 
328  // align pose CAs to tgt
331 
332  // this will only align the subset of CAs present in 'ca_chunk_pose'
333  core::Real rms = RMSwrapper( cas_tgt_i, ca_chunk_pose, R, preT, postT);
334 
335  if (rms < rmsd_thresh_) {
337  if (j != 2) newI = prev_Is[k];
338  newI.push_back(l);
339  motif_hits_i.push_back( newI );
340 
341  TR.Debug << "Motif " << i << " hit at ";
342  for (Size z=1; z<=newI.size(); ++z) TR.Debug << newI[z] << " ";
343  TR.Debug << " rms = " << rms << std::endl;
344 
345  if (j == motif_cuts_i.size()) { // last segment has been placed
346  Rs_i.push_back( R );
347  motif_rms_i.push_back( rms );
348  preTs_i.push_back( preT );
349  postTs_i.push_back( postT );
350  }
351  }
352  }
353  }
354  }
355  }
356 
357  // 2) for each backbone hit pair combination, measure angle error
358  for (Size i=1; i<=motif_hits1.size(); ++i) {
359  for (Size j=1; j<=motif_hits2.size(); ++j) {
360  // a) check for overlap
361  utility::vector1< bool > elim(nres_prot, false);
362  for (Size x=1; x<=motif_hits1[i].size(); ++x) {
363  core::Size segstart_x = motif_hits1[i][x];
364  core::Size seglen_x = motif_cuts[1][x+1] - motif_cuts[1][x] - 1;
365  for (Size k=segstart_x; k<=segstart_x+seglen_x; ++k)
366  elim[k] = true;
367  }
368  bool overlap = false;
369  for (Size x=1; x<=motif_hits2[j].size() && !overlap; ++x) {
370  core::Size segstart_x = motif_hits2[j][x];
371  core::Size seglen_x = motif_cuts[2][x+1] - motif_cuts[2][x] - 1;
372  for (Size k=segstart_x; k<=segstart_x+seglen_x && !overlap; ++k) {
373  overlap |= elim[k];
374  }
375  }
376  if (overlap) continue;
377 
378  // symm axes in global frame
379  numeric::xyzVector< core::Real > x1 = numeric::inverse(Rs1[i])*symm_axes[1];
380  numeric::xyzVector< core::Real > x2 = numeric::inverse(Rs2[j])*symm_axes[2];
381 
382  core::Real angle12 = angle_of( x1, x2 ) * 180/pi;
383  core::Real angle_i = std::fabs(90-angle12);
384  TR.Debug << "Hit " << i << "," << j << ": angle = " << angle_i << std::endl;
385  if (angle_i > angle_thresh_) continue;
386 
387  // centers of mass of motifs in all subunits ... somewhat tricky
388  numeric::xyzMatrix< core::Real > R2 = (numeric::inverse(Rs1[i])*Rdimers[1])*Rs1[i];
389  numeric::xyzMatrix< core::Real > R3 = (numeric::inverse(Rs2[j])*Rdimers[2])*Rs2[j];
392 
393  // motif centers in chain A
394  numeric::xyzVector< core::Real > m1a = postTs1[i];
395  numeric::xyzVector< core::Real > m2a = postTs2[j];
396  numeric::xyzVector< core::Real > m1to2 = m2a-m1a;
397 
398  // ... in chain B
399  numeric::xyzVector< core::Real > m1b = m1a + (numeric::inverse(Rs1[i])*Rdimers[1])*delta_coms[1];
400  numeric::xyzVector< core::Real > m2b = m1b + (R2)*m1to2;
401 
402  // ... in chain C
403  numeric::xyzVector< core::Real > m2c = m2a + (numeric::inverse(Rs2[j])*Rdimers[2])*delta_coms[2];
404  numeric::xyzVector< core::Real > m1c = m2c - (R3)*m1to2;
405 
406  // ... in chain D
407  numeric::xyzVector< core::Real > m1d = m1c + R4a*numeric::inverse(Rs1[i])*delta_coms[1];
408  numeric::xyzVector< core::Real > m2d = m2b + R4b*numeric::inverse(Rs2[j])*delta_coms[2];
409  numeric::xyzVector< core::Real > m2d_alt = m1d + R4a*m1to2;
410 
411  // translation error is the distance between m2_d and m2_d_alt
412  core::Real trans_i = (m2d).distance(m2d_alt);
413 
414  TR.Debug << "Hit " << i << "," << j << ": trans = " << trans_i << std::endl;
415  if (trans_i > trans_thresh_) continue;
416 
417  core::Real rms_i = std::max( motif_rms1[i], motif_rms2[j] );
418 
419  // i,j has passed RMS and angle filters
420 
421  // 3) for each hit passing these filters, do CA clash check (to do: CB??)
422  numeric::xyzMatrix <core::Real> &R1A = Rs1[i];
423  numeric::xyzMatrix <core::Real> R1B = (numeric::inverse(Rdimers[1])*Rs1[i]);
424  numeric::xyzMatrix <core::Real> &R2A = Rs2[j];
425  numeric::xyzMatrix <core::Real> R2B = (numeric::inverse(Rdimers[2])*Rs2[j]);
426 
427  numeric::xyzVector< core::Real > com1A = preTs1[i] - postTs1[i];
428  numeric::xyzVector< core::Real > com1B = preTs1[i] - postTs1[i] + Rdimers[1]*delta_coms[1];
429  numeric::xyzVector< core::Real > com2A = preTs2[j] - postTs2[j];
430  numeric::xyzVector< core::Real > com2B = preTs2[j] - postTs2[j] + Rdimers[2]*delta_coms[2];
431 
432  bool clashcheck = false;
433  Size nclashes = 0;
434  int CUTOFF2 = 3*3;
435  for (Size x=1; x<=nres_prot && !clashcheck; ++x) {
436  for (Size y=1; y<=nres_prot && !clashcheck; ++y) {
437  numeric::xyzVector< core::Real > x_x = R1A*(cas_pose[4*x-3]-postTs1[i]) + com1A; // just check CA
438  numeric::xyzVector< core::Real > x_y = R1B*(cas_pose[4*y-3]-postTs1[i]) + com1B; // just check CA
439  if (x_x.distance_squared(x_y) < CUTOFF2) {
440  nclashes++;
441  clashcheck = (nclashes>clash_thresh_);
442  }
443  }
444  }
445  for (Size x=1; x<=cas_pose.size() && !clashcheck; ++x) {
446  for (Size y=1; y<=cas_pose.size() && !clashcheck; ++y) {
447  numeric::xyzVector< core::Real > x_x = R2A*(cas_pose[4*x]-postTs2[j]) + com2A;
448  numeric::xyzVector< core::Real > x_y = R2B*(cas_pose[4*y]-postTs2[j]) + com2B;
449  if (x_x.distance_squared(x_y) < CUTOFF2) {
450  nclashes++;
451  clashcheck = (nclashes>clash_thresh_);
452  }
453  }
454  }
455 
456  if (clashcheck) {
457  TR.Debug << "Hit " << i << "," << j << ": clash > " << clash_thresh_ << std::endl;
458  continue;
459  }
460 
461  // passed! report rms, angle and clash
462  foundOne = true;
463  core::Real score_i = score_d2(rms_i,angle_i,trans_i,nclashes);
464  if (score_i < best_score) {
465  // dump ID to a string for reporting purposes
466  std::ostringstream oss;
467  oss << "( ";
468  for (Size k=1; k<=motif_hits1[i].size(); ++k) oss << motif_hits1[i][k] << " ";
469  oss << ") ( ";
470  for (Size k=1; k<=motif_hits2[j].size(); ++k) oss << motif_hits2[j][k] << " ";
471  oss << ")";
472  motifhit = oss.str();
473  best_score = score_i;
474  }
475  }
476  }
477  return foundOne;
478 }
479 
480 
481 
482 //
483 // process_motifs
484 //fpd currently only D2 is supported!
485 //fpd at some point more spacegroups will be supported
486 void
488  using numeric::constants::d::pi;
489 
490  // process motifs
491  core::Size nmotifs = ref_motifs_.size();
492  cas_chainA.resize(nmotifs);
493  cas_chainB.resize(nmotifs);
494  motif_cuts.resize(nmotifs);
495 
496  // parse motifs
497  nsegs_ = 0;
498  for (Size i=1; i<=nmotifs; ++i) {
499  motif_cuts[i].push_back( 0 );
500  core::pose::PoseOP motif_i = ref_motifs_[i];
501  for (Size j=1; j<=motif_i->total_residue(); ++j) {
502  if (motif_i->pdb_info()->chain(j) == 'A') {
503  cas_chainA[i].push_back( motif_i->residue(j).atom(" CA ").xyz() );
504  cas_chainA[i].push_back( motif_i->residue(j).atom(" C ").xyz() );
505  cas_chainA[i].push_back( motif_i->residue(j).atom(" N ").xyz() );
506  cas_chainA[i].push_back( motif_i->residue(j).atom(" O ").xyz() );
507 
508  if (j>1 && (motif_i->pdb_info()->number(j) != motif_i->pdb_info()->number(j-1)+1) ) {
509  motif_cuts[i].push_back( j-1 );
510  TR.Debug << i << ": add cut " << j-1 << std::endl;
511  }
512  } else {
513  cas_chainB[i].push_back( motif_i->residue(j).atom(" CA ").xyz() );
514  cas_chainB[i].push_back( motif_i->residue(j).atom(" C ").xyz() );
515  cas_chainB[i].push_back( motif_i->residue(j).atom(" N ").xyz() );
516  cas_chainB[i].push_back( motif_i->residue(j).atom(" O ").xyz() );
517  }
518  }
519  runtime_assert( cas_chainA[i].size() == cas_chainB[i].size() ); // both chains should be same length
520  motif_cuts[i].push_back( cas_chainA[i].size()/4 );
521  nsegs_ += (motif_cuts[i].size() - 1);
522  }
523 
524  // get superposition
525  Qs.resize(nmotifs);
526  Rdimers.resize(nmotifs);
527  delta_coms.resize(nmotifs);
528  symm_orders.resize(nmotifs);
529  symm_axes.resize(nmotifs);
530  for (Size i=1; i<=nmotifs; ++i) {
531  numeric::xyzVector< core::Real > preT(0,0,0), postT(0,0,0);
532  core::Real rms = RMSwrapper( cas_chainB[i], cas_chainA[i], Rdimers[i], preT, postT);
533 
534  // check if near identity
535  core::Real residual =
536  std::fabs(Rdimers[i].xx()-1) + std::fabs(Rdimers[i].yy()-1) + std::fabs(Rdimers[i].zz()-1) +
537  std::fabs(Rdimers[i].xy()) + std::fabs(Rdimers[i].yx()) + std::fabs(Rdimers[i].zy()) +
538  std::fabs(Rdimers[i].xz()) + std::fabs(Rdimers[i].yz()) + std::fabs(Rdimers[i].zx());
539 
540  if (residual < 1e-6) {
541  utility_exit_with_message( "Chains related by transformation only!" );
542  }
543 
544  if (rms > 1.0) {
545  TR << "RMS = " << rms << std::endl;
546  utility_exit_with_message( "Interchain RMS > 1 ... aborting" );
547  }
548 
549  // make transformation perfectly symmetrical
550  R2quat( Rdimers[i], Qs[i]);
551  core::Real Wmult = 1;
552  if (Qs[i].w < 0) { Qs[i].w = -Qs[i].w; Wmult = -1; }
553  core::Real omega = acos( Qs[i].w );
554  symm_orders[i] = (core::Size)floor(pi/omega + 0.5);
555 
556  core::Real newW = -Wmult * cos( pi/symm_orders[i] );
557  core::Real newS = sqrt ( (1-newW*newW)/(Qs[i].x*Qs[i].x+Qs[i].y*Qs[i].y+Qs[i].z*Qs[i].z) );
558  Qs[i].x *= newS; Qs[i].y *= newS; Qs[i].z *= newS;
559  Qs[i].w = newW;
560 
561  symm_axes[i] = numeric::xyzVector< core::Real >( Qs[i].x, Qs[i].y, Qs[i].z );
562  symm_axes[i].normalize();
563  quat2R( Qs[i], Rdimers[i] );
564  delta_coms[i] = postT - preT;
565  delta_coms[i].project_normal( symm_axes[i] );
566  }
567 
568  // symmetry / motif count agreement
569  if (symm_type_ == "D2") {
570  if (nmotifs != 2) {
571  TR << "nmotifs = " << nmotifs << std::endl;
572  utility_exit_with_message( "Symmetry group D2: 2 motifs expected!" );
573  }
574  if (symm_orders[1] != 2 || symm_orders[2] != 2) {
575  TR << "Symm_orders = " << symm_orders[1] << "," << symm_orders[2] << std::endl;
576  utility_exit_with_message( "Symmetry group D2: 2 homodimeric motifs expected!" );
577  }
578  } else {
579  utility_exit_with_message( "Symmetry type unknown!" );
580  }
581 }
582 
583 //
584 // parse_my_tag
585 void
587  utility::tag::TagPtr const tag,
588  protocols::moves::DataMap & /*data_map*/,
591  core::pose::Pose const & /*reference_pose*/ ) {
592  symm_type_ = tag->getOption<std::string>( "symm_type", "D2" );
593 
594  utility::vector1<std::string> motif_files( utility::string_split( tag->getOption< std::string >("motifs"), ',') );
595  for (Size i=1; i<=motif_files.size(); ++i) {
596  core::pose::PoseOP motif = new core::pose::Pose();
597  core::import_pose::pose_from_pdb( *motif, motif_files[i] );
598  ref_motifs_.push_back( motif );
599  }
600  core::Size nmotifs = ref_motifs_.size();
601  TR << "Read " << nmotifs << " motifs" << std::endl;
602  //to do: save on datamap?
603 
604  // override default options
605  if (tag->hasOption("angle_thresh"))
606  angle_thresh_ = tag->getOption<core::Real>( "angle_thresh" );
607  if (tag->hasOption("trans_thresh"))
608  trans_thresh_ = tag->getOption<core::Real>( "trans_thresh" );
609  if (tag->hasOption("rmsd_thresh"))
610  rmsd_thresh_ = tag->getOption<core::Real>( "rmsd_thresh" );
611  if (tag->hasOption("clash_thresh"))
612  clash_thresh_ = tag->getOption<core::Size>( "clash_thresh" );
613  if (tag->hasOption("angle_wt"))
614  angle_wt_ = tag->getOption<core::Real>( "angle_wt" );
615  if (tag->hasOption("trans_wt"))
616  trans_wt_ = tag->getOption<core::Real>( "trans_wt" );
617  if (tag->hasOption("rmsd_wt"))
618  rmsd_wt_ = tag->getOption<core::Real>( "rmsd_wt" );
619  if (tag->hasOption("clash_wt"))
620  clash_wt_ = tag->getOption<core::Real>( "clash_wt" );
621 
622  if (tag->hasOption("force_pos")) {
623  utility::vector1<std::string> forced( utility::string_split( tag->getOption< std::string >("force_pos"), ',') );
624  for (Size i=1; i<=forced.size(); ++i)
625  forced_pos_.push_back( std::atoi( forced[i].c_str() ) );
626  }
627 
628  process_motifs();
629 
630  // make sure that if we force motifs we force all of them
631  runtime_assert( forced_pos_.size() == 0 || forced_pos_.size() == nsegs_ );
632 }
633 
634 
635 } // filters
636 }
637