2 #include <ecl/calibration/eclee5x5Algorithm.h>
3 #include <ecl/dbobjects/ECLCrystalCalib.h>
10 #include "TMatrixDSym.h"
11 #include "TDecompLU.h"
21 "Perform energy calibration of ecl crystals by analyzing energy in 25-crystal sums from Bhabha events"
30 dummy = (TH1F*)gROOT->FindObject(
"AverageExpECrys");
31 if (dummy) {
delete dummy;}
32 dummy = (TH1F*)gROOT->FindObject(
"AverageElecCalib");
33 if (dummy) {
delete dummy;}
34 dummy = (TH1F*)gROOT->FindObject(
"AverageInitCalib");
35 if (dummy) {
delete dummy;}
36 dummy = (TH1F*)gROOT->FindObject(
"meanEnvsCrysID");
37 if (dummy) {
delete dummy;}
44 B2INFO(
"eclee5x5Algorithm parameters:");
60 auto EnVsCrysID = getObjectPtr<TH2F>(
"EnVsCrysID");
61 auto RvsCrysID = getObjectPtr<TH1F>(
"RvsCrysID");
62 auto NRvsCrysID = getObjectPtr<TH1F>(
"NRvsCrysID");
63 auto Qmatrix = getObjectPtr<TH2F>(
"Qmatrix");
64 auto ElecCalibvsCrys = getObjectPtr<TH1F>(
"ElecCalibvsCrys");
65 auto ExpEvsCrys = getObjectPtr<TH1F>(
"ExpEvsCrys");
66 auto InitialCalibvsCrys = getObjectPtr<TH1F>(
"InitialCalibvsCrys");
67 auto CalibEntriesvsCrys = getObjectPtr<TH1F>(
"CalibEntriesvsCrys");
68 auto EntriesvsCrys = getObjectPtr<TH1F>(
"EntriesvsCrys");
69 auto dPhivsThetaID = getObjectPtr<TH2F>(
"dPhivsThetaID");
74 TH1F* AverageExpECrys =
new TH1F(
"AverageExpECrys",
"Average expected E per crys from collector;Crystal ID;Energy (GeV)", 8736, 0,
76 TH1F* AverageElecCalib =
new TH1F(
"AverageElecCalib",
"Average electronics calib const vs crystal;Crystal ID;Calibration constant",
78 TH1F* AverageInitCalib =
new TH1F(
"AverageInitCalib",
"Average initial calib const vs crystal;Crystal ID;Calibration constant",
80 TH1F* meanEnvsCrysID =
new TH1F(
"meanEnvsCrysID",
"Mean normalized energy vs crystal;CrystalID;E/Eexp", 8736, 0, 8736);
82 for (
int cellID = 1; cellID <= 8736; cellID++) {
83 double TotEntries = CalibEntriesvsCrys->GetBinContent(cellID);
84 if (TotEntries > 0.) {
85 AverageElecCalib->SetBinContent(cellID, ElecCalibvsCrys->GetBinContent(cellID) / TotEntries);
86 AverageExpECrys->SetBinContent(cellID, ExpEvsCrys->GetBinContent(cellID) / TotEntries);
87 AverageInitCalib->SetBinContent(cellID, InitialCalibvsCrys->GetBinContent(cellID) / TotEntries);
90 TH1D* En = EnVsCrysID->ProjectionY(
"En", cellID, cellID);
91 meanEnvsCrysID->SetBinContent(cellID, En->GetMean());
92 meanEnvsCrysID->SetBinError(cellID, En->GetStdDev());
98 TFile* histfile =
new TFile(fName,
"recreate");
103 AverageElecCalib->Write();
104 AverageExpECrys->Write();
105 AverageInitCalib->Write();
106 EntriesvsCrys->Write();
107 dPhivsThetaID->Write();
108 meanEnvsCrysID->Write();
113 B2INFO(
"eclee5x5Algorithm has not been asked to find constants; copying input histograms and quitting");
120 for (
int cellID = 1; cellID <= 8736; cellID++) {
123 if (AverageInitCalib->GetBinContent(cellID) > 0.) {
124 if (EntriesvsCrys->GetBinContent(cellID) <
m_minEntries) {
126 B2INFO(
"eclee5x5Algorithm: insufficient data for cellID = " << cellID <<
" " << EntriesvsCrys->GetBinContent(cellID) <<
" entries");
140 bool foundConst =
false;
141 TH1F* gVsCrysID =
new TH1F(
"gVsCrysID",
"Ratio of new to old calibration vs crystal ID;crystal ID;vector g", 8736, 0, 8736);
142 TH1F* CalibVsCrysID =
new TH1F(
"CalibVsCrysID",
"Calibration constant vs crystal ID;crystal ID;counts per GeV", 8736, 0, 8736);
143 TH1F* ExpEnergyperCrys =
new TH1F(
"ExpEnergyperCrys",
"Expected energy per crystal;Crystal ID;Energy in 25 crystal sum (GeV)", 8736,
145 TString title =
"dPhi cut per crystal " +
m_payloadName +
";Crystal ID;dPhi requirement (deg)";
146 TH1F* dPhiperCrys =
new TH1F(
"dPhiperCrys", title, 8736, 0, 8736);
151 for (
int cellID = 1; cellID <= 8736; cellID++) {
152 float mean = meanEnvsCrysID->GetBinContent(cellID);
153 float stdDev = meanEnvsCrysID->GetBinError(cellID);
154 float inputE = AverageExpECrys->GetBinContent(cellID);
155 if (mean > 0. and stdDev > 0.) {
156 ExpEnergyperCrys->SetBinContent(cellID, mean * abs(inputE));
157 ExpEnergyperCrys->SetBinError(cellID, stdDev * abs(inputE));
159 ExpEnergyperCrys->SetBinContent(cellID, inputE);
160 ExpEnergyperCrys->SetBinError(cellID, 0.05 * inputE);
167 std::vector<float> tempCalib;
168 std::vector<float> tempCalibStdDev;
170 for (
int cellID = 1; cellID <= 8736; cellID++) {
171 tempCalib.push_back(ExpEnergyperCrys->GetBinContent(cellID));
172 tempCalibStdDev.push_back(ExpEnergyperCrys->GetBinError(cellID));
177 B2INFO(
"eclCosmicEAlgorithm: successfully stored expected energies ECLExpee5x5E");
185 TMatrixDSym matrixQ(8736);
186 TVectorD vectorR(8736);
187 for (
int ix = 1; ix <= 8736; ix++) {
188 vectorR[ix - 1] = RvsCrysID->GetBinContent(ix);
189 for (
int iy = 1; iy <= 8736; iy++) {
190 matrixQ[ix - 1][iy - 1] = Qmatrix->GetBinContent(ix, iy);
195 int nNotCalibrated = 0;
196 for (
int cellID = 1; cellID <= 8736; cellID++) {
197 if (NRvsCrysID->GetBinContent(cellID) < 0.5) {
198 for (
int othercell = 1; othercell <= 8736; othercell++) {
199 matrixQ[cellID - 1][othercell - 1] = 0.;
200 matrixQ[othercell - 1][cellID - 1] = 0.;
202 matrixQ[cellID - 1][cellID - 1] = 1.;
203 vectorR[cellID - 1] = -1.;
207 B2INFO(
"eclCosmicEAlgorithm: " << nNotCalibrated <<
" crystals will not be calibrated. ");
210 TDecompLU lu(matrixQ);
212 TVectorD vectorg = lu.Solve(vectorR, solved);
217 for (
int cellID = 1; cellID <= 8736; cellID++) {
218 gVsCrysID->SetBinContent(cellID, vectorg[cellID - 1]);
219 gVsCrysID->SetBinError(cellID, 0.);
220 float newCalib = vectorg[cellID - 1] * abs(AverageInitCalib->GetBinContent(cellID));
221 CalibVsCrysID->SetBinContent(cellID, newCalib);
222 CalibVsCrysID->SetBinError(cellID, 0.);
224 if (vectorg[cellID - 1] < 0. and NRvsCrysID->GetBinContent(cellID) > 0.) {foundConst =
false;}
230 std::vector<float> tempCalib;
231 std::vector<float> tempCalibStdDev;
233 for (
int cellID = 1; cellID <= 8736; cellID++) {
234 tempCalib.push_back(CalibVsCrysID->GetBinContent(cellID));
235 tempCalibStdDev.push_back(CalibVsCrysID->GetBinError(cellID));
240 B2INFO(
"eclCosmicEAlgorithm: successfully stored calibration ECLCrystalEnergyee5x5");
248 float dPhiCenter[69] = {};
249 float dPhiHalfWidth[69] = {};
252 const int nbins = dPhivsThetaID->GetNbinsX();
253 for (
int ib = 1; ib <= nbins; ib++) {
254 TH1D* proj = dPhivsThetaID->ProjectionY(
"proj", ib, ib);
255 if (proj->Integral() < 100) {
continue;}
256 int thetaID = (int)dPhivsThetaID->GetXaxis()->GetBinCenter(ib);
257 if (firstID == 0) { firstID = thetaID; }
271 double peak = proj->GetMaximum();
272 int nPhiBins = proj->GetNbinsX();
276 }
while (proj->GetBinContent(binLo) <
m_fracLo * peak and binLo < nPhiBins);
277 double xfitLo = proj->GetBinLowEdge(binLo);
281 int binHi = proj->GetXaxis()->FindBin(175.01);
284 }
while (proj->GetBinContent(binHi)<fracHi* peak and binHi>1);
285 double xfitHi = proj->GetBinLowEdge(binHi + 1);
288 int peakBin = proj->GetMaximumBin();
289 if (binLo >= peakBin or binHi <= peakBin) {
290 B2ERROR(
"Flawed dPhi fit range for thetaID = " << thetaID <<
" peakBin = " << peakBin <<
" binLo = " << binLo <<
"binHi = " <<
295 proj->Fit(
"gaus",
"",
"", xfitLo, xfitHi);
298 TF1* fitGaus = proj->GetFunction(
"gaus");
299 float mean = fitGaus->GetParameter(1);
300 float sigma = fitGaus->GetParameter(2);
301 float dPhiLo = mean -
m_nsigLo * sigma;
302 float dPhiHi = mean + nsigHi * sigma;
303 dPhiCenter[thetaID] = 0.5 * (dPhiLo + dPhiHi);
304 dPhiHalfWidth[thetaID] = 0.5 * (dPhiHi - dPhiLo);
308 for (
int thetaID = 0; thetaID < firstID; thetaID++) {
309 dPhiCenter[thetaID] = dPhiCenter[firstID];
310 dPhiHalfWidth[thetaID] = dPhiHalfWidth[firstID];
312 for (
int thetaID = lastID + 1; thetaID < 69; thetaID++) {
313 dPhiCenter[thetaID] = dPhiCenter[lastID];
314 dPhiHalfWidth[thetaID] = dPhiHalfWidth[lastID];
320 std::vector<float> tempCalib;
321 std::vector<float> tempCalibWidth;
322 tempCalib.resize(8736);
323 tempCalibWidth.resize(8736);
325 for (
int thetaID = 0; thetaID < 69; thetaID++) {
327 tempCalib.at(crysID) = dPhiCenter[thetaID];
328 tempCalibWidth.at(crysID) = dPhiHalfWidth[thetaID];
329 dPhiperCrys->SetBinContent(crysID + 1, dPhiCenter[thetaID]);
330 dPhiperCrys->SetBinError(crysID + 1, dPhiHalfWidth[thetaID]);
341 B2INFO(
"eclCosmicEAlgorithm: successfully stored calibration " <<
m_payloadName);
347 B2ERROR(
"eclee5x5Algorithm: invalid payload name: m_payloadName = " <<
m_payloadName);
354 ExpEnergyperCrys->Write();
357 CalibVsCrysID->Write();
359 dPhiperCrys->Write();
363 dummy = (TH1F*)gROOT->FindObject(
"gVsCrysID");
delete dummy;
364 dummy = (TH1F*)gROOT->FindObject(
"CalibVsCrysID");
delete dummy;
365 dummy = (TH1F*)gROOT->FindObject(
"ExpEnergyperCrys");
delete dummy;
366 dummy = (TH1F*)gROOT->FindObject(
"dPhiperCrys");
delete dummy;
372 B2INFO(
"eclee5x5Algorithm successfully found constants but was not asked to store them");
374 B2INFO(
"eclee5x5Algorithm was not asked to store constants, and did not succeed in finding them");
377 }
else if (!foundConst) {
379 B2INFO(
"eclee5x5Algorithm: failed to store expected values");
381 B2INFO(
"eclee5x5Algorithm: failed to store calibration constants");
383 B2INFO(
"eclee5x5Algorithm: failed to find dPhi* selection criteria");