8 #include <ecl/calibration/eclLeakageAlgorithm.h>
9 #include <ecl/calibration/tools.h>
10 #include <ecl/dbobjects/ECLLeakageCorrections.h>
11 #include <framework/datastore/StoreObjPtr.h>
12 #include <framework/dataobjects/EventMetaData.h>
13 #include <framework/datastore/DataStore.h>
20 #include "TDirectory.h"
27 using namespace Calibration;
55 std::vector<double> eclLeakageFitParameters(TH1F* h,
const double& target)
59 double maxIntegral = h->Integral();
60 const int nBins = h->GetNbinsX();
66 std::vector<double> intVector;
67 intVector.push_back(h->GetBinContent(1));
68 for (
int iLo = 2; iLo <= nBins; iLo++) {
69 double nextIntegral = intVector[iLo - 2] + h->GetBinContent(iLo);
70 intVector.push_back(nextIntegral);
74 for (
int iLo = 2; iLo <= nBins; iLo++) {
75 for (
int iHi = iLo; iHi <= nBins; iHi++) {
78 double integral = intVector[iHi - 1] - intVector[iLo - 2];
81 if ((integral > target and (iHi - iLo) < (minHi - minLo)) or
82 (integral > target and (iHi - iLo) == (minHi - minLo) and integral > maxIntegral)
86 maxIntegral = integral;
92 const double lowE = h->GetBinLowEdge(minLo);
93 const double highE = h->GetBinLowEdge(minHi + 1);
94 const double peak = 0.5 * (lowE + highE);
95 const double sigma = 0.4 * (highE - lowE);
96 const double eta = 0.4;
97 const int nfitBins = (1 + minHi - minLo);
99 std::vector<double> parameters;
100 parameters.push_back(peak);
101 parameters.push_back(sigma);
102 parameters.push_back(eta);
103 parameters.push_back(lowE);
104 parameters.push_back(highE);
105 parameters.push_back(nfitBins);
113 double eclLeakageNovo(Double_t* x, Double_t* par)
116 Double_t peak = par[1];
117 Double_t width = par[2];
118 Double_t sln4 =
sqrt(log(4));
119 Double_t y = par[3] * sln4;
120 Double_t tail = -log(y +
sqrt(1 + y * y)) / sln4;
123 if (TMath::Abs(tail) < 1.e-7)
124 qc = 0.5 * TMath::Power(((x[0] - peak) / width), 2);
126 double qa = tail *
sqrt(log(4.));
127 double qb = sinh(qa) / qa;
128 double qx = (x[0] - peak) / width * qb;
129 double qy = 1. + tail * qx;
132 qc = 0.5 * (TMath::Power((log(qy) / tail), 2) + tail * tail);
137 return par[0] * exp(-qc);
144 int eclLeakageFitQuality(
const double& fitLo,
const double& fitHi,
const double& fitPeak,
const double& fitSigma,
145 const double& fitdEta,
const double& fitProb)
147 const double tolerance = 0.02;
148 const double redoFitProb = 1e-5;
149 const double minFitProb = 1e-9;
152 if (fitProb < redoFitProb) {fitStatus = 1;}
153 if (fitProb < minFitProb) {fitStatus = 3;}
154 double tol = tolerance * (fitHi - fitLo);
155 if (fitPeak < (fitLo + tol) or fitPeak > (fitHi - tol)) {fitStatus = 4;}
156 if (fitSigma<tol or fitSigma>(fitHi - fitLo - tol)) {fitStatus = 5;}
157 double tolEta = tolerance;
158 if (fitdEta < tolEta) {fitStatus = 6;}
166 "Generate payload ECLLeakageCorrection from single photon MC recorded by eclLeakageCollectorModule"
179 B2INFO(
"starting eclLeakageAlgorithm");
183 auto inputParameters = getObjectPtr<TH1F>(
"inputParameters");
184 int lastBin = inputParameters->GetNbinsX();
185 double scale = inputParameters->GetBinContent(lastBin);
186 for (
int ib = 1; ib < lastBin; ib++) {
187 double param = inputParameters->GetBinContent(ib);
188 inputParameters->SetBinContent(ib, param / scale);
189 inputParameters->SetBinError(ib, 0.);
193 TFile* histfile =
new TFile(
"eclLeakageAlgorithm.root",
"recreate");
194 inputParameters->Write();
197 const int nThetaID = 69;
198 const int nLeakReg = 3;
199 const int firstBarrelID = 13;
200 const int lastBarrelID = 58;
201 const int firstUsefulThID = 3;
202 const int lastUsefulThID = 66;
204 const int nPositions = (int)(inputParameters->GetBinContent(1) + 0.001);
205 const int nEnergies = (int)(inputParameters->GetBinContent(2) + 0.001);
206 const int nbinX = nEnergies * nThetaID;
208 const double etaMin = -5.;
209 const double etaMax = 5.;
213 auto generatedE = create2Dvector<float>(nLeakReg, nEnergies);
216 for (
int ireg = 0; ireg < nLeakReg; ireg++) {
217 B2INFO(
"Generated energies for ireg = " << ireg);
218 for (
int ie = 0; ie < nEnergies; ie++) {
220 generatedE[ireg][ie] = inputParameters->GetBinContent(bin);
221 B2INFO(
" " << ie <<
" " << generatedE[ireg][ie] <<
" GeV");
227 auto iEnergiesMeV = create2Dvector<int>(nEnergies, nThetaID);
228 for (
int thID = 0; thID < nThetaID; thID++) {
230 if (thID >= firstBarrelID and thID <= lastBarrelID) {
232 }
else if (thID > lastBarrelID) {
235 for (
int ie = 0; ie < nEnergies; ie++) {
236 iEnergiesMeV[ie][thID] = (int)(1000.*generatedE[ireg][ie] + 0.5);
242 const double eFracLo = 0.4;
243 const double eFracHi = 1.5;
244 auto nEfracBins = create2Dvector<int>(nEnergies, nThetaID);
245 for (
int thID = 0; thID < nThetaID; thID++) {
246 B2DEBUG(25,
"eFrac nBins for thetaID " << thID);
247 for (
int ie = 0; ie < nEnergies; ie++) {
250 double res_squared = 0.0001 + 0.064 / iEnergiesMeV[ie][thID];
253 double binNumOver2 = 3. /
sqrt(res_squared);
254 int tempNBin = (int)(binNumOver2 + 0.5);
255 nEfracBins[ie][thID] = 2 * tempNBin;
256 B2DEBUG(25,
" ie = " << ie <<
" E = " << iEnergiesMeV[ie][thID] <<
" nBins = " << nEfracBins[ie][thID]);
262 TString statusString[7] = {
"good",
"refit",
"lowStat",
"lowProb",
"peakAtLimit",
"sigmaAtLimit",
"etaAtLimit"};
263 const double fracEnt[2] = {0.683, 0.5};
264 const double minEntries = 100.;
265 const double minMaxBin = 50.;
266 const double highMaxBin = 300.;
268 TF1* func =
new TF1(
"eclLeakageNovo", eclLeakageNovo, eFracLo, eFracHi, 4);
269 func->SetParNames(
"normalization",
"peak",
"effSigma",
"eta");
270 func->SetLineColor(kRed);
274 auto tree = getObjectPtr<TTree>(
"tree");
275 tree->SetBranchAddress(
"cellID", &
t_cellID);
276 tree->SetBranchAddress(
"thetaID", &
t_thetaID);
277 tree->SetBranchAddress(
"region", &
t_region);
278 tree->SetBranchAddress(
"thetaBin", &
t_thetaBin);
279 tree->SetBranchAddress(
"phiBin", &
t_phiBin);
280 tree->SetBranchAddress(
"phiMech", &
t_phiMech);
282 tree->SetBranchAddress(
"nCrys", &
t_nCrys);
287 const int treeEntries = tree->GetEntries();
288 B2INFO(
"eclLeakageAlgorithm entries = " << treeEntries);
296 const int iRun = exprun[0].second;
297 const int iExp = exprun[0].first;
308 TH2F existingThetaCorrection = existingCorrections->getThetaCorrections();
309 existingThetaCorrection.SetName(
"existingThetaCorrection");
310 TH2F existingPhiCorrection = existingCorrections->getPhiCorrections();
311 existingPhiCorrection.SetName(
"existingPhiCorrection");
315 existingThetaCorrection.Write();
316 existingPhiCorrection.Write();
329 auto hELabUncorr = create2Dvector<TH1F*>(nEnergies, nThetaID);
330 for (
int thID = firstUsefulThID; thID <= lastUsefulThID; thID++) {
331 TString sthID = std::to_string(thID);
332 for (
int ie = 0; ie < nEnergies; ie++) {
333 name =
"hELabUncorr_" + std::to_string(ie) +
"_" + sthID;
334 title =
"eFrac " + to_string(iEnergiesMeV[ie][thID]) +
" MeV thetaID " + sthID +
";E/Etrue";
337 hELabUncorr[ie][thID] =
new TH1F(name, title, 2 * nEfracBins[ie][thID], eFracLo, eFracHi);
343 for (
int i = 0; i < treeEntries; i++) {
347 bool goodReco =
t_thetaID >= firstUsefulThID and t_thetaID <= lastUsefulThID and t_energyBin >= 0;
348 if (not goodReco) {
continue;}
357 auto peakUncorr = create2Dvector<float>(nEnergies, nThetaID);
358 auto etaUncorr = create2Dvector<float>(nEnergies, nThetaID);
360 std::vector<TString> failedELabUncorr;
361 std::vector<int> statusELabUncorr;
362 int payloadStatus = 0;
365 TH1F* statusOfhELabUncorr =
new TH1F(
"statusOfhELabUncorr",
366 "status of hELabUncorr fits for each thetaID/energy. 0 = good, 1 = redo fit, 2 = lowStat, 3 = lowProb, 4 = peakAtLimit, 5 = sigmaAtLimit",
372 for (
int thID = firstUsefulThID; thID <= lastUsefulThID; thID++) {
373 TString sthID = std::to_string(thID);
374 for (
int ie = 0; ie < nEnergies; ie++) {
375 TH1F* hEnergy = (TH1F*)hELabUncorr[ie][thID];
379 double entries = hEnergy->Integral();
381 double genE = iEnergiesMeV[ie][thID] / 1000.;
382 bool fitHist = entries > minEntries;
388 double norm = hEnergy->GetMaximum();
389 double target = fracEnt[nIter] * entries;
390 std::vector<double> startingParameters;
391 startingParameters = eclLeakageFitParameters(hEnergy, target);
392 func->SetParameters(norm, startingParameters[0], startingParameters[1], startingParameters[2]);
393 func->SetParLimits(1, startingParameters[3], startingParameters[4]);
394 func->SetParLimits(2, 0., startingParameters[4] - startingParameters[3]);
395 func->SetParLimits(3, etaMin, etaMax);
398 name = hEnergy->GetName();
399 B2DEBUG(40,
"Fitting " << name.Data());
400 hEnergy->Fit(func,
"LIEQ",
"", startingParameters[3], startingParameters[4]);
401 peak = func->GetParameter(1);
402 double effSigma = func->GetParameter(2);
403 eta = func->GetParameter(3);
404 double prob = func->GetProb();
408 double dEta = min((etaMax - eta), (eta - etaMin));
409 fitStatus = eclLeakageFitQuality(startingParameters[3], startingParameters[4], peak, effSigma, dEta, prob);
412 if ((fitStatus == 1 or fitStatus == 3) and nIter == 0) {
422 statusOfhELabUncorr->Fill(fitStatus + 0.000001);
423 if (fitStatus == 2 or fitStatus >= 4) {
424 statusELabUncorr.push_back(fitStatus);
425 failedELabUncorr.push_back(hEnergy->GetName());
432 peakUncorr[ie][thID] = peak;
433 etaUncorr[ie][thID] = eta;
436 if (entries > minEntries) {
438 hELabUncorr[ie][thID]->Write();
445 statusOfhELabUncorr->Write();
449 int nbadFit = statusELabUncorr.size();
450 if (nbadFit > 0) {B2ERROR(
"hELabUncorr fit failures (one histogram per energy/thetaID):");}
451 for (
int ibad = 0; ibad < nbadFit; ibad++) {
452 int badStat = statusELabUncorr[ibad];
453 B2ERROR(
" histogram " << failedELabUncorr[ibad].Data() <<
" status " << badStat <<
" " << statusString[badStat].Data());
455 if (payloadStatus != 0) {
456 B2ERROR(
"ecLeakageAlgorithm: fit to hELabUncorr failed. ");
463 for (
int thID = firstUsefulThID; thID <= lastUsefulThID; thID++) {
464 for (
int ie = 0; ie < nEnergies; ie++) {
465 if (peakUncorr[ie][thID] < 0.) {
467 for (
int nextID = thID - 1; thID >= firstUsefulThID; thID--) {
468 if (peakUncorr[ie][nextID] > 0.) {
469 peakUncorr[ie][thID] = peakUncorr[ie][nextID];
474 for (
int nextID = thID + 1; thID <= lastUsefulThID; thID++) {
475 if (peakUncorr[ie][nextID] > 0.) {
476 peakUncorr[ie][thID] = peakUncorr[ie][nextID];
484 if (peakUncorr[ie][thID] < 0.) {
485 B2ERROR(
"ecLeakageAlgorithm: unable to correct hELabUncorr for thetaID " << thID <<
" ie " << ie);
502 const TString dirName[nDir] = {
"theta",
"phiMech",
"phiNoMech"};
504 auto eFracPosition = create4Dvector<TH1F*>(nEnergies, nThetaID, nDir, nPositions);
507 std::vector<TString> failedeFracPosition;
508 std::vector<int> statuseFracPosition;
510 for (
int thID = firstUsefulThID; thID <= lastUsefulThID; thID++) {
511 TString sthID = std::to_string(thID);
512 for (
int ie = 0; ie < nEnergies; ie++) {
513 TString sie = std::to_string(ie);
514 for (
int idir = 0; idir < nDir; idir++) {
515 TString sidir = std::to_string(idir);
516 for (
int ipos = 0; ipos < nPositions; ipos++) {
517 TString sipos = std::to_string(ipos);
518 name =
"eFracPosition_" + sie +
"_" + sthID +
"_" + sidir +
"_" + sipos;
519 title =
"eFrac " + to_string(iEnergiesMeV[ie][thID]) +
" MeV thetaID " + sthID +
" " + dirName[idir] +
" pos " + sipos +
521 eFracPosition[ie][thID][idir][ipos] =
new TH1F(name, title, nEfracBins[ie][thID], eFracLo, eFracHi);
528 TH1F* statusOfeFracPosition =
new TH1F(
"statusOfeFracPosition",
529 "eFrac fit status: -2 noData, -1 lowE, 0 good, 1 redo fit, 2 lowStat, 3 lowProb, 4 peakAtLimit, 5 sigmaAtLimit", 8, -2,
531 TH1F* probOfeFracPosition =
new TH1F(
"probOfeFracPosition",
"fit probability of eFrac fits for each position;probability", 100, 0,
533 TH1F* maxOfeFracPosition =
new TH1F(
"maxOfeFracPosition",
"max entries of eFrac histograms;maximum bin content", 100, 0, 1000);
537 for (
int i = 0; i < treeEntries; i++) {
541 bool goodReco =
t_thetaID >= firstUsefulThID and t_thetaID <= lastUsefulThID and t_energyBin >= 0;
542 if (not goodReco) {
continue;}
555 auto positionCorrection = create4Dvector<float>(nEnergies, nThetaID, nDir, nPositions);
556 auto positionCorrectionUnc = create4Dvector<float>(nEnergies, nThetaID, nDir, nPositions);
561 TH1F* thetaCorSummary =
new TH1F(
"thetaCorSummary",
"Theta dependent corrections;theta dependent correction", 100, 0.4, 1.4);
562 TH1F* phiCorSummary =
new TH1F(
"phiCorSummary",
"Phi dependent corrections;phi dependent correction", 100, 0.4, 1.4);
564 for (
int thID = firstUsefulThID; thID <= lastUsefulThID; thID++) {
565 for (
int ie = 0; ie < nEnergies; ie++) {
566 double genE = iEnergiesMeV[ie][thID] / 1000.;
567 for (
int idir = 0; idir < nDir; idir++) {
568 for (
int ipos = 0; ipos < nPositions; ipos++) {
569 TH1F* hEnergy = (TH1F*)eFracPosition[ie][thID][idir][ipos];
570 if (hEnergy->Integral() > minEntries) {nHistToFit++;}
574 double correction =
sqrt(peakUncorr[ie][thID]);
575 double corrUnc = 0.05;
579 if (hEnergy->GetEntries() < 0.5) {fitStatus = -2;}
581 double entries = hEnergy->Integral();
589 double target = fracEnt[nIter] * entries;
590 std::vector<double> startingParameters;
591 bool findParm =
true;
593 startingParameters = eclLeakageFitParameters(hEnergy, target);
596 if (hEnergy->GetMaximum()<minMaxBin and startingParameters[5]>11.9) {
602 double norm = hEnergy->GetMaximum();
603 double fitLow = startingParameters[3];
604 double fitHigh = startingParameters[4];
607 double etaFix = etaUncorr[ie][thID];
608 func->SetParameters(norm, startingParameters[0], startingParameters[1], etaFix);
609 func->SetParLimits(1, fitLow, fitHigh);
610 func->SetParLimits(2, 0., fitHigh - fitLow);
613 if (hEnergy->GetMaximum() < highMaxBin) {
614 func->SetParLimits(3, etaFix, etaFix);
616 func->SetParLimits(3, etaMin, etaMax);
620 name = hEnergy->GetName();
621 B2DEBUG(40,
"Fitting " << name.Data());
622 hEnergy->Fit(func,
"LIEQ",
"", fitLow, fitHigh);
623 double peak = func->GetParameter(1);
624 double effSigma = func->GetParameter(2);
625 double eta = func->GetParameter(3);
626 prob = func->GetProb();
630 double dEta = min((etaMax - eta), (eta - etaMin));
631 fitStatus = eclLeakageFitQuality(fitLow, fitHigh, peak, effSigma, dEta, prob);
634 if ((fitStatus == 1 or fitStatus == 3) and nIter == 0) {
639 }
else if (fitStatus <= 3) {
643 correction = peak /
sqrt(peakUncorr[ie][thID]);
644 corrUnc = func->GetParError(1) /
sqrt(peakUncorr[ie][thID]);
649 positionCorrection[ie][thID][idir][ipos] = correction;
650 positionCorrectionUnc[ie][thID][idir][ipos] = corrUnc;
651 statusOfeFracPosition->Fill(fitStatus + 0.00001);
652 probOfeFracPosition->Fill(prob);
653 maxOfeFracPosition->Fill(hEnergy->GetMaximum());
656 if (prob > 0 and fitStatus <= 3) {
658 thetaCorSummary->Fill(correction);
660 phiCorSummary->Fill(correction);
665 if (fitStatus >= 2) {
666 statuseFracPosition.push_back(fitStatus);
667 failedeFracPosition.push_back(hEnergy->GetName());
678 B2INFO(
"eclLeakageAlgorithm: " << nHistToFit <<
" eFracPosition histograms to fit");
679 nbadFit = statuseFracPosition.size();
680 B2INFO(
"eFracPosition failed fits: " << nbadFit);
681 for (
int ibad = 0; ibad < nbadFit; ibad++) {
682 int badStat = statuseFracPosition[ibad];
683 B2ERROR(
" histogram " << failedeFracPosition[ibad].Data() <<
" status " << badStat <<
" " << statusString[badStat].Data());
688 statusOfeFracPosition->Write();
689 probOfeFracPosition->Write();
690 maxOfeFracPosition->Write();
691 thetaCorSummary->Write();
692 phiCorSummary->Write();
704 for (
int thID = firstUsefulThID - 1; thID >= 0; thID--) {
705 for (
int ie = 0; ie < nEnergies; ie++) {
707 for (
int idir = 0; idir < 3; idir++) {
708 for (
int ipos = 0; ipos < nPositions; ipos++) {
709 positionCorrection[ie][thID][idir][ipos] = positionCorrection[ie][thID + 1][idir][ipos];
710 positionCorrectionUnc[ie][thID][idir][ipos] = positionCorrectionUnc[ie][thID + 1][idir][ipos];
717 for (
int thID = lastUsefulThID + 1; thID < nThetaID; thID++) {
718 for (
int ie = 0; ie < nEnergies; ie++) {
720 for (
int idir = 0; idir < 3; idir++) {
721 for (
int ipos = 0; ipos < nPositions; ipos++) {
722 positionCorrection[ie][thID][idir][ipos] = positionCorrection[ie][thID - 1][idir][ipos];
723 positionCorrectionUnc[ie][thID][idir][ipos] = positionCorrectionUnc[ie][thID - 1][idir][ipos];
731 std::vector<float> forwardVector;
732 std::vector<float> barrelVector;
733 std::vector<float> backwardVector;
734 for (
int ie = 0; ie < nEnergies; ie++) {
735 forwardVector.push_back(log(generatedE[0][ie]));
736 barrelVector.push_back(log(generatedE[1][ie]));
737 backwardVector.push_back(log(generatedE[2][ie]));
741 float leakLogE[3][12] = {};
742 for (
int ie = 0; ie < nEnergies; ie++) {
743 leakLogE[0][ie] = forwardVector[ie];
744 leakLogE[1][ie] = barrelVector[ie];
745 leakLogE[2][ie] = backwardVector[ie];
752 TH2F thetaCorrection(
"thetaCorrection",
"Theta correction vs bin;bin = thetaID + 69*energyBin;local theta bin", nbinX, 0, nbinX,
753 nPositions, 0, nPositions);
755 for (
int ie = 0; ie < nEnergies; ie++) {
756 for (
int thID = 0; thID < nThetaID; thID++) {
758 for (
int ipos = 0; ipos < nPositions; ipos++) {
760 float correction = positionCorrection[ie][thID][0][ipos];
761 float corrUnc = positionCorrectionUnc[ie][thID][0][ipos];
762 thetaCorrection.SetBinContent(ix, iy, correction);
763 thetaCorrection.SetBinError(ix, iy, corrUnc);
770 TH2F phiCorrection(
"phiCorrection",
"Phi correction vs bin;bin = thetaID + 69*energyBin;local phi bin", 2 * nbinX, 0, 2 * nbinX,
771 nPositions, 0, nPositions);
773 for (
int ie = 0; ie < nEnergies; ie++) {
774 for (
int thID = 0; thID < nThetaID; thID++) {
776 for (
int ipos = 0; ipos < nPositions; ipos++) {
780 float correction = positionCorrection[ie][thID][1][ipos];
781 float corrUnc = positionCorrectionUnc[ie][thID][1][ipos];
782 phiCorrection.SetBinContent(ix, iy, correction);
783 phiCorrection.SetBinError(ix, iy, corrUnc);
786 correction = positionCorrection[ie][thID][2][ipos];
787 corrUnc = positionCorrectionUnc[ie][thID][2][ipos];
788 phiCorrection.SetBinContent(ix + nbinX, iy, correction);
789 phiCorrection.SetBinError(ix + nbinX, iy, corrUnc);
797 TH2F nCrystalCorrection(
"nCrystalCorrection",
"nCrys correction vs bin;bin = thetaID + 69*energyBin;nCrys", nbinX, 0, nbinX,
798 maxN + 1, 0, maxN + 1);
801 for (
int ie = 0; ie < nEnergies; ie++) {
802 for (
int thID = 0; thID < nThetaID; thID++) {
804 for (
int in = 0; in <= maxN; in++) {
806 float correction = 1.;
808 nCrystalCorrection.SetBinContent(ix, iy, correction);
809 nCrystalCorrection.SetBinError(ix, iy, corrUnc);
821 thetaCorrection.Write();
822 phiCorrection.Write();
823 nCrystalCorrection.Write();
830 const int nResType = 5;
831 const TString resName[nResType] = {
"Uncorrected",
"Original",
"Corrected no nCrys",
"Corrected measured",
"Corrected true"};
832 const TString regName[nLeakReg] = {
"forward",
"barrel",
"backward"};
833 auto energyResolution = create3Dvector<TH1F*>(nLeakReg, nEnergies, nResType);
836 int thIDReg[nLeakReg];
841 for (
int ireg = 0; ireg < nLeakReg; ireg++) {
842 for (
int ie = 0; ie < nEnergies; ie++) {
845 TString stireg = std::to_string(ireg);
846 TString stie = std::to_string(ie);
847 TString stieName = std::to_string(iEnergiesMeV[ie][thIDReg[ireg]]);
848 int nbinReg = 20 * nEfracBins[ie][thIDReg[ireg]];
850 for (
int ires = 0; ires < nResType; ires++) {
851 name =
"energyResolution_" + stireg +
"_" + stie +
"_" + std::to_string(ires);
852 title = resName[ires] +
" energy, " + stieName +
" MeV, " + regName[ireg] +
";Reconstructed E/Etrue";
853 energyResolution[ireg][ie][ires] =
new TH1F(name, title, nbinReg, eFracLo, eFracHi);
860 for (
int i = 0; i < treeEntries; i++) {
864 bool goodReco =
t_thetaID >= firstUsefulThID and t_thetaID <= lastUsefulThID and t_energyBin >= 0;
865 if (not goodReco) {
continue;}
876 float corrTrue = thetaPosCor * phiPosCor;
881 float corrMeasured = 0.96;
882 for (
int iter = 0; iter < 2; iter++) {
887 float logEnergy = log(energyRaw / corrMeasured);
889 if (logEnergy < leakLogE[
t_region][0]) {
891 }
else if (logEnergy > leakLogE[
t_region][nEnergies - 1]) {
894 while (logEnergy > leakLogE[
t_region][ie0 + 1]) {ie0++;}
903 corrMeasured = cor0 + (cor1 - cor0) * (logEnergy - leakLogE[
t_region][ie0]) / (leakLogE[
t_region][ie0 + 1] -
908 float corrNonCrys = corrMeasured;
923 auto peakEnergy = create3Dvector<float>(nLeakReg, nEnergies, nResType);
924 auto energyRes = create3Dvector<float>(nLeakReg, nEnergies, nResType);
927 for (
int ireg = 0; ireg < nLeakReg; ireg++) {
928 for (
int ie = 0; ie < nEnergies; ie++) {
931 double entries = energyResolution[ireg][ie][nResType - 1]->Integral();
932 for (
int ires = 0; ires < nResType; ires++) {
933 TH1F* hEnergy = (TH1F*)energyResolution[ireg][ie][ires];
937 bool fitHist = entries > minEntries;
943 double norm = hEnergy->GetMaximum();
944 double target = fracEnt[nIter] * entries;
945 std::vector<double> startingParameters;
946 startingParameters = eclLeakageFitParameters(hEnergy, target);
947 func->SetParameters(norm, startingParameters[0], startingParameters[1], startingParameters[2]);
948 func->SetParLimits(1, startingParameters[3], startingParameters[4]);
949 func->SetParLimits(2, 0., startingParameters[4] - startingParameters[3]);
950 func->SetParLimits(3, etaMin, etaMax);
956 int minLo = hEnergy->GetXaxis()->FindBin(startingParameters[3] + 0.0001);
957 int minHi = hEnergy->GetXaxis()->FindBin(startingParameters[4] - 0.0001);
960 double dx = hEnergy->GetBinLowEdge(minLo + 1) - hEnergy->GetBinLowEdge(minLo);
961 double overage = hEnergy->Integral(minLo, minHi) - target;
962 double subLo = overage / hEnergy->GetBinContent(minLo);
963 double subHi = overage / hEnergy->GetBinContent(minHi);
966 res68 = 0.5 * dx * (1 + minHi - minLo - max(subLo, subHi));
970 name = hEnergy->GetName();
971 B2DEBUG(40,
"Fitting " << name.Data());
972 hEnergy->Fit(func,
"LIEQ",
"", startingParameters[3], startingParameters[4]);
973 peak = func->GetParameter(1);
974 double effSigma = func->GetParameter(2);
975 double eta = func->GetParameter(3);
976 double prob = func->GetProb();
980 double dEta = min((etaMax - eta), (eta - etaMin));
981 int fitStatus = eclLeakageFitQuality(startingParameters[3], startingParameters[4], peak, effSigma, dEta, prob);
984 if ((fitStatus == 1 or fitStatus == 3) and nIter == 0) {
993 peakEnergy[ireg][ie][ires] = peak;
994 energyRes[ireg][ie][ires] = res68;
1005 int nresBins = nEnergies * nLeakReg * (nResType + 1);
1006 TH1F* peakSummary =
new TH1F(
"peakSummary",
"Peak E/Etrue for each method, region, energy;Energy energy point", nresBins, 0,
1008 TH1F* resolutionSummary =
new TH1F(
"resolutionSummary",
"Resolution/peak for each method, region, energy;Energy energy point",
1009 nresBins, 0, nEnergies);
1011 B2INFO(
"Resolution divided by peak for each energy bin and region " << nResType <<
" ways");
1012 for (
int ires = 0; ires < nResType; ires++) {B2INFO(
" " << resName[ires]);}
1014 for (
int ie = 0; ie < nEnergies; ie++) {
1015 B2INFO(
" energy point " << ie);
1016 for (
int ireg = 0; ireg < nLeakReg; ireg++) {
1017 B2INFO(
" region " << ireg);
1018 for (
int ires = 0; ires < nResType; ires++) {
1022 peakSummary->SetBinContent(ix, peakEnergy[ireg][ie][ires]);
1023 peakSummary->SetBinError(ix, 0.);
1024 resolutionSummary->SetBinContent(ix, energyRes[ireg][ie][ires] / peakEnergy[ireg][ie][ires]);
1025 resolutionSummary->SetBinError(ix, 0.);
1028 B2INFO(
" " << ires <<
" " << energyRes[ireg][ie][ires] / peakEnergy[ireg][ie][ires]);
1036 peakSummary->Write();
1037 resolutionSummary->Write();
1059 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)
EResult
The result of calibration.
@ c_OK
Finished successfuly =0 in Python.
@ c_Failure
Failed =3 in Python.
const std::vector< Calibration::ExpRun > & getRunList() const
Get the list of runs for which calibration is called.
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.
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.