59 TFitResult::TFitResult()
69 TFitResult::TFitResult(
const TFitBin& fitBin)
70 : _nmbEvents (fitBin.nmbEvents()),
71 _normNmbEvents (fitBin.normNmbEvents()),
72 _massBinCenter (fitBin.massBinCenter()),
73 _logLikelihood (fitBin.logLikelihood()),
74 _rank (fitBin.rank()),
75 _hasErrors (fitBin.fitParCovMatrixValid()),
76 _fitParCovMatrix (fitBin.fitParCovMatrix()),
77 _fitParCovMatrixIndices(fitBin.fitParCovIndices()),
78 _normIntegral (fitBin.normIntegral()),
79 _normIntIndexMap (fitBin.prodAmpIndexMap())
83 const unsigned int nmbAmpNames = fitBin.
prodAmpNames().size();
84 _prodAmpNames.resize(nmbAmpNames,
"");
85 for (
unsigned int i = 0;
i < nmbAmpNames; ++
i)
89 const unsigned int nmbWaveNames = fitBin.
waveNames().size();
90 _waveNames.resize(nmbWaveNames,
"");
91 for (
unsigned int i = 0;
i < nmbWaveNames; ++
i)
97 TFitResult::TFitResult(
const TFitResult& result)
98 : _nmbEvents (result.nmbEvents()),
99 _normNmbEvents (result.normNmbEvents()),
100 _massBinCenter (result.massBinCenter()),
101 _logLikelihood (result.logLikelihood()),
102 _rank (result.rank()),
103 _prodAmps (result.prodAmps()),
104 _prodAmpNames (result.prodAmpNames()),
105 _waveNames (result.waveNames()),
106 _hasErrors (result.covMatrixValid()),
107 _fitParCovMatrix (result.fitParCovMatrix()),
108 _fitParCovMatrixIndices(result.fitParCovIndices()),
109 _normIntegral (result.normIntegralMatrix()),
110 _normIntIndexMap (result.normIntIndexMap())
114 TFitResult::~TFitResult()
124 TFitResult::evidence()
const {
125 double l = -logLikelihood();
126 double det = _fitParCovMatrix.Determinant();
127 double d = (double)_fitParCovMatrix.GetNcols();
129 unsigned int ni = _normIntegral.ncols();
130 for(
unsigned int i=0;
i<ni;++
i){
131 sum += 1. / _normIntegral(
i,
i).Re();
133 double occ = TMath::Power(TMath::Pi(), d * 0.5 - 1.) * TMath::Sqrt(2 * det) / sum;
134 double locc = TMath::Log(occ);
135 cout <<
"TFitResult::evidence" << endl;
136 cout <<
" LogLikeli: " << l;
137 cout <<
" Occamfactor: " << locc;
146 TFitResult::spinDensityMatrixElem(
const unsigned int waveIndexA,
147 const unsigned int waveIndexB)
const
150 const vector<pair<unsigned int, unsigned int> > prodAmpIndexPairs = prodAmpIndexPairsForWaves(waveIndexA, waveIndexB);
151 if (prodAmpIndexPairs.size() == 0)
154 complex<double> spinDens = 0;
155 for (
unsigned int i = 0;
i < prodAmpIndexPairs.size(); ++
i)
156 spinDens += prodAmp(prodAmpIndexPairs[
i].first) *
conj(prodAmp(prodAmpIndexPairs[
i].second));
163 TFitResult::fitParameter(
const string& parName)
const
166 TString name(parName);
167 const bool realPart = (name.Contains(
"RE") || name.Contains(
"flat"));
170 name.ReplaceAll(
"_RE",
"");
172 name.ReplaceAll(
"_IM",
"");
173 for (
unsigned int i = 0;
i < nmbProdAmps(); ++
i)
174 if (name == _prodAmpNames[
i]) {
176 return prodAmp(i).real();
178 return prodAmp(i).imag();
181 printWarn <<
"Could not find any parameter named '" << parName <<
"'." << endl;
198 TFitResult::prodAmpCov(
const vector<unsigned int>& prodAmpIndices)
const
200 const unsigned int dim = 2 * prodAmpIndices.size();
201 TMatrixT<double> prodAmpCov(dim, dim);
203 printWarn <<
"TFitResult does not have a valid error matrix. Returning zero covariance matrix." << endl;
207 vector<int> parCovIndices;
208 for (
unsigned int i = 0; i < prodAmpIndices.size(); ++
i) {
209 parCovIndices.push_back(_fitParCovMatrixIndices[prodAmpIndices[i]].first);
210 parCovIndices.push_back(_fitParCovMatrixIndices[prodAmpIndices[i]].second);
213 for (
unsigned int row = 0; row < dim; ++row)
214 for (
unsigned int col = 0; col < dim; ++col) {
215 const int i = parCovIndices[row];
216 const int j = parCovIndices[col];
217 if ((i >= 0) && (j >= 0))
218 prodAmpCov[row][col] = fitParameterCov(i, j);
229 TFitResult::spinDensityMatrixElemCov(
const unsigned int waveIndexA,
230 const unsigned int waveIndexB)
const
233 const vector<pair<unsigned int, unsigned int> > prodAmpIndexPairs = prodAmpIndexPairsForWaves(waveIndexA, waveIndexB);
234 if (!_hasErrors || (prodAmpIndexPairs.size() == 0)) {
235 TMatrixT<double> spinDensCov(2, 2);
239 const TMatrixT<double> prodAmpCov = this->prodAmpCov(prodAmpIndexPairs);
243 const unsigned int dim = prodAmpCov.GetNcols();
244 TMatrixT<double> jacobian(2, dim);
246 for (
unsigned int i = 0; i < prodAmpIndexPairs.size(); ++
i) {
247 const unsigned int ampIndexB = prodAmpIndexPairs[
i].second;
248 const TMatrixT<double> subJacobianA = matrixRepr(
conj(prodAmp(ampIndexB)));
249 jacobian.SetSub(0, 2 * i, subJacobianA);
253 TMatrixT<double>
M(2, 2);
256 const unsigned int colOffset = 2 * prodAmpIndexPairs.size();
257 for (
unsigned int i = 0; i < prodAmpIndexPairs.size(); ++
i) {
258 const unsigned int ampIndexA = prodAmpIndexPairs[
i].first;
259 TMatrixT<double> subJacobianB = matrixRepr(prodAmp(ampIndexA));
261 jacobian.SetSub(0, colOffset + 2 * i, subJacobianB);
264 const TMatrixT<double> jacobianT(TMatrixT<double>::kTransposed, jacobian);
267 const TMatrixT<double> prodAmpCovJT = prodAmpCov * jacobianT;
268 const TMatrixT<double> spinDensCov = jacobian * prodAmpCovJT;
277 TFitResult::intensity(
const char* waveNamePattern)
const
279 vector<unsigned int> waveIndices = waveIndicesMatchingPattern(waveNamePattern);
280 double intensity = 0;
281 for (
unsigned int i = 0; i < waveIndices.size(); ++
i) {
282 intensity += this->intensity(waveIndices[i]);
283 for (
unsigned int j = 0; j <
i; ++j)
284 intensity += overlap(waveIndices[i], waveIndices[j]);
292 TFitResult::normIntegralForProdAmp(
const unsigned int prodAmpIndexA,
293 const unsigned int prodAmpIndexB)
const
296 const bool flatWaveA = prodAmpName(prodAmpIndexA).Contains(
"flat");
297 const bool flatWaveB = prodAmpName(prodAmpIndexB).Contains(
"flat");
298 if (flatWaveA && flatWaveB)
300 else if (flatWaveA || flatWaveB)
303 map<int, int>::const_iterator indexA = _normIntIndexMap.find(prodAmpIndexA);
304 map<int, int>::const_iterator indexB = _normIntIndexMap.find(prodAmpIndexB);
305 if ((indexA == _normIntIndexMap.end()) || (indexB == _normIntIndexMap.end())) {
306 printWarn <<
"Amplitude index " << prodAmpIndexA <<
" or " << prodAmpIndexB <<
" is out of bound." << endl;
309 return normIntegral(indexA->second, indexB->second);
318 TFitResult::intensityErr(
const char* waveNamePattern)
const
321 const vector<unsigned int> prodAmpIndices = prodAmpIndicesMatchingPattern(waveNamePattern);
322 const unsigned int nmbAmps = prodAmpIndices.size();
323 if (!_hasErrors || (nmbAmps == 0))
327 TMatrixT<double> jacobian(1, 2 * nmbAmps);
328 for (
unsigned int i = 0; i < nmbAmps; ++
i) {
331 complex<double> ampNorm = 0;
332 const int currentRank = rankOfProdAmp(prodAmpIndices[i]);
333 for (
unsigned int j = 0; j < nmbAmps; ++j) {
334 if (rankOfProdAmp(prodAmpIndices[j]) != currentRank)
336 ampNorm += prodAmp(prodAmpIndices[j]) * normIntegralForProdAmp(j, i);
338 jacobian[0][2 *
i ] = ampNorm.real();
339 jacobian[0][2 * i + 1] = ampNorm.imag();
342 const TMatrixT<double> prodAmpCov = this->prodAmpCov(prodAmpIndices);
343 const TMatrixT<double> jacobianT(TMatrixT<double>::kTransposed, jacobian);
344 const TMatrixT<double> prodAmpCovJT = prodAmpCov * jacobianT;
345 const TMatrixT<double> intensityCov = jacobian * prodAmpCovJT;
346 return sqrt(intensityCov[0][0]);
352 TFitResult::phase(
const unsigned int waveIndexA,
353 const unsigned int waveIndexB)
const
355 if (waveIndexA == waveIndexB)
357 return arg(spinDensityMatrixElem(waveIndexA, waveIndexB)) * TMath::RadToDeg();
363 TFitResult::phaseErr(
const unsigned int waveIndexA,
364 const unsigned int waveIndexB)
const
366 if (!_hasErrors || (waveIndexA == waveIndexB))
369 const complex<double> spinDens = spinDensityMatrixElem(waveIndexA, waveIndexB);
370 TMatrixT<double> jacobian(1, 2);
372 const double x = spinDens.real();
373 const double y = spinDens.imag();
374 if ((x != 0) || (y != 0)) {
375 jacobian[0][0] = 1 / (x + y * y / x);
376 jacobian[0][1] = -y / (x * x + y * y);
380 const double phaseVariance = realValVariance(waveIndexA, waveIndexB, jacobian);
381 return sqrt(phaseVariance) * TMath::RadToDeg();
387 TFitResult::coherence(
const unsigned int waveIndexA,
388 const unsigned int waveIndexB)
const
390 const double rhoAA = spinDensityMatrixElem(waveIndexA, waveIndexA).real();
391 const double rhoBB = spinDensityMatrixElem(waveIndexB, waveIndexB).real();
392 const complex<double> rhoAB = spinDensityMatrixElem(waveIndexA, waveIndexB);
394 cout <<
"coherence("<<waveIndexA<<
","<<waveIndexB<<
"): "
398 <<sqrt(std::norm(rhoAB))<<
" "
399 <<sqrt((rhoAA * rhoBB))<<endl;
403 return sqrt(std::norm(rhoAB) / (rhoAA * rhoBB));
409 TFitResult::coherenceErr(
const unsigned int waveIndexA,
410 const unsigned int waveIndexB)
const
413 const vector<unsigned int> prodAmpIndices[2] = {prodAmpIndicesForWave(waveIndexA),
414 prodAmpIndicesForWave(waveIndexB)};
415 if (!_hasErrors || (prodAmpIndices[0].size() == 0) || (prodAmpIndices[1].size() == 0))
419 const unsigned int nmbAmps = prodAmpIndices[0].size() + prodAmpIndices[1].size();
420 TMatrixT<double> jacobian(1, 2 * nmbAmps);
422 const double rhoAA = spinDensityMatrixElem(waveIndexA, waveIndexA).real();
423 const double rhoBB = spinDensityMatrixElem(waveIndexB, waveIndexB).real();
424 const complex<double> rhoAB = spinDensityMatrixElem(waveIndexA, waveIndexB);
425 const double rhoABRe = rhoAB.real();
426 const double rhoABIm = rhoAB.imag();
427 const double rhoABNorm = std::norm(rhoAB);
428 const double coh = sqrt(rhoABNorm / (rhoAA * rhoBB));
432 for (
unsigned int i = 0; i < prodAmpIndices[0].size(); ++
i) {
433 const unsigned int prodAmpIndexA = prodAmpIndices[0][
i];
434 const complex<double> prodAmpA = prodAmp(prodAmpIndexA);
435 const int prodAmpRankA = rankOfProdAmp(prodAmpIndexA);
437 complex<double> prodAmpB = 0;
438 for (
unsigned int j = 0; j < prodAmpIndices[1].size(); ++j) {
439 const unsigned int prodAmpIndexB = prodAmpIndices[1][j];
440 if (rankOfProdAmp(prodAmpIndexB) == prodAmpRankA) {
441 prodAmpB = prodAmp(prodAmpIndexB);
445 jacobian[0][2 *
i ] = rhoABRe * prodAmpB.real() - rhoABIm * prodAmpB.imag() - (rhoABNorm / rhoAA) * prodAmpA.real();
446 jacobian[0][2 * i + 1] = rhoABRe * prodAmpB.imag() + rhoABIm * prodAmpB.real() - (rhoABNorm / rhoAA) * prodAmpA.imag();
450 const unsigned int colOffset = 2 * prodAmpIndices[0].size();
451 for (
unsigned int i = 0; i < prodAmpIndices[1].size(); ++
i) {
452 const unsigned int prodAmpIndexB = prodAmpIndices[1][
i];
453 const complex<double> prodAmpB = prodAmp(prodAmpIndexB);
454 const int prodAmpRankB = rankOfProdAmp(prodAmpIndexB);
456 complex<double> prodAmpA = 0;
457 for (
unsigned int j = 0; j < prodAmpIndices[0].size(); ++j) {
458 const unsigned int prodAmpIndexA = prodAmpIndices[0][j];
459 if (rankOfProdAmp(prodAmpIndexA) == prodAmpRankB) {
460 prodAmpA = prodAmp(prodAmpIndexA);
464 jacobian[0][colOffset + 2 *
i ] = rhoABRe * prodAmpA.real() + rhoABIm * prodAmpA.imag() - (rhoABNorm / rhoBB) * prodAmpB.real();
465 jacobian[0][colOffset + 2 * i + 1] = rhoABRe * prodAmpA.imag() - rhoABIm * prodAmpA.real() - (rhoABNorm / rhoBB) * prodAmpB.imag();
467 jacobian *= 1 / (coh * rhoAA * rhoBB);
469 const TMatrixT<double> prodAmpCov = this->prodAmpCov(prodAmpIndices[0], prodAmpIndices[1]);
470 const TMatrixT<double> jacobianT(TMatrixT<double>::kTransposed, jacobian);
471 const TMatrixT<double> prodAmpCovJT = prodAmpCov * jacobianT;
472 const TMatrixT<double> cohCov = jacobian * prodAmpCovJT;
473 return sqrt(cohCov[0][0]);
479 TFitResult::overlap(
const unsigned int waveIndexA,
480 const unsigned int waveIndexB)
const
482 const complex<double> spinDens = spinDensityMatrixElem(waveIndexA, waveIndexB);
483 const complex<double> normInt = normIntegral (waveIndexA, waveIndexB);
484 return 2 * (spinDens * normInt).real();
490 TFitResult::overlapErr(
const unsigned int waveIndexA,
491 const unsigned int waveIndexB)
const
495 const complex<double> normInt = normIntegral(waveIndexA, waveIndexB);
496 TMatrixT<double> jacobian(1, 2);
497 jacobian[0][0] = 2 * normInt.real();
498 jacobian[0][1] = -2 * normInt.imag();
499 const double overlapVariance = realValVariance(waveIndexA, waveIndexB, jacobian);
500 return sqrt(overlapVariance);
513 _prodAmpNames.clear();
516 _fitParCovMatrix.ResizeTo(0, 0);
517 _fitParCovMatrixIndices.clear();
518 _normIntegral.ResizeTo(0, 0);
519 _normIntIndexMap.clear();
524 TFitResult::fill(
const unsigned int nmbEvents,
525 const unsigned int normNmbEvents,
526 const double massBinCenter,
527 const double logLikelihood,
529 const vector<complex<double> >& prodAmps,
530 const vector<string>& prodAmpNames,
531 const TMatrixT<double>& fitParCovMatrix,
532 const vector<pair<int, int> >& fitParCovMatrixIndices,
535 _nmbEvents = nmbEvents;
536 _normNmbEvents = normNmbEvents;
537 _massBinCenter = massBinCenter;
538 _logLikelihood = logLikelihood;
540 _prodAmps.resize(prodAmps.size());
541 for (
unsigned int i = 0; i < prodAmps.size(); ++
i)
542 _prodAmps[i] = TComplex(prodAmps[i].real(), prodAmps[
i].imag());
543 _prodAmpNames = prodAmpNames;
544 _fitParCovMatrix.ResizeTo(fitParCovMatrix.GetNrows(), fitParCovMatrix.GetNcols());
545 _fitParCovMatrix = fitParCovMatrix;
546 _fitParCovMatrixIndices = fitParCovMatrixIndices;
547 if (!(fitParCovMatrix.GetNrows() == 0) && !(fitParCovMatrix.GetNcols() == 0))
551 _normIntegral.ResizeTo(normIntegral.
nrows(), normIntegral.
ncols());
552 _normIntegral = normIntegral;
557 if (_prodAmps.size() != _prodAmpNames.size())
558 cout <<
"TFitResult::fill(): warning: number of production amplitudes (" << _prodAmps.size()
559 <<
") does not match number of production amplitude names (" << _prodAmpNames.size() <<
")." << endl;
560 if (_prodAmps.size() != _fitParCovMatrixIndices.size())
561 cout <<
"TFitResult::fill(): warning: number of production amplitudes (" << _prodAmps.size()
562 <<
") does not match number of covariance matrix indices (" << _fitParCovMatrixIndices.size() <<
")." << endl;
563 if (((
int)_waveNames.size() != _normIntegral.nrows()) || ((
int)_waveNames.size() != _normIntegral.ncols()))
564 cout <<
"TFitResult::fill(): warning: number of waves (" << _waveNames.size()
565 <<
") does not match size of normalization integral (" << _normIntegral.nrows() <<
", " << _normIntegral.ncols() <<
")." << endl;
570 TFitResult::buildWaveMap() {
571 int n=_prodAmpNames.size();
572 for(
int i=0;i<
n;++
i){
574 TString title=wavetitle(i);
575 if(find(_waveNames.begin(),_waveNames.end(),title.Data())==_waveNames.end())
576 _waveNames.push_back(title.Data());
581 if(prodAmpName(j).Contains(title))
583 _normIntIndexMap[
i]=j;
588 #endif // USE_TFITRESULT