Rosetta
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
rms.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 numeric/model_quality/rms.hh
11 /// @brief RMS functions imported from rosetta++
12 /// @author James Thompson
13 /// @date Wed Aug 22 12:10:37 2007
14 
15 
16 // Rosetta Headers
17 
18 // numeric libraries
19 #include <numeric/xyzVector.hh>
20 #include <numeric/xyz.functions.hh>
24 #include <numeric/types.hh>
25 
26 #include <utility/vector1.hh>
27 
28 // ObjexxFCL libraries
29 #include <ObjexxFCL/FArray1D.hh>
30 #include <ObjexxFCL/FArray2D.hh>
31 
32 // C++ libraries
33 #include <complex>
34 
35 
36 namespace numeric {
37 namespace model_quality {
38 
43 using ObjexxFCL::FArray2;
44 using ObjexxFCL::FArray1;
45 
50 ) {
51  assert( p1_coords.size() == p2_coords.size() );
52  Size const natoms( p1_coords.size() );
53 
54  FArray2D< numeric::Real > p1a( 3, p1_coords.size() );
55  FArray2D< numeric::Real > p2a( 3, p2_coords.size() );
56 
57  for ( Size i = 1; i <= natoms; ++i ) {
58  for ( Size k = 1; k <= 3; ++k ) { // k = X, Y and Z
59  p1a(k,i) = p1_coords[i](k);
60  p2a(k,i) = p2_coords[i](k);
61  }
62  }
63  return rms_wrapper( natoms, p1a, p2a );
64 }
65 
68  int natoms,
71 ) {
72  // rotate and translate coordinates to minimize rmsd
73  FArray1D< numeric::Real > ww(natoms,1.0);
74  Real bogus = 0;
75  rmsfitca2(natoms,p1a,p2a,ww,natoms,bogus);
76 
77  // manually calculate rmsd
78  numeric::Real tot = 0;
79  for ( int i = 1; i <= natoms; ++i ) {
80  for ( int j = 1; j <= 3; ++j ) {
81  tot += std::pow( p1a(i,j) - p2a(i,j), 2 );
82  }
83  }
84 
85  return std::sqrt(tot/natoms);
86 }
87 
88 // Calculate an RMS based on aligned set of points in p1a and p2a composed
89 // each representing a list of natoms.
92  int natoms,
95 ) {
96  FArray1D< numeric::Real > ww( natoms, 1.0 );
97  FArray2D< numeric::Real > uu( 3, 3, 0.0 );
98  numeric::Real ctx;
99 
100  findUU( p1a, p2a, ww, natoms, uu, ctx );
101 
102  float fast_rms;
103  calc_rms_fast( fast_rms, p1a, p2a, ww, natoms, ctx );
104  return fast_rms;
105 } // rms_wrapper
106 
107 ////////////////////////////////////////////////////////////////////////////////
108 ///
109 /// @brief
110 /// companion function for findUU ( it is optional ) computes the minimum
111 /// RMS deviation beteen XX and YY as though it rotated the arrays, without
112 /// actually rotating them.
113 ///
114 /// @details
115 ///
116 /// @param rms_out [in/out]? - the real-valued output value of the rms deviation
117 /// @param XX - [in/out]? - first set of points representing xyz coordinates
118 /// @param YY - [in/out]? - second set of points representing xyz coordinates
119 /// @param WW - [in/out]? - relative weight for each point
120 /// @param npoints - [in/out]? - number of points
121 /// @param ctx - [in/out]? - magic number computed during find UU that is needed
122 /// for this calculation
123 ///
124 /// @global_read
125 ///
126 /// @global_write
127 ///
128 /// @remarks
129 /// the XX, YY, WW must be the same as call to findUU (remember that findUU
130 /// offsets the XX and YY weighted COM to the origin!)
131 ///
132 /// @references
133 ///
134 /// @author
135 ///
136 /////////////////////////////////////////////////////////////////////////////////
137 void
139  float & rms_out,
143  int npoints,
144  numeric::Real ctx
145 )
146 {
147  xx.dimension( 3, npoints );
148  yy.dimension( 3, npoints );
149  ww.dimension( npoints );
150 
151  numeric::Real rms = 0.0;
152 
153  for ( int k = 1; k <= npoints; ++k ) {
154  numeric::Real const ww_k = ww(k);
155  for ( int j = 1; j <= 3; ++j ) {
156  numeric::Real const xx_jk = xx(j,k);
157  numeric::Real const yy_jk = yy(j,k);
158  rms += ww_k * ( ( xx_jk * xx_jk ) + ( yy_jk * yy_jk ) );
159  }
160  }
161 
162  rms -= 2 * ctx;
163  // abs on next line catches small difference of large numbers that turn out
164  // to be accidental small but negative
165  rms_out = std::sqrt(std::abs(rms/npoints)); // return a float
166 } // calc_rms_fast
167 
168 ////////////////////////////////////////////////////////////////////////////////
169 ///
170 /// @brief
171 /// intended to rotate one protein xyz array onto another one such that
172 /// the point-by-point rms is minimized.
173 ///
174 /// @details
175 /// 1) ORIGINAL PAPER HAD ERROR IN HANDEDNESS OF VECTORS, LEADING
176 /// TO INVERSION MATRICIES ON OCCASION. OOPS. NOW FIXED.
177 /// SEE ACTA CRYST(1978) A34 PAGE 827 FOR REVISED MATH
178 /// 2) TRAP DIVIDE BY ZERO ERRORS WHEN NO ROTATIONS REQUIRED.
179 /// 3) ADDED WEIGHTS (WEIGHTS NOW WORK)
180 /// 4) ADDED FAST RMS CALC AUXILIRARY ROUTINE.
181 /// 5) CHANGED TO numeric::Real TO DEAL WITH HIGHLY DISSIMILAR BUT LARGE PROTEINS.
182 ///
183 /// switched order of array subscripts so that can use logical array sizes
184 /// XX and YY are lists of Npoints XYZ vectors (3xNpoint matrix) to be co-aligned
185 /// these matrices are returned slightly modified: they are translated so their origins
186 /// are at the center of mass (see Weights below ).
187 /// WW is the weight or importance of each point (weighted RMS) vector of size Npoints
188 /// The center of mass is figured including this variable.
189 /// UU is a 3x3 symmetric orthonornal rotation matrix that will rotate YY onto XX such that
190 /// the weighted RMS distance is minimized.
191 ///
192 /// @param[in] XX - in - XX,YY are 2D arrays of x,y,z position of each atom
193 /// @param[in] YY - in -
194 /// @param[in] WW - in - a weight matrix for the points
195 /// @param[in] Npoints - in - the number of XYZ points (need not be physical array size)
196 /// @param[out] UU - out - 3x3 rotation matrix.
197 /// @param[out] sigma3 - out - TO BE PASSED TO OPTIONAL FAST_RMS CALC ROUTINE.
198 ///
199 /// @global_read
200 ///
201 /// @global_write
202 ///
203 /// @remarks
204 /// SIDEEFECTS: the Matrices XX, YY are Modified so that their weighted center
205 /// of mass is moved to (0,0,0).
206 ///
207 /// CAVEATS:
208 /// 1) it is CRITICAL that the first physical dimension of XX and YY is 3
209 ///
210 /// 2) an iterative approx algorithm computes the diagonalization of
211 /// a 3x3 matrix. if this program needs a speed up this could be
212 /// made into an analytic but uggggly diagonalization function.
213 ///
214 /// @references
215 /// Mathethematical Basis from paper:
216 /// (Wolfgang Kabsch) acta Cryst (1976) A32 page 922
217 ///
218 /// @author
219 /// Charlie Strauss 1999
220 /// Revised april 22
221 ///
222 /////////////////////////////////////////////////////////////////////////////////
223 void
227  FArray1< numeric::Real > const & WW,
228  int Npoints,
230  numeric::Real & sigma3
231 )
232 {
233  using numeric::xyzMatrix;
234  using numeric::xyzVector;
235 
236  ObjexxFCL::FArray1D_int sort( 3 );
237  FArray2D< numeric::Real > eVec( 3, 3 );
238  FArray2D< numeric::Real > bb( 3, 3 );
239  FArray1D< numeric::Real > w_w( 3 );
240  FArray2D< numeric::Real > m_moment( 3, 3 );
241  FArray2D< numeric::Real > rr_moment( 3, 3 );
242  numeric::Real temp1;
243  numeric::Real temp2;
244  //numeric::Real temp3;
246 
247  if ( Npoints < 1 ) {
248 
249  // return identity rotation matrix to moron
250  for ( int i = 1; i <= 3; ++i ) {
251  for ( int k = 1; k <= 3; ++k ) {
252  UU(i,k) = 0.0;
253  if ( i == k ) UU(i,i) = 1.0;
254  }
255  }
256  sigma3 = 0.0;
257  return;
258  }
259 
260  // align center of mass to origin
261  for ( int k = 1; k <= 3; ++k ) {
262  temp1 = 0.0;
263  temp2 = 0.0;
264  numeric::Real temp3 = 0.0;
265  for ( int j = 1; j <= Npoints; ++j ) {
266  temp1 += XX(k,j) * WW(j);
267  temp2 += YY(k,j) * WW(j);
268  temp3 += WW(j);
269  }
270  if ( temp3 > 0.001 ) temp1 /= temp3;
271  if ( temp3 > 0.001 ) temp2 /= temp3;
272 
273  for ( int j = 1; j <= Npoints; ++j ) {
274  XX(k,j) -= temp1;
275  YY(k,j) -= temp2;
276  }
277  }
278 
279  // Make cross moments matrix INCLUDE THE WEIGHTS HERE
280  for ( int k = 1; k <= 3; ++k ) {
281  for ( int j = 1; j <= 3; ++j ) {
282  temp1 = 0.0;
283  for ( int i = 1; i <= Npoints; ++i ) {
284  temp1 += WW(i) * YY(k,i) * XX(j,i);
285  }
286  m_moment(k,j) = temp1;
287  }
288  }
289 
290  // Multiply CROSS MOMENTS by transpose
291  BlankMatrixMult(m_moment,3,3,1,m_moment,3,0,rr_moment);
292 
293  // Copy to/from xyzMatrix/xyzVector since rest of functions use FArrays
294  xyzMatrix< numeric::Real > xyz_rr_moment( xyzMatrix< numeric::Real >::cols( &rr_moment( 1,1 ) ) );
297 
298  // Find eigenvalues, eigenvectors of symmetric matrix rr_moment
299  xyz_w_w = eigenvector_jacobi( xyz_rr_moment, (numeric::Real) 1E-9, xyz_eVec );
300 
301  // Copy eigenvalues/vectors back to FArray
302  for ( int i = 1; i <= 3; ++i ) {
303  w_w( i ) = xyz_w_w( i );
304  for ( int j = 1; j <= 3; ++j ) {
305  eVec( i, j ) = xyz_eVec( i, j );
306  }
307  }
308 
309  // explicitly coded 3 level index sort using eigenvalues
310  for ( int i = 1; i <= 3; ++i ) {
311  sort(i) = i;
312  }
313 
314  if ( w_w(1) < w_w(2) ) {
315  sort(2) = 1;
316  sort(1) = 2;
317  }
318 
319  if ( w_w(sort(2)) < w_w(3) ) {
320  sort(3) = sort(2);
321  sort(2) = 3;
322 
323  if ( w_w(sort(1)) < w_w(3) ) {
324  sort(2) = sort(1);
325  sort(1) = 3;
326  }
327  }
328 
329  // sort is now an index to order of eigen values
330 
331  if ( w_w(sort(2)) == 0.0 ) { // holy smokes, two eigen values are zeros
332  // return identity rotation matrix to moron
333  for ( int i = 1; i <= 3; ++i ) {
334  for ( int k = 1; k <= 3; ++k ) {
335  UU(i,k) = 0.0;
336  }
337  UU(i,i) = 1.0;
338  }
339  if ( w_w(sort(1)) < 0.0 ) {
340  w_w(sort(1)) = std::abs(w_w(sort(1)));
341  }
342  sigma3 = std::sqrt(w_w(sort(1)));
343 
344  return; // make like a prom dress and slip off
345  }
346 
347  // sort eigen values
348  temp1 = w_w(sort(1));
349  temp2 = w_w(sort(2));
350  w_w(3) = w_w(sort(3));
351  w_w(2) = temp2;
352  w_w(1) = temp1;
353  // sort first two eigen vectors (dont care about third)
354  for ( int i = 1; i <= 3; ++i ) {
355  temp1 = eVec(i,sort(1));
356  temp2 = eVec(i,sort(2));
357  eVec(i,1) = temp1;
358  eVec(i,2) = temp2;
359  }
360 
361 
362  // april 20: the fix not only fixes bad eigen vectors but solves a problem of
363  // forcing a right-handed coordinate system
364 
365  fixEigenvector(eVec);
366  // at this point we now have three good eigenvectors in a right hand
367  // coordinate system.
368 
369  // make bb basis vectors = moments*eVec
370 
371  BlankMatrixMult(m_moment,3,3,0,eVec,3,0,bb);
372  // std::cerr << "m_moment" << std::endl;
373  // squirrel away a free copy of the third eigenvector before normalization/fix
374  for ( int j = 1; j <= 3; ++j ) {
375  Ra(j) = bb(j,3);
376  }
377 
378  // normalize first two bb-basis vectors
379  // dont care about third since were going to replace it with b1xb2
380  // this also avoids problem of possible zero third eigen value
381  for ( int j = 1; j <= 2; ++j ) {
382  temp1 = 1.0/std::sqrt(w_w(j)); // zero checked for above
383  for ( int k = 1; k <= 3; ++k ) { // x,y,z
384  bb(k,j) *= temp1;
385  }
386  }
387 
388  // fix things so that bb eigenvecs are right handed
389 
390  fixEigenvector(bb); // need to fix this one too
391  // find product of eVec and bb matrices
392 
393  BlankMatrixMult(eVec,3,3,0,bb,3,1,UU);
394  // result is returned in UU.
395 
396  // and lastly determine a value used in another function to compute the rms
397  sigma3 = 0.0;
398  for ( int j = 1; j <= 3; ++j ) {
399  sigma3 += bb(j,3)*Ra(j);
400  }
401  //cems the std::abs() fixes some round off error situations where the w_w values are
402  //cems very small and accidentally negative. (theoretically they are positive,
403  //cems but in practice round off error makes them negative)
404  if ( sigma3 < 0.0 ) {
405  sigma3 = std::sqrt(std::abs(w_w(1))) + std::sqrt(std::abs(w_w(2))) -
406  std::sqrt(std::abs(w_w(3)));
407  } else {
408  sigma3 = std::sqrt(std::abs(w_w(1))) + std::sqrt(std::abs(w_w(2))) +
409  std::sqrt(std::abs(w_w(3)));
410  }
411 
412 } // findUU
413 
414 /// @brief This is a helper function for using the above implementation of findUU. There is some cost to the
415 /// conversion but everything else is probably slower and also you don't have to use FArrays everywhere
416 void
421  int Npoints,
423  numeric::Real & sigma3
424 )
425 {
426  FArray2D< numeric::Real > XX_Farray(numeric::vector_of_xyzvectors_to_FArray<numeric::Real>(XX));
427  FArray2D< numeric::Real > YY_Farray(numeric::vector_of_xyzvectors_to_FArray<numeric::Real>(YY));
428  FArray1D< numeric::Real > WW_Farray(WW.size());
429  FArray2D< numeric::Real > UU_Farray(numeric::xyzmatrix_to_FArray<numeric::Real>(UU));
430 
431  for ( numeric::Size index = 1; index <= WW.size(); ++index ) {
432  WW_Farray(index) = WW[index];
433  }
434 
435  findUU(XX_Farray,YY_Farray,WW_Farray,Npoints,UU_Farray,sigma3);
436 
437  //XX, YY, and UU were updated, convert those back. WW is const so don't bother
438 
441  UU = numeric::FArray_to_xyzmatrix(UU_Farray);
442 
443 
444 }
445 
446 ////////////////////////////////////////////////////////////////////////////////
447 ///
448 /// @brief
449 ///
450 /// @details
451 ///
452 /// @param A - [in/out]? -
453 /// @param n - [in/out]? -
454 /// @param np - [in/out]? -
455 /// @param transposeA - [in/out]? -
456 /// @param B - [in/out]? -
457 /// @param m - [in/out]? -
458 /// @param transposeB - [in/out]? -
459 /// @param AxB_out - [in/out]? -
460 ///
461 /// @global_read
462 ///
463 /// @global_write
464 ///
465 /// @remarks
466 ///
467 /// @references
468 ///
469 /// @author
470 ///
471 /////////////////////////////////////////////////////////////////////////////////
472 void
475  int n,
476  int np,
477  int transposeA,
479  int m,
480  int transposeB,
482 )
483 {
484  A.dimension( np, n );
485  B.dimension( np, m );
486  AxB_out.dimension( m, n );
487 
488  // fills output matrix with zeros before calling matrix multiply
489  AxB_out = 0.0;
490 
491  MatrixMult(A,n,np,transposeA,B,m,transposeB,AxB_out);
492 } // BlankMatrixMult
493 
494 ////////////////////////////////////////////////////////////////////////////////
495 ///
496 /// @brief
497 ///
498 /// @details
499 /// multiplys matrices A (npXn) and B (npXn). results in AxB.out
500 /// IF THE MATRICES are SQUARE. you can also multiply the transposes of these matrices
501 /// to do so set the transposeA or transposeB flags to 1, otherwise they should be zero.
502 ///
503 /// @param A - [in/out]? -
504 /// @param n - [in/out]? -
505 /// @param np - [in/out]? -
506 /// @param transposeA - [in/out]? -
507 /// @param B - [in/out]? -
508 /// @param m - [in/out]? -
509 /// @param transposeB - [in/out]? -
510 /// @param AxB_out - [in/out]? -
511 ///
512 /// @global_read
513 ///
514 /// @global_write
515 ///
516 /// @remarks
517 /// transpose only works correctly for square matricies!
518 ///
519 /// this function does SUMS to the old value of AxB_out...
520 /// you might want to call BlankMatrixMult instead (see above) 4/30/01 jjg
521 ///
522 ///this function works on numeric::Real values
523 ///float version below. jjg
524 ///
525 /// @references
526 ///
527 /// @author
528 /// charlie strauss 1999
529 ///
530 /////////////////////////////////////////////////////////////////////////////////
531 void
534  int n,
535  int np,
536  int transposeA,
538  int m,
539  int transposeB,
541 )
542 {
543  A.dimension( np, n );
544  B.dimension( np, m );
545  AxB_out.dimension( m, n );
546 
547 
548  if ( transposeA == 0 ) {
549  if ( transposeB == 0 ) {
550  for ( int k = 1; k <= m; ++k ) {
551  for ( int j = 1; j <= n; ++j ) {
552  for ( int i = 1; i <= np; ++i ) {
553  AxB_out(k,j) += A(k,i)*B(i,j);
554  }
555  }
556  }
557  } else {
558  for ( int k = 1; k <= m; ++k ) {
559  for ( int j = 1; j <= n; ++j ) {
560  for ( int i = 1; i <= np; ++i ) {
561  AxB_out(k,j) += A(k,i)*B(j,i);
562  }
563  }
564  }
565  }
566  } else {
567  if ( transposeB == 0 ) {
568  for ( int k = 1; k <= m; ++k ) {
569  for ( int j = 1; j <= n; ++j ) {
570  for ( int i = 1; i <= np; ++i ) {
571  AxB_out(k,j) += A(i,k)*B(i,j);
572  }
573  }
574  }
575  } else {
576  for ( int k = 1; k <= m; ++k ) {
577  for ( int j = 1; j <= n; ++j ) {
578  for ( int i = 1; i <= np; ++i ) {
579  AxB_out(k,j) += A(i,k)*B(j,i);
580  }
581  }
582  }
583  }
584  }
585 } // MatrixMult
586 
587 ////////////////////////////////////////////////////////////////////////////////
588 ///
589 /// @brief
590 ///
591 /// @details
592 /// m_v is a 3x3 matrix of 3 eigen vectors
593 /// replaces the third eigenvector by taking cross product of
594 /// of the first two eigenvectors
595 ///
596 /// @param m_v - [in/out]? -
597 ///
598 /// @global_read
599 ///
600 /// @global_write
601 ///
602 /// @remarks
603 ///
604 /// @references
605 ///
606 /// @author
607 ///
608 /////////////////////////////////////////////////////////////////////////////////
609 void
611 {
612  m_v.dimension( 3, 3 );
613 
614  numeric::Real const m_v_13 = m_v(2,1)*m_v(3,2) - m_v(3,1)*m_v(2,2);
615  numeric::Real const m_v_23 = m_v(3,1)*m_v(1,2) - m_v(1,1)*m_v(3,2);
616  numeric::Real const m_v_33 = m_v(1,1)*m_v(2,2) - m_v(2,1)*m_v(1,2);
617  // normalize it to 1 (should already be one but lets be safe)
618  numeric::Real const norm = std::sqrt( 1 /
619  ( ( m_v_13 * m_v_13 ) + ( m_v_23 * m_v_23 ) + ( m_v_33 * m_v_33 ) ) );
620 
621  m_v(1,3) = m_v_13 * norm;
622  m_v(2,3) = m_v_23 * norm;
623  m_v(3,3) = m_v_33 * norm;
624 } // fixEigenvector
625 
626 void
628  int npoints,
632  int natsel,
633  double & esq
634 )
635 {
636  xx.dimension( 3, npoints );
637  yy.dimension( 3, npoints );
638  ww.dimension( npoints );
639 
640 
641  double det;
642  int i,j,k;
643  double temp1,temp3;
644  FArray1D< double > ev( 3 );
645  FArray2D< double > m_moment( 3, 3 );
646  FArray2D< double > rr_moment( 3, 3 );
647  double rms_ctx;
648  double rms_sum;
649  double handedness;
650  FArray1D< double > t( 3 );
651 
652  FArray2D< double > R( 3, 3 );
653  double XPC, YPC, ZPC, XEC, YEC, ZEC;
654  // //COMMON /TRANSFORM/ XPC,YPC,ZPC,XEC,YEC,ZEC,R
655 
656  // align center of mass to origin
657 
658  COMAS(xx,ww,npoints,XPC,YPC,ZPC);
659  COMAS(yy,ww,npoints,XEC,YEC,ZEC);
660  temp3 = 0.0;
661  for ( i = 1; i <= npoints; ++i ) {
662  temp3 += ww(i);
663  // this is outrageous, but there are cases (e.g. in a single-residue pose) where
664  // all the z's are at 0, and this makes the det zero.
665  xx(3,i) -= 1.0e-7;
666  yy(3,i) += 1.0e-7;
667  }
668 
669  // Make cross moments matrix INCLUDE THE WEIGHTS HERE
670  for ( k = 1; k <= 3; ++k ) {
671  for ( j = 1; j <= 3; ++j ) {
672  temp1 = 0.0;
673  for ( i = 1; i <= npoints; ++i ) {
674  temp1 += ww(i)*yy(k,i)*xx(j,i);
675  }
676  m_moment(k,j) = temp1 /(temp3); // rescale by temp3
677  }
678  }
679  det = det3(m_moment); // will get handedness of frame from determinant
680 
681  if ( std::abs(det) <= 1.0E-24 ) {
682  // // std::cerr << "Warning:degenerate cross moments: det=" << det << std::endl;
683  // // might think about returning a zero rms, to avoid any chance of Floating Point Errors?
684 
685  esq = 0.0;
686  return;
687 
688  }
689  handedness = numeric::sign_transfered(det, 1.0);
690  // // weird but documented fortran "feature" of sign(a,b) (but not SIGN) is that if fails if a < 0
691 
692  // // multiply cross moments by itself
693 
694  for ( i = 1; i <= 3; ++i ) {
695  for ( j = i; j <= 3; ++j ) {
696  rr_moment(j,i) = rr_moment(i,j) = // well it is symmetric afterall
697  m_moment(1,i)*m_moment(1,j) +
698  m_moment(2,i)*m_moment(2,j) +
699  m_moment(3,i)*m_moment(3,j);
700  }
701  }
702 
703  // // compute eigen values of cross-cross moments
704 
705  rsym_eigenval(rr_moment,ev);
706 
707  // // reorder eigen values so that ev(3) is the smallest eigenvalue
708 
709  if ( ev(2) > ev(3) ) {
710  if ( ev(3) > ev(1) ) {
711  temp1 = ev(3);
712  ev(3) = ev(1);
713  ev(1) = temp1;
714  }
715  } else {
716  if ( ev(2) > ev(1) ) {
717  temp1 = ev(3);
718  ev(3) = ev(1);
719  ev(1) = temp1;
720  } else {
721  temp1 = ev(3);
722  ev(3) = ev(2);
723  ev(2) = temp1;
724  }
725  }
726 
727  // // ev(3) is now the smallest eigen value. the other two are not
728  // // sorted. this is prefered order for rotation matrix
729 
730 
731  rsym_rotation(m_moment,rr_moment,ev,R);
732 
733  //$$$ for ( i = 1; i <= npoints; ++i ) {
734  //$$$ for ( j = 1; j <= 3; ++j ) {
735  //$$$ temp1 = 0.0;
736  //$$$ for ( k = 1; k <= 3; ++k ) {
737  //$$$ temp1 += R(j,k)*yy(k,i);
738  //$$$ }
739  //$$$ t(j) = temp1;
740  //$$$ }
741  //$$$ yy(1,i) = t(1);
742  //$$$ yy(2,i) = t(2);
743  //$$$ yy(3,i) = t(3);
744  //$$$ }
745 
746  for ( i = 1; i <= npoints; ++i ) {
747  for ( j = 1; j <= 3; ++j ) { // compute rotation
748  t(j) = R(j,1)*yy(1,i) + R(j,2)*yy(2,i) + R(j,3)*yy(3,i);
749  }
750  yy(1,i) = t(1);
751  yy(2,i) = t(2);
752  yy(3,i) = t(3);
753  }
754  // // now we must catch the special case of the rotation with inversion.
755  // // we cannot allow inversion rotations.
756  // // fortunatley, and curiously, the optimal non-inverted rotation matrix
757  // // will have the similar eigen values.
758  // // we just have to make a slight change in how we handle things depending on determinant
759 
760  rms_ctx = std::sqrt(std::abs(ev(1))) + std::sqrt(std::abs(ev(2))) +
761  handedness*std::sqrt(std::abs(ev(3)));
762 
763  rms_ctx *= temp3;
764 
765  // // the std::abs() are theoretically unneccessary since the eigen values of a real symmetric
766  // // matrix are non-negative. in practice sometimes small eigen vals end up just negative
767  rms_sum = 0.0;
768  for ( i = 1; i <= npoints; ++i ) {
769  for ( j = 1; j <= 3; ++j ) {
770  rms_sum += ww(i)*( ( yy(j,i) * yy(j,i) ) + ( xx(j,i) * xx(j,i) ) );
771  }
772  }
773  // rms_sum = rms_sum; // /temp3 (will use natsel instead)
774 
775  // // and combine the outer and cross terms into the final calculation.
776  // // (the std::abs() just saves us a headache when the roundoff error accidantally makes the sum negative)
777 
778  esq = std::sqrt( std::abs( rms_sum - ( 2.0 * rms_ctx ) ) / natsel );
779 
780 } // rmsfitca2
781 
782 
783 void
785  int npoints, // number of points to fit
790  double & esq
791 )
792 {
793 
794  xx0.dimension( 3, npoints );
795  xx.dimension ( 3, npoints );
796  yy0.dimension( 3, npoints );
797  yy.dimension ( 3, npoints );
798 
799  // local
800  double det;
801  double temp1,mass;
802  FArray1D< double > come( 3 );
803  FArray1D< double > comp( 3 );
804  FArray1D< double > ev( 3 );
805  FArray2D< double > m_moment( 3, 3 );
806  FArray2D< double > rr_moment( 3, 3 );
807  double rms_ctx,rms2_sum;
808  double handedness;
809 
810  FArray2D< double > r( 3, 3 );
811  FArray1D< double > t( 3 );
812 
813 
814  // compute center of mass
815  numeric::model_quality::RmsData* rmsdata = RmsData::instance(); // get a pointer to the singleton class
816 
817  mass = rmsdata->count();
818  double xre = rmsdata->xre();
819  double xrp = rmsdata->xrp();
820  FArray1D< double > xse = rmsdata->xse();
821  FArray1D< double > xsp = rmsdata->xsp();
822  FArray2D< double > xm = rmsdata->xm();
823 
824  // std::cerr << mass << " " << xre << " " << xrp << " " << xse(1) << " " << xse(2) << " " << xse(3) << " "
825  // << xsp(1) << " " << xsp(2) << " " << xsp(3) << " " << xm(1,1) << " " << xm(1, 2) << std::endl;
826 
827 
828  come(1) = xse(1)/mass; // x_com
829  come(2) = xse(2)/mass; // y_com
830  come(3) = xse(3)/mass; // z_com
831 
832  comp(1) = xsp(1)/mass; // x_com
833  comp(2) = xsp(2)/mass; // y_com
834  comp(3) = xsp(3)/mass; // z_com
835 
836 
837  // Make cross moments matrix
838 
839  for ( int k = 1; k <= 3; ++k ) {
840  for ( int j = 1; j <= 3; ++j ) {
841  m_moment(k,j) = xm(k,j)/mass - come(k)*comp(j); // flopped com
842  }
843  }
844 
845  det = det3(m_moment); // get handedness of frame from determinant
846 
847  if ( std::abs(det) <= 1.0E-24 ) {
848  // //std::cerr << "Warning:degenerate cross moments: det=" << det << std::endl;
849  // // might think about returning a zero rms, to avoid any chance of
850  // // Floating Point Errors?
851 
852  esq = 0.0;
853  return;
854 
855  }
856  handedness = numeric::sign_transfered(det, 1.0); // changed name of call from sign to sign_transfered in mini!
857  /// OL and order of arguments -- damn
858 
859  // std::cerr << handedness << std::endl;
860  // // weird but documented "feature" of sign(a,b) (but not SIGN) is
861  // // that if fails if a < 0
862 
863  // // multiply cross moments by itself
864 
865  for ( int i = 1; i <= 3; ++i ) {
866  for ( int j = i; j <= 3; ++j ) {
867  rr_moment(j,i) = rr_moment(i,j) =
868  m_moment(1,i)*m_moment(1,j) +
869  m_moment(2,i)*m_moment(2,j) +
870  m_moment(3,i)*m_moment(3,j);
871  }
872  }
873 
874  // // compute eigen values of cross-cross moments
875 
876  rsym_eigenval(rr_moment,ev);
877 
878 
879  // // reorder eigen values so that ev(3) is the smallest eigenvalue
880 
881  if ( ev(2) > ev(3) ) {
882  if ( ev(3) > ev(1) ) {
883  temp1 = ev(3);
884  ev(3) = ev(1);
885  ev(1) = temp1;
886  }
887  } else {
888  if ( ev(2) > ev(1) ) {
889  temp1 = ev(3);
890  ev(3) = ev(1);
891  ev(1) = temp1;
892  } else {
893  temp1 = ev(3);
894  ev(3) = ev(2);
895  ev(2) = temp1;
896  }
897  }
898 
899  // // ev(3) is now the smallest eigen value. the other two are not
900  // // sorted. This is prefered order for computing the rotation matrix
901 
902  rsym_rotation(m_moment,rr_moment,ev,r);
903 
904  // // now we rotate and offset all npoints
905 
906 
907  for ( int i = 1; i <= npoints; ++i ) {
908  for ( int k = 1; k <= 3; ++k ) { // remove center of mass
909  yy(k,i) = yy0(k,i)-come(k);
910  xx(k,i) = xx0(k,i)-comp(k);
911  }
912  for ( int j = 1; j <= 3; ++j ) { // compute rotation
913  // // temp1 = 0.0;
914  // // for ( k = 1; k <= 3; ++k ) {
915  // // temp1 += r(j,k)*yy(k,i);
916  // // }
917  // // t(j) = temp1;
918  t(j) = r(j,1)*yy(1,i) + r(j,2)*yy(2,i) + r(j,3)*yy(3,i);
919 
920  }
921  yy(1,i) = t(1);
922  yy(2,i) = t(2);
923  yy(3,i) = t(3);
924  }
925 
926  // // now we must catch the special case of the rotation with inversion.
927  // // fortunatley, and curiously, the optimal non-inverted rotation
928  // // matrix will have a similar relation between rmsd and the eigen values.
929  // // we just have to make a slight change in how we handle things
930  // // depending on determinant
931 
932  rms_ctx = std::sqrt(std::abs(ev(1))) + std::sqrt(std::abs(ev(2))) +
933  handedness*std::sqrt(std::abs(ev(3)));
934  // std::cerr << handedness << std::endl;
935  // // the std::abs() are theoretically unneccessary since the eigen values
936  // // of a real symmetric matrix are non-negative.
937  // // in practice sometimes small eigen vals end up as tiny negatives.
938 
939  temp1 = ( come(1) * come(1) ) + ( come(2) * come(2) ) + ( come(3) * come(3) ) +
940  ( comp(1) * comp(1) ) + ( comp(2) * comp(2) ) + ( comp(3) * comp(3) );
941 
942  rms2_sum = (xre + xrp)/mass - temp1;
943 
944  // // and combine the outer and cross terms into the final calculation.
945  // // (the std::abs() just saves us a headache when the roundoff error
946  // // accidantally makes the sum negative)
947 
948  esq = std::sqrt(std::abs(rms2_sum-2.0*rms_ctx));
949 
950 } // rmsfitca3
951 
952 double
954 {
955 
956  m.dimension( 3, 3 );
957 
958  return
959  m(1,3)*( m(2,1)*m(3,2) - m(2,2)*m(3,1) ) -
960  m(2,3)*( m(1,1)*m(3,2) - m(1,2)*m(3,1) ) +
961  m(3,3)*( m(1,1)*m(2,2) - m(1,2)*m(2,1) );
962 }
963 
964 
965 void
969 )
970 {
971  m.dimension( 3, 3 );
972  ev.dimension( 3 );
973 
974 
975  double xx,yy,zz,xy,xz,yz;
976  double a,b,c,s0;
977  std::complex< double > f1,f2,f3,f4,f5;
978 
979  static std::complex< double > const unity = std::complex< double >(1.0,0.0);
980  static std::complex< double > const sqrt_3i =
981  std::sqrt( 3.0 ) * std::complex< double >(0.0,1.0);
982 
983  // first, for lexical sanity, name some temporary variables
984  xx = m(1,1);
985  yy = m(2,2);
986  zz = m(3,3);
987  xy = m(1,2);
988  xz = m(1,3);
989  yz = m(2,3);
990 
991  // coefficients of characterisitic polynomial
992  a = xx+yy+zz;
993  b = -xx*zz-xx*yy-yy*zz+xy*xy+xz*xz+yz*yz;
994  c = xx*yy*zz-xz*xz*yy-xy*xy*zz-yz*yz*xx+2*xy*xz*yz;
995 
996  // For numerical dynamic range we rescale the variables here
997  // with rare exceptions this is unnessary but it doesn't add much to the calculation time.
998  // this also allows use of double if desired. cems
999  // for complex< float > the rescaling trigger should be 1e15 (or less)
1000  // for complex< double > the rescaling trigger should be 1e150 (or less)
1001  // note we completely ignore the possiblity of needing rescaling to avoid
1002  // underflow due to too small numbers. left as an excercise to the reader.
1003 
1004  double norm = std::max(std::abs(a),std::max(std::abs(b),std::abs(c)));
1005  if ( norm > 1.0E50 ) { // rescaling trigger
1006  a /= norm;
1007  b /= norm * norm;
1008  c /= norm * norm * norm;
1009  } else {
1010  norm = 1.0;
1011  }
1012  // we undo the scaling by de-scaling the eigen values at the end
1013 
1014  // Power constants
1015  double const a2 = a * a;
1016  double const a3 = a * a * a;
1017 
1018  // eigenvals are the roots of the characteristic polymonial 0 = c + b*e + a*e^2 - e^3
1019  // solving for the three roots now:
1020  // dont try to follow this in detail: its just a tricky
1021  // factorization of the formulas for cubic equation roots.
1022 
1023  s0 = ( -12.0 * ( b * b * b ) ) - ( 3.0 * ( b * b ) * a2 ) +
1024  ( 54.0 * c * b * a ) + ( 81.0 * ( c * c ) ) + ( 12.0 * c * a3 );
1025  // butt ugly term
1026 
1027  f1 = b*a/6.0 + c/2.0 + a3/27.0 + std::sqrt(s0*unity)/18.0;
1028 
1029  f2 = std::pow( f1, (1.0/3.0) ); // note f1 is a complex number
1030 
1031  f3 = (-b/3.0 - a2/9.0)/f2;
1032 
1033  f4 = f2-f3;
1034 
1035  f5 = sqrt_3i * (f2+f3); // just our imaginary friend, mr. i
1036 
1037  s0 = a/3.0;
1038  ev(1) = f4.real();
1039  // note implicitly take real part, imag part "should" be zero
1040  ev(1) = norm*(ev(1)+s0 );
1041  // do addition after type conversion in previous line.
1042  ev(2) = (-f4+f5).real(); // note real part, imag part is zero
1043  ev(2) = norm*(ev(2)*0.5 + s0 );
1044  ev(3) = (-f4-f5).real(); // note real part, imag part is zero
1045  ev(3) = norm*(ev(3)*0.5 + s0);
1046 
1047 }
1048 
1049 void
1055 )
1056 {
1057  mm.dimension( 3, 3 );
1058  m.dimension( 3, 3 );
1059  ev.dimension( 3 );
1060  rot.dimension( 3, 3 );
1061 
1062 
1063  FArray2D< double > temp( 3, 3 );
1064  FArray2D< double > mvec( 3, 3 );
1065 
1066  rsym_evector(m,ev,mvec);
1067 
1068  for ( int i = 1; i <= 2; ++i ) { // dont need no stinkin third component
1069  double norm = 1.0 / std::sqrt(std::abs(ev(i) )); // abs just fixes boo boos
1070  // if one was nervous here one could explicitly
1071  // compute the norm of temp.
1072  for ( int j = 1; j <= 3; ++j ) {
1073  temp(j,i) = 0.0;
1074  for ( int k = 1; k <= 3; ++k ) {
1075  temp(j,i) += mvec(k,i)*mm(j,k);
1076  }
1077  temp(j,i) *= norm;
1078  }
1079  }
1080 
1081  temp(1,3) = temp(2,1)*temp(3,2) - temp(2,2)*temp(3,1);
1082  temp(2,3) = -temp(1,1)*temp(3,2) + temp(1,2)*temp(3,1);
1083  temp(3,3) = temp(1,1)*temp(2,2) - temp(1,2)*temp(2,1);
1084 
1085  for ( int i = 1; i <= 3; ++i ) {
1086  for ( int j = 1; j <= 3; ++j ) {
1087  rot(j,i) = 0.0;
1088  for ( int k = 1; k <= 3; ++k ) {
1089  rot(j,i) += temp(i,k)*mvec(j,k);
1090  }
1091  }
1092  }
1093 }
1094 
1095 
1096 void
1101 )
1102 {
1103  m.dimension( 3, 3 );
1104  ev.dimension( 3 );
1105  mvec.dimension( 3, 3 );
1106 
1107  // local
1108  double xx,yy,xy,zx,yz; //zz
1109  double e1,e2,e3,znorm;
1110 
1111 
1112  // first, for sanity only, name some temporary variables
1113  //zz = m(3,3);
1114  xy = m(1,2);
1115  zx = m(1,3);
1116  yz = m(2,3);
1117 
1118  if ( ev(1) != ev(2) ) { // test for degenerate eigen values
1119 
1120  for ( int i = 1; i <= 2; ++i ) {
1121  // only computer first two eigen vectors using this method
1122  // note you could compute all three this way if you wanted to,
1123  // but you would run into problems with degenerate eigen values.
1124 
1125  xx = m(1,1)-ev(i);
1126  yy = m(2,2)-ev(i);
1127  // I marvel at how simple this is when you know the eigen values.
1128  e1 = xy*yz-zx*yy;
1129  e2 = xy*zx-yz*xx;
1130  e3 = xx*yy-xy*xy;
1131 
1132  znorm = std::sqrt( ( e1 * e1 ) + ( e2 * e2 ) + ( e3 * e3 ) );
1133 
1134  mvec(1,i) = e1/znorm;
1135  mvec(2,i) = e2/znorm;
1136  mvec(3,i) = e3/znorm;
1137 
1138  }
1139 
1140  // now compute the third eigenvector
1141  mvec(1,3) = mvec(2,1)*mvec(3,2) - mvec(2,2)*mvec(3,1);
1142  mvec(2,3) = -mvec(1,1)*mvec(3,2) + mvec(1,2)*mvec(3,1);
1143  mvec(3,3) = mvec(1,1)*mvec(2,2) - mvec(1,2)*mvec(2,1);
1144 
1145  // pathologically nervous people would explicitly normalize this vector too.
1146 
1147  return;
1148 
1149  } else {
1150 
1151  if ( ev(2) != ev(3) ) {
1152  std::cerr << " hey is this the right thing to be doing??? " << std::endl;
1153 
1154  for ( int i = 2; i <= 3; ++i ) {
1155  // Okay, since 1 and 2 are degenerate we will use 2 and 3 instead.
1156 
1157  xx = m(1,1)-ev(i);
1158  yy = m(2,2)-ev(i);
1159  // I marvel at how simple this is when you know the eigen values.
1160  e1 = xy*yz-zx*yy;
1161  e2 = xy*zx-yz*xx;
1162  e3 = xx*yy-xy*xy;
1163  // yes you sharp eyed person, its not quite symmetric here too.
1164  // life is odd.
1165 
1166  znorm = std::sqrt( ( e1 * e1 ) + ( e2 * e2 ) + ( e3 * e3 ) );
1167 
1168  mvec(1,i) = e1/znorm;
1169  mvec(2,i) = e2/znorm;
1170  mvec(3,i) = e3/znorm;
1171 
1172  }
1173 
1174  // now compute the third eigenvector
1175  mvec(1,1) = mvec(2,2)*mvec(3,3) - mvec(2,3)*mvec(3,2);
1176  mvec(2,1) = -mvec(1,2)*mvec(3,3) + mvec(1,3)*mvec(3,2);
1177  mvec(3,1) = mvec(1,2)*mvec(2,3) - mvec(1,3)*mvec(2,2);
1178 
1179  // pathologically nervous people would explicitly normalize this vector too.
1180 
1181  return;
1182 
1183  } else {
1184 
1185  std::cerr << "warning: all eigen values are equal" << std::endl;
1186 
1187  for ( int i = 1; i <= 3; ++i ) {
1188  mvec(1,i) = 0.0;
1189  mvec(2,i) = 0.0;
1190  mvec(3,i) = 0.0;
1191  mvec(i,i) = 1.0;
1192  }
1193  return;
1194  }
1195  }
1196 } // rsym_evector
1197 
1198 
1199 } // rms
1200 } // numeric
ocstream cerr(std::cerr)
Wrapper around std::cerr.
Definition: ocstream.hh:290
xyzVector< T > eigenvector_jacobi(xyzMatrix< T > const &a, T const &tol, xyzMatrix< T > &J)
Classic Jacobi algorithm for the eigenvalues and eigenvectors of a real symmetric matrix...
int count()
returns the number of points in this RmsData
Definition: RmsData.hh:77
void fixEigenvector(FArray2A< numeric::Real > m_v)
Definition: rms.cc:610
RMS functions imported from rosetta++.
Coordinate norm(Coordinate const &a)
Definition: vector.cc:40
platform::Size Size
Definition: types.hh:42
void calc_rms_fast(float &rms_out, FArray2A< numeric::Real > xx, FArray2A< numeric::Real > yy, FArray1A< numeric::Real > ww, int npoints, numeric::Real ctx)
companion function for findUU ( it is optional ) computes the minimum RMS deviation beteen XX and YY ...
Definition: rms.cc:138
FArray1A & dimension(IR const &I_a)
Dimension by IndexRanges.
Definition: FArray1A.hh:680
FArray2A: Fortran-Compatible 2D Argument Array.
Definition: FArray2.hh:29
FArray1A: Fortran-Compatible 1D Argument Array.
Definition: FArray1.hh:32
FArray1: Fortran-Compatible 1D Array Abstract Base Class.
Definition: FArray1.fwd.hh:27
std::string E(int const w, int const d, float const &t)
Exponential Format: float.
Definition: format.cc:312
utility::vector1< xyzVector< T > > FArray_to_vector_of_xyzvectors(ObjexxFCL::FArray2D< T > const &input)
convert an FArray2D to a vector of xyzVectors
void rsym_eigenval(ObjexxFCL::FArray2A< double > m, ObjexxFCL::FArray1A< double > ev)
computes the eigen values of a real symmetric 3x3 matrix
Definition: rms.cc:966
Fstring::size_type index(Fstring const &s, Fstring const &ss)
First Index Position of a Substring in an Fstring.
Definition: Fstring.hh:2180
xyzVector: Fast (x,y,z)-coordinate numeric vector
FArray2A & dimension(IR const &I1_a, IR const &I2_a)
Dimension by IndexRange.
Definition: FArray2A.hh:737
ObjexxFCL::FArray1D< double > xsp()
Definition: RmsData.hh:81
FArray2: Fortran-Compatible 2D Array Abstract Base Class.
Definition: FArray2.fwd.hh:27
static RmsData * instance()
Definition: RmsData.cc:26
T abs(T const &x)
std::abs( x ) == | x |
Definition: Fmath.hh:295
std::vector with 1-based indexing
Definition: vector1.fwd.hh:44
RmsData is a class intended to replace the global rms_obj namespace from rosetta++. Initial implementation is with a singleton design pattern to mimic a global namespace from rosetta++.
Definition: RmsData.hh:31
ObjexxFCL::FArray2D< double > xm()
Definition: RmsData.hh:89
numeric::Real rms_wrapper_slow_and_correct(int natoms, FArray2D< numeric::Real > p1a, FArray2D< numeric::Real > p2a)
Definition: rms.cc:67
rosetta project type declarations. Should be kept updated with core/types.hh. This exists because num...
tuple rms
Definition: loops_kic.py:130
double Real
Definition: types.hh:39
void MatrixMult(FArray2A< numeric::Real > A, int n, int np, int transposeA, FArray2A< numeric::Real > B, int m, int transposeB, FArray2A< numeric::Real > AxB_out)
Definition: rms.cc:532
void rmsfitca2(int npoints, ObjexxFCL::FArray2A< double > xx, ObjexxFCL::FArray2A< double > yy, ObjexxFCL::FArray1A< double > ww, int natsel, double &esq)
computes the rms between two weighted point vectors.
Definition: rms.cc:627
DimensionExpressionPow pow(Dimension const &dim1, Dimension const &dim2)
pow( Dimension, Dimension )
void BlankMatrixMult(FArray2A< numeric::Real > A, int n, int np, int transposeA, FArray2A< numeric::Real > B, int m, int transposeB, FArray2A< numeric::Real > AxB_out)
Definition: rms.cc:473
numeric::Real rms_wrapper(int natoms, FArray2D< numeric::Real > p1a, FArray2D< numeric::Real > p2a)
Definition: rms.cc:91
vector1: std::vector with 1-based indexing
xyzMatrix: Fast 3x3 xyz matrix template
void findUU(FArray2< numeric::Real > &XX, FArray2< numeric::Real > &YY, FArray1< numeric::Real > const &WW, int Npoints, FArray2< numeric::Real > &UU, numeric::Real &sigma3)
intended to rotate one protein xyz array onto another one such that the point-by-point rms is minimiz...
Definition: rms.cc:224
numeric::xyzMatrix< T > FArray_to_xyzmatrix(ObjexxFCL::FArray2D< T > const &input)
convert a 3x3 FArray 2D to an xyzMatrix
Numeric functions.
double det3(FArray2A< double > m)
determinant of a 3x3 matrix
Definition: rms.cc:953
xyzVector and xyzMatrix functions
ObjexxFCL::FArray1D< double > xse()
Definition: RmsData.hh:85
Fast (x,y,z)-coordinate numeric vector.
void rmsfitca3(int npoints, ObjexxFCL::FArray2A< double > xx0, ObjexxFCL::FArray2A< double > xx, ObjexxFCL::FArray2A< double > yy0, ObjexxFCL::FArray2A< double > yy, double &esq)
Definition: rms.cc:784
static T max(T x, T y)
Definition: Svm.cc:19
void COMAS(ObjexxFCL::FArray1A_double C, ObjexxFCL::FArray1A_double WT, int NAT, double &XC, double &YC, double &ZC)
Definition: maxsub.cc:504
T sign_transfered(S const &sigma, T const &x)
Sign transfered value.
numeric::Real calc_rms(utility::vector1< xyzVector< Real > > p1_coords, utility::vector1< xyzVector< Real > > p2_coords)
Definition: rms.cc:47
std::string A(int const w, char const c)
char Format
Definition: format.cc:175
void rsym_evector(ObjexxFCL::FArray2A< double > m, ObjexxFCL::FArray1A< double > ev, ObjexxFCL::FArray2A< double > mvec)
Author: charlie strauss (cems) 2001 given original matrix plus its eigen values compute the eigen vec...
Definition: rms.cc:1097
void rsym_rotation(ObjexxFCL::FArray2A< double > mm, ObjexxFCL::FArray2A< double > m, ObjexxFCL::FArray1A< double > ev, ObjexxFCL::FArray2A< double > rot)
finds a (proper) rotation matrix that minimizes the rms.
Definition: rms.cc:1050
FArray2D: Fortran-Compatible 2D Array.
Definition: FArray2.hh:27
FArray1D: Fortran-Compatible 1D Array.
Definition: FArray1.hh:30