ROOTPWA
TPWALikelihoodC.cc
Go to the documentation of this file.
1 
2 //
3 // Copyright 2009 Sebastian Neubert
4 //
5 // This file is part of rootpwa
6 //
7 // rootpwa is free software: you can redistribute it and/or modify
8 // it under the terms of the GNU General Public License as published by
9 // the Free Software Foundation, either version 3 of the License, or
10 // (at your option) any later version.
11 //
12 // rootpwa is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU General Public License for more details.
16 //
17 // You should have received a copy of the GNU General Public License
18 // along with rootpwa. If not, see <http://www.gnu.org/licenses/>.
19 //
21 //-----------------------------------------------------------
22 // File and Version Information:
23 // $Id$
24 //
25 // Description:
26 // Implementation of class TPWALikelihoodC
27 // see TPWALikelihoodC.hh for details
28 //
29 //
30 // Author List:
31 // Sebastian Neubert TUM (original author)
32 //
33 //
34 //-----------------------------------------------------------
35 
36 // This Class' Header ------------------
37 #include "TPWALikelihoodC.h"
38 
39 // C/C++ Headers ----------------------
40 #include <fstream>
41 #include <iostream>
42 #include <sstream>
43 #include <string>
44 #include <list>
45 #include <algorithm>
46 #include <assert.h>
47 
48 // Collaborating Class Headers --------
49 #include "TString.h"
50 #include "TMath.h"
51 #include "TSystem.h"
52 #include "TCMatrix.h"
53 #include "TStopwatch.h"
54 #include "TPWARealConstraint.h"
55 #include "TPWANullConstraint.h"
56 #include "TPWAPhaseConstraint.h"
57 
58 
59 using namespace std;
60 using namespace ROOT;
61 
62 
63 // Class Member definitions ----------
64 
65 
66 TPWALikelihoodC::TPWALikelihoodC() : _rank(1),_dim(0),_nposrefl(0),_nnegrefl(0), _nevents(0),_nwaves(0),_ncalls(0), _Ltime(0), _Ntime(0), _quiet(false),_useNorm(true),_Vflat("flat__+",0),_NumNullConstraints(0)
67 {
69 }
70 
72 {
73  ClearCache();
74 }
75 
76 void
78  for(unsigned int i=0;i<_data.size();++i){
79  if(_data[i]!=NULL){
80  _data[i]->clear();
81  delete (_data[i]);
82  _data[i]=0;
83  }
84  }
85  _data.clear();
86 }
87 
88 
89 void
90 TPWALikelihoodC::Init(const TString& wavelist, unsigned int rank,
91  const TString& norm,
92  const TString& acceptance,
93  int scaleevents,
94  const TString constraints){
95  cout<<"Reading Integrals "<<endl;
96  ifstream file(norm.Data());
97  _I.scan(file);
98  //if(!_quiet)_I.print(cout);
99  file.close();
100  _mat=_I.mat();
101  list<string> normwaves=_I.files();
102  // load acceptance integral
103  file.open(acceptance.Data());
104  _Acc.scan(file);
105  //if(!_quiet)_Acc.print(cout);
106  file.close();
107  _Acc.events(scaleevents);
108  _accmat=_Acc.mat();
109  list<string> accwaves=_Acc.files();
110 
111  cout<<"Reading amplitude names from wavelist "<<wavelist<<endl;
112  // clear production amplitude vector
113  _V.clear();
114  _V.reserve(_rank);
115  _parnames.clear();
116  _rank=rank;
117  // setup vectors
118  for(unsigned int ir=0;ir<rank;++ir){
119  _V.push_back(new vector<TPWAAmp>);
120  }
121  assert(_V.size()==_rank);
122  // read wavelist and fill wavelist vector
123  unsigned int npos=0; // number of positive reflectivity waves
124  unsigned int nneg=0; // number of negative reflectivity waves
125 
126  file.open(wavelist.Data());
127  string line;
128  while(file.good()){
129  getline(file,line);
130  unsigned int pos=line.find(" ");
131  string name=line.substr(0,pos);
132  double thres;
133  if(pos<line.length()){
134  thres=atof(line.substr(pos,line.length()).c_str());
135  } else thres=0;
136 
137  if(!_quiet){
138  cout << name << " thresh=" << thres << endl;
139  }
140  if(line.length()>1){
141  // check normalization and acceptance integral index
142  if(find(normwaves.begin(),normwaves.end(),name)==normwaves.end()){
143  cout << "Wave " << name
144  << " not in normalization integrals! Aborting!" << endl;
145  throw;
146  }
147  unsigned int normindex=_I.index(name);
148  if(find(accwaves.begin(),accwaves.end(),name)==accwaves.end()){
149  cout << "Wave " << name
150  << " not in acceptance integrals! Aborting!" << endl;
151  throw;
152  }
153  unsigned int accindex=_Acc.index(name);
154 
155  _wavenames.push_back(name);
156 
157  // assign to rank
158  for(unsigned int ir=0;ir<_rank;++ir){
159  // positivity constraints:
160  TPWAAmp amp(name,ir,thres,normindex,accindex);
161  unsigned int nrefl;
162  if(amp.reflectivity()==1){
163  nrefl=npos;
164  if(ir==_rank-1)++npos;
165  }
166  else{
167  nrefl=nneg;
168  if(ir==_rank-1)++nneg;
169  }
170  if(nrefl<ir){
172  ++_NumNullConstraints; // number of null-constraint waves
173  }
174  if(nrefl==ir)amp.setConstraint(new TPWARealConstraint());
175  _V[ir]->push_back(amp);
176 
177  if(!_quiet){
178  cout << amp.name() << " rank" << ir << " " << amp.type() << endl;
179  }
180  } // end loop over rank
181  } // end checking line length
182  } // end reading waveset file
183 
184  // IMPORTANT TO PUT THIS HERE!!!
185  _nwaves=_V[0]->size();
186 
187  // apply constraints
188  if(constraints.Length()>1){
189  cout << "Loading Constraint Config: "<< constraints << endl;
190  addConstraints(constraints);
191  }
192  // calculate dimension of parameter vector
193  _dim=0;
194  for(unsigned int iamp=0;iamp<_nwaves; ++iamp){
195  for(unsigned int ir=0;ir<_rank;++ir){
196  _dim+=(*_V[ir])[iamp].npar();
197  for(int ipar=0;ipar<(*_V[ir])[iamp].npar();++ipar){
198  _parnames.push_back((*_V[ir])[iamp].parname(ipar));
199  _parthresholds.push_back((*_V[ir])[iamp].threshold());
200  }
201  }
202  }
203 
204 
205 
206  // add flat
207  _dim+=_Vflat.npar();
208  _parnames.push_back("V_flat_RE");
209 
210  assert(_dim==_parnames.size());
211  _parcache.resize(_dim);
212  _dLcache.resize(_dim);
213  // Number of waves from first rank
214 
215 
216  // prepare some memory:
217  for(unsigned int ir=0;ir<_rank;++ir){
218  _dL.push_back(new vector<complex<double> >(_nwaves,complex<double>(0,0)));
219  _dl.push_back(new vector<complex<double> >(_nwaves,complex<double>(0,0)));
220  _dLN.push_back(new vector<complex<double> >(_nwaves,complex<double>(0,0)));
221  }
222 }
223 
224 // reads in all amplitude files and stores values in memory
225 void
227  // for normalization the integrals need to be loaded first!
228  if( _mat.nrows()==0 ) {
229  cout << "Normalization integrals have to be loaded before amplitudes! "
230  << " ABORTING!" << endl;
231  throw;
232  }
233 
234  ProcInfo_t info1, info2;
235  gSystem->GetProcInfo(&info1);
236  if(!_quiet){
237  cout << "Memory before: " << info1.fMemResident << endl;
238  cout<<"Loading amplitudes"<<endl;
239  }
240 
241  // first clear cache
242  ClearCache();
243 
244  // loop over amplitudes and read in data:
245 
246  for(unsigned int i=0;i<_nwaves;++i){
247  ifstream ampfile(_V[0]->at(i).name().c_str());
248  if(!ampfile.good()){
249  cout<<" File not found! Aborting!"<<endl;
250  throw;
251  }
252  // get integral
253  unsigned int index=_V[0]->at(i).normindex();
254  complex<double> I=_mat.el(index,index);
255  // create cache:
256  vector<complex<double> >* amps=new vector<complex<double> >();
257  amps->reserve(_nevents);
258  _data.push_back(amps);
259  // read file
260  complex<double> a1;
261  while (ampfile.read((char*) &a1,sizeof(complex<double>))){
262  //cout << a1 << endl;
263  // if option is switched on -> renormalize:
264  if(_useNorm){
265  // rescale decay amplitude
266  a1/=sqrt(I.real());
267  }
268  amps->push_back(a1);
269  }
270  if(!_quiet)cout<<amps->size()<<" events"<<endl;
271  _nevents=amps->size();
272  // TODO: cross check that all files have the same number of events!
273  }
274 
275  if(!_quiet){
276  gSystem->GetProcInfo(&info2);
277  cout << "Memory after: " << info2.fMemResident << endl;
278  cout << "Memory used for amplitudes: "
279  << info2.fMemResident-info1.fMemResident << endl;
280  }// endif quiet
281 
282  // ***********************************************************
283  // rescale integrals if necessary
284  // remember: we have two copies of the matrix! -> change both!
285  // so far only one is changed!!!!!!!!!!!!!!!
286  if(_useNorm){
287  if(!_quiet)cout << "Renormalizing Integrals ... ";
288  // Normalization:
289  for(unsigned int i=0;i<_nwaves;++i){// outer loop over waves
290  unsigned int index1=_V[0]->at(i).normindex();
291  double Ni=sqrt(_mat.el(index1,index1).real());
292  for(unsigned int j=0;j<_nwaves;++j){
293  if(i==j)continue; // do diagonal terms later!
294  unsigned int index2=_V[0]->at(j).normindex();
295  double Nj=sqrt(_mat.el(index2,index2).real());
296  _mat.el(index1,index2)/=(Ni*Nj);
297  } // end inner loop
298  }// end out loop
299  if(!_quiet)cout << "Renormalizing Acceptance Integrals ... " << endl;
300  if(!_quiet)cout << "Note: Diagonal Terms of Renorm.Integrals are not = 1 here!";
301  // Acceptance:
302  // Remember that the matrices _mat and _accmat are already normalized
303  // to the number of montecarlo events!
304  for(unsigned int i=0;i<_nwaves;++i){// outer loop over waves
305  unsigned int index1=_V[0]->at(i).normindex();
306  unsigned int accindex1=_V[0]->at(i).accindex();
307  double Ni=sqrt(_mat.el(index1,index1).real());
308  for(unsigned int j=0;j<_nwaves;++j){
309  unsigned int index2=_V[0]->at(j).normindex();
310  unsigned int accindex2=_V[0]->at(j).accindex();
311  double Nj=sqrt(_mat.el(index2,index2).real());
312  _accmat.el(accindex1,accindex2)/=(Ni*Nj);
313  if(!_quiet) cout <<" Norm("<<i<<j<<"): "
314  <<_mat.el(index1,index2)
315  << " Acc("<<i<<j<<"): "
316  <<_accmat.el(accindex1,accindex2)<< endl;
317  } // end inner loop
318  }// end out loop
319 
320  // do diagonal terms of normalization only after all other things have
321  // been done
322  if(!_quiet)cout << "Renormalizing Diagonal terms ... " << endl;
323  for(unsigned int i=0;i<_nwaves;++i){
324  unsigned int index1=_V[0]->at(i).normindex();
325  _mat.el(index1,index1)=1;
326  if(!_quiet) cout <<" Norm("<<i<<i<<"): "
327  << _mat.el(index1,index1) << endl;
328  }
329  if(!_quiet)cout << "...finished." << endl;
330  }// end if useNorm
331 } // end load amplitudes
332 
333 
334 
335 void
336 TPWALikelihoodC::partoamp(const double* x) const {
337  double par[2];
338  unsigned int k=0;
339 
340  for(unsigned int r=0;r<_rank;++r){
341  vector<TPWAAmp>* V=_V[r];
342  unsigned int nwaves=V->size();
343  for(unsigned int i=0;i<nwaves;++i){
344  unsigned int npar=(*V)[i].npar();
345  for(unsigned int ipar=0;ipar<npar;++ipar){
346  par[ipar]=x[k++];
347  }
348  (*V)[i].setPar(par);
349  } // loop over waves
350  } // end loop over rank
351  // loop again to update contraints
352  for(unsigned int r=0;r<_rank;++r){
353  for(unsigned int i=0;i<_nwaves;++i){
354  (*_V[r])[i].updateAmp();
355  } // loop over waves
356  } // end loop over rank
357  // do background:
358  par[0]=x[k];par[1]=0;
359  assert(k==_dim-1);
360  _Vflat.setPar(par);
361 }
362 
363 void
364 TPWALikelihoodC::amptopar(double* x) const {
365  unsigned int k=0;
366  for(unsigned int r=0;r<_rank;++r){
367  unsigned int nwaves=_V[r]->size();
368  for(unsigned int i=0;i<nwaves;++i){
369  unsigned int npar=(*_V[r])[i].npar();
370  for(unsigned int ipar=0;ipar<npar;++ipar){
371  x[k++]=(*_V[r])[i].par(ipar);
372  }
373  } // loop over waves
374  } // end loop over rank
375  x[k]=_Vflat.par(0);
376 }
377 
378 void
380  for(unsigned int r=0;r<_rank;++r){
381  unsigned int nwaves=_V[r]->size();
382  for(unsigned int i=0;i<nwaves;++i){
383  cout << (*_V[r])[i] << endl;
384  }
385  }
386  cout << _Vflat << endl;
387 }
388 
389 
390 // Likelyhood and first derivatives in one go: *****************************
391 
392 void
393 TPWALikelihoodC::FdF(const double* x, double& f, double* df) const {
394  if(!_quiet)cout << " Calling FdF !!!!!!!!!!! " << endl;
395 
396  ++_ncalls;
397 
398  // check timing
399  TStopwatch timer;
400  timer.Start(true);
401 
402  // parameter cache:
403  for(unsigned int ix=0;ix<_dim;++ix)(*const_cast<vector<double>*>(&_parcache))[ix]=x[ix];
404 
405  // build complex numbers from parameters
406  // remember rank restrictions!
407  // vector<complex<double> > V(_rank*_nwaves);
408 
409  // load parameters into amplitudes
410  partoamp(x);
411 
412  // loglikelyhood:
413  double L=0;
414  // reset derivatives
415  for(unsigned int ir=0;ir<_rank;++ir){
416  for(unsigned int ia=0;ia<_nwaves;++ia){
417  (*_dL[ir])[ia]=complex<double>(0,0);
418  (*_dl[ir])[ia]=complex<double>(0,0);
419  (*_dLN[ir])[ia]=complex<double>(0,0);
420  }
421  }
422 
423  double dLdflat=0;
424  // amplitude:
425  // two contributions for two reflectivities
426  complex<double> Aplus(0,0);
427  complex<double> Aminus(0,0);
428  // loop over events and calculate log likelihood
429  // and calculate derivatives with respect to parameters
430  for(unsigned int ievt=0;ievt<_nevents;++ievt){
431  //if(ievt<3 || _nevents-ievt<4)cout << "event"<< ievt << "_____________________" << endl;
432  double l=0; // likelihood contribution of this event
433  // incoherent sum over ranks: loop
434  for(unsigned int r=0;r<_rank;++r){
435  for(unsigned int iamp=0;iamp<_nwaves;++iamp){ // loop over waves
436  // contribution to likelihood:
437  complex<double> a=(*_V[r])[iamp] * ((*_data[iamp])[ievt]);
438  int thisrefl=(*_V[r])[iamp].reflectivity();
439  if(thisrefl==-1)Aminus+=a;
440  else Aplus+=a;
441  //if(ievt<3 || _nevents-ievt<4)cout << "refl="<<thisrefl<< a << endl;
442  // contributions to derivatives:
443  for(unsigned int k=0;k<_nwaves; ++k){ // loop over derivatives
444  // loop (only inside current rank) and only for waves with same refl
445  if(thisrefl==(*_V[r])[k].reflectivity())(*_dl[r])[k]+=a;
446  } // end loop over derivatives
447 
448  } // end loop over waves
449  l+=std::norm(Aplus);
450  l+=std::norm(Aminus);
451  Aplus.real()=0;Aplus.imag()=0;Aminus.real()=0;Aminus.imag()=0;
452  assert(l>=0);
453  for(unsigned int k=0;k<_nwaves; ++k){ // again loop over derivatives
454  // loop (only inside current rank)
455  (*_dl[r])[k]*=std::conj((*_data[k])[ievt]);
456  } // end loop over derivatives
457 
458  }// end loop over rank
459  l+=std::norm(_Vflat.amp());
460  L-=TMath::Log(l);
461  //loop over derivatives to incorporate factor 2/sigma
462  double g=2./l;
463  for(unsigned int ir=0;ir<_rank;++ir){
464  for(unsigned int id=0;id<_nwaves; ++id){
465  (*_dL[ir])[id]-=(*_dl[ir])[id]*g;
466  (*_dl[ir])[id].real()=0;
467  (*_dl[ir])[id].imag()=0;
468  }
469  }
470  dLdflat-=_Vflat.amp().real()*g;
471  }// end loop over events for calculation of intensity term
472 
473 
474  double t1=timer.RealTime();
475  timer.Start(true);
476 
477  // add normalization integrals ?? TODO: can we exploit symmetry here?
478  complex<double> N(0,0);
479  unsigned int outcount=0; // output array counter
480 
481  // event number normalization
482  double nevt;
483  double n2;
484  if(!_useNorm){
485  nevt=(double)_nevents;
486  n2=2*nevt;
487  }
488  else {
489  nevt=1;
490  n2=2;
491  }
492 
493  for(unsigned int r=0; r<_rank;++r){ // loop over rank **********************
494  //cout <<"/n Rank"<<r<<endl;
495  for(unsigned int iamp=0;iamp<_nwaves;++iamp){// outer loop *************
496  TPWAAmp& ampi=(*_V[r])[iamp];
497  for(unsigned int jamp=0;jamp<_nwaves;++jamp){ // inner loop ********
498  TPWAAmp& ampj=(*_V[r])[jamp];
499  // check if i and j are of the same reflectivity
500  if(ampi.reflectivity()!=ampj.reflectivity())continue;
501  complex<double> p=ampi.amp()*std::conj(ampj.amp());
502  //cout<<_wavenames[iamp]<<" "<<_wavenames[jamp]<<endl;
503  complex<double> I=_accmat.el(ampi.accindex(),ampj.accindex());
504  //cout<<"I="<<I<<endl;
505  //cout<<"p="<<p<<endl;
506  p*=I;
507  N+=p;
508  // calculate contribution to derivative
509  (*_dLN[r])[iamp]+=ampj.amp()*std::conj(I);
510  }// end inner loop over waves **************************************
511  // account for 2nevents:
512  (*_dL[r])[iamp]+=(*_dLN[r])[iamp]*n2;
513  // ---------------------------------------
514  // sort results for derivatives into output array and cache:
515  unsigned int npar=ampi.npar();
516  for(unsigned int ipar=0;ipar<npar;++ipar){
517  // dL/dpar = dL/dRE*dR/dpar + dL/dIM*dIM/dpar
518  std::complex<double> deriv=ampi.dampdpar(ipar);
519  _dLcache[outcount]=(*_dL[r])[iamp].real()*deriv.real()+(*_dL[r])[iamp].imag()*deriv.imag();
520  df[outcount]=_dLcache[outcount];
521  ++outcount;
522  } // end loop over parameters (given by possibly contraint amp)
523 
524  //cout << "df(r="<<r<<",i="<<iamp<<")="<<dL[_offset[r]+iamp]<<endl;
525  }// end outer loop over waves ******************************************
526  } // end loop over rank ****************************************************
527  // take care of derivative for flat:
528  _dLcache[outcount]=dLdflat+n2*_Vflat.amp().real();
529  df[outcount]=dLdflat+n2*_Vflat.amp().real();
530 
531 
532  N.real()+=std::norm(_Vflat.amp());
533 
534  double t2=timer.RealTime();
535  timer.Stop();
536 
537  _Ltime+=t1;
538  _Ntime+=t2;
539 
540  if(!_quiet){
541  cout << "LikelihoodC: "<<L<<endl;
542  cout << "Normalization: "<< N.real() << endl;
543  cout << "Normalized: "<<L + nevt*N.real() << endl;
544  cout << "Time for LikelihoodC: "<< t1 <<endl;
545  cout << "Time for Normalization: "<< t2 <<endl;
546  }
547  f=L + nevt*N.real(); // return value of likelihood
548 
549 
550 
551 
552 
553  return;
554 }
555 
556 
557 //************************************************************************
558 
559 double
560 TPWALikelihoodC::DoEval(const double* x) const
561 {
562 
563  // call FdF
564  double df[_dim];
565  double L;
566  FdF(x, L,df);
567  return L;
568  /*
569 
570  // build complex numbers from parameters
571  // remember rank restrictions!
572  ++(*const_cast<unsigned int*>(&_ncalls));
573 
574  // check timing
575  TStopwatch timer;
576  timer.Start(true);
577 
578 
579  vector<complex<double> > V(_rank*_nwaves);
580  double re,im;
581  unsigned int k=0;
582  for(unsigned int r=0;r<_rank;++r){
583  //cout<<"Rank "<<r<<" offset="<<_offset[r]<<endl;
584  for(unsigned int i=0;i<_nwaves;++i){
585  if(i<r){re=0;im=0;}
586  else if(i==r){re=x[k++];im=0;} // real parameter
587  else {
588  re=x[k++];
589  im=x[k++];
590  }
591  V[_offset[r]+i]=complex<double>(re,im);
592  //cout<<"Wave"<<i<<"="<<V[_offset[r]+i]<<endl;
593  }
594  } // end loop over rank
595  double flat=x[k];
596  double flat2=flat*flat;
597 
598  double L=0;
599  // loop over events and calculate log likelyhood
600  for(unsigned int ievt=0;ievt<_nevents;++ievt){
601  double l=0;
602  // incoherent sum over ranks: loop
603  for(unsigned int r=0;r<_rank;++r){
604  complex<double> A(0,0);
605  for(unsigned int iamp=0;iamp<_nwaves;++iamp){
606  A+=(V[_offset[r]+iamp]*((*_data[iamp])[ievt]));
607  } // end loop over waves
608  //cout << "A2=" << std::norm(A) << endl;
609  l+=std::norm(A);
610  assert(l>=0);
611  //cout << "l="<< l << endl;
612  }// end loop over rank
613  l+=flat2;
614  L-=TMath::Log(l);
615  //cout << "L="<< L << endl;
616  }// end loop over events
617 
618  double t1=timer.RealTime();
619  timer.Start(true);
620  // add normalization integrals ?? TODO: can we exploit symmetry here?
621  complex<double> N(0,0);
622  for(unsigned int r=0; r<_rank;++r){
623  //cout <<"/n Rank"<<r<<endl;
624  for(unsigned int iamp=r;iamp<_nwaves;++iamp){
625  for(unsigned int jamp=r;jamp<_nwaves;++jamp){
626  complex<double> p=V[_offset[r]+iamp]*std::conj(V[_offset[r]+jamp]);
627  //cout<<_wavenames[iamp]<<" "<<_wavenames[jamp]<<endl;
628  complex<double> I=(const_cast<intmat*>(&_mat)->el(_wmap[iamp],_wmap[jamp]));
629  //cout<<"I="<<I<<endl;
630  //cout<<"p="<<p<<endl;
631  p*=I;
632  N+=p;
633  }// end inner loop over waves
634  }// end outer loop over waves
635  } // end loop over rank
636  N.real()+=flat2;
637 
638  double t2=timer.RealTime();
639  timer.Stop();
640 
641  (*const_cast<double*>(&_Ltime))+=t1;
642  (*const_cast<double*>(&_Ntime))+=t2;
643 
644  cout << "LikelihoodC: "<<L<<endl;
645  cout << "Normalization: "<< N.real() << endl;
646  cout << "Normalized: "<<L + (double)_nevents*N.real() << endl;
647  cout << "Time for LikelihoodC: "<< t1 <<endl;
648  cout << "Time for Normalization: "<< t2 <<endl;
649 
650  return L + (double)_nevents*N.real();
651  */
652 }
653 
654 double
655 TPWALikelihoodC::DoDerivative(const double* x, unsigned int idf) const
656 {
657  //cout << " Calling Derivative !!!!!!!!!!! " << endl;
658 
659  // check if we have cached this
660  bool same_x=true;
661  for(unsigned int i=0; i<_dim; ++i){
662  same_x &= (_parcache[i]==x[i]);
663  }
664  if(same_x){
665  //cout << "using cached derivative! " << endl;
666  return _dLcache[idf];
667  }
668 
669  // call FdF
670  double L;
671  double df[_dim];
672  FdF(x, L,df);
673 
674  return df[idf];
675 }
676 
677 unsigned int
679  return _dim;
680 }
681 
682 // Complex valued Amplitudes and
683 // mapping of real and imaginary part of amplitudes
684 // in error matrix (needed by TFitBin)
685 // takes into account real-valued parameters
686 void
687 TPWALikelihoodC::buildCAmps(const double* x, vector<complex<double> >& V,
688  vector<pair<int,int> >& indices,
689  vector<string>& names,
690  const TMatrixD& errpar,
691  TMatrixD& erramp,
692  bool withFlat){
693  // build complex numbers from parameters
694  // remember rank restrictions!
695  V.clear();
696  indices.clear();
697  names.clear();
698  erramp.Clear();
699  //unsigned int namp=_rank*_nwaves;
700  //if(withFlat)namp+=1;
701 
702 
703  partoamp(x);
704  unsigned int m=2*(_nwaves*_rank);
705  if(withFlat)m+=2;
706  erramp.ResizeTo(m,m);
707  // transformation matrix from parameters to amps
708  // (linearized version of partoamp)
709  TMatrixD T(m,NDim());
710 
711 
712  unsigned int parcount=0;
713  for(unsigned int r=0;r<_rank;++r){
714  //cout<<"Rank "<<r<<" offset="<<_offset[r]<<endl;
715  for(unsigned int i=0;i<_nwaves;++i){
716  string wavename=(*_V[r])[i].name();
717  V.push_back((*_V[r])[i].amp());
718  stringstream name;
719  name << "V" << r << "_" << wavename;
720  names.push_back(name.str());
721  // now produce error matrix for amplitudes
722  // loop over amplitudes to get all the entries for this row
723  unsigned int npar=(*_V[r])[i].npar();
724  for(unsigned int ipar=0;ipar<npar;++ipar){
725  complex<double> dAdp=(*_V[r])[i].dampdpar(ipar);
726  T[r*2*_nwaves+2*i][parcount]=dAdp.real(); // d(real)/dpar
727  T[r*2*_nwaves+2*i+1][parcount]=dAdp.imag(); // d(im)/dpar
728  ++parcount;
729  }
730  indices.push_back(pair<int,int>(r*2*_nwaves+2*i,r*2*_nwaves+2*i+1));
731  } // end loop over waves
732  } // end loop over rank
733 
734  if(withFlat){
735  V.push_back(complex<double>(x[parcount],0));
736  T[_rank*2*_nwaves][parcount]=1;
737  T[_rank*2*_nwaves+1][parcount]=0;
738  indices.push_back(pair<int,int>(_rank*2*_nwaves,_rank*2*_nwaves+1));
739  names.push_back("V_flat");
740  }
741 
742  TMatrixD TT(TMatrixD::kTransposed,T);
743  TMatrixD CTT=errpar*TT;
744  erramp=T*CTT;
745 
746 }
747 
748 
749 
750 // depends on naming convention for waves!!!
751 // VR_IGJPCMEIso....
752 int
753 TPWALikelihoodC::geteps(TString wavename){
754  int eps=0;
755  unsigned int i=6;
756  if(wavename[0] == 'V') {
757  i=9; // check if we have a parameter name
758  //cout << "geteps from parameter name" << endl;
759  }
760  if(wavename[i] == '-') eps= -1;
761  else if(wavename[i] == '+') eps= 1;
762  else {
763  cout<<"Wrong wavename format. "
764  <<"Could not determine reflectivity! Aborting!"<<endl;
765  throw;
766  }
767  //cout << "eps=" << eps << endl;
768  return eps;
769 }
770 
771 void
773  //integr.ResizeTo(_nwaves,_nwaves
774  for(unsigned int i=0;i<_nwaves;++i){// begin outer loop
775  for(unsigned int j=0;j<_nwaves;++j){
776  integr.set(i,j,_mat.el((*_V[0])[i].normindex(),(*_V[0])[j].normindex()));
777  acceptance.set(i,j,_mat.el((*_V[0])[i].accindex(),(*_V[0])[j].accindex()));
778  }// end inner loop
779  } // end outere loop over parameters;
780  // add flat
781  integr.set(_nwaves,_nwaves,complex<double>(1,0));
782  acceptance.set(_nwaves,_nwaves,complex<double>(1,0));
783 }
784 
785 // A simple factory for creating contraint objects
786 // Supports: TPWAPhaseContsraint
787 // config file format:
788 //
789 // <ConstraintType> {
790 // ConstraintWave
791 // Parameter2
792 // ...
793 // ParameterN
794 // }
795 //
796 // For example:
797 // Phase {
798 // ConstraintWave
799 // Masterwave
800 // RelativePhase
801 // }
802 
803 unsigned int
804 TPWALikelihoodC::addConstraints(TString ConstraintsFile){
805  ifstream cfile(ConstraintsFile.Data());
806  unsigned int ccounter=0;
807  char line[256];
808  if(!cfile.good()){
809  cout << "Invalid constraint file " << ConstraintsFile << endl;
810  return 0;
811  }
812 
813  while(cfile.good()){
814  cfile.getline(line,256);
815  // check if we have a valid token
816  if(strchr(line,'{')!=NULL){
817  // process constraint:
818  // which contraint?
819  if(strstr(line,"Phase")){
820  // get 3 paramters:
821  cfile.getline(line,256);
822  string slavewave(line);
823  cfile.getline(line,256);
824  string masterwave(line);
825  cfile.getline(line,256);
826  double phase=atof(line);
827  // check if master and slave are in our waveset
828  unsigned int imaster=_nwaves+1;
829  unsigned int islave=_nwaves+1;
830  for(unsigned int iamp=0;iamp<_nwaves; ++iamp){
831  if((*_V[0])[iamp].name()==masterwave)imaster=iamp;
832  else if((*_V[0])[iamp].name()==slavewave)islave=iamp;
833  } // end loop over waves
834  if(imaster>=_nwaves){
835  cout << "Master wave " << masterwave << " not in waveset. Skipping phase constraint of " << slavewave << endl;
836  }
837  if(islave>=_nwaves){
838  cout << "Constraint wave " << slavewave << " not in waveset. Skipping phase constraint to " << masterwave << endl;
839  }
840  else { // checks succeed
841  cout << "Constraining " << slavewave
842  << " to " << masterwave
843  << " with relative phase dPhi=" << phase << endl;
844  // INSTALL CONSTRAINT IN ALL RENKS
845  for(unsigned int ir=0; ir<_rank; ++ir){
846  (*_V[ir])[islave].setConstraint(new TPWAPhaseConstraint(phase,&(*_V[0])[imaster]));
847  ++ccounter;
848  } // end loop over rank
849  } // end checks if waves are found soucceed
850  } // end PHASE CONSTRAINT --------------------------------------
851  else {
852  cout << "Unknown constraint" << line << " Aborting." << endl;
853  throw;
854  } // end Unknown constraint -------------------------------------
855  cfile.getline(line,256); // get trailing line.
856  } // end constraint block
857  } // end loop through constraint config file
858  cfile.close();
859  cout << "Installed "<<ccounter<< " contraints."<<endl;
860  return ccounter;
861 }