Rosetta 3.5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
ResidualDipolarCoupling.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 core/scoring/ResidualDipolarCoupling.cc
11 /// @brief Uses NMR RDC for scoring
12 /// @author Oliver Lange
13 /// @author Srivatsan Raman
14 /// @author Nikolas Sgourakis
15 /// @author Lei Shi (nls and modifications to original code)
16 
17 //Unit headers
19 
20 // Package headers
21 
22 // Project headers
25 
26 // AUTO-REMOVED #include <basic/options/after_opts.hh>
27 #include <basic/options/option.hh>
28 
29 #include <basic/datacache/BasicDataCache.hh>
31 #include <core/pose/Pose.hh>
32 #include <core/pose/util.hh>
33 
34 #include <basic/Tracer.hh>
35 
36 //#include <protocols/loops/Loops.hh>
37 
38 // ObjexxFCL headers
39 #include <ObjexxFCL/format.hh>
40 
41 //C++ headers
42 #include <iostream>
43 #include <fstream>
44 #include <string>
45 
46 
47 
48 /// Utility headers
49 #include <utility/excn/Exceptions.hh>
50 #include <utility/io/izstream.hh>
51 #include <utility/io/ozstream.hh>
52 // AUTO-REMOVED #include <basic/options/option_macros.hh>
53 
54 // option key includes
55 #include <basic/options/keys/in.OptionKeys.gen.hh>
56 #include <basic/options/keys/rdc.OptionKeys.gen.hh>
57 
58 #include <numeric/nls/lmmin.hh>
59 // AUTO-REMOVED #include <numeric/random/random.hh>
60 
61 #include <utility/vector1.hh>
62 #include <numeric/random/random.fwd.hh>
63 #include <numeric/NumericTraits.hh>
64 
65 static basic::Tracer tr("core.scoring.ResidualDipolarCoupling");
66 
67 namespace core {
68 namespace scoring {
69 
70 inline Real sqr(Real x) {
71  return x * x;
72 }
73 //////////////////////////////////////////////////////
74 //@brief reads in RDC data file
75 //////////////////////////////////////////////////////
77  core::pose::Pose& pose) {
78  // ////using core::pose::datacache::CacheableDataType::RESIDUAL_DIPOLAR_COUPLING_DATA;
80 }
81 
83  core::pose::Pose const& pose) {
84  // ////using core::pose::datacache::CacheableDataType::RESIDUAL_DIPOLAR_COUPLING_DATA;
86  return static_cast<ResidualDipolarCoupling const *> (pose.data().get_const_ptr(
88  };
89  return NULL;
90 }
91 
93  // ////using core::pose::datacache::CacheableDataType::RESIDUAL_DIPOLAR_COUPLING_DATA;
95  return static_cast<ResidualDipolarCoupling*> (pose.data().get_ptr(
97  };
98  return NULL;
99 }
100 
101 void ResidualDipolarCoupling::show(std::ostream& out) const {
102  Size ct=0;
103  for (RDC_lines::const_iterator it=All_RDC_lines_.begin();it!=All_RDC_lines_.end();it++){
104  out << "RDC "<<++ct << " ";
105  out << (*it) << std::endl;
106  }
107 }
108 
109 void RDC::show(std::ostream& out) const {
110  using namespace ObjexxFCL::fmt;
111  out << RJ(4, res1_) << RJ(3, atom1_) << " " << RJ(4, res2_)
112  << RJ(3, atom2_) << " " << RJ(5, Jdipolar_);
113 }
114 
115 std::ostream& operator<<(std::ostream& out, RDC const& rdc) {
116  rdc.show(out);
117  return out;
118 }
119 
120 std::ostream& operator<<(std::ostream& out, ResidualDipolarCoupling const& rdc) {
121  rdc.show(out);
122  return out;
123 }
124 
126  basic::datacache::CacheableData(other) {
128  preprocess_data();
129  reserve_buffers();
130 }
131 
132 
133 //explicit assignment operator to initialize buffers
136  basic::datacache::CacheableData::operator=(other);
138  release_buffers();
139  preprocess_data();
140  reserve_buffers();
141  return *this;
142 }
143 
145 
146  std::string line;
147  utility::io::izstream infile(filename.c_str());
148  if ( !infile.good() ) {
149  throw( utility::excn::EXCN_FileNotFound( filename ) );
150  }
151  // std::cout << "Reading RDC file " << filename << std::endl;
152  tr.Info << "Reading RDC file " << filename << std::endl;
153  Size lines_previously_read( All_RDC_lines_.size() );
154  while (getline(infile, line)) {
155  std::istringstream line_stream(line);
156  std::string atom1, atom2;
157  Size res1, res2;
158  Real Jdipolar;
159  line_stream >> res1 >> atom1 >> res2 >> atom2 >> Jdipolar;
160 
161  if ( atom1 == "HN" ) atom1 = "H"; //take care of typical NMR community notation
162  if ( atom2 == "HN" ) atom2 = "H";
163  // if ( res1 == 1 && atom1 == "H" ) atom1 = "1H"; //this does not work since it is "H" in centroid mode and "1H" in full-atom mode
164  // if ( res2 == 1 && atom2 == "H" ) atom2 = "1H";
165  if ( line_stream.fail() ) {
166  tr.Error << "couldn't read line " << line << " in rdc-file " << filename << std::endl;
167  throw( utility::excn::EXCN_BadInput(" invalid line "+line+" in rdc-file "+filename));
168  }
169 
170  if ( res1 < 1 || res2 < 1 ) {
171  tr.Error << "negative residue number in line " << line << " in rdc-file " << filename << std::endl;
172  throw( utility::excn::EXCN_BadInput(" invalid line "+line+" in rdc_file " + filename ) );
173  }
174 
175  Real weight(1.0);
176  line_stream >> weight;
177  if (line_stream.fail()) {
178  tr.Debug << " set weight for RDC " << res1 << " to 1.0 ";
179  weight = 1.0;
180  }
181  // if ( core.size() == 0 || ( core.has( res1 ) && core.has( res2 ) ) ) {
182  tr.Debug << "... added to dataset!";
183  All_RDC_lines_.push_back(RDC(res1, atom1, res2, atom2, Jdipolar,
184  weight, expid - 1 /*C-style counting*/));
185  // }
186  tr.Debug << std::endl;
187  }
188  if ( All_RDC_lines_.size() == lines_previously_read ) {
189  tr.Error << "file empty ? " << std::endl;
190  throw( utility::excn::EXCN_BadInput(" no valid RDCs found in file " + filename + "\n" ));
191  }
192  lines_previously_read = All_RDC_lines_.size();
193 
194 
195 }
196 
198  using namespace basic::options;
199  using namespace basic::options::OptionKeys;
200  if ( !option[ OptionKeys::in::file::rdc ].user() ) {
201  tr.Warning << "no RDC file specified" << std::endl;
202  return;
203  }
204 
205  nex_ = 0;
206  // protocols::loops::Loops core;
207  // if ( option[ OptionKeys::rdc::select_residues_file ].user() ) {
208  // core.read_loop_file( option[ OptionKeys::rdc::select_residues_file ](), false, "RIGID" );
209  // }
210  for ( Size expid = 1; expid <= option[ OptionKeys::in::file::rdc ]().size(); expid++ ) {
211  nex_ = expid;
212  std::string filename( option[ OptionKeys::in::file::rdc ]()[expid] );
213  read_RDC_file( expid, filename);
214  }
215 
216 
217 
218  //extra weight file?
219  if (option[OptionKeys::rdc::weights].user()) {
220  std::string filename(option[OptionKeys::rdc::weights]().name());
221  std::ifstream infile(filename.c_str());
222  std::string line;
223  while (getline(infile, line)) {
224  std::istringstream line_stream(line);
225  Real weight;
226  Size res1;
227  line_stream >> res1 >> weight;
228  if (line_stream.fail()) {
229  tr.Error << "[Error] reading rdc-weight-file " << filename
230  << std::endl;
231  throw(utility::excn::EXCN_BadInput(" invalid line " + line
232  + " in rdc-weight-file " + filename));
233  }
234  for (RDC_lines::iterator it = All_RDC_lines_.begin(); it
235  != All_RDC_lines_.end(); ++it) {
236  if (it->res1() == res1) {
237  it->weight(weight);
238  tr.Info << "set tensor-weight for RDCs to " << weight
239  << " at residue (res1) " << res1 << std::endl;
240  }
241  }
242  }
243  }
244 
245  release_buffers();
246  preprocess_data();
247  reserve_buffers();
248 }
249 
251  release_buffers();
252 }
253 
255  Size nex(nex_);
256  Size nrows(nrows_);
257  if (nex_ < 1)
258  nex = 1; //keep always 1 around so that pointers are never empty
259  if (nrows_ < 1)
260  nrows = 1;
261  tr.Trace << "reserve buffers for nex: " << nex << " and nrows " << nrows << std::endl;
262  D_ = new rvec5[nrows];
263  rhs_ = new rvec5[nex];
264  T_ = new Tensor5[nex];
265  S_ = new Tensor[nex];
266  EV_ = new rvec[nex];
267  EIG_ = new Tensor[nex];
268  SD_ = new Tensor[nex];
269  FA_ =new core::Real[nex];
270  trace_=new core::Real[nex];
271  maxz_=new core::Real[nex];
272  r0_=new core::Real[nrows];
273  r1_=new core::Real[nrows];
274  r2_=new core::Real[nrows];
275  exprdc_=new core::Real[nrows];
276  rdcconst_=new core::Real[nrows];
277  rdcweight_=new core::Real[nrows];
278  lenex_=new core::Size[nex+1];
279 }
280 
282  delete[] D_;
283  delete[] rhs_;
284  delete[] T_;
285  delete[] S_;
286  delete[] SD_;
287  delete[] EV_;
288  delete[] FA_;
289  delete[] trace_;
290  delete[] maxz_;
291  delete[] EIG_;
292  delete[] r0_;
293  delete[] r1_;
294  delete[] r2_;
295  delete[] exprdc_;
296  delete[] rdcconst_;
297  delete[] rdcweight_;
298  delete[] lenex_;
299 }
300 
301 //initialize local buffers ( S, T, etc. )
302 //call whenever All_RDC_lines_ is changed
304 
305  //find highest expid
306  nex_ = 0;
308  for (it = All_RDC_lines_.begin(); it != All_RDC_lines_.end(); ++it) {
309  if (it->expid() >= nex_)
310  nex_ = it->expid() + 1; //C-counting
311  }
312 
313  nrows_ = All_RDC_lines_.size();
314 }
315 
317  if (atom == "HN" || atom == "H" || atom == "HA" || atom == "1H" )
318  return "H";
319  if (atom == "C" || atom == "CA")
320  return "C";
321  if (atom == "N")
322  return "N";
323  throw(utility::excn::EXCN_BadInput("unknown atom for RDC: " + atom));
324  return ""; //to make compile happy.
325 }
326 //////////////////////////////////////////////////////
327 //@brief returns type of RDC data N-H, HA-CA etc
328 //////////////////////////////////////////////////////
330  std::string const & atom2) {
331  std::string elem1(element_string(atom1));
332  std::string elem2(element_string(atom2));
333 
334  RDC_TYPE RDC_type;
335  if ((elem1 == "N" && elem2 == "H") || (elem1 == "H" && elem2 == "N"))
336  RDC_type = RDC_TYPE_NH;
337  else if ((elem1 == "CA" && elem2 == "HA") || (elem1 == "HA" && elem2 == "CA"))
338  RDC_type = RDC_TYPE_CH;
339  else if ((elem1 == "C" && elem2 == "N") || (elem1 == "N" && elem2 == "C"))
340  RDC_type = RDC_TYPE_NC;
341  else if ((elem1 == "C" && elem2 == "C"))
342  RDC_type = RDC_TYPE_CC;
343  else
344  throw(utility::excn::EXCN_BadInput(
345  "unknown combination of atoms for RDC " + atom1 + " " + atom2));
346  return RDC_type;
347 }
348 
349 typedef core::Real Tensor[3][3];
350 typedef core::Real Tensor5[5][5];
351 typedef core::Real rvec[3];
352 int m_inv_gen(Tensor5 m, int n, Tensor5 minv);
353 void jacobi(Real a[5][5], Real d[], Real v[5][5], int *nrot);
354 void jacobi3(Real a[3][3], Real d[], Real v[3][3], int *nrot);
355 
356 //void sort_rvec(rvec rv);
357 #define XX 0
358 #define YY 1
359 #define ZZ 2
360 typedef core::Real matrix[3][3];
361 typedef core::Real rvec[3];
362 typedef core::Real rvec5[5];
363 inline Real iprod(const rvec a, const rvec b) {
364  return (a[XX] * b[XX] + a[YY] * b[YY] + a[ZZ] * b[ZZ]);
365 }
366 inline void mvmul(matrix a, const rvec src, rvec dest) {
367  dest[XX] = a[XX][XX] * src[XX] + a[XX][YY] * src[YY] + a[XX][ZZ] * src[ZZ];
368  dest[YY] = a[YY][XX] * src[XX] + a[YY][YY] * src[YY] + a[YY][ZZ] * src[ZZ];
369  dest[ZZ] = a[ZZ][XX] * src[XX] + a[ZZ][YY] * src[YY] + a[ZZ][ZZ] * src[ZZ];
370 }
371 
372 
373 inline int compare_by_abs(const void * a, const void * b)
374 {
375  // int a_i = (int*) a;
376 // int b_i = (const int*) b;
377 // std::cout << std::abs(*(int*)a) << ' '<< std::abs(*(int*)b) << ' ' <<std::abs(*(core::Real*)a) - std::abs(*(core::Real*)b) <<std::endl;
378 // std::cout << "james_hack: " << a_i << ' ' << b_i << std::endl;
379 // int temp = std::abs(*(int*)a) - std::abs(*(int*)b) ;
380 // std::cout <<temp <<std::endl;
381 
382  if ( *(core::Real*)a == *(core::Real*)b ) {
383  return 0;
384  } else if ( std::abs( *(core::Real*)a) - std::abs( *(core::Real*)b) > 0){
385  return 1;
386  } else {return -1;}
387 
388 }
389 
390 
392  core::pose::Pose const& pose, core::Real sigma2, core::Real tolerance,
393  bool reset) {
395  if (reset) {
396  for (it = All_RDC_lines_.begin(); it != All_RDC_lines_.end(); ++it) {
397  it->weight(1.0);
398  }
399  }
400 
401  Real wsum_old = 100;
402  Real wsum(1.0);
403  Real invn(1.0 / All_RDC_lines_.size());
404  tr.Debug << "wRDC: iter wsum wRDC" << std::endl;
405  Size ct(0);
406  Real score(999);
407  while (std::abs(wsum_old - wsum) > tolerance) {
408  score = compute_dipscore(pose);
409  wsum_old = wsum;
410  wsum = 0.0;
411  Real wMSD = 0.0;
412  for (it = All_RDC_lines_.begin(); it != All_RDC_lines_.end(); ++it) {
413  Real dev = it->Jcomputed() - it->Jdipolar();
414  it->weight(exp(-dev * dev / sigma2));
415  wsum += it->weight() * invn;
416  wMSD += it->weight() * dev * dev;
417  }
418  tr.Debug << "wRMSD: " << ++ct << " " << wsum << " " << sqrt(wMSD)
419  << std::endl;
420  if (ct > 200) {
421  tr.Warning << "no convergence in wRDC aka iterate_tensor_weights"
422  << std::endl;
423  return score;
424  break;
425  }
426  }
427  return score;
428 }
429 
431  if ( nex_ == 0 || nrows_ == 0 ) return 0;
432 
433  //taken from gromacs/gmxlib/orires.c
434  //ref: B. Hess and RM Scheek, Journal of Magnetic Resonance 164 ( 2003 ) 19-27
436  bool const correct_NH( basic::options::option[basic::options::OptionKeys::rdc::correct_NH_length]);
437  bool const bReduced( basic::options::option[basic::options::OptionKeys::rdc::reduced_couplings]);
438  Size nrow(0);
439 
440  /* Calculate the order tensor S for each experiment via optimization */
441  for (core::Size ex = 0; ex < nex_; ex++) {
442  for (Size i = 0; i < 5; i++) {
443  rhs_[ex][i] = 0;
444  for (Size j = 0; j <= i; j++) {
445  T_[ex][i][j] = 0;
446  }
447  }
448  }
449 
450  for (it = All_RDC_lines_.begin(); it != All_RDC_lines_.end(); ++it) {
451  if ( it->res1() > pose.total_residue() || it->res2() > pose.total_residue() ) {
452  tr.Warning << "non-existing residue, ignore RDC" << std::endl;
453  continue;
454  }
455 
456  if ( it->res1() == 1 || it->res2() == 1 ) {
457  tr.Warning << "residue 1, always problematic with 1H vs H, just ignore RDC" << std::endl;
458  continue;
459  }
460 
461  //check for cutpoints!!!
462  kinematics::FoldTree const& ft(pose.fold_tree());
463  if ((ft.is_cutpoint(std::min((int) it->res1(), (int) it->res2())))
464  && it->res1() != it->res2()) {
465  tr.Warning << "cutpoint: ignore RDC " << *it << std::endl;
466  continue;
467  }
468 
469 
470  ++nrow;
471  numeric::xyzVector<Real> r( pose.residue(it->res1()).atom(it->atom1()).xyz() - pose.residue(it->res2()).atom(it->atom2()).xyz());
472 
473  core::Real r2 = r.norm_squared();
474  //core::Real scale_to_NH = 36.5089/1.041/1.041/1.041;
475  //if ( correct_NH ) scale_to_NH = 36.5089/1.041/1.041/1.041; // set but never used ~Labonte
476  core::Real invr = 1.0 / sqrt(r2);
477  if ( it->type() == RDC::RDC_TYPE_NH && correct_NH ) {
478  r.normalize(1.041);
479  r2 = 1.041 * 1.041;
480  invr = 1.0 / sqrt(r2);
481  }
482 
483  core::Real pfac = it->Dconst();
484  bool bCSA(false);// hook up for later... to compute chemical shift anisotropy
485  if (!bCSA) {
486  pfac *= invr * invr * invr;
487  }
488  Size const d(nrow - 1);
489 
490  //put a length there should change it
491  //r.normalized(1);
492 
493  D_[d][0] = pfac * (2* r [0] * r[0] + r[1] * r[1] - r.norm_squared());
494  D_[d][1] = pfac * (2* r [0] * r[1]);
495  D_[d][2] = pfac * (2* r [0] * r[2]);
496  D_[d][3] = pfac * (2* r [1] * r[1] + r[0] * r[0] - r.norm_squared());
497  D_[d][4] = pfac * (2* r [1] * r[2]);
498  // Real umn_x = umn.x()/it->fixed_dist();
499  // Real umn_y = umn.y()/it->fixed_dist();
500  // Real umn_z = umn.z()/it->fixed_dist();
501 
502 
503  //type = forceatoms[fa];
504  core::Size ex = it->expid(); //only one experiment now
505  core::Real weight = it->weight(); //force constant
506  core::Real obs = it->Jdipolar();
507  /* Calculate the vector rhs and half the matrix T for the 5 equations */
508  for (Size i = 0; i < 5; i++) {
509  rhs_[ex][i] += D_[d][i] * obs * weight;
510  for (Size j = 0; j <= i; j++)
511  T_[ex][i][j] += D_[d][i] * D_[d][j] * weight;
512  }
513  } //cycle over atoms
514 
515  /* Now we have all the data we can calculate S */
516  runtime_assert( nex_ < 200 );
517  Real Smax[200];
518  for (Size ex = 0; ex < nex_; ex++) {
519  /* Correct corrfac and copy one half of T to the other half */
520  // std::cout << " T_[ex][j][i]: ";
521  for (Size i = 0; i < 5; i++) {
522  for (Size j = 0; j < i; j++) {
523  T_[ex][j][i] = T_[ex][i][j];
524  // std::cout << " " << T_[ex][j][i] ;
525  }
526  }
527  // std::cout << std::endl;
528  try {
529  m_inv_gen(T_[ex], 5, T_[ex]);
530 // std::cout << "performing SVD decomposition" << std::endl;
531  } catch (utility::excn::EXCN_BadInput &excn) {
532  if (tr.Debug) {
533  pose.dump_pdb("failed_jacobi.pdb");
534  }
535  throw excn;
536  }
537 
538  /* Calculate the orientation tensor S for this experiment */
539  S_[ex][0][0] = 0;
540  S_[ex][0][1] = 0;
541  S_[ex][0][2] = 0;
542  S_[ex][1][1] = 0;
543  S_[ex][1][2] = 0;
544  for (Size i = 0; i < 5; i++) {
545  S_[ex][0][0] += T_[ex][0][i] * rhs_[ex][i];
546  S_[ex][0][1] += T_[ex][1][i] * rhs_[ex][i];
547  S_[ex][0][2] += T_[ex][2][i] * rhs_[ex][i];
548  S_[ex][1][1] += T_[ex][3][i] * rhs_[ex][i];
549  S_[ex][1][2] += T_[ex][4][i] * rhs_[ex][i];
550  }
551  S_[ex][1][0] = S_[ex][0][1];
552  S_[ex][2][0] = S_[ex][0][2];
553  S_[ex][2][1] = S_[ex][1][2];
554  S_[ex][2][2] = -S_[ex][0][0] - S_[ex][1][1];
555 
556  //Always use one, otherwise it is overwritten.
557  Smax[ex] = 1;
558 
559  // std::cout << "AL.TENSOR (molecular frame): " << S_[ex][0][0] << ' ' << S_[ex][0][1] << ' ' << S_[ex][0][2] << ' ' << S_[ex][1][1] << ' ' << S_[ex][1][2] << std::endl;
560 
561 
562  {
563  using namespace basic::options;
564 
565  if ( option[ OptionKeys::rdc::fix_normAzz ].user() ) {
566  if ( option[ OptionKeys::rdc::fix_normAzz ]().size() != nex_ ) {
567  utility_exit_with_message("fix_normAzz must have one value for each alignment medium !");
568  }
569  Smax[ ex ] = option[ OptionKeys::rdc::fix_normAzz ]()[ ex+1 ];
570  }
571  }
572 
573  tr.Debug << "Smax( " << ex << " ): " << Smax[ex] << std::endl;
574 
575  // std::cout << 'AL.TENSOR elements : ' << S_[ex][0][0]) << ' ' << S_[ex][0][1] << ' ' << S_[ex][0][2] << ' '
576  // << S_[ex][1][1] << ' ' << S_[ex][1][2] << std::endl;
577 
578 
579 
580  } // for ( ex = 0 .. nex )
581 
582  //Always diagonalize the matrix to find out the alignment
583  try{
585  } catch (utility::excn::EXCN_BadInput &excn) {
586  if ( tr.Debug.visible() ) {
587  pose.dump_pdb("failed_jacobi.pdb");
588  }
589  throw excn;
590  }
591 
592  //Compute the fitting stats
593  Real wsv2 = 0;
594  Real sw = 0;
595  Real vtot = 0;
596  //Real vtoti = 0;
597  Real Q = 0;
598  Real Qnorm = 0;
599 
600  Size irow(0);
601  //Size excnt(0);
602  Size ex(0);
603  //Size exold(0);
605  All_RDC_lines_.begin(); it != All_RDC_lines_.end(); ++it) {
606 
607  //check for cutpoints!!!
608  kinematics::FoldTree const& ft(pose.fold_tree());
609  if ( it->res1() > pose.total_residue() || it->res2() > pose.total_residue() ) {
610  tr.Warning << "non-existing residue, ignore RDC" << *it << std::endl;
611  continue;
612  }
613  if ((ft.is_cutpoint(std::min((int) it->res1(), (int) it->res2())))
614  && it->res1() != it->res2()) {
615  tr.Warning << "cutpoint: ignore RDC " << *it << std::endl;
616  continue;
617  }
618  if ( it->res1() == 1 || it->res2() == 1 ) {
619  tr.Warning << "residue 1, always problematic with 1H vs H, just ignore RDC" << std::endl;
620  continue;
621  }
622 
623 
624  ++irow;
625  Size const d(irow - 1);
626 
627  ex = it->expid();
628 
629  Real computed_coupling = it->Jdipolar_computed_ = S_[ex][0][0] * D_[d][0] + S_[ex][0][1] * D_[d][1] + S_[ex][0][2] * D_[d][2] + S_[ex][1][1] * D_[d][3] + S_[ex][1][2] * D_[d][4];
630 
631  // pfac = fc*ip[type].orires.c*invr2;
632  //for(i=0; i<power; i++)
633  // pfac *= invr;
634  //Size const power(3); //this will be 0 for CSA see above
635  RDC& rdc = *it;
636  numeric::xyzVector<Real> r( pose.residue(rdc.res1()).atom(rdc.atom1()).xyz() - pose.residue(rdc.res2()).atom(rdc.atom2()).xyz());
637  core::Real r2 = r.norm_squared();
638  core::Real invr = 1.0 / sqrt(r2);
639  core::Real invr2 = sqr(invr);
640  Real obs = it->Jdipolar();
641  Real dev = computed_coupling - obs;
642  Real weight = it->weight()*Smax[ex]; //force constant
643 
644  //compute derivatives
645  //prefactor used in derivative calculations
646  core::Real pfac = weight* rdc.Dconst() * invr2 * invr;
647  core::Real const pfac_NH = weight * 36.5089/1.041/1.041/1.041;
648 
649  if (bReduced) {
650  if ( tr.Trace.visible() ) tr.Trace << "reducing coupling for " << rdc << " dev: " << dev
651  << " pfac: " << pfac << " pfac_NH " << pfac_NH;
652  pfac = pfac_NH;
653  dev *= pfac_NH / pfac;
654  obs *= pfac_NH / pfac;
655  if ( tr.Trace.visible() ) tr.Trace << " new dev: " << dev << std::endl;
656  }
657 
658 // rvec Sr;
659 // rvec rgmx;
660 // rgmx[0] = r[0];
661 // rgmx[1] = r[1];
662 // rgmx[2] = r[2];
663 // mvmul(S_[ex], rgmx, Sr);
664 // for (Size i = 0; i < 3; i++) {
665 // rdc.fij_[i] = -pfac * dev * (4* Sr [i] - 2* (2 + power ) * invr2 * iprod (Sr ,rgmx) * rgmx[ i]);
666 // }
667  rdc.fij_[0]= -dev * pfac * (S_[ex][0][0]*2*r.x()+S_[ex][0][1]*2*r.y()+S_[ex][0][2]*2*r.z()+S_[ex][1][1]*0+S_[ex][1][2]*0);
668  rdc.fij_[1]= -dev * pfac * (S_[ex][0][0]*0+S_[ex][0][1]*2*r.x()+S_[ex][0][2]*0+S_[ex][1][1]*2*r.y()+S_[ex][1][2]*2*r.z());
669  rdc.fij_[2]= -dev * pfac * (-S_[ex][0][0]*2*r.z()+S_[ex][0][1]*0+S_[ex][0][2]*2*r.x()-S_[ex][1][1]*2*r.z()+S_[ex][1][2]*2*r.y());
670 
671  //compute size for each experiment and normalize energy by size
672 /*
673  if (ex==exold) {
674  excnt++;
675  } else {
676  vtot=vtot+vtoti/excnt;
677  vtoti=0;
678  excnt=1;
679  }
680  exold = ex;
681 */
682 
683  //compute contribution from one ex
684  // std::cout << "WEIGHT " << weight <<std::endl;
685  //(36.5089/1.041/1.041/1.041) is the Dcnst_NH/1.041^3
686  vtot += 0.5*sqr( dev )*weight;
687  //vtoti += 0.5*sqr( dev )*Smax[ex];
688  //vtoti += 0.5*sqr( dev )*Smax[ex]/( EV_[ex][0]/2*(36.5089/1.041/1.041/1.041)*EV_[ex][0]/2*(36.5089/1.041/1.041/1.041)); //weight by Da
689  //vtoti += 0.5*sqr( dev )*Smax[ex]/( EV_[ex][0]/2*pfac*EV_[ex][0]/2*pfac); //weight by Da
690  wsv2 += weight*sqr(dev);
691  sw += weight;
692  Q += sqr( dev );
693  Qnorm += sqr( obs );
694 
695  }
696  //compute size for each experiment and normalize energy by size
697  //vtot=vtot+vtoti/excnt;
698 
699  R_ = sqrt( Q/Qnorm/2 );
700  rmsd_ = sqrt(wsv2/sw);
701 
702  // /* Rotate the S matrices back, so we get the correct grad(tr(S D)) */
703  // for(ex=0; ex<od->nex; ex++) {
704  // tmmul(R,S_[ex],TMP);
705  // mmul(TMP,R,S_[ex]);
706  // }
707  //this is a factor that brings the score roughly back in the range where it was
708  //with the old implementation: i.e., norm by Azz*Azz and deviation of "reduced" couplings instead of the real ones.
709  //std::cout << "DEV_TOT " << vtot <<std::endl;
710 
711  using namespace basic::options;
712  using namespace basic::options::OptionKeys;
713  using namespace ObjexxFCL;
714  using namespace ObjexxFCL::fmt;
715  if ( option[ OptionKeys::rdc::print_rdc_values ].user() ) {
716  std::string filename( option[ OptionKeys::rdc::print_rdc_values ]() );
717  utility::io::ozstream out;
718 
719  out.open_append( filename ) ;
720  using namespace core::pose::datacache;
721  //Size const width( 8 );
722  //Size const width_large(6);
723  // mjo comment out precision because it is not used and causes a warning.
724  //Size const precision( 2 );
726  for (Size ex = 0; ex < nex_; ex++) {
727  //Real Smax = sqrt(sqr(S_[ex][0][0]) + sqr(S_[ex][0][1]) + sqr(S_[ex][0][2]) + sqr(S_[ex][1][1]) + sqr(S_[ex][1][2]));
728  //out << A( width_large, "TAG ") << A( width, tag ) << A( width, "EXP ") << I( width, ex ) << I( width, Smax )
729  // << I( width, vtot )<< I( width, Rohl2Hess )<< std::endl;
730  show_tensor_stats( out, ex );
731  show_tensor_matrix( out, ex );
732  show_rdc_values( out, ex );
733  }
734  out << "//" <<std::endl;
735  out.close();
736  //std::cout << "RDC values " << obs << ' ' << computed_coupling <<std::endl;
737  }
738 
739  return vtot;
740 }//end of compute_dipscore
741 
742 //added by LS Aug 2011
743 //Auxillary functions for compute_dipscore_nls
744 double frdc( double r0, double r1, double r2, double rdcconst, const double *par)
745 {
746  double Ax=par[0];
747  double Ay=par[1];
748  double Az=-par[0]-par[1];
749 //use radius instead
750  double a=par[2];
751  double b=par[3];
752  double c=par[4];
753  double rdcx=0.0,rdcy=0.0,rdcz=0.0;
754  rdcx = cos(b)*cos(c)*r0+(-cos(a)*sin(c)+sin(a)*sin(b)*cos(c))*r1+(sin(a)*sin(c)+cos(a)*sin(b)*cos(c))*r2;
755  rdcy = cos(b)*sin(c)*r0+(cos(a)*cos(c)+sin(a)*sin(b)*sin(c))*r1+(-sin(a)*cos(c)+cos(a)*sin(b)*sin(c))*r2;
756  rdcz = -sin(b)*r0+sin(a)*cos(b)*r1+cos(a)*cos(b)*r2;
757  return rdcconst*(rdcx*rdcx*Ax+rdcy*rdcy*Ay+rdcz*rdcz*Az);
758 }//frdc
759 
760 double frdcDa( double r0, double r1, double r2, double rdcconst, double const tensorDa, const double *par)
761 {
762  double Ax=(3.0*par[0]/2.0-1.0)*tensorDa/(36.5089/1.041/1.041/1.041);
763  double Ay=-(3.0*par[0]/2.0+1.0)*tensorDa/(36.5089/1.041/1.041/1.041);
764  double Az=2.0*tensorDa/(36.5089/1.041/1.041/1.041);
765 //use radius instead
766  double a=par[1];
767  double b=par[2];
768  double c=par[3];
769  double rdcx=0.0,rdcy=0.0,rdcz=0.0;
770  rdcx = cos(b)*cos(c)*r0+(-cos(a)*sin(c)+sin(a)*sin(b)*cos(c))*r1+(sin(a)*sin(c)+cos(a)*sin(b)*cos(c))*r2;
771  rdcy = cos(b)*sin(c)*r0+(cos(a)*cos(c)+sin(a)*sin(b)*sin(c))*r1+(-sin(a)*cos(c)+cos(a)*sin(b)*sin(c))*r2;
772  rdcz = -sin(b)*r0+sin(a)*cos(b)*r1+cos(a)*cos(b)*r2;
773  return rdcconst*(rdcx*rdcx*Ax+rdcy*rdcy*Ay+rdcz*rdcz*Az);
774 }//frdcDa
775 
776 double frdcR( double r0, double r1, double r2, double rdcconst, double const tensorR, const double *par)
777 {
778  double Ax=(3.0*tensorR/2.0-1.0)*par[0]/(36.5089/1.041/1.041/1.041);
779  double Ay=-(3.0*tensorR/2.0+1.0)*par[0]/(36.5089/1.041/1.041/1.041);
780  double Az=2.0*par[0]/(36.5089/1.041/1.041/1.041);
781 //use radius instead
782  double a=par[1];
783  double b=par[2];
784  double c=par[3];
785  double rdcx=0.0,rdcy=0.0,rdcz=0.0;
786  rdcx = cos(b)*cos(c)*r0+(-cos(a)*sin(c)+sin(a)*sin(b)*cos(c))*r1+(sin(a)*sin(c)+cos(a)*sin(b)*cos(c))*r2;
787  rdcy = cos(b)*sin(c)*r0+(cos(a)*cos(c)+sin(a)*sin(b)*sin(c))*r1+(-sin(a)*cos(c)+cos(a)*sin(b)*sin(c))*r2;
788  rdcz = -sin(b)*r0+sin(a)*cos(b)*r1+cos(a)*cos(b)*r2;
789  return rdcconst*(rdcx*rdcx*Ax+rdcy*rdcy*Ay+rdcz*rdcz*Az);
790 }//frdcR
791 
792 double frdcDaR( double r0, double r1, double r2, double rdcconst, double const tensorDa, double const tensorR, const double *par)
793 {
794  double Ax=(3.0*tensorR/2.0-1.0)*tensorDa/(36.5089/1.041/1.041/1.041);
795  double Ay=-(3.0*tensorR/2.0+1.0)*tensorDa/(36.5089/1.041/1.041/1.041);
796  double Az=2.0*tensorDa/(36.5089/1.041/1.041/1.041);
797 //use radius instead
798  double a=par[0];
799  double b=par[1];
800  double c=par[2];
801  double rdcx=0.0,rdcy=0.0,rdcz=0.0;
802  rdcx = cos(b)*cos(c)*r0+(-cos(a)*sin(c)+sin(a)*sin(b)*cos(c))*r1+(sin(a)*sin(c)+cos(a)*sin(b)*cos(c))*r2;
803  rdcy = cos(b)*sin(c)*r0+(cos(a)*cos(c)+sin(a)*sin(b)*sin(c))*r1+(-sin(a)*cos(c)+cos(a)*sin(b)*sin(c))*r2;
804  rdcz = -sin(b)*r0+sin(a)*cos(b)*r1+cos(a)*cos(b)*r2;
805  return rdcconst*(rdcx*rdcx*Ax+rdcy*rdcy*Ay+rdcz*rdcz*Az);
806 }//frdcDaR
807 
808 /* data structure to transmit model data to function evalution */
809 typedef struct {
810  double *r0, *r1, *r2;
811  double *rdc;
812  double *rdcconst;
813  double *rdcweight;
814  double (*frdc)( double r0, double r1, double r2, double rdcconst, const double *par );
815 } data_struct;
816 
817 typedef struct {
818  double *r0, *r1, *r2;
819  double *rdc;
820  double *rdcconst;
821  double *rdcweight;
822  double const tensorDa;
823  double (*frdcDa)( double r0, double r1, double r2, double rdcconst, double const tensorDa, const double *par );
824 } data_structDa;
825 
826 typedef struct {
827  double *r0, *r1, *r2;
828  double *rdc;
829  double *rdcconst;
830  double *rdcweight;
831  double const tensorR;
832  double (*frdcR)( double r0, double r1, double r2, double rdcconst, double const tensorR, const double *par );
833 } data_structR;
834 
835 typedef struct {
836  double *r0, *r1, *r2;
837  double *rdc;
838  double *rdcconst;
839  double *rdcweight;
840  double const tensorDa;
841  double const tensorR;
842  double (*frdcDaR)( double r0, double r1, double r2, double rdcconst, double const tensorDa, double const tensorR, const double *par );
844 
845 //Evaluaterdc function required by lmmin
846 void evaluaterdc(const double *par, int m_dat, const void *data, double *fvec, int * ) {
847  data_struct *mydata;
848  mydata= (data_struct*)data;
849  int i;
850  for ( i = 0; i < m_dat; i++ ) {
851  fvec[i] = ( mydata->rdc[i] - mydata->frdc( mydata->r0[i], mydata->r1[i],mydata->r2[i],mydata->rdcconst[i], par ))*sqrt(mydata->rdcweight[i]);
852  }
853 }//evaluaterdc
854 
855 void evaluaterdcDa(const double *par, int m_dat, const void *data, double *fvec, int * ) {
856  data_structDa *mydata;
857  mydata= (data_structDa*)data;
858  int i;
859  for ( i = 0; i < m_dat; i++ ) {
860  fvec[i] = (mydata->rdc[i] - mydata->frdcDa( mydata->r0[i], mydata->r1[i],mydata->r2[i],mydata->rdcconst[i],mydata->tensorDa, par ))*sqrt(mydata->rdcweight[i]);
861  }
862 }//evaluaterdcDa
863 
864 void evaluaterdcR(const double *par, int m_dat, const void *data, double *fvec, int * ) {
865  data_structR *mydata;
866  mydata= (data_structR*)data;
867  int i;
868  for ( i = 0; i < m_dat; i++ ) {
869  fvec[i] = (mydata->rdc[i] - mydata->frdcR( mydata->r0[i], mydata->r1[i],mydata->r2[i],mydata->rdcconst[i],mydata->tensorR, par ))*sqrt(mydata->rdcweight[i]);
870  }
871 }//evaluaterdcR
872 
873 void evaluaterdcDaR(const double *par, int m_dat, const void *data, double *fvec, int * ) {
874  data_structDaR *mydata;
875  mydata= (data_structDaR*)data;
876  int i;
877  for ( i = 0; i < m_dat; i++ ) {
878  fvec[i] = (mydata->rdc[i] - mydata->frdcDaR( mydata->r0[i], mydata->r1[i],mydata->r2[i],mydata->rdcconst[i],mydata->tensorDa,mydata->tensorR, par ))*sqrt(mydata->rdcweight[i]);
879  }
880 }//evaluaterdcDaR
881 
882 //Interface lmmin with compute_dipscore_nls
884  if ( nex_ == 0 || nrows_ == 0 ) return 0;
885 
886  //non-linear square fitting of RDC data
888  bool const correct_NH( basic::options::option[basic::options::OptionKeys::rdc::correct_NH_length]);
889  core::Size nrow(0);
890  core::Size id(0);
891  core::Real obs(0.0);
892 
893  //initialize the cnt
894  for (id = 0; id < nex_+1; id++) {
895  lenex_[id]=0;
896  }
897  id=0;
898 
899  core::Real scale_to_NH = 36.5089/1.041/1.041/1.041;
900 
901  for (it = All_RDC_lines_.begin(); it != All_RDC_lines_.end(); ++it) {
902  if ( it->res1() > pose.total_residue() || it->res2() > pose.total_residue() ) {
903  if ( tr.Debug.visible() ) tr.Debug << "non-existing residue, ignore RDC" << std::endl;
904  continue;
905  }
906 
907  //check for cutpoints!!!
908  kinematics::FoldTree const& ft(pose.fold_tree());
909  if ((ft.is_cutpoint(std::min((int) it->res1(), (int) it->res2()))) && it->res1() != it->res2()) {
910  if ( tr.Trace.visible() ) tr.Trace << "cutpoint: ignore RDC " << *it << std::endl;
911  continue;
912  }
913 
914  ++nrow;
915  numeric::xyzVector<Real> r(pose.residue(it->res1()).atom(it->atom1()).xyz() - pose.residue(it->res2()).atom(it->atom2()).xyz());
916 
917 
918  core::Real r2 = r.norm_squared();
919  core::Real invr = 1.0 / sqrt(r2);
920 
921  //tr.Trace << " invr before correction: " << invr << std::endl;
922 
923  if ( correct_NH ) {
924  scale_to_NH = 36.5089/1.041/1.041/1.041;
925  if ( it->type() == RDC::RDC_TYPE_NH && std::abs((int) it->res1()-(int) it->res2())==0 ) {
926  r.normalize(1.041);
927  r2 = r.norm_squared();
928  invr = 1.0 / sqrt(r2);
929  } else if ( it->type() == RDC::RDC_TYPE_NC && std::abs((int) it->res1()-(int) it->res2())==1 ) {
930  r.normalize(1.329);
931  r2 = r.norm_squared();
932  invr = 1.0 / sqrt(r2);
933  } else if ( it->type() == RDC::RDC_TYPE_CH && std::abs((int) it->res1()-(int) it->res2())==0 ) {
934  r.normalize(1.107);
935  r2 = r.norm_squared();
936  invr = 1.0 / sqrt(r2);
937  } else if ( it->type() == RDC::RDC_TYPE_CC && std::abs((int) it->res1()-(int) it->res2())==0 ) {
938  r.normalize(1.525);
939  r2 = r.norm_squared();
940  invr = 1.0 / sqrt(r2);
941  } else {
942  tr.Error << "unreognized type or residue sequence separation does not allow using correct_NH" << std::endl;
943  throw( utility::excn::EXCN_BadInput("unreognized type or residue sequence separation does not allow using correct_NH "));
944  }
945  }//end of correct_NH
946 
947 
948  core::Real pfac = it->Dconst();
949  bool bCSA(false);// hook up for later... to compute chemical shift anisotropy
950  if (!bCSA) {
951  pfac *= invr * invr * invr;
952  }
953 
954 
955  //check the -1 if it is correct
956  id = All_RDC_lines_[nrow].expid();
957  //scale rdcs accordingly
958  obs = All_RDC_lines_[nrow].Jdipolar()*(scale_to_NH)/pfac;
959 
960  //tr.Trace << " invr after correction: " << invr << std::endl;
961  //tr.Trace << " scaling: " << (scale_to_NH)/pfac << " original: " << All_RDC_lines_[nrow].Jdipolar() << " after " << obs << std::endl;
962 
963  r0_[nrow-1] = r.normalized().x();
964  r1_[nrow-1] = r.normalized().y();
965  r2_[nrow-1] = r.normalized().z();
966  rdcconst_[nrow-1]=scale_to_NH;
967  rdcweight_[nrow-1]=it->weight();
968  exprdc_[nrow-1]=obs;
969  lenex_[id+1]=lenex_[id+1]+1;
970  //tr.Trace << std::endl;
971  //tr.Trace << " it->res1(): "<< it->res1() << " it->res2(): " << it->res2() << std::endl;
972  //tr.Trace << " r0_[nrow-1]: "<< r0_[nrow-1] << " r1_[nrow-1]: "<< r1_[nrow-1] << " r2_[nrow-1]: "<< r2_[nrow-1] << std::endl;
973  //tr.Trace << " it->Dconst(): "<< it->Dconst() << " r2: " << r2 << " invr " << invr << std::endl;
974  //tr.Trace << "rdcconst_[" << nrow-1 << "]= " << rdcconst_[nrow-1] << " it->Dconst(): "<< it->Dconst() << " invr " <<invr<<std::endl;
975  //tr.Trace << "it->Jdipolar()" << All_RDC_lines_[nrow].Jdipolar() << "scaled obs"<<obs<<std::endl;
976  //tr.Trace << "it->weight()" << it->weight() << std::endl;
977  } //cycle over atoms
978 
979 
980  //parameters
981  int n_par = 5; // number of parameters in model function frdc
982  int nrepeat = 5; // number of repeat lmfit
983 
984  //double parbest[n_par*nex_];
985  std::vector<double> parbest(n_par*nex_);
986 
987  //double par[n_par*nex_];
988  std::vector<double> par(n_par*nex_);
989 
990  int i,j;
991  double bestnorm;
992  Size prelen=0;
993 
994  //optional weighting provided by user
995  runtime_assert( nex_ < 200 );
996  Real Smax[200];
997 
998  //experimental data array
999  for (Size ex = 0; ex < nex_; ex++) {
1000 
1001  //compute the length of previous exps
1002  prelen=0;
1003  for (Size cnt=0; cnt<=ex; cnt++) {
1004  prelen+=lenex_[cnt];
1005  }
1006 
1007  //perform lmfit on each exp
1008  data_struct data = { r0_+prelen, r1_+prelen, r2_+prelen, exprdc_+prelen, rdcconst_+prelen, rdcweight_+prelen, frdc};
1009  //definition of auxiliary parameters
1010  numeric::nls::lm_status_struct status;
1011 
1012  Smax[ex] = 1;
1013  {
1014  using namespace basic::options;
1015  if ( option[ OptionKeys::rdc::fix_normAzz ].user() ) {
1016  if ( option[ OptionKeys::rdc::fix_normAzz ]().size() != nex_ ) {
1017  utility_exit_with_message("fix_normAzz must have one value for each alignment medium !");
1018  }
1019  Smax[ ex ] = option[ OptionKeys::rdc::fix_normAzz ]()[ ex+1 ];
1020  }
1021  }
1022 
1023  bestnorm=1e12;
1024 
1025  for (j = 0; j < nrepeat; j++) {
1026  //random starting value
1027  par[ex*n_par+0]=numeric::random::uniform();//Ax
1028  par[ex*n_par+1]=numeric::random::uniform();//Ay
1029  par[ex*n_par+2]=2.0*numeric::NumericTraits<Real>::pi()*numeric::random::uniform();//alpha
1030  par[ex*n_par+3]=2.0*numeric::NumericTraits<Real>::pi()*numeric::random::uniform();//beta
1031  par[ex*n_par+4]=2.0*numeric::NumericTraits<Real>::pi()*numeric::random::uniform();//gamma
1032  //call lmmin
1033  numeric::nls::lmmin( n_par, &par[ex*n_par], lenex_[ex+1], (const void*) &data, evaluaterdc, &status,numeric::nls::lm_printout_std);
1034  if ( tr.Trace.visible() ) {
1035  tr.Trace << std::endl;
1036  tr.Trace << "Iteration: " << j << "status.fnorm:" << status.fnorm << "bestnorm: "<< bestnorm << std::endl;
1037  }
1038  //save to best fitting parameter
1039  if (status.fnorm < bestnorm) {
1040  bestnorm=status.fnorm;
1041  for (i=0; i<n_par ; i++)
1042  parbest[ex*n_par+i]=par[ex*n_par+i];
1043  }
1044  }//repeat lmfit five times with different starting parameters
1045 
1046  //copy back to par only if there is a good fitting
1047  for (i=0; i<n_par ; i++)
1048  par[ex*n_par+i]=parbest[ex*n_par+i];
1049 
1050  //test
1051  //for (i=0; i<n_par ; i++)
1052  // tr.Trace << "debug par[" << ex*n_par+i << "]: " << par[ex*n_par+i] << std::endl;
1053 
1054  double Ax;
1055  double Ay;
1056  //sort the right order Ax<Ay and calculate Da and R
1057  if (parbest[ex*n_par+0]>0) {
1058  if (parbest[ex*n_par+1]>0) {
1059  if (parbest[ex*n_par+0]<parbest[ex*n_par+1]) {
1060  Ax=parbest[ex*n_par+0];
1061  Ay=parbest[ex*n_par+1];
1062  }else {
1063  Ax=parbest[ex*n_par+1];
1064  Ay=parbest[ex*n_par+0];
1065  }
1066  }else {
1067  if (parbest[ex*n_par+0]<-parbest[ex*n_par+1]) {
1068  Ax=std::min(parbest[ex*n_par+0],-parbest[ex*n_par+1]-parbest[ex*n_par+0]);
1069  Ay=std::max(parbest[ex*n_par+0],-parbest[ex*n_par+1]-parbest[ex*n_par+0]);
1070  }else {
1071  Ax=std::max(parbest[ex*n_par+1],-parbest[ex*n_par+1]-parbest[ex*n_par+0]);
1072  Ay=std::min(parbest[ex*n_par+1],-parbest[ex*n_par+1]-parbest[ex*n_par+0]);
1073  }
1074  }
1075  } else {
1076  if (parbest[ex*n_par+1]>0) {
1077  if (-parbest[ex*n_par+0]<parbest[ex*n_par+1]) {
1078  Ax=std::max(parbest[ex*n_par+0],-parbest[ex*n_par+1]-parbest[ex*n_par+0]);
1079  Ay=std::min(parbest[ex*n_par+0],-parbest[ex*n_par+1]-parbest[ex*n_par+0]);
1080  }else{
1081  Ax=std::min(parbest[ex*n_par+1],-parbest[ex*n_par+1]-parbest[ex*n_par+0]);
1082  Ay=std::max(parbest[ex*n_par+1],-parbest[ex*n_par+1]-parbest[ex*n_par+0]);
1083  }
1084  }else{
1085  if (parbest[ex*n_par+0]<parbest[ex*n_par+1]) {
1086  Ax=parbest[ex*n_par+1];
1087  Ay=parbest[ex*n_par+0];
1088  }else {
1089  Ax=parbest[ex*n_par+0];
1090  Ay=parbest[ex*n_par+1];
1091  }
1092  }
1093  }
1094  //store in the temporarily in parbest
1095  parbest[ex*n_par+0]=1.0/2.0*(-Ax-Ay);
1096  parbest[ex*n_par+1]=2.0/3.0*(Ay-Ax)/(Ax+Ay);
1097 
1098  if ( tr.Trace.visible() ) {
1099  //debug
1100  tr.Trace << std::endl;
1101  tr.Trace << "ex: " << ex << std::endl;
1102  tr.Trace << "Ax: " << Ax << std::endl;
1103  tr.Trace << "Ay: " << Ay << std::endl;
1104  tr.Trace << "alpha: " << par[ex*n_par+2]*180/numeric::NumericTraits<Real>::pi()<< std::endl;
1105  tr.Trace << "beta: " << par[ex*n_par+3]*180/numeric::NumericTraits<Real>::pi()<< std::endl;
1106  tr.Trace << "gamma:" << par[ex*n_par+4]*180/numeric::NumericTraits<Real>::pi()<< std::endl;
1107  tr.Trace << "Da:" << 1.0/2.0*(-Ax-Ay)*(36.5089/1.041/1.041/1.041)<< std::endl;
1108  tr.Trace << "R:" << 2.0/3.0*(Ay-Ax)/(Ax+Ay)<< std::endl;
1109  tr.Trace << "norm:" << bestnorm<<std::endl;
1110  tr.Trace << "Pales Da:" << 3.0/4.0*(-Ax-Ay)<< std::endl;
1111  tr.Trace << "Pales Dr:" << 1.0/2.0*(Ax-Ay)<< std::endl;
1112  }
1113  }//end of loop through all exps
1114 
1115  //compute scores and other stats for all exps
1116  Real wsv2 = 0;
1117  Real sw = 0;
1118  Real vtot = 0;
1119  Real Q = 0;
1120  Real Qex = 0;
1121  //Real Qexunscale = 0;
1122  Real Qnorm = 0;
1123 
1124  Size irow(0);
1125  for (utility::vector1<core::scoring::RDC>::iterator it = All_RDC_lines_.begin(); it != All_RDC_lines_.end(); ++it) {
1126 
1127  Size ex = it->expid();
1128 
1129  //tr.Trace << "ex: " << ex << " lenex_[ex+1]: " << lenex_[ex+1] <<std::endl;
1130 
1131  //compute the length of previous exps
1132  prelen=0;
1133  for (Size cnt=0; cnt<=ex; cnt++) {
1134  prelen+=lenex_[cnt];
1135  }
1136 
1137  Real computed_coupling = frdc(r0_[prelen+irow], r1_[prelen+irow], r2_[prelen+irow], rdcconst_[prelen+irow], &par[ex*n_par]);
1138 
1139  //compute derivatives
1140  RDC& rdc = *it;
1141  numeric::xyzVector<Real> r( pose.residue(rdc.res1()).atom(rdc.atom1()).xyz() - pose.residue(rdc.res2()).atom(rdc.atom2()).xyz());
1142  numeric::xyzVector<Real> r_copy( pose.residue(rdc.res1()).atom(rdc.atom1()).xyz() - pose.residue(rdc.res2()).atom(rdc.atom2()).xyz());
1143  core::Real r2 = r.norm_squared();
1144  core::Real invr = 1.0 / sqrt(r2);
1145 
1146  if ( correct_NH ) {
1147  if ( it->type() == RDC::RDC_TYPE_NH && std::abs((int) it->res1()-(int) it->res2())==0 ) {
1148  r.normalize(1.041);
1149  r2 = r.norm_squared();
1150  invr = 1.0 / sqrt(r2);
1151  } else if ( it->type() == RDC::RDC_TYPE_NC && std::abs((int) it->res1()-(int) it->res2())==1 ) {
1152  r.normalize(1.329);
1153  r2 = r.norm_squared();
1154  invr = 1.0 / sqrt(r2);
1155  } else if ( it->type() == RDC::RDC_TYPE_CH && std::abs((int) it->res1()-(int) it->res2())==0 ) {
1156  r.normalize(1.107);
1157  r2 = r.norm_squared();
1158  invr = 1.0 / sqrt(r2);
1159  } else if ( it->type() == RDC::RDC_TYPE_CC && std::abs((int) it->res1()-(int) it->res2())==0 ) {
1160  r.normalize(1.525);
1161  r2 = r.norm_squared();
1162  invr = 1.0 / sqrt(r2);
1163  } else {
1164  tr.Error << "unreognized type or residue sequence separation does not allow using correct_NH" << std::endl;
1165  throw( utility::excn::EXCN_BadInput("unreognized type or residue sequence separation does not allow using correct_NH "));
1166  }
1167  }//end of correct_NH
1168 
1169  core::Real invr2 = sqr(invr);
1170 
1171  //prefactor used in derivative calculations
1172  Real weight = it->weight()*Smax[ex]; //force constant
1173  //core::Real pfac = scale_to_NH*invr2* weight;
1174  core::Real pfac = scale_to_NH*(1/r.length())*(1/r_copy.length())*weight;
1175  Real obs = rdc.Jdipolar()*(scale_to_NH)/(rdc.Dconst() * invr2 * invr);
1176  Real dev = computed_coupling - obs;
1177  //scale Jdipolar_computed_ back
1178  it->Jdipolar_computed_ = computed_coupling/((scale_to_NH)/(rdc.Dconst() * invr2 * invr));
1179 
1180  //parameters after fitting
1181  core::Real Axx=par[ex*n_par+0];
1182  core::Real Ayy=par[ex*n_par+1];
1183  core::Real Azz=-par[ex*n_par+0]-par[ex*n_par+1];
1184  core::Real a=par[ex*n_par+2];
1185  core::Real b=par[ex*n_par+3];
1186  core::Real c=par[ex*n_par+4];
1187  //rotation matrix
1188  core::Real r00=cos(b)*cos(c);
1189  core::Real r01=-cos(a)*sin(c)+sin(a)*sin(b)*cos(c);
1190  core::Real r02=sin(a)*sin(c)+cos(a)*sin(b)*cos(c);
1191  core::Real r10=cos(b)*sin(c);
1192  core::Real r11=cos(a)*cos(c)+sin(a)*sin(b)*sin(c);
1193  core::Real r12=-sin(a)*cos(c)+cos(a)*sin(b)*sin(c);
1194  core::Real r20=-sin(b);
1195  core::Real r21=sin(a)*cos(b);
1196  core::Real r22=cos(a)*cos(b);
1197  //projects in the PAF
1198  core::Real rx=r00*r.x()+r01*r.y()+r02*r.z();
1199  core::Real ry=r10*r.x()+r11*r.y()+r12*r.z();
1200  core::Real rz=r20*r.x()+r21*r.y()+r22*r.z();
1201  rdc.fij_[0] = - dev * pfac * 2 * (Axx*rx*r00+Ayy*ry*r10+Azz*rz*r20) ;
1202  rdc.fij_[1] = - dev * pfac * 2 * (Axx*rx*r01+Ayy*ry*r11+Azz*rz*r21);
1203  rdc.fij_[2] = - dev * pfac * 2 * (Axx*rx*r02+Ayy*ry*r12+Azz*rz*r22) ;
1204 
1205  //rdc.fij_[0] = - dev * (rdc.Dconst() * (2*Axx*rx*r00+2*Ayy*ry*r10+2*Azz*rz*r20) * r2 * r2 * r
1206  // - rdc.Dconst() * (Axx*rx*rx+Ayy*ry*ry+Azz*rz*rz) * 5 * r2 *r2 )/ (r2*r2*r2*r2*r2) ;
1207  //rdc.fij_[1] = - dev * (rdc.Dconst() * (2*Axx*rx*r01+2*Ayy*ry*r11+2*Azz*rz*r21) * r2 * r2 * r
1208  // - rdc.Dconst() * (Axx*rx*rx+Ayy*ry*ry+Azz*rz*rz) * 5 * r2 *r2 )/ (r2*r2*r2*r2*r2) ;
1209  //rdc.fij_[2] = - dev * (rdc.Dconst() * (2*Axx*rx*r02+2*Ayy*ry*r12+2*Azz*rz*r22) * r2 * r2 * r
1210  // - rdc.Dconst() * (Axx*rx*rx+Ayy*ry*ry+Azz*rz*rz) * 5 * r2 *r2 )/ (r2*r2*r2*r2*r2) ;
1211 
1212 
1213  //compute energy
1214  vtot += 0.5*sqr( dev )*weight;
1215 
1216  //vtot += 0.5*sqr( dev )*Smax[ex]/(lenex_[ex+1]);
1217  //vtot += 0.5*sqr( dev )*Smax[ex]/( parbest[ex*n_par+0]*(36.5089/1.041/1.041/1.041)* parbest[ex*n_par+0] *(36.5089/1.041/1.041/1.041)* lenex_[ex+1]);
1218  //vtot += 0.5*sqr( dev )*Smax[ex]/( parbest[ex*n_par+0]*rdcconst_[prelen+irow] * parbest[ex*n_par+0] *rdcconst_[prelen+irow] * lenex_[ex+1]);
1219 
1220  //tr.Trace << "debug ex: " << ex << " lenex_[ex] " << lenex_[ex] << " irow " << irow <<std::endl;
1221  //tr.Trace << "debug prelen+irow: " << prelen+irow << std::endl;
1222  //tr.Trace << "debug computed: " << computed_coupling << std::endl;
1223  //tr.Trace << "debug obs: " << obs << std::endl;
1224  //tr.Trace << "debug dev: " << dev << " Smax[ex] " << Smax[ex] << std::endl;
1225  //tr.Trace << "debug par[ex*n_par+0]=Axx= " << par[ex*n_par+0] << " rdcconst_[prelen+irow] " << rdcconst_[prelen+irow] << std::endl;
1226  //tr.Trace << "debug par[ex*n_par+1]=Ayy= " << par[ex*n_par+1] << " rdcconst_[prelen+irow] " << rdcconst_[prelen+irow] << std::endl;
1227  //tr.Trace << "debug par[ex*n_par+2]=a= " << par[ex*n_par+2] << " rdcconst_[prelen+irow] " << rdcconst_[prelen+irow] << std::endl;
1228  //tr.Trace << "debug par[ex*n_par+3]=b= " << par[ex*n_par+3] << " rdcconst_[prelen+irow] " << rdcconst_[prelen+irow] << std::endl;
1229  //tr.Trace << "debug par[ex*n_par+4]=c= " << par[ex*n_par+4] << " rdcconst_[prelen+irow] " << rdcconst_[prelen+irow] << std::endl;
1230  //tr.Trace << "debug lenex_[ex+1]: " << lenex_[ex+1] << std::endl;
1231  //tr.Trace << "debug Dconst: " << rdc.Dconst() << std::endl;
1232  //tr.Trace << "debug r.x(): " << r.x() << std::endl;
1233  //tr.Trace << "debug r.y(): " << r.y() << std::endl;
1234  //tr.Trace << "debug r.z(): " << r.z() << std::endl;
1235  //tr.Trace << "debug fij_[0]: " << rdc.fij_[0] << std::endl;
1236  //tr.Trace << "debug fij_[1]: " << rdc.fij_[1] << std::endl;
1237  //tr.Trace << "debug fij_[2]: " << rdc.fij_[2] << std::endl;
1238  //tr.Trace << "debug weight: " << weight << std::endl;
1239  //tr.Trace << "debug vtot: " << vtot << std::endl;
1240 
1241  //vtot += 0.5*sqr( dev )*weight; //xweight if we want that
1242  // vtot += sqrt( dev );
1243 
1244 
1245  wsv2 += weight*sqr(dev);
1246  sw += weight;
1247  Q += sqr( dev );
1248  Qex +=sqr( dev );
1249  //Qexunscale +=sqr( dev )/((scale_to_NH)/(rdc.Dconst() * invr2 * invr))/((scale_to_NH)/(rdc.Dconst() * invr2 * invr));
1250  Qnorm += sqr( obs );
1251 
1252  //printout Qbax_ for each experiment
1253  if ( irow==lenex_[ex+1]-1 ) {
1254  if ( tr.Trace.visible() ) {
1255  tr.Trace << "ex: " << ex << " Qbax: " << sqrt(Qex/lenex_[ex+1])/sqrt(sqr(parbest[ex*n_par+0]*(36.5089/1.041/1.041/1.041))*(4+3*sqr(parbest[ex*n_par+1]))/5) << std::endl; //JACS 2003 125(30) 9179-9191 Table 2 lagend
1256  tr.Trace << "ex: " << ex << " rms: " << sqrt(Qex/lenex_[ex+1]) << std::endl;
1257  //tr.Trace << "ex: " << ex << " Qbax_2: " << sqrt(Qexunscale/lenex_[ex+1])/sqrt(sqr(parbest[ex*n_par+0]*(36.5089/1.041/1.041/1.041))*(4+3*sqr(parbest[ex*n_par+1]))/5) << std::endl; //JACS 2003 125(30) 9179-9191 Table 2 lagend
1258  //tr.Trace << "ex: " << ex << " rms_dc2: " << sqrt(Qexunscale/lenex_[ex+1]) << std::endl;
1259  }
1260  Qex=0;
1261  //Qexunscale =0;
1262  }
1263 
1264  //increament the array
1265  if (irow<lenex_[ex+1]-1) {
1266  irow++;
1267  } else {
1268  irow=0;
1269  }
1270 
1271 
1272  }
1273 
1274  R_ = sqrt( Q/Qnorm/2 );
1275  rmsd_ = sqrt(wsv2/sw);
1276 
1277  if ( tr.Trace.visible() ) {
1278  tr.Trace << "R_: " << R_ << std::endl;
1279  tr.Trace << "Q_: " << sqrt(2.)*R_ << std::endl;
1280  tr.Trace << "rmsd_: " << rmsd_ << std::endl;
1281  tr.Trace << "All_RDC_lines_.size(): " << All_RDC_lines_.size() << std::endl;
1282  }
1283 
1284  using namespace basic::options;
1285  using namespace basic::options::OptionKeys;
1286  using namespace ObjexxFCL;
1287  using namespace ObjexxFCL::fmt;
1288 
1289 //print the rdc values
1290  if ( option[ OptionKeys::rdc::print_rdc_values ].user() ) {
1291  std::string filename( option[ OptionKeys::rdc::print_rdc_values ]() );
1292  utility::io::ozstream out;
1293 
1294  out.open_append( filename ) ;
1295  using namespace core::pose::datacache;
1296  //Size const width( 8 );
1297  //Size const width_large(6);
1299  for (Size ex = 0; ex < nex_; ex++) {
1300  //show_tensor_stats_nls( out, ex, par);
1301  show_rdc_values( out, ex );
1302  }
1303  out << "//" <<std::endl;
1304  out.close();
1305  }
1306 
1307  return vtot;
1308 }//compute_dipscore_nls
1309 
1310 //Interface lmmin with compute_dipscore_nlsDa
1312  if ( nex_ == 0 || nrows_ == 0 ) return 0;
1313 
1314  //non-linear square fitting of RDC data
1316  bool const correct_NH( basic::options::option[basic::options::OptionKeys::rdc::correct_NH_length]);
1317  core::Size nrow(0);
1318  core::Size id(0);
1319  core::Real obs(0.0);
1320 
1321  //initialize the cnt
1322  for (id = 0; id < nex_+1; id++) {
1323  lenex_[id]=0;
1324  }
1325  id=0;
1326 
1327  core::Real scale_to_NH = 36.5089/1.041/1.041/1.041;
1328  for (it = All_RDC_lines_.begin(); it != All_RDC_lines_.end(); ++it) {
1329  if ( it->res1() > pose.total_residue() || it->res2() > pose.total_residue() ) {
1330  if ( tr.Debug.visible() ) tr.Debug << "non-existing residue, ignore RDC" << std::endl;
1331  continue;
1332  }
1333 
1334  //check for cutpoints!!!
1335  kinematics::FoldTree const& ft(pose.fold_tree());
1336  if ((ft.is_cutpoint(std::min((int) it->res1(), (int) it->res2()))) && it->res1() != it->res2()) {
1337  if ( tr.Trace.visible() ) tr.Trace << "cutpoint: ignore RDC " << *it << std::endl;
1338  continue;
1339  }
1340 
1341  ++nrow;
1342  numeric::xyzVector<Real> r( pose.residue(it->res1()).atom(it->atom1()).xyz() - pose.residue(it->res2()).atom(it->atom2()).xyz());
1343 
1344  core::Real r2 = r.norm_squared();
1345  core::Real invr = 1.0 / sqrt(r2);
1346 
1347  if ( correct_NH ) {
1348  scale_to_NH = 36.5089/1.041/1.041/1.041;
1349  if ( it->type() == RDC::RDC_TYPE_NH && std::abs((int) it->res1()-(int) it->res2())==0 ) {
1350  r.normalize(1.041);
1351  r2 = r.norm_squared();
1352  invr = 1.0 / sqrt(r2);
1353  } else if ( it->type() == RDC::RDC_TYPE_NC && std::abs((int) it->res1()-(int) it->res2())==1 ) {
1354  r.normalize(1.329);
1355  r2 = r.norm_squared();
1356  invr = 1.0 / sqrt(r2);
1357  } else if ( it->type() == RDC::RDC_TYPE_CH && std::abs((int) it->res1()-(int) it->res2())==0 ) {
1358  r.normalize(1.107);
1359  r2 = r.norm_squared();
1360  invr = 1.0 / sqrt(r2);
1361  } else if ( it->type() == RDC::RDC_TYPE_CC && std::abs((int) it->res1()-(int) it->res2())==0 ) {
1362  r.normalize(1.525);
1363  r2 = r.norm_squared();
1364  invr = 1.0 / sqrt(r2);
1365  } else {
1366  tr.Error << "unreognized type or residue sequence separation does not allow using correct_NH" << std::endl;
1367  throw( utility::excn::EXCN_BadInput("unreognized type or residue sequence separation does not allow using correct_NH "));
1368  }
1369  }//end of correct_NH
1370 
1371  core::Real pfac = it->Dconst();
1372  bool bCSA(false);// hook up for later... to compute chemical shift anisotropy
1373  if (!bCSA) {
1374  pfac *= invr * invr * invr;
1375  }
1376 
1377  //check the -1 if it is correct
1378  id = All_RDC_lines_[nrow].expid();
1379  obs = All_RDC_lines_[nrow].Jdipolar()*(scale_to_NH)/pfac;
1380 
1381  r0_[nrow-1] = r.normalized().x();
1382  r1_[nrow-1] = r.normalized().y();
1383  r2_[nrow-1] = r.normalized().z();
1384  rdcconst_[nrow-1]=scale_to_NH;
1385  exprdc_[nrow-1]=obs;
1386  rdcweight_[nrow-1]=it->weight();
1387  lenex_[id+1]=lenex_[id+1]+1;
1388  } //cycle over atoms
1389 
1390 
1391  //parameters
1392  int n_par = 4; // number of parameters in model function frdcDa
1393  int nrepeat = 5; // number of repeat lmfit
1394 
1395  //double parbest[n_par*nex_];
1396  std::vector<double> parbest(n_par*nex_);
1397 
1398  //double par[n_par*nex_];
1399  std::vector<double> par(n_par*nex_);
1400 
1401 
1402  int i,j;
1403  double bestnorm;
1404  Size prelen=0;
1405 
1406  //optional weighting provided by user
1407  runtime_assert( nex_ < 200 );
1408  Real Smax[200];
1409 
1410  //experimental data array
1411  for (Size ex = 0; ex < nex_; ex++) {
1412  //compute the length of previous exps
1413  prelen=0;
1414  for (Size cnt=0; cnt<=ex; cnt++) {
1415  prelen+=lenex_[cnt];
1416  }
1417 
1418  //perform lmfit on each exp
1419  data_structDa data = { r0_+prelen, r1_+prelen, r2_+prelen, exprdc_+prelen, rdcconst_+prelen,rdcweight_+prelen, tensorDa[ex+1], frdcDa};
1420  //definition of auxiliary parameters
1421  numeric::nls::lm_status_struct status;
1422 
1423  Smax[ex] = 1;
1424  {
1425  using namespace basic::options;
1426  if ( option[ OptionKeys::rdc::fix_normAzz ].user() ) {
1427  if ( option[ OptionKeys::rdc::fix_normAzz ]().size() != nex_ ) {
1428  utility_exit_with_message("fix_normAzz must have one value for each alignment medium !");
1429  }
1430  Smax[ ex ] = option[ OptionKeys::rdc::fix_normAzz ]()[ ex+1 ];
1431  }
1432  }
1433 
1434  bestnorm=1e12;
1435 
1436  for (j = 0; j < nrepeat; j++) {
1437  //random starting value
1438  par[ex*n_par+0]=numeric::random::uniform();//R
1439  par[ex*n_par+1]=2.0*numeric::NumericTraits<Real>::pi()*numeric::random::uniform();//alpha
1440  par[ex*n_par+2]=2.0*numeric::NumericTraits<Real>::pi()*numeric::random::uniform();//beta
1441  par[ex*n_par+3]=2.0*numeric::NumericTraits<Real>::pi()*numeric::random::uniform();//gamma
1442  //call lmmin
1443  numeric::nls::lmmin( n_par, &par[ex*n_par], lenex_[ex+1], (const void*) &data, evaluaterdcDa, &status,numeric::nls::lm_printout_std);
1444  if ( tr.Trace.visible() ) {
1445  tr.Trace << std::endl;
1446  tr.Trace << "Iteration: " << j << "status.fnorm:" << status.fnorm << "bestnorm: "<< bestnorm << std::endl;
1447  }
1448  //save to best fitting parameter
1449  if (status.fnorm < bestnorm) {
1450  bestnorm=status.fnorm;
1451  for (i=0; i<n_par ; i++)
1452  parbest[ex*n_par+i]=par[ex*n_par+i];
1453  }
1454  }//repeat lmfit five times with different starting parameters
1455  //copy back to par
1456  for (i=0; i<n_par ; i++)
1457  par[ex*n_par+i]=parbest[ex*n_par+i];
1458 
1459  //debug
1460  if ( tr.Trace.visible() ) {
1461  tr.Trace << std::endl;
1462  tr.Trace << "ex: " << ex << std::endl;
1463  tr.Trace << "Ax: " << (3.0*par[ex*n_par+0]/2.0-1.0)*tensorDa[ex+1]/(36.5089/1.041/1.041/1.041)<< std::endl;
1464  tr.Trace << "Ay: " << -(3.0*par[ex*n_par+0]/2.0+1.0)*tensorDa[ex+1]/(36.5089/1.041/1.041/1.041)<< std::endl;
1465  tr.Trace << "alpha: " << par[ex*n_par+1]<< std::endl;
1466  tr.Trace << "beta: " << par[ex*n_par+2]<< std::endl;
1467  tr.Trace << "gamma:" << par[ex*n_par+3]<< std::endl;
1468  tr.Trace << "norm:" << bestnorm<<std::endl;
1469  }
1470  }//end of loop through all exps
1471 
1472  //compute scores and other stats for all exps
1473  Real wsv2 = 0;
1474  Real sw = 0;
1475  Real vtot = 0;
1476  Real Q = 0;
1477  Real Qex = 0;
1478  //Real Qexunscale = 0;
1479  Real Qnorm = 0;
1480 
1481  Size irow(0);
1482  for (utility::vector1<core::scoring::RDC>::iterator it = All_RDC_lines_.begin(); it != All_RDC_lines_.end(); ++it) {
1483 
1484  Size ex = it->expid();
1485  //tr.Trace << "ex: " << ex << " lenex_[ex]: " << lenex_[ex+1] <<std::endl;
1486  //compute the length of previous exps
1487  prelen=0;
1488  for (Size cnt=0; cnt<=ex; cnt++) {
1489  prelen+=lenex_[cnt];
1490  }
1491 
1492  Real computed_coupling = frdcDa(r0_[prelen+irow], r1_[prelen+irow], r2_[prelen+irow], rdcconst_[prelen+irow], tensorDa[ex+1], &par[ex*n_par]);
1493 
1494  //compute derivatives
1495  RDC& rdc = *it;
1496  numeric::xyzVector<Real> r( pose.residue(rdc.res1()).atom(rdc.atom1()).xyz() - pose.residue(rdc.res2()).atom(rdc.atom2()).xyz());
1497  numeric::xyzVector<Real> r_copy( pose.residue(rdc.res1()).atom(rdc.atom1()).xyz() - pose.residue(rdc.res2()).atom(rdc.atom2()).xyz());
1498  core::Real r2 = r.norm_squared();
1499  core::Real invr = 1.0 / sqrt(r2);
1500 
1501  if ( correct_NH ) {
1502  if ( it->type() == RDC::RDC_TYPE_NH && std::abs((int) it->res1()-(int) it->res2())==0 ) {
1503  r.normalize(1.041);
1504  r2 = r.norm_squared();
1505  invr = 1.0 / sqrt(r2);
1506  } else if ( it->type() == RDC::RDC_TYPE_NC && std::abs((int) it->res1()-(int) it->res2())==1 ) {
1507  r.normalize(1.329);
1508  r2 = r.norm_squared();
1509  invr = 1.0 / sqrt(r2);
1510  } else if ( it->type() == RDC::RDC_TYPE_CH && std::abs((int) it->res1()-(int) it->res2())==0 ) {
1511  r.normalize(1.107);
1512  r2 = r.norm_squared();
1513  invr = 1.0 / sqrt(r2);
1514  } else if ( it->type() == RDC::RDC_TYPE_CC && std::abs((int) it->res1()-(int) it->res2())==0 ) {
1515  r.normalize(1.525);
1516  r2 = r.norm_squared();
1517  invr = 1.0 / sqrt(r2);
1518  } else {
1519  tr.Error << "unreognized type or residue sequence separation does not allow using correct_NH" << std::endl;
1520  throw( utility::excn::EXCN_BadInput("unreognized type or residue sequence separation does not allow using correct_NH "));
1521  }
1522  }//end of correct_NH
1523 
1524  core::Real invr2 = sqr(invr);
1525 
1526  //prefactor used in derivative calculations
1527  Real weight = it->weight()*Smax[ex]; //force constant
1528  //core::Real pfac = scale_to_NH*invr2* weight;
1529  core::Real pfac = scale_to_NH*(1/r.length())*(1/r_copy.length())*weight;
1530  Real obs = rdc.Jdipolar()*(scale_to_NH)/(rdc.Dconst() * invr2 * invr);
1531  Real dev = computed_coupling - obs;
1532  it->Jdipolar_computed_ = computed_coupling/((scale_to_NH)/(rdc.Dconst() * invr2 * invr));
1533 
1534  //parameters after fitting
1535  core::Real Axx=(3.0*par[ex*n_par+0]/2.0-1.0)*tensorDa[ex+1]/(36.5089/1.041/1.041/1.041);
1536  core::Real Ayy=-(3.0*par[ex*n_par+0]/2.0+1.0)*tensorDa[ex+1]/(36.5089/1.041/1.041/1.041);
1537  core::Real Azz=2.0*tensorDa[ex+1]/(36.5089/1.041/1.041/1.041);
1538  core::Real a=par[ex*n_par+1];
1539  core::Real b=par[ex*n_par+2];
1540  core::Real c=par[ex*n_par+3];
1541  //rotation matrix
1542  core::Real r00=cos(b)*cos(c);
1543  core::Real r01=-cos(a)*sin(c)+sin(a)*sin(b)*cos(c);
1544  core::Real r02=sin(a)*sin(c)+cos(a)*sin(b)*cos(c);
1545  core::Real r10=cos(b)*sin(c);
1546  core::Real r11=cos(a)*cos(c)+sin(a)*sin(b)*sin(c);
1547  core::Real r12=-sin(a)*cos(c)+cos(a)*sin(b)*sin(c);
1548  core::Real r20=-sin(b);
1549  core::Real r21=sin(a)*cos(b);
1550  core::Real r22=cos(a)*cos(b);
1551  //projects in the PAF
1552  core::Real rx=r00*r.x()+r01*r.y()+r02*r.z();
1553  core::Real ry=r10*r.x()+r11*r.y()+r12*r.z();
1554  core::Real rz=r20*r.x()+r21*r.y()+r22*r.z();
1555  //derivatives
1556  rdc.fij_[0] = - dev * pfac * 2 * (Axx*rx*r00+Ayy*ry*r10+Azz*rz*r20) ;
1557  rdc.fij_[1] = - dev * pfac * 2 * (Axx*rx*r01+Ayy*ry*r11+Azz*rz*r21);
1558  rdc.fij_[2] = - dev * pfac * 2 * (Axx*rx*r02+Ayy*ry*r12+Azz*rz*r22) ;
1559 
1560  //compute energy
1561  vtot += 0.5*sqr( dev )*weight;
1562  //vtot += 0.5*sqr( dev )*Smax[ex]/(lenex_[ex+1]);
1563  //vtot += 0.5*sqr( dev )*Smax[ex]/( tensorDa[ex+1] * tensorDa[ex+1] * lenex_[ex+1]);
1564  //vtot += 0.5*sqr( dev )*weight; //xweight if we want that
1565  // vtot += sqrt( dev );
1566  wsv2 += weight*sqr(dev);
1567  sw += weight;
1568  Q += sqr( dev );
1569  Qex +=sqr( dev );
1570  Qnorm += sqr( obs );
1571 
1572  //printout Qbax_ for each experiment
1573  if ( irow==lenex_[ex+1]-1 ) {
1574  if ( tr.Trace.visible() ) {
1575  tr.Trace << "ex: " << ex << " Qbax_: " << sqrt(Qex/lenex_[ex+1])/sqrt(sqr(tensorDa[ex+1])*(4+3*sqr(par[ex*n_par+0]))/5) << std::endl; //JACS 2003 125(30) 9179-9191 Table 2 lagend
1576  tr.Trace << "ex: " << ex << " rms_dc: " << sqrt(Qex/lenex_[ex+1]) << std::endl;
1577  }
1578  Qex=0;
1579  }
1580 
1581 
1582  //increament the array
1583  if (irow<lenex_[ex+1]-1) {
1584  irow++;
1585  } else {
1586  irow=0;
1587  }
1588 
1589  }
1590 
1591  R_ = sqrt( Q/Qnorm/2 );
1592  rmsd_ = sqrt(wsv2/sw);
1593 
1594  if ( tr.Trace.visible() ) {
1595  tr.Trace << "R_: " << R_ << std::endl;
1596  tr.Trace << "rmsd_: " << rmsd_ << std::endl;
1597  tr.Trace << "All_RDC_lines_.size(): " << All_RDC_lines_.size() << std::endl;
1598  }
1599 
1600  using namespace basic::options;
1601  using namespace basic::options::OptionKeys;
1602  using namespace ObjexxFCL;
1603  using namespace ObjexxFCL::fmt;
1604 
1605 //print the rdc values
1606  if ( option[ OptionKeys::rdc::print_rdc_values ].user() ) {
1607  std::string filename( option[ OptionKeys::rdc::print_rdc_values ]() );
1608  utility::io::ozstream out;
1609 
1610  out.open_append( filename ) ;
1611  using namespace core::pose::datacache;
1612  //Size const width( 8 );
1613  //Size const width_large(6);
1615  for (Size ex = 0; ex < nex_; ex++) {
1616  show_rdc_values( out, ex );
1617  }
1618  out << "//" <<std::endl;
1619  out.close();
1620  }
1621 
1622  return vtot;
1623 }//compute_dipscore_nlsDa
1624 
1625 //Interface lmmin with compute_dipscore_nlsR
1627  if ( nex_ == 0 || nrows_ == 0 ) return 0;
1628 
1629  //non-linear square fitting of RDC data
1631  bool const correct_NH( basic::options::option[basic::options::OptionKeys::rdc::correct_NH_length]);
1632  core::Size nrow(0);
1633  core::Size id(0);
1634  core::Real obs(0.0);
1635 
1636  //initialize the cnt
1637  for (id = 0; id < nex_+1; id++) {
1638  lenex_[id]=0;
1639  }
1640  id=0;
1641 
1642  core::Real scale_to_NH = 36.5089/1.041/1.041/1.041;
1643 
1644  for (it = All_RDC_lines_.begin(); it != All_RDC_lines_.end(); ++it) {
1645  if ( it->res1() > pose.total_residue() || it->res2() > pose.total_residue() ) {
1646  if ( tr.Debug.visible() ) tr.Debug << "non-existing residue, ignore RDC" << std::endl;
1647  continue;
1648  }
1649 
1650  //check for cutpoints!!!
1651  kinematics::FoldTree const& ft(pose.fold_tree());
1652  if ((ft.is_cutpoint(std::min((int) it->res1(), (int) it->res2()))) && it->res1() != it->res2()) {
1653  if ( tr.Trace.visible() ) tr.Trace << "cutpoint: ignore RDC " << *it << std::endl;
1654  continue;
1655  }
1656 
1657  ++nrow;
1658  numeric::xyzVector<Real> r( pose.residue(it->res1()).atom(it->atom1()).xyz() - pose.residue(it->res2()).atom(it->atom2()).xyz());
1659 
1660  core::Real r2 = r.norm_squared();
1661  core::Real invr = 1.0 / sqrt(r2);
1662 
1663  if ( correct_NH ) {
1664  scale_to_NH = 36.5089/1.041/1.041/1.041;
1665  if ( it->type() == RDC::RDC_TYPE_NH && std::abs((int) it->res1()-(int) it->res2())==0 ) {
1666  r.normalize(1.041);
1667  r2 = r.norm_squared();
1668  invr = 1.0 / sqrt(r2);
1669  } else if ( it->type() == RDC::RDC_TYPE_NC && std::abs((int) it->res1()-(int) it->res2())==1 ) {
1670  r.normalize(1.329);
1671  r2 = r.norm_squared();
1672  invr = 1.0 / sqrt(r2);
1673  } else if ( it->type() == RDC::RDC_TYPE_CH && std::abs((int) it->res1()-(int) it->res2())==0 ) {
1674  r.normalize(1.107);
1675  r2 = r.norm_squared();
1676  invr = 1.0 / sqrt(r2);
1677  } else if ( it->type() == RDC::RDC_TYPE_CC && std::abs((int) it->res1()-(int) it->res2())==0 ) {
1678  r.normalize(1.525);
1679  r2 = r.norm_squared();
1680  invr = 1.0 / sqrt(r2);
1681  } else {
1682  tr.Error << "unreognized type or residue sequence separation does not allow using correct_NH" << std::endl;
1683  throw( utility::excn::EXCN_BadInput("unreognized type or residue sequence separation does not allow using correct_NH "));
1684  }
1685  }//end of correct_NH
1686 
1687  core::Real pfac = it->Dconst();
1688  bool bCSA(false);// hook up for later... to compute chemical shift anisotropy
1689  if (!bCSA) {
1690  pfac *= invr * invr * invr;
1691  }
1692 
1693  //check the -1 if it is correct
1694  id = All_RDC_lines_[nrow].expid();
1695  obs = All_RDC_lines_[nrow].Jdipolar()*(scale_to_NH)/pfac;
1696 
1697  r0_[nrow-1] = r.normalized().x();
1698  r1_[nrow-1] = r.normalized().y();
1699  r2_[nrow-1] = r.normalized().z();
1700  rdcconst_[nrow-1]=scale_to_NH;
1701  exprdc_[nrow-1]=obs;
1702  rdcweight_[nrow-1]=it->weight();
1703  lenex_[id+1]=lenex_[id+1]+1;
1704  } //cycle over atoms
1705 
1706 
1707  //parameters
1708  int n_par = 4; // number of parameters in model function frdcR
1709  int nrepeat = 5; // number of repeat lmfit
1710  //double parbest[n_par*nex_];
1711  //double par[n_par*nex_];
1712  std::vector<double> parbest(n_par*nex_);
1713  std::vector<double> par(n_par*nex_);
1714 
1715  int i,j;
1716  double bestnorm;
1717  Size prelen=0;
1718 
1719  //optional weighting provided by user
1720  runtime_assert( nex_ < 200 );
1721  Real Smax[200];
1722 
1723  //experimental data array
1724  for (Size ex = 0; ex < nex_; ex++) {
1725 
1726  //compute the length of previous exps
1727  prelen=0;
1728  for (Size cnt=0; cnt<=ex; cnt++) {
1729  prelen+=lenex_[cnt];
1730  }
1731  //perform lmfit on each exp
1732  data_structR data = { r0_+prelen, r1_+prelen, r2_+prelen, exprdc_+prelen, rdcconst_+prelen, rdcweight_+prelen, tensorR[ex+1], frdcR};
1733  //definition of auxiliary parameters
1734  numeric::nls::lm_status_struct status;
1735 
1736  Smax[ex] = 1;
1737  {
1738  using namespace basic::options;
1739  if ( option[ OptionKeys::rdc::fix_normAzz ].user() ) {
1740  if ( option[ OptionKeys::rdc::fix_normAzz ]().size() != nex_ ) {
1741  utility_exit_with_message("fix_normAzz must have one value for each alignment medium !");
1742  }
1743  Smax[ ex ] = option[ OptionKeys::rdc::fix_normAzz ]()[ ex+1 ];
1744  }
1745  }
1746 
1747  bestnorm=1e12;
1748 
1749  for (j = 0; j < nrepeat; j++) {
1750  //random starting value
1751  par[ex*n_par+0]=numeric::random::uniform();//Da
1752  par[ex*n_par+1]=2.0*numeric::NumericTraits<Real>::pi()*numeric::random::uniform();//alpha
1753  par[ex*n_par+2]=2.0*numeric::NumericTraits<Real>::pi()*numeric::random::uniform();//beta
1754  par[ex*n_par+3]=2.0*numeric::NumericTraits<Real>::pi()*numeric::random::uniform();//gamma
1755  //call lmmin
1756  numeric::nls::lmmin( n_par, &par[ex*n_par], lenex_[ex+1], (const void*) &data, evaluaterdcR, &status,numeric::nls::lm_printout_std);
1757  if ( tr.Trace.visible() ) {
1758  tr.Trace << std::endl;
1759  tr.Trace << "Iteration: " << j << "status.fnorm:" << status.fnorm << "bestnorm: "<< bestnorm << std::endl;
1760  }
1761  //save to best fitting parameter
1762  if (status.fnorm < bestnorm) {
1763  bestnorm=status.fnorm;
1764  for (i=0; i<n_par ; i++)
1765  parbest[ex*n_par+i]=par[ex*n_par+i];
1766  }
1767  }//repeat lmfit five times with different starting parameters
1768  //copy back to par
1769  for (i=0; i<n_par ; i++)
1770  par[ex*n_par+i]=parbest[ex*n_par+i];
1771 
1772  //debug
1773  if ( tr.Trace.visible() ) {
1774  tr.Trace << std::endl;
1775  tr.Trace << "ex: " << ex << std::endl;
1776  tr.Trace << "Ax: " << (3.0*tensorR[ex+1]/2.0-1.0)*par[ex*n_par+0]/(36.5089/1.041/1.041/1.041)<< std::endl;
1777  tr.Trace << "Ay: " << -(3.0*tensorR[ex+1]/2.0+1.0)*par[ex*n_par+0]/(36.5089/1.041/1.041/1.041)<< std::endl;
1778  tr.Trace << "alpha: " << par[ex*n_par+1]<< std::endl;
1779  tr.Trace << "beta: " << par[ex*n_par+2]<< std::endl;
1780  tr.Trace << "gamma:" << par[ex*n_par+3]<< std::endl;
1781  tr.Trace << "norm:" << bestnorm<<std::endl;
1782  }
1783  }//end of loop through all exps
1784 
1785  //compute scores and other stats for all exps
1786  Real wsv2 = 0;
1787  Real sw = 0;
1788  Real vtot = 0;
1789  Real Q = 0;
1790  Real Qex = 0;
1791  Real Qnorm = 0;
1792 
1793  Size irow(0);
1794  for (utility::vector1<core::scoring::RDC>::iterator it = All_RDC_lines_.begin(); it != All_RDC_lines_.end(); ++it) {
1795 
1796  Size ex = it->expid();
1797  //tr.Trace << "ex: " << ex << " lenex_[ex]: " << lenex_[ex] <<std::endl;
1798 
1799  //compute the length of previous exps
1800  prelen=0;
1801  for (Size cnt=0; cnt<=ex; cnt++) {
1802  prelen+=lenex_[cnt];
1803  }
1804 
1805  Real computed_coupling = frdcR(r0_[prelen+irow], r1_[prelen+irow], r2_[prelen+irow], rdcconst_[prelen+irow], tensorR[ex+1], &par[ex*n_par]);
1806 
1807  //compute derivatives
1808  RDC& rdc = *it;
1809  numeric::xyzVector<Real> r( pose.residue(rdc.res1()).atom(rdc.atom1()).xyz() - pose.residue(rdc.res2()).atom(rdc.atom2()).xyz());
1810  numeric::xyzVector<Real> r_copy( pose.residue(rdc.res1()).atom(rdc.atom1()).xyz() - pose.residue(rdc.res2()).atom(rdc.atom2()).xyz());
1811  core::Real r2 = r.norm_squared();
1812  core::Real invr = 1.0 / sqrt(r2);
1813 
1814  if ( correct_NH ) {
1815  if ( it->type() == RDC::RDC_TYPE_NH && std::abs((int) it->res1()-(int) it->res2())==0 ) {
1816  r.normalize(1.041);
1817  r2 = r.norm_squared();
1818  invr = 1.0 / sqrt(r2);
1819  } else if ( it->type() == RDC::RDC_TYPE_NC && std::abs((int) it->res1()-(int) it->res2())==1 ) {
1820  r.normalize(1.329);
1821  r2 = r.norm_squared();
1822  invr = 1.0 / sqrt(r2);
1823  } else if ( it->type() == RDC::RDC_TYPE_CH && std::abs((int) it->res1()-(int) it->res2())==0 ) {
1824  r.normalize(1.107);
1825  r2 = r.norm_squared();
1826  invr = 1.0 / sqrt(r2);
1827  } else if ( it->type() == RDC::RDC_TYPE_CC && std::abs((int) it->res1()-(int) it->res2())==0 ) {
1828  r.normalize(1.525);
1829  r2 = r.norm_squared();
1830  invr = 1.0 / sqrt(r2);
1831  } else {
1832  tr.Error << "unreognized type or residue sequence separation does not allow using correct_NH" << std::endl;
1833  throw( utility::excn::EXCN_BadInput("unreognized type or residue sequence separation does not allow using correct_NH "));
1834  }
1835  }//end of correct_NH
1836  core::Real invr2 = sqr(invr);
1837 
1838  //prefactor used in derivative calculations
1839  Real weight = it->weight()*Smax[ex]; //force constant
1840  //core::Real pfac = scale_to_NH*invr2* weight;
1841  core::Real pfac = scale_to_NH*(1/r.length())*(1/r_copy.length())*weight;
1842  Real obs = rdc.Jdipolar()*(scale_to_NH)/(rdc.Dconst() * invr2 * invr);
1843  Real dev = computed_coupling - obs;
1844  it->Jdipolar_computed_ = computed_coupling/((scale_to_NH)/(rdc.Dconst() * invr2 * invr));
1845 
1846  //parameters after fitting
1847  core::Real Axx=(3.0*tensorR[ex+1]/2.0-1.0)*par[ex*n_par+0]/(36.5089/1.041/1.041/1.041);
1848  core::Real Ayy=-(3.0*tensorR[ex+1]/2.0+1.0)*par[ex*n_par+0]/(36.5089/1.041/1.041/1.041);
1849  core::Real Azz=2.0*par[ex*n_par+0]/(36.5089/1.041/1.041/1.041);
1850  core::Real a=par[ex*n_par+1];
1851  core::Real b=par[ex*n_par+2];
1852  core::Real c=par[ex*n_par+3];
1853  //rotation matrix
1854  core::Real r00=cos(b)*cos(c);
1855  core::Real r01=-cos(a)*sin(c)+sin(a)*sin(b)*cos(c);
1856  core::Real r02=sin(a)*sin(c)+cos(a)*sin(b)*cos(c);
1857  core::Real r10=cos(b)*sin(c);
1858  core::Real r11=cos(a)*cos(c)+sin(a)*sin(b)*sin(c);
1859  core::Real r12=-sin(a)*cos(c)+cos(a)*sin(b)*sin(c);
1860  core::Real r20=-sin(b);
1861  core::Real r21=sin(a)*cos(b);
1862  core::Real r22=cos(a)*cos(b);
1863  //projects in the PAF
1864  core::Real rx=r00*r.x()+r01*r.y()+r02*r.z();
1865  core::Real ry=r10*r.x()+r11*r.y()+r12*r.z();
1866  core::Real rz=r20*r.x()+r21*r.y()+r22*r.z();
1867  //derivatives
1868  rdc.fij_[0] = - dev * pfac * 2 * (Axx*rx*r00+Ayy*ry*r10+Azz*rz*r20) ;
1869  rdc.fij_[1] = - dev * pfac * 2 * (Axx*rx*r01+Ayy*ry*r11+Azz*rz*r21);
1870  rdc.fij_[2] = - dev * pfac * 2 * (Axx*rx*r02+Ayy*ry*r12+Azz*rz*r22) ;
1871 
1872  //compute energy
1873  vtot += 0.5*sqr( dev )*weight;
1874  //vtot += 0.5*sqr( dev )*Smax[ex]/(lenex_[ex+1]);
1875  //vtot += 0.5*sqr( dev )*Smax[ex]/( par[ex*n_par+0]/(2*(36.5089/1.041/1.041/1.041))*par[ex*n_par+0]/(2*(36.5089/1.041/1.041/1.041))*lenex_[ex+1]);
1876  //vtot += 0.5*sqr( dev )*Smax[ex]/( par[ex*n_par+0]/(2*rdcconst_[prelen+irow])*par[ex*n_par+0]/(2*rdcconst_[prelen+irow])*lenex_[ex+1]);
1877  //vtot += 0.5*sqr( dev )*weight; //xweight if we want that
1878  // vtot += sqrt( dev );
1879  wsv2 += weight*sqr(dev);
1880  sw += weight;
1881  Q += sqr( dev );
1882  Qex +=sqr( dev );
1883  Qnorm += sqr( obs );
1884 
1885  //printout Qbax_ for each experiment
1886  if ( irow==lenex_[ex+1]-1 ) {
1887  if ( tr.Trace.visible() ) {
1888  tr.Trace << "ex: " << ex << " Qbax_: " << sqrt(Qex/lenex_[ex+1])/sqrt(sqr(par[ex*n_par+0])*(4+3*sqr(tensorR[ex+1]))/5) << std::endl; //JACS 2003 125(30) 9179-9191 Table 2 lagend
1889  tr.Trace << "ex: " << ex << " rms_dc: " << sqrt(Qex/lenex_[ex+1]) << std::endl;
1890  }
1891  Qex=0;
1892  }
1893 
1894 
1895  //increament the array
1896  if (irow<lenex_[ex+1]-1) {
1897  irow++;
1898  } else {
1899  irow=0;
1900  }
1901 
1902  }
1903 
1904  R_ = sqrt( Q/Qnorm/2 );
1905  rmsd_ = sqrt(wsv2/sw);
1906 
1907  if ( tr.Trace.visible() ) {
1908  tr.Trace << "R_: " << R_ << std::endl;
1909  tr.Trace << "rmsd_: " << rmsd_ << std::endl;
1910  tr.Trace << "All_RDC_lines_.size(): " << All_RDC_lines_.size() << std::endl;
1911  }
1912 
1913  using namespace basic::options;
1914  using namespace basic::options::OptionKeys;
1915  using namespace ObjexxFCL;
1916  using namespace ObjexxFCL::fmt;
1917 
1918 //print the rdc values
1919  if ( option[ OptionKeys::rdc::print_rdc_values ].user() ) {
1920  std::string filename( option[ OptionKeys::rdc::print_rdc_values ]() );
1921  utility::io::ozstream out;
1922 
1923  out.open_append( filename ) ;
1924  using namespace core::pose::datacache;
1925  //Size const width( 8 );
1926  //Size const width_large(6);
1927  // mjo comment out precision because it is not used and causes a warning.
1928  //Size const precision( 2 );
1930  for (Size ex = 0; ex < nex_; ex++) {
1931  show_rdc_values( out, ex );
1932  }
1933  out << "//" <<std::endl;
1934  out.close();
1935  }
1936 
1937  return vtot;
1938 }//compute_dipscore_nlsR
1939 
1940 //Interface lmmin with compute_dipscore_nlsDaR
1942  if ( nex_ == 0 || nrows_ == 0 ) return 0;
1943 
1944  //non-linear square fitting of RDC data
1946  bool const correct_NH( basic::options::option[basic::options::OptionKeys::rdc::correct_NH_length]);
1947  core::Size nrow(0);
1948  core::Size id(0);
1949  core::Real obs(0.0);
1950 
1951  //initialize the cnt
1952  for (id = 0; id < nex_+1; id++) {
1953  lenex_[id]=0;
1954  }
1955  id=0;
1956 
1957  core::Real scale_to_NH = 36.5089/1.041/1.041/1.041;
1958 
1959  for (it = All_RDC_lines_.begin(); it != All_RDC_lines_.end(); ++it) {
1960  if ( it->res1() > pose.total_residue() || it->res2() > pose.total_residue() ) {
1961  if ( tr.Debug.visible() ) tr.Debug << "non-existing residue, ignore RDC" << std::endl;
1962  continue;
1963  }
1964 
1965  //check for cutpoints!!!
1966  kinematics::FoldTree const& ft(pose.fold_tree());
1967  if ((ft.is_cutpoint(std::min((int) it->res1(), (int) it->res2()))) && it->res1() != it->res2()) {
1968  if ( tr.Trace.visible() ) tr.Trace << "cutpoint: ignore RDC " << *it << std::endl;
1969  continue;
1970  }
1971 
1972  ++nrow;
1973  numeric::xyzVector<Real> r( pose.residue(it->res1()).atom(it->atom1()).xyz() - pose.residue(it->res2()).atom(it->atom2()).xyz());
1974  core::Real r2 = r.norm_squared();
1975  core::Real invr = 1.0 / sqrt(r2);
1976 
1977  if ( correct_NH ) {
1978  scale_to_NH = 36.5089/1.041/1.041/1.041;
1979  if ( it->type() == RDC::RDC_TYPE_NH && std::abs((int) it->res1()-(int) it->res2())==0 ) {
1980  r.normalize(1.041);
1981  r2 = r.norm_squared();
1982  invr = 1.0 / sqrt(r2);
1983  } else if ( it->type() == RDC::RDC_TYPE_NC && std::abs((int) it->res1()-(int) it->res2())==1 ) {
1984  r.normalize(1.329);
1985  r2 = r.norm_squared();
1986  invr = 1.0 / sqrt(r2);
1987  } else if ( it->type() == RDC::RDC_TYPE_CH && std::abs((int) it->res1()-(int) it->res2())==0 ) {
1988  r.normalize(1.107);
1989  r2 = r.norm_squared();
1990  invr = 1.0 / sqrt(r2);
1991  } else if ( it->type() == RDC::RDC_TYPE_CC && std::abs((int) it->res1()-(int) it->res2())==0 ) {
1992  r.normalize(1.525);
1993  r2 = r.norm_squared();
1994  invr = 1.0 / sqrt(r2);
1995  } else {
1996  tr.Error << "unreognized type or residue sequence separation does not allow using correct_NH" << std::endl;
1997  throw( utility::excn::EXCN_BadInput("unreognized type or residue sequence separation does not allow using correct_NH "));
1998  }
1999  }//end of correct_NH
2000 
2001  core::Real pfac = it->Dconst();
2002  bool bCSA(false);// hook up for later... to compute chemical shift anisotropy
2003  if (!bCSA) {
2004  pfac *= invr * invr * invr;
2005  }
2006 
2007  //check the -1 if it is correct
2008  id = All_RDC_lines_[nrow].expid();
2009  obs = All_RDC_lines_[nrow].Jdipolar()*(scale_to_NH)/pfac;
2010 
2011  r0_[nrow-1] = r.normalized().x();
2012  r1_[nrow-1] = r.normalized().y();
2013  r2_[nrow-1] = r.normalized().z();
2014  rdcconst_[nrow-1]=scale_to_NH;
2015  exprdc_[nrow-1]=obs;
2016  rdcweight_[nrow-1]=it->weight();
2017  lenex_[id+1]=lenex_[id+1]+1;
2018  //tr.Trace << "weight: " << it->weight() << std::endl;
2019  } //cycle over atoms
2020 
2021 
2022  //parameters
2023  int n_par = 3; // number of parameters in model function frdcR
2024  int nrepeat = 5; // number of repeat lmfit
2025  //double parbest[n_par*nex_];
2026  //double par[n_par*nex_];
2027  std::vector<double> parbest(n_par*nex_);
2028  std::vector<double> par(n_par*nex_);
2029 
2030  int i,j;
2031  double bestnorm;
2032  Size prelen=0;
2033 
2034  //optional weighting provided by user
2035  runtime_assert( nex_ < 200 );
2036  Real Smax[200];
2037 
2038  //experimental data array
2039  for (Size ex = 0; ex < nex_; ex++) {
2040  //compute the length of previous exps
2041  prelen=0;
2042  for (Size cnt=0; cnt<=ex; cnt++) {
2043  prelen+=lenex_[cnt];
2044  }
2045 
2046  //perform lmfit on each exp
2047  data_structDaR data = { r0_+prelen, r1_+prelen, r2_+prelen, exprdc_+prelen, rdcconst_+prelen, rdcweight_+prelen, tensorDa[ex+1], tensorR[ex+1], frdcDaR};
2048  //definition of auxiliary parameters
2049  numeric::nls::lm_status_struct status;
2050 
2051  Smax[ex] = 1;
2052  {
2053  using namespace basic::options;
2054  if ( option[ OptionKeys::rdc::fix_normAzz ].user() ) {
2055  if ( option[ OptionKeys::rdc::fix_normAzz ]().size() != nex_ ) {
2056  utility_exit_with_message("fix_normAzz must have one value for each alignment medium !");
2057  }
2058  Smax[ ex ] = option[ OptionKeys::rdc::fix_normAzz ]()[ ex+1 ];
2059  }
2060  }
2061 
2062  bestnorm=1e12;
2063 
2064  for (j = 0; j < nrepeat; j++) {
2065  //random starting value
2066  par[ex*n_par+0]=2.0*numeric::NumericTraits<Real>::pi()*numeric::random::uniform();//alpha
2067  par[ex*n_par+1]=2.0*numeric::NumericTraits<Real>::pi()*numeric::random::uniform();//beta
2068  par[ex*n_par+2]=2.0*numeric::NumericTraits<Real>::pi()*numeric::random::uniform();//gamma
2069  //call lmmin
2070  numeric::nls::lmmin( n_par, &par[ex*n_par], lenex_[ex+1], (const void*) &data, evaluaterdcDaR, &status,numeric::nls::lm_printout_std);
2071  if ( tr.Trace.visible() ) {
2072  tr.Trace << std::endl;
2073  tr.Trace << "Iteration: " << j << " status.fnorm: " << status.fnorm << " bestnorm: "<< bestnorm << std::endl;
2074  }
2075  //save to best fitting parameter
2076  if (status.fnorm < bestnorm) {
2077  tr.Trace << "status.fnorm: " << status.fnorm << " replaced by bestnorm: " << bestnorm << std::endl;
2078  bestnorm=status.fnorm;
2079  for (i=0; i<n_par ; i++)
2080  parbest[ex*n_par+i]=par[ex*n_par+i];
2081  }
2082  }//repeat lmfit five times with different starting parameters
2083 
2084  //copy back to par
2085  for (i=0; i<n_par ; i++)
2086  par[ex*n_par+i]=parbest[ex*n_par+i];
2087 
2088  //debug
2089  if ( tr.Trace.visible() ) {
2090  tr.Trace << std::endl;
2091  tr.Trace << "ex: " << ex << std::endl;
2092  tr.Trace << " tensorDa["<<ex<<"]: "<<tensorDa[ex+1]<< std::endl;
2093  tr.Trace << " tensorR["<<ex<<"]: "<<tensorR[ex+1]<< std::endl;
2094  tr.Trace << "Ax: " << (3.0*tensorR[ex+1]/2.0-1.0)*tensorDa[ex+1]/(36.5089/1.041/1.041/1.041)<< std::endl;
2095  tr.Trace << "Ay: " << -(3.0*tensorR[ex+1]/2.0+1.0)*tensorDa[ex+1]/(36.5089/1.041/1.041/1.041)<< std::endl;
2096  tr.Trace << "alpha: " << par[ex*n_par+0]<< std::endl;
2097  tr.Trace << "beta: " << par[ex*n_par+1]<< std::endl;
2098  tr.Trace << "gamma:" << par[ex*n_par+2]<< std::endl;
2099  tr.Trace << "norm:" << bestnorm<<std::endl;
2100  }
2101  }//end of loop through all exps
2102 
2103  //compute scores and other stats for all exps
2104  Real wsv2 = 0;
2105  Real sw = 0;
2106  Real vtot = 0;
2107  Real Q = 0;
2108  Real Qex = 0;
2109  Real Qnorm = 0;
2110 
2111  Size irow(0);
2112  for (utility::vector1<core::scoring::RDC>::iterator it = All_RDC_lines_.begin(); it != All_RDC_lines_.end(); ++it) {
2113 
2114  Size ex = it->expid();
2115 
2116  //compute the length of previous exps
2117  prelen=0;
2118  for (Size cnt=0; cnt<=ex; cnt++) {
2119  prelen+=lenex_[cnt];
2120  }
2121 
2122  Real computed_coupling = frdcDaR(r0_[prelen+irow], r1_[prelen+irow], r2_[prelen+irow], rdcconst_[prelen+irow], tensorDa[ex+1], tensorR[ex+1], &par[ex*n_par]);
2123 
2124 
2125  // std::cout << "WEIGHT " << weight <<std::endl;
2126  //normalized by the tensor values and number of experiments
2127 
2128  //compute derivatives
2129  RDC& rdc = *it;
2130  numeric::xyzVector<Real> r( pose.residue(rdc.res1()).atom(rdc.atom1()).xyz() - pose.residue(rdc.res2()).atom(rdc.atom2()).xyz());
2131  numeric::xyzVector<Real> r_copy( pose.residue(rdc.res1()).atom(rdc.atom1()).xyz() - pose.residue(rdc.res2()).atom(rdc.atom2()).xyz());
2132  core::Real r2 = r.norm_squared();
2133  core::Real invr = 1.0 / sqrt(r2);
2134 
2135  if ( correct_NH ) {
2136  if ( it->type() == RDC::RDC_TYPE_NH && std::abs((int) it->res1()-(int) it->res2())==0 ) {
2137  r.normalize(1.041);
2138  r2 = r.norm_squared();
2139  invr = 1.0 / sqrt(r2);
2140  } else if ( it->type() == RDC::RDC_TYPE_NC && std::abs((int) it->res1()-(int) it->res2())==1 ) {
2141  r.normalize(1.329);
2142  r2 = r.norm_squared();
2143  invr = 1.0 / sqrt(r2);
2144  } else if ( it->type() == RDC::RDC_TYPE_CH && std::abs((int) it->res1()-(int) it->res2())==0 ) {
2145  r.normalize(1.107);
2146  r2 = r.norm_squared();
2147  invr = 1.0 / sqrt(r2);
2148  } else if ( it->type() == RDC::RDC_TYPE_CC && std::abs((int) it->res1()-(int) it->res2())==0 ) {
2149  r.normalize(1.525);
2150  r2 = r.norm_squared();
2151  invr = 1.0 / sqrt(r2);
2152  } else {
2153  tr.Error << "unreognized type or residue sequence separation does not allow using correct_NH" << std::endl;
2154  throw( utility::excn::EXCN_BadInput("unreognized type or residue sequence separation does not allow using correct_NH "));
2155  }
2156  }//end of correct_NH
2157 
2158  core::Real invr2 = sqr(invr);
2159 
2160  //prefactor used in derivative calculations
2161  Real weight = it->weight()*Smax[ex]; //force constant
2162  core::Real pfac = scale_to_NH*(1/r.length())*(1/r_copy.length())*weight;
2163  Real obs = rdc.Jdipolar()*(scale_to_NH)/(rdc.Dconst() * invr2 * invr);
2164  Real dev = computed_coupling - obs;
2165  it->Jdipolar_computed_ = computed_coupling/((scale_to_NH)/(rdc.Dconst() * invr2 * invr));
2166 
2167  //parameters after fitting
2168  core::Real Axx=(3.0*tensorR[ex+1]/2.0-1.0)*tensorDa[ex+1]/(36.5089/1.041/1.041/1.041);
2169  core::Real Ayy=-(3.0*tensorR[ex+1]/2.0+1.0)*tensorDa[ex+1]/(36.5089/1.041/1.041/1.041);
2170  core::Real Azz=2.0*tensorDa[ex+1]/(36.5089/1.041/1.041/1.041);
2171  core::Real a=par[ex*n_par+0];
2172  core::Real b=par[ex*n_par+1];
2173  core::Real c=par[ex*n_par+2];
2174  //rotation matrix
2175  core::Real r00=cos(b)*cos(c);
2176  core::Real r01=-cos(a)*sin(c)+sin(a)*sin(b)*cos(c);
2177  core::Real r02=sin(a)*sin(c)+cos(a)*sin(b)*cos(c);
2178  core::Real r10=cos(b)*sin(c);
2179  core::Real r11=cos(a)*cos(c)+sin(a)*sin(b)*sin(c);
2180  core::Real r12=-sin(a)*cos(c)+cos(a)*sin(b)*sin(c);
2181  core::Real r20=-sin(b);
2182  core::Real r21=sin(a)*cos(b);
2183  core::Real r22=cos(a)*cos(b);
2184  //projects in the PAF
2185  core::Real rx=r00*r.x()+r01*r.y()+r02*r.z();
2186  core::Real ry=r10*r.x()+r11*r.y()+r12*r.z();
2187  core::Real rz=r20*r.x()+r21*r.y()+r22*r.z();
2188  //derivatives
2189  rdc.fij_[0] = - dev * pfac * 2 * (Axx*rx*r00+Ayy*ry*r10+Azz*rz*r20) ;
2190  rdc.fij_[1] = - dev * pfac * 2 * (Axx*rx*r01+Ayy*ry*r11+Azz*rz*r21);
2191  rdc.fij_[2] = - dev * pfac * 2 * (Axx*rx*r02+Ayy*ry*r12+Azz*rz*r22) ;
2192 
2193  //compute energy
2194  vtot += 0.5*sqr( dev )*weight;
2195  //vtot += 0.5*sqr( dev )*Smax[ex]/(lenex_[ex+1]);
2196  //vtot += 0.5*sqr( dev )*Smax[ex]/( tensorDa[ ex+1 ] * tensorDa[ ex+1 ] * lenex_[ex+1]);
2197  wsv2 += weight*sqr(dev);
2198  sw += weight;
2199  Q += sqr( dev );
2200  Qex +=sqr( dev );
2201  Qnorm += sqr( obs );
2202 
2203  //printout Qbax_ for each experiment
2204  if ( irow==lenex_[ex+1]-1 ) {
2205  if ( tr.Trace.visible() ) {
2206  tr.Trace << "ex: " << ex << " Qbax_: " << sqrt(Qex/lenex_[ex+1])/sqrt(sqr(tensorDa[ex+1])*(4+3*sqr(tensorR[ex+1]))/5) << std::endl; //JACS 2003 125(30) 9179-9191 Table 2 lagend
2207  tr.Trace << "ex: " << ex << " rms_dc: " << sqrt(Qex/lenex_[ex+1]) << std::endl;
2208  }
2209  Qex=0;
2210  }
2211 
2212 
2213  //increament the array
2214  if (irow<lenex_[ex+1]-1) {
2215  irow++;
2216  } else {
2217  irow=0;
2218  }
2219 
2220  }
2221 
2222  R_ = sqrt( Q/Qnorm/2 );
2223  rmsd_ = sqrt(wsv2/sw);
2224 
2225  if ( tr.Trace.visible() ) {
2226  tr.Trace << "R_: " << R_ << std::endl;
2227  tr.Trace << "rmsd_: " << rmsd_ << std::endl;
2228  tr.Trace << "All_RDC_lines_.size(): " << All_RDC_lines_.size() << std::endl;
2229  }
2230 
2231  using namespace basic::options;
2232  using namespace basic::options::OptionKeys;
2233  using namespace ObjexxFCL;
2234  using namespace ObjexxFCL::fmt;
2235 
2236 //print the rdc values
2237  if ( option[ OptionKeys::rdc::print_rdc_values ].user() ) {
2238  std::string filename( option[ OptionKeys::rdc::print_rdc_values ]() );
2239  utility::io::ozstream out;
2240 
2241  out.open_append( filename ) ;
2242  using namespace core::pose::datacache;
2243  //Size const width( 8 );
2244  //Size const width_large(6);
2246  for (Size ex = 0; ex < nex_; ex++) {
2247  show_rdc_values( out, ex );
2248  }
2249  out << "//" <<std::endl;
2250  out.close();
2251  }
2252 
2253  return vtot;
2254 }//compute_dipscore_nlsDaR
2255 
2256 void ResidualDipolarCoupling::show_tensor_stats( std::ostream& out, Size ex ) const {
2257  using namespace ObjexxFCL;
2258  using namespace ObjexxFCL::fmt;
2259 
2260  Real Aa = EV_[ex][0]/2;
2261  Real Ar = (EV_[ex][2]-EV_[ex][1])/3;
2262 
2263  Size const width( 10 );
2264  Size const precision( 2 );
2265  Real rhombicity = Ar/Aa;
2266  out << A( width, "Ev[ex][0]" ) << " " << A( width, "Ev[ex][1]" ) << A( width, "Ev[ex][2]" ) << std::endl;
2267  out << F( width, precision, EV_[ex][0] ) << F( width, precision, EV_[ex][1] ) << F( width, precision, EV_[ex][2]) << std::endl;
2268  out << A( width, "Aa" ) << " " << A( width, "Ar" ) << A( width, "rhombicity" ) << std::endl;
2269  out << F( width, precision, Aa ) << F( width, precision, Ar ) << F( width, precision, rhombicity ) << std::endl;
2270 }
2271 
2272 void ResidualDipolarCoupling::show_tensor_stats_nls( std::ostream& out, Size, const double *par) const {
2273  using namespace ObjexxFCL;
2274  using namespace ObjexxFCL::fmt;
2275 
2276  Real Ax = par[0];
2277  Real Ay = par[1];
2278  Real Az = -par[0]-par[1];
2279  Size const width( 10 );
2280  Size const precision( 2 );
2281  out << A( width, "Ax" ) << " " << A( width, "Ay" ) << A( width, "Az" ) << std::endl;
2282  out << F( width, precision, Ax ) << F( width, precision, Ay ) << F( width, precision, Az) << std::endl;
2283 }
2284 
2285 void ResidualDipolarCoupling::show_tensor_matrix( std::ostream& out, Size ex ) const {
2286  using namespace ObjexxFCL;
2287  using namespace ObjexxFCL::fmt;
2288 
2289  Size const width( 8 );
2290  //mjo comment out width_large because it is unused and causes a warning
2291  //Size const width_large(6);
2292  Size const precision( 2 );
2293  out << A( width, "AL.EVAL ") << F(width, precision, EV_[ex][0]) << F(width, precision, EV_[ex][1]) << F(width, precision, EV_[ex][2]) << std::endl
2294  << A( width, "AL.EVEC XX") << F(width, precision, EIG_[ex][0][0]) << F(width, precision, EIG_[ex][1][0]) << F(width, precision, EIG_[ex][2][0]) << std::endl
2295  << A( width, "AL.EVEC YY") << F(width, precision, EIG_[ex][0][1]) << F(width, precision, EIG_[ex][1][1]) << F(width, precision, EIG_[ex][2][1]) << std::endl
2296  << A( width, "AL.EVEC ZZ") << F(width, precision, EIG_[ex][0][2]) << F(width, precision, EIG_[ex][1][2]) << F(width, precision, EIG_[ex][2][2]) << std::endl;
2297 }
2298 
2299 void ResidualDipolarCoupling::show_rdc_values( std::ostream& out, Size ex ) const {
2300  using namespace ObjexxFCL;
2301  using namespace ObjexxFCL::fmt;
2302 
2303  Size const width( 8 );
2304  //mjo comment out width_large because it is unused and causes a warning
2305  //Size const width_large(6);
2306  Size const precision( 3 );
2308  for (it = All_RDC_lines_.begin(); it != All_RDC_lines_.end(); ++it) {
2309  if(it->expid() == ex){
2310  Size count( it->res1() );
2311  std::string type;
2312  if ( it->type() == RDC::RDC_TYPE_NH ) {type ="NH";}
2313  if ( it->type() == RDC::RDC_TYPE_CH ) {type ="CH";}
2314  if ( it->type() == RDC::RDC_TYPE_NC ) {type ="NC";}
2315  if ( it->type() == RDC::RDC_TYPE_CC ) {type ="CC";}
2316  Real rdc_exp( it->Jdipolar() );
2317  Real rdc_computed ( it->Jcomputed());
2318  out << A( width, "RDC" )
2319  << A( width, type )
2320  << I( width, count )
2321  << F( width, precision, rdc_exp )
2322  << F( width, precision, rdc_computed )
2323  << std::endl;
2324  }
2325  }
2326 }
2327 
2329  for (Size ex = 0; ex < nex_; ex++) {
2330  // This section performs diagonlization of the recently optimized alignment tensor (NGS)
2331 
2332  SD_[ex][0][0] = S_[ex][0][0];
2333  SD_[ex][0][1] = S_[ex][0][1];
2334  SD_[ex][0][2] = S_[ex][0][2];
2335  SD_[ex][1][1] = S_[ex][1][1];
2336  SD_[ex][1][2] = S_[ex][1][2];
2337  SD_[ex][1][0] = S_[ex][1][0];
2338  SD_[ex][2][0] = S_[ex][2][0];
2339  SD_[ex][2][1] = S_[ex][2][1];
2340  SD_[ex][2][2] = S_[ex][2][2];
2341 
2342 
2343  // std::cout << "AL.TENSOR (molecular frame): " << SD_[ex][0][0] << ' ' << SD_[ex][0][1] << ' ' << SD_[ex][0][2] << ' ' << SD_[ex][1][1] << ' ' << SD_[ex][1][2] << std::endl;
2344 
2345 
2346  Tensor v2;
2347  int nrot2;
2348  rvec ev2;
2349 
2350  jacobi3(SD_[ex],ev2,v2,&nrot2);
2351 
2352  EIG_[ex][0][0] = v2[0][0];
2353  EIG_[ex][0][1] = v2[0][1];
2354  EIG_[ex][0][2] = v2[0][2];
2355  EIG_[ex][1][1] = v2[1][1];
2356  EIG_[ex][1][2] = v2[1][2];
2357  EIG_[ex][1][0] = v2[1][0];
2358  EIG_[ex][2][0] = v2[2][0];
2359  EIG_[ex][2][1] = v2[2][1];
2360  EIG_[ex][2][2] = v2[2][2];
2361 
2362  qsort(ev2, 3 ,sizeof(core::Real),compare_by_abs);
2363 
2364  EV_[ex][0] = ev2[2];
2365  EV_[ex][1] = ev2[1];
2366  EV_[ex][2] = ev2[0];
2367 
2368  // std::cout << "AL_TENSOR eigenvalues : " << EV_[ex][0] << ' ' << EV_[ex][1] << ' ' << EV_[ex][2] << ' ' << nrot2 << std::endl;
2369 
2370  /*std::cout << "AL_TENSOR eigenvectors : " << std::endl;
2371  std::cout << v2[0][0] << "\t" << v2[1][0] << "\t" << v2[2][0] << std::endl;
2372  std::cout << v2[0][1] << "\t" << v2[1][1] << "\t" << v2[2][1] << std::endl;
2373  std::cout << v2[0][2] << "\t" << v2[1][2] << "\t" << v2[2][2] << std::endl;*/
2374  trace_[ex] = v2[0][0] + v2[1][1] + v2[2][2];
2375  rvec tempvec;
2376  tempvec[0] = v2[0][2];
2377  tempvec[1] = v2[1][2];
2378  tempvec[2] = v2[2][2];
2379  qsort(tempvec, 3, sizeof(core::Real),compare_by_abs);
2380  maxz_[ex] = tempvec[0];
2381  // Real ev_trace = (ev2[2] + ev2[1] +ev2[0]) / 3;
2382  // FA_[ex] = 4.0;
2383  // FA_[ex] = sqrt (0.5) * sqrt( (ev2[0] - ev_trace)*(ev2[0] - ev_trace) + (ev2[1] - ev_trace)*(ev2[1] - ev_trace) + (ev2[2] - ev_trace)*(ev2[2] - ev_trace) ) / sqrt (ev2[0] * ev2[0] + ev2[1] * ev2[1] + ev2[2] * ev2[2]);
2384  // std::cout << "Fractional Anisotropy " << FA_[ex] << std::endl;
2385 
2386  // std::cout << "AL.TENSOR (molecular frame after): " << S_[ex][0][0] << ' ' << S_[ex][0][1] << ' ' << S_[ex][0][2] << ' ' << S_[ex][1][1] << ' ' << S_[ex][1][2] << std::endl;
2387 
2388  // delete[] v2;
2389  // delete[] ev2;
2390 
2391  } //for ( ex = 0 .. nex )
2392 }
2393 
2394 int m_inv_gen(Tensor5 m,int n,Tensor5 minv)
2395 {
2396  Tensor5 md,v;
2397  rvec5 eig;
2398  Real tol,s;
2399  int nzero,i,j,k,nrot;
2400  // md = new Real*[n];
2401  // v = new Real*[n];
2402  // for(i=0; i<n; i++) {
2403  // md[i] = new Real[n];
2404  // v[i] = new Real[n];
2405  // }
2406  // eig = new Real[ n ];
2407  for(i=0; i<n; i++)
2408  for(j=0; j<n; j++)
2409  md[i][j] = m[i][j];
2410 
2411  tol = 0;
2412  for(i=0; i<n; i++)
2413  tol += fabs(md[i][i]);
2414  tol = 1e-6*tol/n;
2415 
2416  jacobi(md,eig,v,&nrot);
2417 
2418  nzero = 0;
2419  for(i=0; i<n; i++)
2420  if (fabs(eig[i]) < tol) {
2421  eig[i] = 0;
2422  nzero++;
2423  } else
2424  eig[i] = 1.0/eig[i];
2425 
2426  for(i=0; i<n; i++)
2427  for(j=0; j<n; j++) {
2428  s = 0;
2429  for(k=0; k<n; k++)
2430  s += eig[k]*v[i][k]*v[j][k];
2431  minv[i][j] = s;
2432  }
2433 
2434  // delete[] eig;
2435  // for(i=0; i<n; i++) {
2436  // delete[] v[i];
2437  // delete[] md[i];
2438  // }
2439 
2440  // delete[] v;
2441  // delete[] md;
2442 
2443  return nzero;
2444  }
2445 
2446 #define ROTATE(a,i,j,k,l) g=a[i][j];h=a[k][l];a[i][j]=g-s*(h+g*tau);\
2447  a[k][l]=h+s*(g-h*tau);
2448 
2449  void jacobi(Real a[5][5],Real d[],Real v[5][5],int *nrot)
2450  {
2451  int j,i;
2452  int iq,ip;
2453  Real tresh,theta,tau,t,sm,s,h,g,c;
2454  Real b[5];
2455  Real z[5];
2456  int const n( 5 );
2457  for (ip=0; ip<n; ip++) {
2458  for (iq=0; iq<n; iq++) v[ip][iq]=0.0;
2459  v[ip][ip]=1.0;
2460  }
2461  for (ip=0; ip<n;ip++) {
2462  b[ip]=d[ip]=a[ip][ip];
2463  z[ip]=0.0;
2464  }
2465  *nrot=0;
2466  for (i=1; i<=50; i++) {
2467  sm=0.0;
2468  for (ip=0; ip<n-1; ip++) {
2469  for (iq=ip+1; iq<n; iq++)
2470  sm += fabs(a[ip][iq]);
2471  }
2472  if (sm == 0.0) {
2473  return;
2474  }
2475  if (i < 4) //first 3 iterations
2476  tresh=0.2*sm/(n*n);
2477  else
2478  tresh=0.0;
2479  for (ip=0; ip<n-1; ip++) {
2480  for (iq=ip+1; iq<n; iq++) {
2481  g=100.0*fabs(a[ip][iq]);
2482  if (i > 4 && fabs(d[ip])+g == fabs(d[ip])
2483  && fabs(d[iq])+g == fabs(d[iq]))
2484  a[ip][iq]=0.0;
2485  else if (fabs(a[ip][iq]) > tresh) {
2486  h=d[iq]-d[ip];
2487  if (fabs(h)+g == fabs(h))
2488  t=(a[ip][iq])/h;
2489  else {
2490  theta=0.5*h/(a[ip][iq]);
2491  t=1.0/(fabs(theta)+sqrt(1.0+theta*theta));
2492  if (theta < 0.0) t = -t;
2493  }
2494  c=1.0/sqrt(1+t*t);
2495  s=t*c;
2496  tau=s/(1.0+c);
2497  h=t*a[ip][iq];
2498  z[ip] -= h;
2499  z[iq] += h;
2500  d[ip] -= h;
2501  d[iq] += h;
2502  a[ip][iq]=0.0;
2503  for (j=0; j<ip; j++) {
2504  ROTATE(a,j,ip,j,iq)
2505  }
2506  for (j=ip+1; j<iq; j++) {
2507  ROTATE(a,ip,j,j,iq)
2508  }
2509  for (j=iq+1; j<n; j++) {
2510  ROTATE(a,ip,j,iq,j)
2511  }
2512  for (j=0; j<n; j++) {
2513  ROTATE(v,j,ip,j,iq)
2514  }
2515  ++(*nrot);
2516  }
2517  }
2518  }
2519  for (ip=0; ip<n; ip++) {
2520  b[ip] += z[ip];
2521  d[ip] = b[ip];
2522  z[ip] = 0.0;
2523  }
2524  }
2525  //probably different type of Exception is better suited
2526  throw( utility::excn::EXCN_BadInput(" too many iterations in Jacobi when compute RDC tensor") );
2527 }
2528 
2529 
2530  void jacobi3(Real a[3][3],Real d[],Real v[3][3],int *nrot)
2531  {
2532  int j,i;
2533  int iq,ip;
2534  Real tresh,theta,tau,t,sm,s,h,g,c;
2535  Real b[3];
2536  Real z[3];
2537  int const n( 3 );
2538  for (ip=0; ip<n; ip++) {
2539  for (iq=0; iq<n; iq++) v[ip][iq]=0.0;
2540  v[ip][ip]=1.0;
2541  }
2542  for (ip=0; ip<n;ip++) {
2543  b[ip]=d[ip]=a[ip][ip];
2544  z[ip]=0.0;
2545  }
2546  *nrot=0;
2547  for (i=1; i<=50; i++) {
2548  sm=0.0;
2549  for (ip=0; ip<n-1; ip++) {
2550  for (iq=ip+1; iq<n; iq++)
2551  sm += fabs(a[ip][iq]);
2552  }
2553  if (sm == 0.0) {
2554  return;
2555  }
2556  if (i < 4) //first 3 iterations
2557  tresh=0.2*sm/(n*n);
2558  else
2559  tresh=0.0;
2560  for (ip=0; ip<n-1; ip++) {
2561  for (iq=ip+1; iq<n; iq++) {
2562  g=100.0*fabs(a[ip][iq]);
2563  if (i > 4 && fabs(d[ip])+g == fabs(d[ip])
2564  && fabs(d[iq])+g == fabs(d[iq]))
2565  a[ip][iq]=0.0;
2566  else if (fabs(a[ip][iq]) > tresh) {
2567  h=d[iq]-d[ip];
2568  if (fabs(h)+g == fabs(h))
2569  t=(a[ip][iq])/h;
2570  else {
2571  theta=0.5*h/(a[ip][iq]);
2572  t=1.0/(fabs(theta)+sqrt(1.0+theta*theta));
2573  if (theta < 0.0) t = -t;
2574  }
2575  c=1.0/sqrt(1+t*t);
2576  s=t*c;
2577  tau=s/(1.0+c);
2578  h=t*a[ip][iq];
2579  z[ip] -= h;
2580  z[iq] += h;
2581  d[ip] -= h;
2582  d[iq] += h;
2583  a[ip][iq]=0.0;
2584  for (j=0; j<ip; j++) {
2585  ROTATE(a,j,ip,j,iq)
2586  }
2587  for (j=ip+1; j<iq; j++) {
2588  ROTATE(a,ip,j,j,iq)
2589  }
2590  for (j=iq+1; j<n; j++) {
2591  ROTATE(a,ip,j,iq,j)
2592  }
2593  for (j=0; j<n; j++) {
2594  ROTATE(v,j,ip,j,iq)
2595  }
2596  ++(*nrot);
2597  }
2598  }
2599  }
2600  for (ip=0; ip<n; ip++) {
2601  b[ip] += z[ip];
2602  d[ip] = b[ip];
2603  z[ip] = 0.0;
2604  }
2605  }
2606  //probably different type of Exception is better suited
2607  throw( utility::excn::EXCN_BadInput(" too many iterations in Jacobi when compute RDC tensor") );
2608 }
2609 
2610 } //namespace Scoring
2611 } //namespace core