40 #include "Math/SpecFuncMathCore.h"
41 #include "Math/ProbFuncMathCore.h"
42 #include "TDecompChol.h"
44 #include "TMatrixDSym.h"
60 fitResult::fitResult()
66 _covMatrixValid(false),
73 : _nmbEvents (fitBin.nmbEvents()),
74 _normNmbEvents (fitBin.normNmbEvents()),
75 _massBinCenter (fitBin.massBinCenter()),
76 _logLikelihood (fitBin.logLikelihood()),
77 _rank (fitBin.rank()),
78 _covMatrixValid (fitBin.fitParCovMatrixValid()),
79 _fitParCovMatrix (fitBin.fitParCovMatrix()),
80 _fitParCovMatrixIndices(fitBin.fitParCovIndices()),
81 _normIntegral (fitBin.normIntegral()),
82 _normIntIndexMap (fitBin.prodAmpIndexMap()),
88 const unsigned int nmbAmpNames = fitBin.
prodAmpNames().size();
90 for (
unsigned int i = 0;
i < nmbAmpNames; ++
i)
94 const unsigned int nmbWaveNames = fitBin.
waveNames().size();
96 for (
unsigned int i = 0;
i < nmbWaveNames; ++
i)
103 : _nmbEvents (result.nmbEvents()),
104 _normNmbEvents (result.normNmbEvents()),
105 _massBinCenter (result.massBinCenter()),
106 _logLikelihood (result.logLikelihood()),
107 _rank (result.rank()),
108 _prodAmps (result.prodAmps()),
109 _prodAmpNames (result.prodAmpNames()),
110 _waveNames (result.waveNames()),
111 _covMatrixValid (result.covMatrixValid()),
112 _fitParCovMatrix (result.fitParCovMatrix()),
113 _fitParCovMatrixIndices(result.fitParCovIndices()),
114 _normIntegral (result.normIntegralMatrix()),
115 _normIntIndexMap (result.normIntIndexMap()),
116 _phaseSpaceIntegral (result._phaseSpaceIntegral),
117 _converged (result._converged),
118 _hasHessian (result._hasHessian)
123 #ifdef USE_TFITRESULT
125 : _nmbEvents (result.nmbEvents()),
126 _normNmbEvents (result.normNmbEvents()),
127 _massBinCenter (result.massBinCenter()),
128 _logLikelihood (result.logLikelihood()),
129 _rank (result.rank()),
130 _prodAmps (result.prodAmps()),
131 _prodAmpNames (result.prodAmpNames()),
132 _waveNames (result.waveNames()),
133 _covMatrixValid (result.covMatrixValid()),
134 _fitParCovMatrix (result.fitParCovMatrix()),
135 _fitParCovMatrixIndices(result.fitParCovIndices()),
136 _normIntegral (result.normIntegralMatrix()),
137 _normIntIndexMap (result.normIntIndexMap())
153 cerr <<
"Starting Cholesky Decomposition" << endl;
156 TMatrixT<Double_t> C(decomp.GetU());
157 cerr <<
"...Done" << endl;
159 unsigned int npar=C.GetNrows();
162 for(
unsigned int ipar=0;ipar<npar;++ipar){
163 x(ipar,0)=gRandom->Gaus();
168 TMatrixD y(C,TMatrixD::kMult,x);
173 for(
unsigned int it=0;it<nt;++it){
177 if(jre>-1)re+=y(jre,0);
178 if(jim>-1)im+=y(jim,0);
180 cerr <<
"Modifying amp " << it <<
" by (" << (jre>-1 ? y(jre,0) : 0)
181 <<
"," << (jim>-1 ? y(jim,0) : 0) <<
")" << endl;
210 for (
unsigned int i = 0;
i < ni ; ++
i)
216 double lvad=0.5*(d*1.837877066+TMath::Log(det));
220 double lva= TMath::Log(d) + 0.5*(d*1.144729886+(d-1)*TMath::Log(
_nmbEvents))-ROOT::Math::lgamma(0.5*d+1);
230 for(
unsigned int iwaves=0;iwaves<nwaves;++iwaves){
235 double prob=ROOT::Math::normal_cdf_c(5.*err,err,val);
237 logprob+=TMath::Log(prob);
254 return l + lvad - lva + logprob;
263 const unsigned int waveIndexB)
const
266 const vector<pair<unsigned int, unsigned int> > prodAmpIndexPairs
268 if (prodAmpIndexPairs.size() == 0)
271 complex<double> spinDens = 0;
272 for (
unsigned int i = 0;
i < prodAmpIndexPairs.size(); ++
i)
283 TString name(parName);
284 const bool realPart = (name.Contains(
"RE") || name.Contains(
"flat"));
287 name.ReplaceAll(
"_RE",
"");
289 name.ReplaceAll(
"_IM",
"");
315 const unsigned int dim = 2 * prodAmpIndices.size();
318 printWarn <<
"fitResult does not have a valid error matrix. Returning zero covariance matrix." << endl;
322 vector<int> parCovIndices;
323 for (
unsigned int i = 0;
i < prodAmpIndices.size(); ++
i) {
328 for (
unsigned int row = 0; row < dim; ++row)
329 for (
unsigned int col = 0; col < dim; ++col) {
330 const int i = parCovIndices[row];
331 const int j = parCovIndices[col];
332 if ((i >= 0) && (j >= 0))
345 const unsigned int waveIndexB)
const
348 const vector<pair<unsigned int, unsigned int> > prodAmpIndexPairs
351 TMatrixT<double> spinDensCov(2, 2);
359 const unsigned int dim = prodAmpCov.GetNcols();
360 TMatrixT<double> jacobian(2, dim);
362 for (
unsigned int i = 0;
i < prodAmpIndexPairs.size(); ++
i) {
363 const unsigned int ampIndexB = prodAmpIndexPairs[
i].second;
365 jacobian.SetSub(0, 2 *
i, subJacobianA);
369 TMatrixT<double>
M(2, 2);
372 const unsigned int colOffset = 2 * prodAmpIndexPairs.size();
373 for (
unsigned int i = 0;
i < prodAmpIndexPairs.size(); ++
i) {
374 const unsigned int ampIndexA = prodAmpIndexPairs[
i].first;
377 jacobian.SetSub(0, colOffset + 2 *
i, subJacobianB);
381 const TMatrixT<double> jacobianT(TMatrixT<double>::kTransposed, jacobian);
384 const TMatrixT<double> prodAmpCovJT = prodAmpCov * jacobianT;
385 const TMatrixT<double> spinDensCov = jacobian * prodAmpCovJT;
398 for (
unsigned int i = 0;
i < waveIndices.size(); ++
i) {
402 for (
unsigned int j = 0; j <
i; ++j) {
403 intensity +=
overlap(waveIndices[i], waveIndices[j]);
415 const unsigned int prodAmpIndexB)
const
418 const bool flatWaveA =
prodAmpName(prodAmpIndexA).Contains(
"flat");
419 const bool flatWaveB =
prodAmpName(prodAmpIndexB).Contains(
"flat");
420 if (flatWaveA && flatWaveB)
422 else if (flatWaveA || flatWaveB)
425 map<int, int>::const_iterator indexA =
_normIntIndexMap.find(prodAmpIndexA);
426 map<int, int>::const_iterator indexB =
_normIntIndexMap.find(prodAmpIndexB);
428 printWarn <<
"Amplitude index " << prodAmpIndexA <<
" or " << prodAmpIndexB
429 <<
" is out of bound." << endl;
445 const unsigned int nmbAmps = prodAmpIndices.size();
450 TMatrixT<double> jacobian(1, 2 * nmbAmps);
451 for (
unsigned int i = 0;
i < nmbAmps; ++
i) {
454 complex<double> ampNorm = 0;
456 for (
unsigned int j = 0; j < nmbAmps; ++j) {
461 jacobian[0][2 *
i ] = ampNorm.real();
462 jacobian[0][2 * i + 1] = ampNorm.imag();
466 const TMatrixT<double> jacobianT(TMatrixT<double>::kTransposed, jacobian);
467 const TMatrixT<double> prodAmpCovJT = prodAmpCov * jacobianT;
468 const TMatrixT<double> intensityCov = jacobian * prodAmpCovJT;
469 return sqrt(intensityCov[0][0]);
476 const unsigned int waveIndexB)
const
478 if (waveIndexA == waveIndexB)
487 const unsigned int waveIndexB)
const
493 TMatrixT<double> jacobian(1, 2);
495 const double x = spinDens.real();
496 const double y = spinDens.imag();
497 if ((x != 0) || (y != 0)) {
498 jacobian[0][0] = 1 / (x + y * y / x);
499 jacobian[0][1] = -y / (x * x + y * y);
503 const double phaseVariance =
realValVariance(waveIndexA, waveIndexB, jacobian);
504 return sqrt(phaseVariance) * TMath::RadToDeg();
511 const unsigned int waveIndexB)
const
516 return sqrt(std::norm(rhoAB) / (rhoAA * rhoBB));
523 const unsigned int waveIndexB)
const
528 if (!
_covMatrixValid || (prodAmpIndices[0].size() == 0) || (prodAmpIndices[1].size() == 0))
532 const unsigned int nmbAmps = prodAmpIndices[0].size() + prodAmpIndices[1].size();
533 TMatrixT<double> jacobian(1, 2 * nmbAmps);
538 const double rhoABRe = rhoAB.real();
539 const double rhoABIm = rhoAB.imag();
540 const double rhoABNorm = std::norm(rhoAB);
541 const double coh = sqrt(rhoABNorm / (rhoAA * rhoBB));
545 for (
unsigned int i = 0;
i < prodAmpIndices[0].size(); ++
i) {
546 const unsigned int prodAmpIndexA = prodAmpIndices[0][
i];
547 const complex<double> prodAmpA =
prodAmp(prodAmpIndexA);
550 complex<double> prodAmpB = 0;
551 for (
unsigned int j = 0; j < prodAmpIndices[1].size(); ++j) {
552 const unsigned int prodAmpIndexB = prodAmpIndices[1][j];
554 prodAmpB =
prodAmp(prodAmpIndexB);
558 jacobian[0][2 *
i ] = rhoABRe * prodAmpB.real() - rhoABIm * prodAmpB.imag() - (rhoABNorm / rhoAA) * prodAmpA.real();
559 jacobian[0][2 *
i + 1] = rhoABRe * prodAmpB.imag() + rhoABIm * prodAmpB.real() - (rhoABNorm / rhoAA) * prodAmpA.imag();
563 const unsigned int colOffset = 2 * prodAmpIndices[0].size();
564 for (
unsigned int i = 0;
i < prodAmpIndices[1].size(); ++
i) {
565 const unsigned int prodAmpIndexB = prodAmpIndices[1][
i];
566 const complex<double> prodAmpB =
prodAmp(prodAmpIndexB);
569 complex<double> prodAmpA = 0;
570 for (
unsigned int j = 0; j < prodAmpIndices[0].size(); ++j) {
571 const unsigned int prodAmpIndexA = prodAmpIndices[0][j];
573 prodAmpA =
prodAmp(prodAmpIndexA);
577 jacobian[0][colOffset + 2 *
i ] = rhoABRe * prodAmpA.real() + rhoABIm * prodAmpA.imag() - (rhoABNorm / rhoBB) * prodAmpB.real();
578 jacobian[0][colOffset + 2 *
i + 1] = rhoABRe * prodAmpA.imag() - rhoABIm * prodAmpA.real() - (rhoABNorm / rhoBB) * prodAmpB.imag();
580 jacobian *= 1 / (coh * rhoAA * rhoBB);
583 const TMatrixT<double> jacobianT(TMatrixT<double>::kTransposed, jacobian);
584 const TMatrixT<double> prodAmpCovJT = prodAmpCov * jacobianT;
585 const TMatrixT<double> cohCov = jacobian * prodAmpCovJT;
586 return sqrt(cohCov[0][0]);
593 const unsigned int waveIndexB)
const
596 const complex<double> normInt =
normIntegral (waveIndexA, waveIndexB);
597 return 2 * (spinDens * normInt).real();
604 const unsigned int waveIndexB)
const
608 const complex<double> normInt =
normIntegral(waveIndexA, waveIndexB);
609 TMatrixT<double> jacobian(1, 2);
610 jacobian[0][0] = 2 * normInt.real();
611 jacobian[0][1] = -2 * normInt.imag();
612 const double overlapVariance =
realValVariance(waveIndexA, waveIndexB, jacobian);
613 return sqrt(overlapVariance);
641 (
const unsigned int nmbEvents,
642 const unsigned int normNmbEvents,
643 const double massBinCenter,
644 const double logLikelihood,
646 const vector<complex<double> >& prodAmps,
647 const vector<string>& prodAmpNames,
648 const TMatrixT<double>& fitParCovMatrix,
649 const vector<pair<int, int> >& fitParCovMatrixIndices,
651 const vector<double>& phaseSpaceIntegral,
652 const bool converged,
653 const bool hasHessian)
655 _converged = converged;
656 _hasHessian = hasHessian;
657 _nmbEvents = nmbEvents;
658 _normNmbEvents = normNmbEvents;
659 _massBinCenter = massBinCenter;
660 _logLikelihood = logLikelihood;
662 _prodAmps.resize(prodAmps.size());
663 for (
unsigned int i = 0;
i < prodAmps.size(); ++
i)
664 _prodAmps[
i] = TComplex(prodAmps[
i].real(), prodAmps[
i].imag());
665 _prodAmpNames = prodAmpNames;
666 _fitParCovMatrix.ResizeTo(fitParCovMatrix.GetNrows(), fitParCovMatrix.GetNcols());
667 _fitParCovMatrix = fitParCovMatrix;
668 _fitParCovMatrixIndices = fitParCovMatrixIndices;
670 if (!(fitParCovMatrix.GetNrows() == 0) && !(fitParCovMatrix.GetNcols() == 0))
671 _covMatrixValid =
true;
673 _covMatrixValid =
false;
674 _normIntegral.ResizeTo(normIntegral.
nrows(), normIntegral.
ncols());
675 _normIntegral = normIntegral;
676 _phaseSpaceIntegral = phaseSpaceIntegral;
681 if (_prodAmps.size() != _prodAmpNames.size())
682 cout <<
"fitResult::fill(): warning: number of production amplitudes "
683 <<
"(" << _prodAmps.size() <<
") does not match number of "
684 <<
"production amplitude names (" << _prodAmpNames.size() <<
")." << endl;
685 if (_prodAmps.size() != _fitParCovMatrixIndices.size())
686 cout <<
"fitResult::fill(): warning: number of production amplitudes "
687 <<
"(" << _prodAmps.size() <<
") does not match number of "
688 <<
"covariance matrix indices (" << _fitParCovMatrixIndices.size() <<
")." << endl;
689 if ( ((
int)_waveNames.size() != _normIntegral.nrows())
690 || ((
int)_waveNames.size() != _normIntegral.ncols()))
691 cout <<
"fitResult::fill(): warning: number of waves (" << _waveNames.size()
692 <<
") does not match size of normalization integral "
693 <<
"(" << _normIntegral.nrows() <<
", " << _normIntegral.ncols() <<
")." << endl;
697 map<TString, complex<double> > V;
698 for (
unsigned int i = 0;
i < nmbProdAmps(); ++
i)
699 V[prodAmpName(
i)] = prodAmp(
i);
700 printInfo <<
"production amplitudes:" << endl;
701 for (map<TString, complex<double> >::const_iterator
i = V.begin();
i != V.end(); ++
i)
702 cout <<
" " <<
i->first <<
" = " <<
i->second << endl;
703 printInfo <<
"normalization integral matrix:" << endl;
704 map<TString, unsigned int> waveIndexMap;
705 for (
unsigned int i = 0;
i < nmbWaves(); ++
i)
706 waveIndexMap[waveName(
i)] =
i;
707 for (map<TString, unsigned int>::const_iterator
i = waveIndexMap.begin();
708 i != waveIndexMap.end(); ++
i)
709 for (map<TString, unsigned int>::const_iterator j = waveIndexMap.begin();
710 j != waveIndexMap.end(); ++j) {
711 cout <<
" [" <<
i->first <<
"][" << j->first <<
"] = "
712 << this->normIntegral(
i->second, j->second) << endl;
714 printInfo <<
"covariance matrix:" << endl;
715 map<TString, unsigned int> prodAmpIndexMap;
716 for (
unsigned int i = 0;
i < nmbProdAmps(); ++
i)
717 prodAmpIndexMap[prodAmpName(
i)] =
i;
718 for (map<TString, unsigned int>::const_iterator
i = prodAmpIndexMap.begin();
719 i != prodAmpIndexMap.end(); ++
i) {
720 const int iIdx[2] = { _fitParCovMatrixIndices[
i->second].first,
721 _fitParCovMatrixIndices[
i->second].second};
722 for (map<TString, unsigned int>::const_iterator j = prodAmpIndexMap.begin();
723 j != prodAmpIndexMap.end(); ++j) {
724 const int jIdx[2] = { _fitParCovMatrixIndices[j->second].first,
725 _fitParCovMatrixIndices[j->second].second};
726 cout <<
" [" <<
i->first <<
"][" << j->first <<
"]: " << flush;
729 cout <<
"ReRe = " << fitParameterCov(iIdx[0], jIdx[0]) <<
", " << flush;
731 cout <<
"ReIm = " << fitParameterCov(iIdx[0], jIdx[1]) <<
", " << flush;
735 cout <<
"ImRe = " << fitParameterCov(iIdx[1], jIdx[0]) <<
", " << flush;
737 cout <<
"ImIm = " << fitParameterCov(iIdx[1], jIdx[1]) << flush;
756 printWarn <<
"could not find any wave named '" << waveName <<
"'." << endl;
771 printWarn <<
"could not find any production amplitude named '" << prodAmpName <<
"'." << endl;
780 for (
int i = 0;
i <
n; ++
i) {
788 for (j = 0; j <
n; ++j)