47 #include "TStopwatch.h"
50 #include "reportingUtils.hpp"
51 #include "conversionUtils.hpp"
52 #include "fileUtils.hpp"
54 #include "complex.cuh"
55 #include "likelihoodInterface.cuh"
66 using namespace boost;
67 using namespace boost::accumulators;
73 template<
typename complexT>
83 _useNormalizedAmps(true),
90 printInfo <<
"using FdF() to calculate likelihood" << endl;
92 printInfo <<
"using DoEval() to calculate likelihood" << endl;
97 template<
typename complexT>
104 template<
typename complexT>
109 double* gradient)
const
111 ++(_funcCallInfo[FDF].nmbCalls);
118 for (
unsigned int i = 0;
i < _nmbPars; ++
i)
119 _parCache[
i] = par[
i];
124 copyFromParArray(par, prodAmps, prodAmpFlat);
125 const value_type prodAmpFlat2 = prodAmpFlat * prodAmpFlat;
132 array<typename ampsArrayType::index, 3> derivShape = {{ _rank, 2, _nmbWavesReflMax }};
139 accumulator_set<value_type, stats<tag::sum(compensated)> > logLikelihoodAcc;
140 accumulator_set<value_type, stats<tag::sum(compensated)> > derivativeFlatAcc;
141 multi_array<accumulator_set<complexT, stats<tag::sum(compensated)> >, 3>
142 derivativesAcc(derivShape);
143 for (
unsigned int iEvt = 0; iEvt < _nmbEvents; ++iEvt) {
144 accumulator_set<value_type, stats<tag::sum(compensated)> > likelihoodAcc;
146 for (
unsigned int iRank = 0; iRank < _rank; ++iRank) {
147 for (
unsigned int iRefl = 0; iRefl < 2; ++iRefl) {
148 accumulator_set<complexT, stats<tag::sum(compensated)> > ampProdAcc;
149 for (
unsigned int iWave = 0; iWave < _nmbWavesRefl[iRefl]; ++iWave)
150 ampProdAcc(prodAmps[iRank][iRefl][iWave] * _decayAmps[iEvt][iRefl][iWave]);
151 const complexT ampProdSum = sum(ampProdAcc);
152 likelihoodAcc(norm(ampProdSum));
154 for (
unsigned int jWave = 0; jWave < _nmbWavesRefl[iRefl]; ++jWave)
156 derivative[iRank][iRefl][jWave] = ampProdSum;
160 for (
unsigned int iRefl = 0; iRefl < 2; ++iRefl)
161 for (
unsigned int iWave = 0; iWave < _nmbWavesRefl[iRefl]; ++iWave)
162 derivative[iRank][iRefl][iWave] *=
conj(_decayAmps[iEvt][iRefl][iWave]);
164 likelihoodAcc (prodAmpFlat2 );
165 logLikelihoodAcc(-log(sum(likelihoodAcc)));
167 const value_type factor = 2. / sum(likelihoodAcc);
168 for (
unsigned int iRank = 0; iRank < _rank; ++iRank)
169 for (
unsigned int iRefl = 0; iRefl < 2; ++iRefl)
170 for (
unsigned int iWave = 0; iWave < _nmbWavesRefl[iRefl]; ++iWave)
171 derivativesAcc[iRank][iRefl][iWave](-factor * derivative[iRank][iRefl][iWave]);
172 derivativeFlatAcc(-factor * prodAmpFlat);
174 for (
unsigned int iRank = 0; iRank < _rank; ++iRank)
175 for (
unsigned int iRefl = 0; iRefl < 2; ++iRefl)
176 for (
unsigned int iWave = 0; iWave < _nmbWavesRefl[iRefl]; ++iWave)
177 derivatives[iRank][iRefl][iWave] = sum(derivativesAcc[iRank][iRefl][iWave]);
178 derivativeFlat = sum(derivativeFlatAcc);
181 _funcCallInfo[FDF].funcTime(timer.RealTime());
185 accumulator_set<value_type, stats<tag::sum(compensated)> > normFactorAcc;
186 const value_type nmbEvt = (_useNormalizedAmps) ? 1 : _nmbEvents;
188 for (
unsigned int iRank = 0; iRank < _rank; ++iRank)
189 for (
unsigned int iRefl = 0; iRefl < 2; ++iRefl)
190 for (
unsigned int iWave = 0; iWave < _nmbWavesRefl[iRefl]; ++iWave) {
191 accumulator_set<complexT, stats<tag::sum(compensated)> > normFactorDerivAcc;
192 for (
unsigned int jWave = 0; jWave < _nmbWavesRefl[iRefl]; ++jWave) {
193 const complexT I = _accMatrix[iRefl][iWave][iRefl][jWave];
194 normFactorAcc(real((prodAmps[iRank][iRefl][iWave] *
conj(prodAmps[iRank][iRefl][jWave]))
196 normFactorDerivAcc(prodAmps[iRank][iRefl][jWave] *
conj(I));
198 derivatives[iRank][iRefl][iWave] += sum(normFactorDerivAcc) * twiceNmbEvt;
201 normFactorAcc(prodAmpFlat2 * _totAcc);
202 derivativeFlat += prodAmpFlat * twiceNmbEvt * _totAcc;
205 _funcCallInfo[FDF].normTime(timer.RealTime());
208 copyToParArray(derivatives, derivativeFlat, gradient);
209 copyToParArray(derivatives, derivativeFlat, toArray(_derivCache));
212 funcVal = sum(logLikelihoodAcc) + nmbEvt * sum(normFactorAcc);
216 _funcCallInfo[FDF].totalTime(timerTot.RealTime());
219 printDebug <<
"log likelihood = " << maxPrecisionAlign(sum(logLikelihoodAcc)) <<
", "
220 <<
"normalization = " << maxPrecisionAlign(sum(normFactorAcc) ) <<
", "
221 <<
"normalized likelihood = " << maxPrecisionAlign(funcVal ) << endl;
225 template<
typename complexT>
229 ++(_funcCallInfo[DOEVAL].nmbCalls);
234 double logLikelihood;
235 double gradient[_nmbPars];
236 FdF(par, logLikelihood, gradient);
237 return logLikelihood;
248 copyFromParArray(par, prodAmps, prodAmpFlat);
249 const value_type prodAmpFlat2 = prodAmpFlat * prodAmpFlat;
257 logLikelihood = cuda::likelihoodInterface<cuda::complex<value_type> >::logLikelihood
258 (
reinterpret_cast<cuda::complex<value_type>*
>(prodAmps.data()),
259 prodAmps.num_elements(), prodAmpFlat, _rank);
263 accumulator_set<value_type, stats<tag::sum(compensated)> > logLikelihoodAcc;
264 for (
unsigned int iEvt = 0; iEvt < _nmbEvents; ++iEvt) {
265 accumulator_set<value_type, stats<tag::sum(compensated)> > likelihoodAcc;
266 for (
unsigned int iRank = 0; iRank < _rank; ++iRank) {
267 for (
unsigned int iRefl = 0; iRefl < 2; ++iRefl) {
268 accumulator_set<complexT, stats<tag::sum(compensated)> > ampProdAcc;
269 for (
unsigned int iWave = 0; iWave < _nmbWavesRefl[iRefl]; ++iWave) {
270 ampProdAcc(prodAmps[iRank][iRefl][iWave] * _decayAmps[iEvt][iRefl][iWave]);
276 likelihoodAcc(norm(sum(ampProdAcc)));
279 likelihoodAcc(prodAmpFlat2);
280 logLikelihoodAcc(-log(sum(likelihoodAcc)));
283 logLikelihood = sum(logLikelihoodAcc);
284 assert(logLikelihood==logLikelihood);
285 if(numeric_limits<double>::has_infinity)assert(logLikelihood != numeric_limits<double>::infinity());
289 _funcCallInfo[DOEVAL].funcTime(timer.RealTime());
293 accumulator_set<value_type, stats<tag::sum(compensated)> > normFactorAcc;
294 const value_type nmbEvt = (_useNormalizedAmps) ? 1 : _nmbEvents;
295 for (
unsigned int iRank = 0; iRank < _rank; ++iRank)
296 for (
unsigned int iRefl = 0; iRefl < 2; ++iRefl)
297 for (
unsigned int iWave = 0; iWave < _nmbWavesRefl[iRefl]; ++iWave)
298 for (
unsigned int jWave = 0; jWave < _nmbWavesRefl[iRefl]; ++jWave)
299 normFactorAcc(real((prodAmps[iRank][iRefl][iWave] *
conj(prodAmps[iRank][iRefl][jWave]))
300 * _accMatrix[iRefl][iWave][iRefl][jWave]));
302 normFactorAcc(prodAmpFlat2 * _totAcc);
305 _funcCallInfo[DOEVAL].normTime(timer.RealTime());
308 const double funcVal = logLikelihood + nmbEvt * sum(normFactorAcc);
309 assert(funcVal==funcVal);
310 if(numeric_limits<double>::has_infinity)assert(funcVal != numeric_limits<double>::infinity());
315 _funcCallInfo[DOEVAL].totalTime(timerTot.RealTime());
318 printDebug <<
"raw log likelihood = " << maxPrecisionAlign(logLikelihood ) <<
", "
319 <<
"normalization = " << maxPrecisionAlign(sum(normFactorAcc)) <<
", "
320 <<
"normalized log likelihood = " << maxPrecisionAlign(funcVal ) << endl;
328 template<
typename complexT>
331 unsigned int derivativeIndex)
const
333 ++(_funcCallInfo[DODERIVATIVE].nmbCalls);
341 for (
unsigned int i = 0;
i < _nmbPars; ++
i)
342 if (_parCache[
i] != par[
i]) {
349 _funcCallInfo[DODERIVATIVE].totalTime(timerTot.RealTime());
350 _funcCallInfo[DODERIVATIVE].funcTime (sum(_funcCallInfo[DODERIVATIVE].totalTime));
351 return _derivCache[derivativeIndex];
354 double logLikelihood;
355 double gradient[_nmbPars];
356 FdF(par, logLikelihood, gradient);
357 return gradient[derivativeIndex];
362 template<
typename complexT>
366 double* gradient)
const
368 ++(_funcCallInfo[GRADIENT].nmbCalls);
378 for (
unsigned int i = 0;
i < _nmbPars; ++
i)
379 if (_parCache[
i] != par[
i]) {
384 for (
unsigned int i = 0; i < _nmbPars ; ++
i)
385 gradient[i] = _derivCache[i];
387 _funcCallInfo[GRADIENT].totalTime(timerTot.RealTime());
388 _funcCallInfo[GRADIENT].funcTime (sum(_funcCallInfo[GRADIENT].totalTime));
392 double logLikelihood;
393 FdF(par, logLikelihood, gradient);
398 for (
unsigned int i = 0; i < _nmbPars; ++
i)
399 _parCache[i] = par[i];
404 copyFromParArray(par, prodAmps, prodAmpFlat);
411 array<typename ampsArrayType::index, 3> derivShape = {{ _rank, 2, _nmbWavesReflMax }};
419 cuda::likelihoodInterface<cuda::complex<value_type> >::logLikelihoodDeriv
420 (
reinterpret_cast<cuda::complex<value_type>*
>(prodAmps.data()),
421 prodAmps.num_elements(), prodAmpFlat, _rank,
422 reinterpret_cast<cuda::complex<value_type>*
>(derivatives.data()),
427 accumulator_set<value_type, stats<tag::sum(compensated)> > derivativeFlatAcc;
428 multi_array<accumulator_set<complexT, stats<tag::sum(compensated)> >, 3>
429 derivativesAcc(derivShape);
430 const value_type prodAmpFlat2 = prodAmpFlat * prodAmpFlat;
431 for (
unsigned int iEvt = 0; iEvt < _nmbEvents; ++iEvt) {
432 accumulator_set<value_type, stats<tag::sum(compensated)> > likelihoodAcc;
434 for (
unsigned int iRank = 0; iRank < _rank; ++iRank) {
435 for (
unsigned int iRefl = 0; iRefl < 2; ++iRefl) {
436 accumulator_set<complexT, stats<tag::sum(compensated)> > ampProdAcc;
437 for (
unsigned int iWave = 0; iWave < _nmbWavesRefl[iRefl]; ++iWave)
438 ampProdAcc(prodAmps[iRank][iRefl][iWave] * _decayAmps[iEvt][iRefl][iWave]);
439 const complexT ampProdSum = sum(ampProdAcc);
440 likelihoodAcc(norm(ampProdSum));
442 for (
unsigned int jWave = 0; jWave < _nmbWavesRefl[iRefl]; ++jWave)
444 derivative[iRank][iRefl][jWave] = ampProdSum;
448 for (
unsigned int iRefl = 0; iRefl < 2; ++iRefl)
449 for (
unsigned int jWave = 0; jWave < _nmbWavesRefl[iRefl]; ++jWave)
450 derivative[iRank][iRefl][jWave] *=
conj(_decayAmps[iEvt][iRefl][jWave]);
452 likelihoodAcc(prodAmpFlat2);
454 const value_type factor = 2. / sum(likelihoodAcc);
455 for (
unsigned int iRank = 0; iRank < _rank; ++iRank)
456 for (
unsigned int iRefl = 0; iRefl < 2; ++iRefl)
457 for (
unsigned int jWave = 0; jWave < _nmbWavesRefl[iRefl]; ++jWave)
458 derivativesAcc[iRank][iRefl][jWave](-factor * derivative[iRank][iRefl][jWave]);
459 derivativeFlatAcc(-factor * prodAmpFlat);
461 for (
unsigned int iRank = 0; iRank < _rank; ++iRank)
462 for (
unsigned int iRefl = 0; iRefl < 2; ++iRefl)
463 for (
unsigned int iWave = 0; iWave < _nmbWavesRefl[iRefl]; ++iWave)
464 derivatives[iRank][iRefl][iWave] = sum(derivativesAcc[iRank][iRefl][iWave]);
465 derivativeFlat = sum(derivativeFlatAcc);
469 _funcCallInfo[GRADIENT].funcTime(timer.RealTime());
473 const value_type nmbEvt = (_useNormalizedAmps) ? 1 : _nmbEvents;
475 for (
unsigned int iRank = 0; iRank < _rank; ++iRank)
476 for (
unsigned int iRefl = 0; iRefl < 2; ++iRefl)
477 for (
unsigned int iWave = 0; iWave < _nmbWavesRefl[iRefl]; ++iWave) {
478 accumulator_set<complexT, stats<tag::sum(compensated)> > normFactorDerivAcc;
479 for (
unsigned int jWave = 0; jWave < _nmbWavesRefl[iRefl]; ++jWave) {
480 const complexT I = _accMatrix[iRefl][iWave][iRefl][jWave];
481 normFactorDerivAcc(prodAmps[iRank][iRefl][jWave] *
conj(I));
483 derivatives[iRank][iRefl][iWave] += sum(normFactorDerivAcc) * twiceNmbEvt;
486 derivativeFlat += prodAmpFlat * twiceNmbEvt * _totAcc;
489 _funcCallInfo[GRADIENT].normTime(timer.RealTime());
492 copyToParArray(derivatives, derivativeFlat, gradient);
493 copyToParArray(derivatives, derivativeFlat, toArray(_derivCache));
497 _funcCallInfo[GRADIENT].totalTime(timerTot.RealTime());
503 template<
typename complexT>
507 if (reflectivity == 0)
509 else if (reflectivity > 0)
510 return _nmbWavesRefl[1];
512 return _nmbWavesRefl[0];
516 template<
typename complexT>
521 _cudaEnabled = enableCuda;
528 template<
typename complexT>
540 template<
typename complexT>
543 const std::string& waveListFileName,
544 const std::string& normIntFileName,
545 const std::string& accIntFileName,
546 const std::string& ampDirName,
547 const unsigned int numbAccEvents,
548 const bool useRootAmps)
550 _numbAccEvents = numbAccEvents;
551 readWaveList(waveListFileName);
552 buildParDataStruct(rank);
553 readIntegrals(normIntFileName, accIntFileName);
554 readDecayAmplitudes(ampDirName, useRootAmps);
557 cuda::likelihoodInterface<cuda::complex<value_type> >::init
558 (
reinterpret_cast<cuda::complex<value_type>*
>(_decayAmps.data()),
559 _decayAmps.num_elements(), _nmbEvents, _nmbWavesRefl,
true);
564 template<
typename complexT>
568 printInfo <<
"reading amplitude names and thresholds from wave list file "
569 <<
"'" << waveListFileName <<
"'." << endl;
570 ifstream waveListFile(waveListFileName.c_str());
571 if (not waveListFile) {
572 printErr <<
"cannot open file '" << waveListFileName <<
"'. aborting." << endl;
575 vector<string> waveNames [2];
576 vector<double> waveThresholds[2];
577 vector<unsigned int> waveIndices [2];
578 unsigned int countWave = 0;
579 unsigned int lineNmb = 0;
581 while (getline(waveListFile, line)) {
584 stringstream lineStream;
585 lineStream.str(line);
587 if (lineStream >> waveName) {
590 if (not (lineStream >> threshold))
593 printDebug <<
"reading line " << setw(3) << lineNmb + 1 <<
": " << waveName<<
", "
594 <<
"threshold = " << setw(4) << threshold <<
" MeV/c^2" << endl;
597 waveNames [1].push_back(waveName);
598 waveThresholds[1].push_back(threshold);
599 waveIndices [1].push_back(countWave);
602 waveNames [0].push_back(waveName);
603 waveThresholds[0].push_back(threshold);
604 waveIndices [0].push_back(countWave);
608 printWarn <<
"cannot parse line '" << line <<
"' in wave list file "
609 <<
"'" << waveListFileName <<
"'" << endl;
612 waveListFile.close();
613 printInfo <<
"read " << lineNmb <<
" lines from wave list file "
614 <<
"'" << waveListFileName <<
"'" << endl;
615 _nmbWaves = _nmbWavesRefl[0] + _nmbWavesRefl[1];
616 _nmbWavesReflMax = max(_nmbWavesRefl[0], _nmbWavesRefl[1]);
617 _waveNames.resize (extents[2][_nmbWavesReflMax]);
618 _waveThresholds.resize (extents[2][_nmbWavesReflMax]);
619 _waveToWaveIndex.resize(extents[2][_nmbWavesReflMax]);
620 for (
unsigned int iRefl = 0; iRefl < 2; ++iRefl)
621 for (
unsigned int iWave = 0; iWave < _nmbWavesRefl[iRefl]; ++iWave) {
622 _waveNames [iRefl][iWave] = waveNames [iRefl][iWave];
623 _waveThresholds [iRefl][iWave] = waveThresholds[iRefl][iWave];
624 _waveToWaveIndex[iRefl][iWave] = waveIndices [iRefl][iWave];
629 template<
typename complexT>
633 if ((_nmbWavesRefl[0] + _nmbWavesRefl[1] == 0) or (_waveThresholds.size() == 0)) {
634 printErr <<
"no wave info. was readWaveList() executed successfully? aborting.";
640 for (
unsigned int iRank = 0; iRank < _rank; ++iRank) {
641 const int nmbProdAmpsPos = _nmbWavesRefl[1] - iRank;
642 int nmbProdAmpsPosC = nmbProdAmpsPos - 1;
643 if (nmbProdAmpsPosC < 0)
645 const int nmbProdAmpsNeg = _nmbWavesRefl[0] - iRank;
646 int nmbProdAmpsNegC = nmbProdAmpsNeg - 1;
647 if (nmbProdAmpsNegC < 0)
649 _nmbPars += 2 * (nmbProdAmpsPosC + nmbProdAmpsNegC);
651 if (nmbProdAmpsPos > 0)
653 if (nmbProdAmpsNeg > 0)
657 printInfo <<
"dimension of likelihood function is " << _nmbPars <<
"." << endl;
658 _parNames.resize (_nmbPars,
"");
659 _parThresholds.resize(_nmbPars, 0);
660 _parCache.resize (_nmbPars, 0);
661 _derivCache.resize (_nmbPars, 0);
662 _prodAmpToFuncParMap.resize(extents[_rank][2][_nmbWavesReflMax]);
664 unsigned int parIndex = 0;
665 for (
unsigned int iRank = 0; iRank < _rank; ++iRank)
666 for (
unsigned int iRefl = 0; iRefl < 2; ++iRefl)
667 for (
unsigned int iWave = 0; iWave < _nmbWavesRefl[iRefl]; ++iWave) {
668 ostringstream parName;
670 _prodAmpToFuncParMap[iRank][iRefl][iWave] = make_tuple(-1, -1);
671 else if (iWave == iRank) {
672 parName <<
"V" << iRank <<
"_" << _waveNames[iRefl][iWave] <<
"_RE";
673 _parNames [parIndex] = parName.str();
674 _parThresholds[parIndex] = _waveThresholds[iRefl][iWave];
675 _prodAmpToFuncParMap[iRank][iRefl][iWave] = make_tuple(parIndex, -1);
678 parName <<
"V" << iRank <<
"_" << _waveNames[iRefl][iWave];
679 _parNames [parIndex] = parName.str() +
"_RE";
680 _parThresholds[parIndex] = _waveThresholds[iRefl][iWave];
681 _parNames [parIndex + 1] = parName.str() +
"_IM";
682 _parThresholds[parIndex + 1] = _waveThresholds[iRefl][iWave];
683 _prodAmpToFuncParMap[iRank][iRefl][iWave] = make_tuple(parIndex, parIndex + 1);
688 _parNames [parIndex] =
"V_flat";
689 _parThresholds[parIndex] = 0;
694 template<
typename complexT>
701 list<string> intWaveNames = integral.
files();
703 for (list<string>::iterator it = intWaveNames.begin(); it != intWaveNames.end(); ++it) {
705 const size_t slashPos = it->rfind(
'/');
706 if (slashPos != string::npos)
707 it->erase(0, slashPos + 1);
711 for (
unsigned int iRefl = 0; iRefl < 2; ++iRefl)
712 for (
unsigned int iWave = 0; iWave < _nmbWavesRefl[iRefl]; ++iWave) {
713 if (find(intWaveNames.begin(), intWaveNames.end(), _waveNames[iRefl][iWave])
714 == intWaveNames.end()) {
715 printErr <<
"wave " << _waveNames[iRefl][iWave] <<
" is not in integral. aborting." << endl;
718 indexLookUp[iRefl][iWave] = integral.
index(_waveNames[iRefl][iWave]);
720 printDebug <<
" mapping wave [" << sign((
int)iRefl * 2 - 1) <<
", "
721 << setw(3) << iWave <<
"] '" << _waveNames[iRefl][iWave] <<
"' "
722 <<
"to index " << setw(3) << indexLookUp[iRefl][iWave] <<
" in integral." << endl;
725 reorderedMatrix.resize(extents[2][_nmbWavesReflMax][2][_nmbWavesReflMax]);
726 for (
unsigned int iRefl = 0; iRefl < 2; ++iRefl)
727 for (
unsigned int iWave = 0; iWave < _nmbWavesRefl[iRefl]; ++iWave)
728 for (
unsigned int jRefl = 0; jRefl < 2; ++jRefl)
729 for (
unsigned int jWave = 0; jWave < _nmbWavesRefl[jRefl]; ++jWave) {
730 const complex<double> val = intMatrix.
element(indexLookUp[iRefl][iWave],
731 indexLookUp[jRefl][jWave]);
732 reorderedMatrix[iRefl][iWave][jRefl][jWave] = complexT(val.real(), val.imag());
738 template<
typename complexT>
744 reorderedMatrix.resize(extents[2][_nmbWavesReflMax][2][_nmbWavesReflMax]);
745 for (
unsigned int iRefl = 0; iRefl < 2; ++iRefl)
746 for (
unsigned int iWave = 0; iWave < _nmbWavesRefl[iRefl]; ++iWave)
747 for (
unsigned int jRefl = 0; jRefl < 2; ++jRefl)
748 for (
unsigned int jWave = 0; jWave < _nmbWavesRefl[jRefl]; ++jWave) {
749 const complex<double> val = integral.
element(_waveNames[iRefl][iWave],
750 _waveNames[jRefl][jWave]);
751 reorderedMatrix[iRefl][iWave][jRefl][jWave] = complexT(val.real(), val.imag());
756 template<
typename complexT>
759 (
const string& normIntFileName,
760 const string& accIntFileName,
761 const string& integralTKeyName)
763 printInfo <<
"loading normalization integral from '" << normIntFileName <<
"'" << endl;
764 const string normIntFileExt = extensionFromPath(normIntFileName);
765 #ifdef USE_STD_COMPLEX_TREE_LEAFS
766 if (normIntFileExt ==
"root") {
767 TFile* intFile = TFile::Open(normIntFileName.c_str(),
"READ");
768 if (not intFile or intFile->IsZombie()) {
769 printErr <<
"could open normalization integral file '" << normIntFileName <<
"'. "
770 <<
"aborting." << endl;
774 intFile->GetObject(integralTKeyName.c_str(), integral);
776 printErr <<
"cannot find integral object in TKey '" << integralTKeyName <<
"' in file "
777 <<
"'" << normIntFileName <<
"'. aborting." << endl;
780 reorderIntegralMatrix(*integral, _normMatrix);
783 #endif // USE_STD_COMPLEX_TREE_LEAFS
784 if (normIntFileExt ==
"int") {
785 ifstream intFile(normIntFileName.c_str());
787 printErr <<
"cannot open file '" << normIntFileName <<
"'. aborting." << endl;
792 integral.
scan(intFile);
794 reorderIntegralMatrix(integral, _normMatrix);
796 printErr <<
"unknown file type '" << normIntFileName <<
"'. "
797 <<
"only .int and .root files are supported. aborting." << endl;
801 printInfo <<
"loading acceptance integral from '" << accIntFileName <<
"'" << endl;
802 const string accIntFileExt = extensionFromPath(accIntFileName);
803 #ifdef USE_STD_COMPLEX_TREE_LEAFS
804 if (accIntFileExt ==
"root") {
805 TFile* intFile = TFile::Open(accIntFileName.c_str(),
"READ");
806 if (not intFile or intFile->IsZombie()) {
807 printErr <<
"could open normalization integral file '" << accIntFileName <<
"'. "
808 <<
"aborting." << endl;
812 intFile->GetObject(integralTKeyName.c_str(), integral);
814 printErr <<
"cannot find integral object in TKey '" << integralTKeyName <<
"' in file "
815 <<
"'" << accIntFileName <<
"'. aborting." << endl;
818 if (_numbAccEvents != 0) {
819 _totAcc = ((double)integral->nmbEvents()) / (
double)_numbAccEvents;
820 printInfo <<
"total acceptance in this bin: " << _totAcc << endl;
821 integral->setNmbEvents(_numbAccEvents);
824 reorderIntegralMatrix(*integral, _accMatrix);
827 #endif // USE_STD_COMPLEX_TREE_LEAFS
828 if (accIntFileExt ==
"int") {
829 ifstream intFile(accIntFileName.c_str());
831 printErr <<
"cannot open file '" << accIntFileName <<
"'. aborting." << endl;
836 integral.
scan(intFile);
838 if (_numbAccEvents != 0) {
839 _totAcc = ((double)integral.
nevents()) / (
double)_numbAccEvents;
840 printInfo <<
"total acceptance in this bin: " << _totAcc << endl;
841 integral.
events(_numbAccEvents);
844 reorderIntegralMatrix(integral, _accMatrix);
846 printErr <<
"unknown file type '" << accIntFileName <<
"'. "
847 <<
"only .int and .root files are supported. exiting." << endl;
853 template<
typename complexT>
856 const bool useRootAmps,
857 const string& ampLeafName)
860 if (_normMatrix.num_elements() == 0) {
861 printErr <<
"normalization integrals have to be loaded before loading the amplitudes. "
862 <<
"aborting." << endl;
867 printInfo <<
"loading amplitude data from " << ((useRootAmps) ?
".root" :
".amp")
870 unsigned int nmbEvents = 0;
871 bool firstWave =
true;
872 for (
unsigned int iRefl = 0; iRefl < 2; ++iRefl)
873 for (
unsigned int iWave = 0; iWave < _nmbWavesRefl[iRefl]; ++iWave) {
875 const complexT normInt = _normMatrix[iRefl][iWave][iRefl][iWave];
876 vector<complexT> amps;
878 amps.reserve(nmbEvents);
880 string ampFilePath = ampDirName +
"/" + _waveNames[iRefl][iWave];
881 #ifdef USE_STD_COMPLEX_TREE_LEAFS
883 ampFilePath = changeFileExtension(ampFilePath,
".root");
884 printInfo <<
"loading amplitude data from '" << ampFilePath <<
"'" << endl;
886 TFile* ampFile = TFile::Open(ampFilePath.c_str(),
"READ");
887 if (not ampFile or ampFile->IsZombie()) {
888 printWarn <<
"cannot open amplitude file '" << ampFilePath <<
"'. skipping." << endl;
893 const string ampTreeName = changeFileExtension(_waveNames[iRefl][iWave],
".amp");
894 ampFile->GetObject(ampTreeName.c_str(), ampTree);
896 printWarn <<
"cannot find tree '" << ampTreeName <<
"' in file "
897 <<
"'" << ampFilePath <<
"'. skipping." << endl;
902 ampTree->SetBranchAddress(ampLeafName.c_str(), &TreeLeaf);
903 for (
long int eventIndex = 0; eventIndex < ampTree->GetEntriesFast(); ++eventIndex) {
904 ampTree->GetEntry(eventIndex);
906 printWarn <<
"null pointer to amplitude leaf for event " << eventIndex <<
". "
907 <<
"skipping." << endl;
912 if (_useNormalizedAmps)
913 amp /= sqrt(normInt.real());
917 #endif // USE_STD_COMPLEX_TREE_LEAFS
919 printInfo <<
"loading amplitude data from '" << ampFilePath <<
"'" << endl;
920 ifstream ampFile(ampFilePath.c_str());
922 printErr <<
"cannot open amplitude file '" << ampFilePath <<
"'. aborting." << endl;
926 while (ampFile.read((
char*)&,
sizeof(complexT))) {
927 if (_useNormalizedAmps) {
929 if(mynorm==0)mynorm=1;
936 nmbEvents = _nmbEvents = amps.size();
938 nmbEvents = amps.size();
939 if (nmbEvents != _nmbEvents)
940 printWarn <<
"size mismatch in amplitude files: this file contains " << nmbEvents
941 <<
" events, previous file had " << _nmbEvents <<
" events." << endl;
942 nmbEvents = _nmbEvents;
947 _decayAmps.resize(extents[_nmbEvents][2][_nmbWavesReflMax]);
948 for (
unsigned int iEvt = 0; iEvt < _nmbEvents; ++iEvt)
949 _decayAmps[iEvt][iRefl][iWave] = amps[iEvt];
951 printDebug <<
"read " << _nmbEvents <<
" events from file "
952 <<
"'" << _waveNames[iRefl][iWave] <<
"'" << endl;
954 printInfo <<
"loaded decay amplitudes for " << _nmbEvents <<
" events into memory" << endl;
957 _phaseSpaceIntegral.resize(extents[2][_nmbWavesReflMax]);
958 for (
unsigned int iRefl = 0; iRefl < 2; ++iRefl)
959 for (
unsigned int iWave = 0; iWave < _nmbWavesRefl[iRefl]; ++iWave)
960 _phaseSpaceIntegral[iRefl][iWave] = sqrt(_normMatrix[iRefl][iWave][iRefl][iWave].real());
963 if (_useNormalizedAmps) {
965 printInfo <<
"rescaling integrals" << endl;
967 for (
unsigned int iRefl = 0; iRefl < 2; ++iRefl)
968 for (
unsigned int iWave = 0; iWave < _nmbWavesRefl[iRefl]; ++iWave) {
969 value_type norm_i = sqrt(_normMatrix[iRefl][iWave][iRefl][iWave].real());
970 if(norm_i==0)norm_i=1;
971 for (
unsigned int jRefl = 0; jRefl < 2; ++jRefl)
972 for (
unsigned int jWave = 0; jWave < _nmbWavesRefl[jRefl]; ++jWave) {
973 value_type norm_j = sqrt(_normMatrix[jRefl][jWave][jRefl][jWave].real());
975 if(norm_j==0)norm_j=1;
976 if ((iRefl != jRefl) or (iWave != jWave))
978 _normMatrix[iRefl][iWave][jRefl][jWave] /= norm_i * norm_j;
979 _accMatrix[iRefl][iWave][jRefl][jWave] /= norm_i * norm_j;
983 for (
unsigned int iRefl = 0; iRefl < 2; ++iRefl)
984 for (
unsigned int iWave = 0; iWave < _nmbWavesRefl[iRefl]; ++iWave)
985 _normMatrix[iRefl][iWave][iRefl][iWave] = 1;
987 printDebug <<
"normalized integral matrices" << endl;
988 for (
unsigned int iRefl = 0; iRefl < 2; ++iRefl)
989 for (
unsigned int iWave = 0; iWave < _nmbWavesRefl[iRefl]; ++iWave)
990 for (
unsigned int jRefl = 0; jRefl < 2; ++jRefl)
991 for (
unsigned int jWave = 0; jWave < _nmbWavesRefl[jRefl]; ++jWave) {
992 cout <<
" normalization matrix [" << sign((
int)iRefl * 2 - 1) <<
", "
993 << setw(3) << iWave <<
", " << sign((
int)jRefl * 2 - 1) <<
", "
994 << setw(3) << jWave <<
"] = "
995 <<
"(" << maxPrecisionAlign(_normMatrix[iRefl][iWave][jRefl][jWave].real())
996 <<
", " << maxPrecisionAlign(_normMatrix[iRefl][iWave][jRefl][jWave].imag())
997 <<
"), acceptance matrix [" << setw(3) << iWave <<
", "
998 << setw(3) << jWave <<
"] = "
999 <<
"(" << maxPrecisionAlign(_accMatrix[iRefl][iWave][jRefl][jWave].real())
1000 <<
", " << maxPrecisionAlign(_accMatrix[iRefl][iWave][jRefl][jWave].imag()) <<
")"
1008 template<
typename complexT>
1012 vector<double>& phaseSpaceIntegral)
const
1014 phaseSpaceIntegral.clear();
1015 phaseSpaceIntegral.resize(_nmbWaves + 1, 0);
1016 unsigned int iIndex = 0;
1017 for (
unsigned int iRefl = 0; iRefl < 2; ++iRefl) {
1018 for (
unsigned int iWave = 0; iWave < _nmbWavesRefl[iRefl]; ++iWave) {
1019 phaseSpaceIntegral[iIndex] = _phaseSpaceIntegral[iRefl][iWave];
1020 unsigned int jIndex = 0;
1021 for (
unsigned int jRefl = 0; jRefl < 2; ++jRefl) {
1022 for (
unsigned int jWave = 0; jWave < _nmbWavesRefl[jRefl]; ++jWave) {
1023 const complexT normVal = _normMatrix[iRefl][iWave][jRefl][jWave];
1024 const complexT accVal = _accMatrix [iRefl][iWave][jRefl][jWave];
1025 normMatrix.
set(iIndex, jIndex, complex<double>(normVal.real(), normVal.imag()));
1026 accMatrix.
set (iIndex, jIndex, complex<double>(accVal.real(), accVal.imag() ));
1034 normMatrix.
set(_nmbWaves, _nmbWaves, complexT(1,0));
1035 accMatrix.
set (_nmbWaves, _nmbWaves, complexT(1,0));
1036 phaseSpaceIntegral[_nmbWaves] = 1;
1043 template<
typename complexT>
1046 vector<complex<double> >& prodAmps,
1047 vector<pair<int, int> >& parIndices,
1048 vector<string>& prodAmpNames,
1049 const bool withFlat)
const
1053 prodAmpNames.clear();
1054 unsigned int parIndex = 0;
1055 for (
unsigned int iRank = 0; iRank < _rank; ++iRank)
1056 for (
unsigned int iRefl = 0; iRefl < 2; ++iRefl)
1057 for (
unsigned int iWave = 0; iWave < _nmbWavesRefl[iRefl]; ++iWave) {
1061 else if (iWave == iRank) {
1062 parIndices.push_back(make_pair(parIndex, -1));
1063 re = inPar[parIndex];
1067 parIndices.push_back(make_pair(parIndex, parIndex + 1));
1068 re = inPar[parIndex];
1069 im = inPar[parIndex + 1];
1072 prodAmps.push_back(complex<double>(re, im));
1073 stringstream prodAmpName;
1074 prodAmpName <<
"V" << iRank <<
"_" << _waveNames[iRefl][iWave];
1075 prodAmpNames.push_back(prodAmpName.str());
1078 prodAmps.push_back(complex<double>(inPar[parIndex], 0));
1079 parIndices.push_back(make_pair(parIndex, -1));
1080 prodAmpNames.push_back(
"V_flat");
1085 template<
typename complexT>
1089 _decayAmps.resize(extents[0][0][0]);
1095 template<
typename complexT>
1100 unsigned int reflIndex = 6;
1102 if (waveName[0] ==
'V')
1104 if (waveName[reflIndex] ==
'-')
1106 else if (waveName[reflIndex] ==
'+')
1109 printErr <<
"cannot parse parameter/wave name '" << waveName <<
"'. "
1110 <<
"cannot not determine reflectivity. aborting." << endl;
1114 printDebug <<
"extracted reflectivity = " << refl <<
" from parameter name "
1115 <<
"'" << waveName <<
"' (char position " << reflIndex <<
")" << endl;
1123 template<
typename complexT>
1126 (
const double* inPar,
1131 outVal.resize(extents[_rank][2][max(_nmbWavesRefl[0], _nmbWavesRefl[1])]);
1132 unsigned int parIndex = 0;
1133 for (
unsigned int iRank = 0; iRank < _rank; ++iRank)
1134 for (
unsigned int iRefl = 0; iRefl < 2; ++iRefl)
1135 for (
unsigned int iWave = 0; iWave < _nmbWavesRefl[iRefl]; ++iWave) {
1139 else if (iWave == iRank) {
1140 re = inPar[parIndex];
1144 re = inPar[parIndex];
1145 im = inPar[parIndex + 1];
1148 outVal[iRank][iRefl][iWave] = complexT(re, im);
1150 outFlatVal = inPar[parIndex];
1157 template<
typename complexT>
1162 double* outPar)
const
1164 for (
unsigned int iRank = 0; iRank < _rank; ++iRank)
1165 for (
unsigned int iRefl = 0; iRefl < 2; ++iRefl)
1166 for (
unsigned int iWave = 0; iWave < _nmbWavesRefl[iRefl]; ++iWave) {
1167 tuple<int, int> parIndices = _prodAmpToFuncParMap[iRank][iRefl][iWave];
1168 if (get<0>(parIndices) >= 0)
1169 outPar[get<0>(parIndices)] = inVal[iRank][iRefl][iWave].real();
1170 if (get<1>(parIndices) >= 0)
1171 outPar[get<1>(parIndices)] = inVal[iRank][iRefl][iWave].imag();
1173 outPar[_nmbPars - 1] = inFlatVal;
1177 template<
typename complexT>
1181 out <<
"TPWALikelihood parameters:" << endl
1182 <<
"number of events ........................ " << _nmbEvents << endl
1183 <<
"rank .................................... " << _rank << endl
1184 <<
"number of waves ......................... " << _nmbWaves << endl
1185 <<
"number of positive reflectivity waves ... " << _nmbWavesRefl[1] << endl
1186 <<
"number of negative reflectivity waves ... " << _nmbWavesRefl[0] << endl
1187 <<
"number of function parameters ........... " << _nmbPars << endl
1188 <<
"print debug messages .................... " << _debug << endl
1190 <<
"use CUDA kernels ........................ " << _cudaEnabled << endl
1192 <<
"use normalized amplitudes ............... " << _useNormalizedAmps << endl
1193 <<
"list of waves: " << endl;
1194 for (
unsigned int iRefl = 0; iRefl < 2; ++iRefl)
1195 for (
unsigned int iWave = 0; iWave < _nmbWavesRefl[iRefl]; ++iWave)
1196 out <<
" [" << setw(2) << sign((
int)iRefl * 2 - 1) <<
" " << setw(3) << iWave <<
"] "
1197 << _waveNames[iRefl][iWave] <<
" threshold = "
1198 << _waveThresholds[iRefl][iWave] <<
" MeV/c^2" << endl;
1199 out <<
"list of function parameters: " << endl;
1200 for (
unsigned int iPar = 0; iPar < _nmbPars; ++iPar)
1201 out <<
" [" << setw(3) << iPar <<
"] " << _parNames[iPar] <<
" "
1202 <<
"threshold = " << _parThresholds[iPar] <<
" MeV/c^2" << endl;
1207 template<
typename complexT>
1211 const string funcNames[NMB_FUNCTIONCALLENUM] = {
"FdF",
"Gradient",
"DoEval",
"DoDerivative"};
1212 for (
unsigned int i = 0;
i < NMB_FUNCTIONCALLENUM; ++
i)
1213 if (_funcCallInfo[
i].nmbCalls > 0)
1214 out <<
" " << _funcCallInfo[
i].nmbCalls
1215 <<
" calls to TPWALikelihood<complexT>::" << funcNames[
i] <<
"()" << endl
1216 <<
" time spent in TPWALikelihood<complexT>::" << funcNames[
i] <<
"(): " << endl
1217 <<
" total time ................. " << sum(_funcCallInfo[
i].totalTime) <<
" sec" << endl
1218 <<
" return value calculation ... " << sum(_funcCallInfo[
i].funcTime ) <<
" sec" << endl
1219 <<
" normalization .............. " << sum(_funcCallInfo[
i].normTime ) <<
" sec" << endl;
1224 template<
typename complexT>
1225 vector<unsigned int>
1228 vector<unsigned int> orderedIndices;
1229 for (
unsigned int iRank = 0; iRank < _rank; ++iRank)
1230 for (
unsigned int waveIndex = 0; waveIndex < _nmbWaves; ++waveIndex) {
1231 unsigned int iRefl, iWave;
1232 for (iRefl = 0; iRefl < 2; ++iRefl)
1233 for (iWave = 0; iWave < _nmbWavesRefl[iRefl]; ++iWave)
1234 if (_waveToWaveIndex[iRefl][iWave] == waveIndex)
1236 printWarn <<
"indices are inconsistent. cannot find wave with index " << waveIndex
1237 <<
" in wave list" << endl;
1242 tuple<int, int> parIndices = _prodAmpToFuncParMap[iRank][iRefl][iWave];
1243 int parIndex = get<0>(parIndices);
1245 orderedIndices.push_back(parIndex);
1246 parIndex = get<1>(parIndices);
1248 orderedIndices.push_back(parIndex);
1250 orderedIndices.push_back(_nmbPars - 1);
1251 if (orderedIndices.size() != _nmbPars)
1252 printWarn <<
"ordered list of parameter indices has inconsistent size "
1253 <<
"(" << orderedIndices.size() <<
" vs. " << _nmbPars <<
")" << endl;
1254 return orderedIndices;
1258 template<
typename complexT>
1262 vector<string> names(_nmbWaves,
"");
1263 for (
unsigned int iRefl = 0; iRefl < 2; ++iRefl)
1264 for (
unsigned int iWave = 0; iWave < _nmbWavesRefl[iRefl]; ++iWave) {
1265 const unsigned int index = _waveToWaveIndex[iRefl][iWave];
1266 names[index] = _waveNames[iRefl][iWave];
1272 template<
typename complexT>
1276 for (
unsigned int i = 0;
i < NMB_FUNCTIONCALLENUM; ++
i) {
1277 _funcCallInfo[
i].nmbCalls = 0;