10#include <ecl/calibration/eclLeakageAlgorithm.h>
13#include <ecl/calibration/tools.h>
14#include <ecl/dbobjects/ECLLeakageCorrections.h>
17#include <framework/database/DBObjPtr.h>
18#include <framework/dataobjects/EventMetaData.h>
19#include <framework/datastore/DataStore.h>
20#include <framework/datastore/StoreObjPtr.h>
34using namespace Calibration;
62std::vector<double> eclLeakageFitParameters(TH1F* h,
const double& target)
66 double maxIntegral = h->Integral();
67 const int nBins = h->GetNbinsX();
73 std::vector<double> intVector;
74 intVector.push_back(h->GetBinContent(1));
75 for (
int iLo = 2; iLo <= nBins; iLo++) {
76 double nextIntegral = intVector[iLo - 2] + h->GetBinContent(iLo);
77 intVector.push_back(nextIntegral);
81 for (
int iLo = 2; iLo <= nBins; iLo++) {
82 for (
int iHi = iLo; iHi <= nBins; iHi++) {
85 double integral = intVector[iHi - 1] - intVector[iLo - 2];
88 if ((integral > target and (iHi - iLo) < (minHi - minLo)) or
89 (integral > target and (iHi - iLo) == (minHi - minLo) and integral > maxIntegral)
93 maxIntegral = integral;
99 const double lowE = h->GetBinLowEdge(minLo);
100 const double highE = h->GetBinLowEdge(minHi + 1);
101 const double peak = 0.5 * (lowE + highE);
102 const double sigma = 0.4 * (highE - lowE);
103 const double eta = 0.4;
104 const int nfitBins = (1 + minHi - minLo);
106 std::vector<double> parameters;
107 parameters.push_back(peak);
108 parameters.push_back(sigma);
109 parameters.push_back(eta);
110 parameters.push_back(lowE);
111 parameters.push_back(highE);
112 parameters.push_back(nfitBins);
120double eclLeakageNovo(Double_t* x, Double_t* par)
123 Double_t peak = par[1];
124 Double_t width = par[2];
125 Double_t sln4 =
sqrt(log(4));
126 Double_t y = par[3] * sln4;
127 Double_t tail = -log(y +
sqrt(1 + y * y)) / sln4;
130 if (TMath::Abs(tail) < 1.e-7)
131 qc = 0.5 * TMath::Power(((x[0] - peak) / width), 2);
133 double qa = tail *
sqrt(log(4.));
134 double qb = sinh(qa) / qa;
135 double qx = (x[0] - peak) / width * qb;
136 double qy = 1. + tail * qx;
139 qc = 0.5 * (TMath::Power((log(qy) / tail), 2) + tail * tail);
144 return par[0] * exp(-qc);
151int eclLeakageFitQuality(
const double& fitLo,
const double& fitHi,
const double& fitPeak,
const double& fitSigma,
152 const double& fitdEta,
const double& fitProb)
154 const double tolerance = 0.02;
155 const double redoFitProb = 1e-5;
156 const double minFitProb = 1e-9;
159 if (fitProb < redoFitProb) {fitStatus = 1;}
160 if (fitProb < minFitProb) {fitStatus = 3;}
161 double tol = tolerance * (fitHi - fitLo);
162 if (fitPeak < (fitLo + tol) or fitPeak > (fitHi - tol)) {fitStatus = 4;}
163 if (fitSigma<tol or fitSigma>(fitHi - fitLo - tol)) {fitStatus = 5;}
164 double tolEta = tolerance;
165 if (fitdEta < tolEta) {fitStatus = 6;}
173 "Generate payload ECLLeakageCorrection from single photon MC recorded by eclLeakageCollectorModule"
186 B2INFO(
"starting eclLeakageAlgorithm");
190 auto inputParameters = getObjectPtr<TH1F>(
"inputParameters");
191 int lastBin = inputParameters->GetNbinsX();
192 double scale = inputParameters->GetBinContent(lastBin);
193 for (
int ib = 1; ib < lastBin; ib++) {
194 double param = inputParameters->GetBinContent(ib);
195 inputParameters->SetBinContent(ib, param / scale);
196 inputParameters->SetBinError(ib, 0.);
200 TFile* histfile =
new TFile(
"eclLeakageAlgorithm.root",
"recreate");
201 inputParameters->Write();
204 const int nThetaID = 69;
205 const int nLeakReg = 3;
206 const int firstBarrelID = 13;
207 const int lastBarrelID = 58;
208 const int firstUsefulThID = 3;
209 const int lastUsefulThID = 66;
211 const int nPositions = (int)(inputParameters->GetBinContent(1) + 0.001);
212 const int nEnergies = (int)(inputParameters->GetBinContent(2) + 0.001);
213 const int nbinX = nEnergies * nThetaID;
215 const double etaMin = -5.;
216 const double etaMax = 5.;
220 auto generatedE = create2Dvector<float>(nLeakReg, nEnergies);
223 for (
int ireg = 0; ireg < nLeakReg; ireg++) {
224 B2INFO(
"Generated energies for ireg = " << ireg);
225 for (
int ie = 0; ie < nEnergies; ie++) {
227 generatedE[ireg][ie] = inputParameters->GetBinContent(bin);
228 B2INFO(
" " << ie <<
" " << generatedE[ireg][ie] <<
" GeV");
234 auto iEnergiesMeV = create2Dvector<int>(nEnergies, nThetaID);
235 for (
int thID = 0; thID < nThetaID; thID++) {
237 if (thID >= firstBarrelID and thID <= lastBarrelID) {
239 }
else if (thID > lastBarrelID) {
242 for (
int ie = 0; ie < nEnergies; ie++) {
243 iEnergiesMeV[ie][thID] = (int)(1000.*generatedE[ireg][ie] + 0.5);
249 const double eFracLo = 0.4;
250 const double eFracHi = 1.5;
251 auto nEfracBins = create2Dvector<int>(nEnergies, nThetaID);
252 for (
int thID = 0; thID < nThetaID; thID++) {
253 B2DEBUG(25,
"eFrac nBins for thetaID " << thID);
254 for (
int ie = 0; ie < nEnergies; ie++) {
257 double res_squared = 0.0001 + 0.064 / iEnergiesMeV[ie][thID];
260 double binNumOver2 = 3. /
sqrt(res_squared);
261 int tempNBin = (int)(binNumOver2 + 0.5);
262 nEfracBins[ie][thID] = 2 * tempNBin;
263 B2DEBUG(25,
" ie = " << ie <<
" E = " << iEnergiesMeV[ie][thID] <<
" nBins = " << nEfracBins[ie][thID]);
269 TString statusString[7] = {
"good",
"refit",
"lowStat",
"lowProb",
"peakAtLimit",
"sigmaAtLimit",
"etaAtLimit"};
270 const double fracEnt[2] = {0.683, 0.5};
271 const double minEntries = 100.;
272 const double minMaxBin = 50.;
273 const double highMaxBin = 300.;
275 TF1* func =
new TF1(
"eclLeakageNovo", eclLeakageNovo, eFracLo, eFracHi, 4);
276 func->SetParNames(
"normalization",
"peak",
"effSigma",
"eta");
277 func->SetLineColor(kRed);
281 auto tree = getObjectPtr<TTree>(
"tree");
282 tree->SetBranchAddress(
"cellID", &
t_cellID);
283 tree->SetBranchAddress(
"thetaID", &
t_thetaID);
284 tree->SetBranchAddress(
"region", &
t_region);
285 tree->SetBranchAddress(
"thetaBin", &
t_thetaBin);
286 tree->SetBranchAddress(
"phiBin", &
t_phiBin);
287 tree->SetBranchAddress(
"phiMech", &
t_phiMech);
289 tree->SetBranchAddress(
"nCrys", &
t_nCrys);
294 const int treeEntries = tree->GetEntries();
295 B2INFO(
"eclLeakageAlgorithm entries = " << treeEntries);
303 const int iRun = exprun[0].second;
304 const int iExp = exprun[0].first;
315 TH2F existingThetaCorrection = existingCorrections->getThetaCorrections();
316 existingThetaCorrection.SetName(
"existingThetaCorrection");
317 TH2F existingPhiCorrection = existingCorrections->getPhiCorrections();
318 existingPhiCorrection.SetName(
"existingPhiCorrection");
322 existingThetaCorrection.Write();
323 existingPhiCorrection.Write();
336 auto hELabUncorr = create2Dvector<TH1F*>(nEnergies, nThetaID);
337 for (
int thID = firstUsefulThID; thID <= lastUsefulThID; thID++) {
338 TString sthID = std::to_string(thID);
339 for (
int ie = 0; ie < nEnergies; ie++) {
340 name =
"hELabUncorr_" + std::to_string(ie) +
"_" + sthID;
341 title =
"eFrac " + to_string(iEnergiesMeV[ie][thID]) +
" MeV thetaID " + sthID +
";E/Etrue";
344 hELabUncorr[ie][thID] =
new TH1F(name, title, 2 * nEfracBins[ie][thID], eFracLo, eFracHi);
350 for (
int i = 0; i < treeEntries; i++) {
354 bool goodReco =
t_thetaID >= firstUsefulThID and t_thetaID <= lastUsefulThID and t_energyBin >= 0;
355 if (not goodReco) {
continue;}
364 auto peakUncorr = create2Dvector<float>(nEnergies, nThetaID);
365 auto etaUncorr = create2Dvector<float>(nEnergies, nThetaID);
367 std::vector<TString> failedELabUncorr;
368 std::vector<int> statusELabUncorr;
369 int payloadStatus = 0;
372 TH1F* statusOfhELabUncorr =
new TH1F(
"statusOfhELabUncorr",
373 "status of hELabUncorr fits for each thetaID/energy. 0 = good, 1 = redo fit, 2 = lowStat, 3 = lowProb, 4 = peakAtLimit, 5 = sigmaAtLimit",
379 for (
int thID = firstUsefulThID; thID <= lastUsefulThID; thID++) {
380 TString sthID = std::to_string(thID);
381 for (
int ie = 0; ie < nEnergies; ie++) {
382 TH1F* hEnergy = (TH1F*)hELabUncorr[ie][thID];
386 double entries = hEnergy->Integral();
388 double genE = iEnergiesMeV[ie][thID] / 1000.;
389 bool fitHist = entries > minEntries;
395 double norm = hEnergy->GetMaximum();
396 double target = fracEnt[nIter] * entries;
397 std::vector<double> startingParameters;
398 startingParameters = eclLeakageFitParameters(hEnergy, target);
399 func->SetParameters(norm, startingParameters[0], startingParameters[1], startingParameters[2]);
400 func->SetParLimits(1, startingParameters[3], startingParameters[4]);
401 func->SetParLimits(2, 0., startingParameters[4] - startingParameters[3]);
402 func->SetParLimits(3, etaMin, etaMax);
405 name = hEnergy->GetName();
406 B2DEBUG(40,
"Fitting " << name.Data());
407 hEnergy->Fit(func,
"LIEQ",
"", startingParameters[3], startingParameters[4]);
408 peak = func->GetParameter(1);
409 double effSigma = func->GetParameter(2);
410 eta = func->GetParameter(3);
411 double prob = func->GetProb();
415 double dEta = min((etaMax - eta), (eta - etaMin));
416 fitStatus = eclLeakageFitQuality(startingParameters[3], startingParameters[4], peak, effSigma, dEta, prob);
419 if ((fitStatus == 1 or fitStatus == 3) and nIter == 0) {
429 statusOfhELabUncorr->Fill(fitStatus + 0.000001);
430 if (fitStatus == 2 or fitStatus >= 4) {
431 statusELabUncorr.push_back(fitStatus);
432 failedELabUncorr.push_back(hEnergy->GetName());
439 peakUncorr[ie][thID] = peak;
440 etaUncorr[ie][thID] = eta;
443 if (entries > minEntries) {
445 hELabUncorr[ie][thID]->Write();
452 statusOfhELabUncorr->Write();
456 int nbadFit = statusELabUncorr.size();
457 if (nbadFit > 0) {B2ERROR(
"hELabUncorr fit failures (one histogram per energy/thetaID):");}
458 for (
int ibad = 0; ibad < nbadFit; ibad++) {
459 int badStat = statusELabUncorr[ibad];
460 B2ERROR(
" histogram " << failedELabUncorr[ibad].Data() <<
" status " << badStat <<
" " << statusString[badStat].Data());
462 if (payloadStatus != 0) {
463 B2ERROR(
"ecLeakageAlgorithm: fit to hELabUncorr failed. ");
470 for (
int thID = firstUsefulThID; thID <= lastUsefulThID; thID++) {
471 for (
int ie = 0; ie < nEnergies; ie++) {
472 if (peakUncorr[ie][thID] < 0.) {
474 for (
int nextID = thID - 1; thID >= firstUsefulThID; thID--) {
475 if (peakUncorr[ie][nextID] > 0.) {
476 peakUncorr[ie][thID] = peakUncorr[ie][nextID];
481 for (
int nextID = thID + 1; thID <= lastUsefulThID; thID++) {
482 if (peakUncorr[ie][nextID] > 0.) {
483 peakUncorr[ie][thID] = peakUncorr[ie][nextID];
491 if (peakUncorr[ie][thID] < 0.) {
492 B2ERROR(
"ecLeakageAlgorithm: unable to correct hELabUncorr for thetaID " << thID <<
" ie " << ie);
509 const TString dirName[nDir] = {
"theta",
"phiMech",
"phiNoMech"};
511 auto eFracPosition = create4Dvector<TH1F*>(nEnergies, nThetaID, nDir, nPositions);
514 std::vector<TString> failedeFracPosition;
515 std::vector<int> statuseFracPosition;
517 for (
int thID = firstUsefulThID; thID <= lastUsefulThID; thID++) {
518 TString sthID = std::to_string(thID);
519 for (
int ie = 0; ie < nEnergies; ie++) {
520 TString sie = std::to_string(ie);
521 for (
int idir = 0; idir < nDir; idir++) {
522 TString sidir = std::to_string(idir);
523 for (
int ipos = 0; ipos < nPositions; ipos++) {
524 TString sipos = std::to_string(ipos);
525 name =
"eFracPosition_" + sie +
"_" + sthID +
"_" + sidir +
"_" + sipos;
526 title =
"eFrac " + to_string(iEnergiesMeV[ie][thID]) +
" MeV thetaID " + sthID +
" " + dirName[idir] +
" pos " + sipos +
528 eFracPosition[ie][thID][idir][ipos] =
new TH1F(name, title, nEfracBins[ie][thID], eFracLo, eFracHi);
535 TH1F* statusOfeFracPosition =
new TH1F(
"statusOfeFracPosition",
536 "eFrac fit status: -2 noData, -1 lowE, 0 good, 1 redo fit, 2 lowStat, 3 lowProb, 4 peakAtLimit, 5 sigmaAtLimit", 8, -2,
538 TH1F* probOfeFracPosition =
new TH1F(
"probOfeFracPosition",
"fit probability of eFrac fits for each position;probability", 100, 0,
540 TH1F* maxOfeFracPosition =
new TH1F(
"maxOfeFracPosition",
"max entries of eFrac histograms;maximum bin content", 100, 0, 1000);
544 for (
int i = 0; i < treeEntries; i++) {
548 bool goodReco =
t_thetaID >= firstUsefulThID and t_thetaID <= lastUsefulThID and t_energyBin >= 0;
549 if (not goodReco) {
continue;}
562 auto positionCorrection = create4Dvector<float>(nEnergies, nThetaID, nDir, nPositions);
563 auto positionCorrectionUnc = create4Dvector<float>(nEnergies, nThetaID, nDir, nPositions);
568 TH1F* thetaCorSummary =
new TH1F(
"thetaCorSummary",
"Theta dependent corrections;theta dependent correction", 100, 0.4, 1.4);
569 TH1F* phiCorSummary =
new TH1F(
"phiCorSummary",
"Phi dependent corrections;phi dependent correction", 100, 0.4, 1.4);
571 for (
int thID = firstUsefulThID; thID <= lastUsefulThID; thID++) {
572 for (
int ie = 0; ie < nEnergies; ie++) {
573 double genE = iEnergiesMeV[ie][thID] / 1000.;
574 for (
int idir = 0; idir < nDir; idir++) {
575 for (
int ipos = 0; ipos < nPositions; ipos++) {
576 TH1F* hEnergy = (TH1F*)eFracPosition[ie][thID][idir][ipos];
577 if (hEnergy->Integral() > minEntries) {nHistToFit++;}
581 double correction =
sqrt(peakUncorr[ie][thID]);
582 double corrUnc = 0.05;
586 if (hEnergy->GetEntries() < 0.5) {fitStatus = -2;}
588 double entries = hEnergy->Integral();
596 double target = fracEnt[nIter] * entries;
597 std::vector<double> startingParameters;
598 bool findParm =
true;
600 startingParameters = eclLeakageFitParameters(hEnergy, target);
603 if (hEnergy->GetMaximum()<minMaxBin and startingParameters[5]>11.9) {
609 double norm = hEnergy->GetMaximum();
610 double fitLow = startingParameters[3];
611 double fitHigh = startingParameters[4];
614 double etaFix = etaUncorr[ie][thID];
615 func->SetParameters(norm, startingParameters[0], startingParameters[1], etaFix);
616 func->SetParLimits(1, fitLow, fitHigh);
617 func->SetParLimits(2, 0., fitHigh - fitLow);
620 if (hEnergy->GetMaximum() < highMaxBin) {
621 func->SetParLimits(3, etaFix, etaFix);
623 func->SetParLimits(3, etaMin, etaMax);
627 name = hEnergy->GetName();
628 B2DEBUG(40,
"Fitting " << name.Data());
629 hEnergy->Fit(func,
"LIEQ",
"", fitLow, fitHigh);
630 double peak = func->GetParameter(1);
631 double effSigma = func->GetParameter(2);
632 double eta = func->GetParameter(3);
633 prob = func->GetProb();
637 double dEta = min((etaMax - eta), (eta - etaMin));
638 fitStatus = eclLeakageFitQuality(fitLow, fitHigh, peak, effSigma, dEta, prob);
641 if ((fitStatus == 1 or fitStatus == 3) and nIter == 0) {
646 }
else if (fitStatus <= 3) {
650 correction = peak /
sqrt(peakUncorr[ie][thID]);
651 corrUnc = func->GetParError(1) /
sqrt(peakUncorr[ie][thID]);
656 positionCorrection[ie][thID][idir][ipos] = correction;
657 positionCorrectionUnc[ie][thID][idir][ipos] = corrUnc;
658 statusOfeFracPosition->Fill(fitStatus + 0.00001);
659 probOfeFracPosition->Fill(prob);
660 maxOfeFracPosition->Fill(hEnergy->GetMaximum());
663 if (prob > 0 and fitStatus <= 3) {
665 thetaCorSummary->Fill(correction);
667 phiCorSummary->Fill(correction);
672 if (fitStatus >= 2) {
673 statuseFracPosition.push_back(fitStatus);
674 failedeFracPosition.push_back(hEnergy->GetName());
685 B2INFO(
"eclLeakageAlgorithm: " << nHistToFit <<
" eFracPosition histograms to fit");
686 nbadFit = statuseFracPosition.size();
687 B2INFO(
"eFracPosition failed fits: " << nbadFit);
688 for (
int ibad = 0; ibad < nbadFit; ibad++) {
689 int badStat = statuseFracPosition[ibad];
690 B2ERROR(
" histogram " << failedeFracPosition[ibad].Data() <<
" status " << badStat <<
" " << statusString[badStat].Data());
695 statusOfeFracPosition->Write();
696 probOfeFracPosition->Write();
697 maxOfeFracPosition->Write();
698 thetaCorSummary->Write();
699 phiCorSummary->Write();
711 for (
int thID = firstUsefulThID - 1; thID >= 0; thID--) {
712 for (
int ie = 0; ie < nEnergies; ie++) {
714 for (
int idir = 0; idir < 3; idir++) {
715 for (
int ipos = 0; ipos < nPositions; ipos++) {
716 positionCorrection[ie][thID][idir][ipos] = positionCorrection[ie][thID + 1][idir][ipos];
717 positionCorrectionUnc[ie][thID][idir][ipos] = positionCorrectionUnc[ie][thID + 1][idir][ipos];
724 for (
int thID = lastUsefulThID + 1; thID < nThetaID; thID++) {
725 for (
int ie = 0; ie < nEnergies; ie++) {
727 for (
int idir = 0; idir < 3; idir++) {
728 for (
int ipos = 0; ipos < nPositions; ipos++) {
729 positionCorrection[ie][thID][idir][ipos] = positionCorrection[ie][thID - 1][idir][ipos];
730 positionCorrectionUnc[ie][thID][idir][ipos] = positionCorrectionUnc[ie][thID - 1][idir][ipos];
738 std::vector<float> forwardVector;
739 std::vector<float> barrelVector;
740 std::vector<float> backwardVector;
741 for (
int ie = 0; ie < nEnergies; ie++) {
742 forwardVector.push_back(log(generatedE[0][ie]));
743 barrelVector.push_back(log(generatedE[1][ie]));
744 backwardVector.push_back(log(generatedE[2][ie]));
748 float leakLogE[3][12] = {};
749 for (
int ie = 0; ie < nEnergies; ie++) {
750 leakLogE[0][ie] = forwardVector[ie];
751 leakLogE[1][ie] = barrelVector[ie];
752 leakLogE[2][ie] = backwardVector[ie];
759 TH2F thetaCorrection(
"thetaCorrection",
"Theta correction vs bin;bin = thetaID + 69*energyBin;local theta bin", nbinX, 0, nbinX,
760 nPositions, 0, nPositions);
762 for (
int ie = 0; ie < nEnergies; ie++) {
763 for (
int thID = 0; thID < nThetaID; thID++) {
765 for (
int ipos = 0; ipos < nPositions; ipos++) {
767 float correction = positionCorrection[ie][thID][0][ipos];
768 float corrUnc = positionCorrectionUnc[ie][thID][0][ipos];
769 thetaCorrection.SetBinContent(ix, iy, correction);
770 thetaCorrection.SetBinError(ix, iy, corrUnc);
777 TH2F phiCorrection(
"phiCorrection",
"Phi correction vs bin;bin = thetaID + 69*energyBin;local phi bin", 2 * nbinX, 0, 2 * nbinX,
778 nPositions, 0, nPositions);
780 for (
int ie = 0; ie < nEnergies; ie++) {
781 for (
int thID = 0; thID < nThetaID; thID++) {
783 for (
int ipos = 0; ipos < nPositions; ipos++) {
787 float correction = positionCorrection[ie][thID][1][ipos];
788 float corrUnc = positionCorrectionUnc[ie][thID][1][ipos];
789 phiCorrection.SetBinContent(ix, iy, correction);
790 phiCorrection.SetBinError(ix, iy, corrUnc);
793 correction = positionCorrection[ie][thID][2][ipos];
794 corrUnc = positionCorrectionUnc[ie][thID][2][ipos];
795 phiCorrection.SetBinContent(ix + nbinX, iy, correction);
796 phiCorrection.SetBinError(ix + nbinX, iy, corrUnc);
804 TH2F nCrystalCorrection(
"nCrystalCorrection",
"nCrys correction vs bin;bin = thetaID + 69*energyBin;nCrys", nbinX, 0, nbinX,
805 maxN + 1, 0, maxN + 1);
808 for (
int ie = 0; ie < nEnergies; ie++) {
809 for (
int thID = 0; thID < nThetaID; thID++) {
811 for (
int in = 0; in <= maxN; in++) {
813 float correction = 1.;
815 nCrystalCorrection.SetBinContent(ix, iy, correction);
816 nCrystalCorrection.SetBinError(ix, iy, corrUnc);
828 thetaCorrection.Write();
829 phiCorrection.Write();
830 nCrystalCorrection.Write();
837 const int nResType = 5;
838 const TString resName[nResType] = {
"Uncorrected",
"Original",
"Corrected no nCrys",
"Corrected measured",
"Corrected true"};
839 const TString regName[nLeakReg] = {
"forward",
"barrel",
"backward"};
840 auto energyResolution = create3Dvector<TH1F*>(nLeakReg, nEnergies, nResType);
843 int thIDReg[nLeakReg];
848 for (
int ireg = 0; ireg < nLeakReg; ireg++) {
849 for (
int ie = 0; ie < nEnergies; ie++) {
852 TString stireg = std::to_string(ireg);
853 TString stie = std::to_string(ie);
854 TString stieName = std::to_string(iEnergiesMeV[ie][thIDReg[ireg]]);
855 int nbinReg = 20 * nEfracBins[ie][thIDReg[ireg]];
857 for (
int ires = 0; ires < nResType; ires++) {
858 name =
"energyResolution_" + stireg +
"_" + stie +
"_" + std::to_string(ires);
859 title = resName[ires] +
" energy, " + stieName +
" MeV, " + regName[ireg] +
";Reconstructed E/Etrue";
860 energyResolution[ireg][ie][ires] =
new TH1F(name, title, nbinReg, eFracLo, eFracHi);
867 for (
int i = 0; i < treeEntries; i++) {
871 bool goodReco =
t_thetaID >= firstUsefulThID and t_thetaID <= lastUsefulThID and t_energyBin >= 0;
872 if (not goodReco) {
continue;}
883 float corrTrue = thetaPosCor * phiPosCor;
888 float corrMeasured = 0.96;
889 for (
int iter = 0; iter < 2; iter++) {
894 float logEnergy = log(energyRaw / corrMeasured);
896 if (logEnergy < leakLogE[
t_region][0]) {
898 }
else if (logEnergy > leakLogE[
t_region][nEnergies - 1]) {
901 while (logEnergy > leakLogE[
t_region][ie0 + 1]) {ie0++;}
910 corrMeasured = cor0 + (cor1 - cor0) * (logEnergy - leakLogE[
t_region][ie0]) / (leakLogE[
t_region][ie0 + 1] -
915 float corrNonCrys = corrMeasured;
930 auto peakEnergy = create3Dvector<float>(nLeakReg, nEnergies, nResType);
931 auto energyRes = create3Dvector<float>(nLeakReg, nEnergies, nResType);
934 for (
int ireg = 0; ireg < nLeakReg; ireg++) {
935 for (
int ie = 0; ie < nEnergies; ie++) {
938 double entries = energyResolution[ireg][ie][nResType - 1]->Integral();
939 for (
int ires = 0; ires < nResType; ires++) {
940 TH1F* hEnergy = (TH1F*)energyResolution[ireg][ie][ires];
944 bool fitHist = entries > minEntries;
950 double norm = hEnergy->GetMaximum();
951 double target = fracEnt[nIter] * entries;
952 std::vector<double> startingParameters;
953 startingParameters = eclLeakageFitParameters(hEnergy, target);
954 func->SetParameters(norm, startingParameters[0], startingParameters[1], startingParameters[2]);
955 func->SetParLimits(1, startingParameters[3], startingParameters[4]);
956 func->SetParLimits(2, 0., startingParameters[4] - startingParameters[3]);
957 func->SetParLimits(3, etaMin, etaMax);
963 int minLo = hEnergy->GetXaxis()->FindBin(startingParameters[3] + 0.0001);
964 int minHi = hEnergy->GetXaxis()->FindBin(startingParameters[4] - 0.0001);
967 double dx = hEnergy->GetBinLowEdge(minLo + 1) - hEnergy->GetBinLowEdge(minLo);
968 double overage = hEnergy->Integral(minLo, minHi) - target;
969 double subLo = overage / hEnergy->GetBinContent(minLo);
970 double subHi = overage / hEnergy->GetBinContent(minHi);
973 res68 = 0.5 * dx * (1 + minHi - minLo - max(subLo, subHi));
977 name = hEnergy->GetName();
978 B2DEBUG(40,
"Fitting " << name.Data());
979 hEnergy->Fit(func,
"LIEQ",
"", startingParameters[3], startingParameters[4]);
980 peak = func->GetParameter(1);
981 double effSigma = func->GetParameter(2);
982 double eta = func->GetParameter(3);
983 double prob = func->GetProb();
987 double dEta = min((etaMax - eta), (eta - etaMin));
988 int fitStatus = eclLeakageFitQuality(startingParameters[3], startingParameters[4], peak, effSigma, dEta, prob);
991 if ((fitStatus == 1 or fitStatus == 3) and nIter == 0) {
1000 peakEnergy[ireg][ie][ires] = peak;
1001 energyRes[ireg][ie][ires] = res68;
1012 int nresBins = nEnergies * nLeakReg * (nResType + 1);
1013 TH1F* peakSummary =
new TH1F(
"peakSummary",
"Peak E/Etrue for each method, region, energy;Energy energy point", nresBins, 0,
1015 TH1F* resolutionSummary =
new TH1F(
"resolutionSummary",
"Resolution/peak for each method, region, energy;Energy energy point",
1016 nresBins, 0, nEnergies);
1018 B2INFO(
"Resolution divided by peak for each energy bin and region " << nResType <<
" ways");
1019 for (
int ires = 0; ires < nResType; ires++) {B2INFO(
" " << resName[ires]);}
1021 for (
int ie = 0; ie < nEnergies; ie++) {
1022 B2INFO(
" energy point " << ie);
1023 for (
int ireg = 0; ireg < nLeakReg; ireg++) {
1024 B2INFO(
" region " << ireg);
1025 for (
int ires = 0; ires < nResType; ires++) {
1029 peakSummary->SetBinContent(ix, peakEnergy[ireg][ie][ires]);
1030 peakSummary->SetBinError(ix, 0.);
1031 resolutionSummary->SetBinContent(ix, energyRes[ireg][ie][ires] / peakEnergy[ireg][ie][ires]);
1032 resolutionSummary->SetBinError(ix, 0.);
1035 B2INFO(
" " << ires <<
" " << energyRes[ireg][ie][ires] / peakEnergy[ireg][ie][ires]);
1043 peakSummary->Write();
1044 resolutionSummary->Write();
1066 B2INFO(
"eclLeakageAlgorithm: successfully stored payload ECLLeakageCorrections");
Base class for calibration algorithms.
void saveCalibration(TClonesArray *data, const std::string &name)
Store DBArray payload with given name with default IOV.
void setDescription(const std::string &description)
Set algorithm description (in constructor)
const std::vector< Calibration::ExpRun > & getRunList() const
Get the list of runs for which calibration is called.
EResult
The result of calibration.
@ c_OK
Finished successfully =0 in Python.
@ c_Failure
Failed =3 in Python.
Class for accessing objects in the database.
Singleton class to cache database objects.
static DataStore & Instance()
Instance of singleton Store.
void setInitializeActive(bool active)
Setter for m_initializeActive.
DB object to store leakage corrections, including nCrys dependence
void setThetaCorrections(const TH2F &thetaCorrections)
Set the 2D histogram containing the theta corrections for each thetaID and energy.
void setlogEnergiesBrl(const std::vector< float > &logEnergiesBrl)
Set the vector of energies used to evaluate the leakage corrections in the barrel.
void setnCrystalCorrections(const TH2F &nCrystalCorrections)
Set the 2D histogram containing the nCrys corrections for each thetaID and energy.
void setlogEnergiesFwd(const std::vector< float > &logEnergiesFwd)
Set the vector of energies used to evaluate the leakage corrections in the forward endcap.
void setPhiCorrections(const TH2F &phiCorrections)
Set the 2D histogram containing the phi corrections for each thetaID and energy.
void setlogEnergiesBwd(const std::vector< float > &logEnergiesBwd)
Set the vector of energies used to evaluate the leakage corrections in the backward endcap.
float t_energyFrac
measured energy after nOptimal bias and peak corrections, divided by generated
float t_locationError
reconstructed minus generated position (cm)
int t_energyBin
generated energy point
int t_thetaID
thetaID of photon
int t_phiBin
binned location in phi relative to crystal edge
int t_phiMech
mechanical structure next to lower phi (0), upper phi (1), or neither (2)
int t_region
region of photon 0=forward 1=barrel 2=backward
int t_thetaBin
binned location in theta relative to crystal edge
int t_nCrys
number of crystals used to calculate energy
virtual EResult calibrate() override
Run algorithm.
eclLeakageAlgorithm()
Constructor.
double m_lowEnergyThreshold
Parameters to control fit procedure.
float t_origEnergyFrac
corrected energy at time of generation, divided by generated
bool registerInDataStore(DataStore::EStoreFlags storeFlags=DataStore::c_WriteOut)
Register the object/array in the DataStore.
Type-safe access to single objects in the data store.
bool construct(Args &&... params)
Construct an object of type T in this StoreObjPtr, using the provided constructor arguments.
static DBStore & Instance()
Instance of a singleton DBStore.
void update()
Updates all objects that are outside their interval of validity.
double sqrt(double a)
sqrt for double
Abstract base class for different kinds of events.