10 #include <ecl/calibration/eclWaveformTemplateCalibrationC2Algorithm.h>
13 #include <ecl/dataobjects/ECLElementNumbers.h>
14 #include <ecl/digitization/OfflineFitFunction.h>
15 #include <ecl/dbobjects/ECLDigitWaveformParameters.h>
16 #include <ecl/dbobjects/ECLCrystalCalib.h>
29 using namespace Calibration;
32 eclWaveformTemplateCalibrationC2Algorithm::eclWaveformTemplateCalibrationC2Algorithm():
36 "Perform the photon template shape calibration using waveforms from high energy crystals from e+e- --> gamma gamma events"
45 std::vector<TF1*> FitFunctions;
46 const double numberofADCPoints = 31.0;
48 double fitf(
double* x,
double* par)
51 double xtoeval = std::fmod(x[0], numberofADCPoints);
52 int whichFitFunctions = x[0] / numberofADCPoints;
54 for (
int i = 0; i < (int)FitFunctions.size(); i++) {
55 FitFunctions[i]->SetParameter(0, par[i]);
56 FitFunctions[i]->SetParameter(1, par[FitFunctions.size() + i]);
57 FitFunctions[i]->SetParameter(2, par[(2 * FitFunctions.size()) + i]);
58 FitFunctions[i]->FixParameter(3, 0);
59 for (
int k = 0; k < 10; k++) {
60 FitFunctions[i]->SetParameter(4 + k, par[(3 * FitFunctions.size()) + k]);
64 return FitFunctions[whichFitFunctions]->Eval(xtoeval * 0.5);
72 B2INFO(
"Reading ECLCrystalCalib payload: eclWaveformTemplateCalibrationC1MaxResLimit");
73 DBObjPtr<ECLCrystalCalib> existingeclWaveformTemplateCalibrationC1MaxResLimit(
"eclWaveformTemplateCalibrationC1MaxResLimit");
75 ExpRun chosenRun = runs.front();
82 std::vector<double> cellIDArray;
83 std::vector<double> maxResidualArray;
84 std::vector<double> limitResidualArray;
85 std::vector<double> parLimitFactorArray;
88 TFile* histfile =
new TFile(
m_outputName.c_str(),
"recreate");
91 TFile* f_PhotonTemplateOutput =
new TFile(Form(
"PhotonShapes_Low%d_High%d.root",
m_firstCellID,
m_lastCellID),
"RECREATE");
92 TTree* mtree =
new TTree(
"mtree",
"");
93 std::vector<double> PhotonWaveformArray(100000);
94 mtree->Branch(
"PhotonArray", PhotonWaveformArray.data(),
"PhotonWaveformArray[100000]/D");
97 auto tree = getObjectPtr<TTree>(
"tree");
99 tree->SetBranchAddress(
"CellID", &CellID);
103 tree->SetBranchAddress(Form(
"ADC%d", i), &Waveform[i]);
107 std::time_t t = std::time(0);
110 int AttemptCounter = 0;
117 double ParMin11t[11];
123 if (CellID_i > 7776 || CellID_i < 1153) {
124 ParMin11t[0] = 20.3216;
125 ParMin11t[1] = -0.0206266;
126 ParMin11t[2] = 0.313928;
127 ParMin11t[3] = 0.589646;
128 ParMin11t[4] = 0.455526;
129 ParMin11t[5] = 1.03656;
130 ParMin11t[6] = 0.000822467;
131 ParMin11t[7] = 45.1574;
132 ParMin11t[8] = 0.716034;
133 ParMin11t[9] = 0.616753;
134 ParMin11t[10] = 0.0851222;
136 ParMin11t[0] = 24.6176;
137 ParMin11t[1] = 0.00725002;
138 ParMin11t[2] = 0.601578;
139 ParMin11t[3] = 0.491976;
140 ParMin11t[4] = 0.601034;
141 ParMin11t[5] = 0.601684;
142 ParMin11t[6] = -0.0103788;
143 ParMin11t[7] = 2.22615;
144 ParMin11t[8] = 0.671294;
145 ParMin11t[9] = 0.529878;
146 ParMin11t[10] = 0.0757927;
149 double resLimit = 2 * existingeclWaveformTemplateCalibrationC1MaxResLimit->getCalibVector()[CellID_i -
151 double resLimitOriginal = resLimit;
154 std::vector<int> EntriesToSkip;
157 double maxResidual = 1000.0;
161 while (PASS ==
false) {
164 std::vector<double> xValuesToFit;
165 std::vector<double> yValuesToFit;
168 std::vector<double> guessBaseline;
169 std::vector<double> guessAmp;
170 std::vector<double> guessTime;
173 std::vector<int> NtupleEntries;
176 int counterWaveforms = 0;
178 for (
int i = 0; i < tree->GetEntries(); i++) {
181 bool skipEvent =
false;
182 for (
int k = 0; k < (int)EntriesToSkip.size(); k++) {
183 if (EntriesToSkip[k] == i) skipEvent =
true;
185 if (skipEvent)
continue;
189 if (CellID != CellID_i)
continue;
194 xValuesToFit.push_back(counter);
195 yValuesToFit.push_back(Waveform[j]);
196 if (Waveform[j] > maxval) {
197 maxval = Waveform[j];
204 guessBaseline.push_back(Waveform[0]);
205 guessAmp.push_back(maxval);
206 guessTime.push_back((maxIndex - 4.5) * 0.5);
208 NtupleEntries.push_back(i);
209 B2INFO(
"Entry: " << i);
218 B2INFO(
"CellID " << CellID_i <<
" counterWaveforms = " << counterWaveforms);
221 B2INFO(
"eclWaveformTemplateCalibrationC2Algorithm: warning total entries for cell ID " << CellID_i <<
" is only: " <<
230 auto gWaveformToFit =
new TGraph(xValuesToFit.size(), xValuesToFit.data(), yValuesToFit.data());
231 gWaveformToFit->SetName(Form(
"gWaveformToFit_%d",
int(CellID_i)));
236 FitFunctions.clear();
237 for (
int i = 0; i < counterWaveforms; i++) {
238 FitFunctions.push_back(
new TF1(Form(
"Shp_%d", i), Belle2::ECL::WaveFuncTwoComponent, 0, 30.5, 26));
239 FitFunctions[i]->SetNpx(10000);
240 FitFunctions[i]->FixParameter(3, 0);
241 for (
int k = 0; k < 10; k++) {
242 FitFunctions[i]->SetParameter(4 + k, ParMin11t[k + 1]);
243 FitFunctions[i]->FixParameter(10 + 4 + k, ParMin11t[k + 1]);
245 FitFunctions[i]->FixParameter(24, ParMin11t[0]);
246 FitFunctions[i]->FixParameter(25, 1);
250 TF1* TotalFitFunction =
new TF1(
"TotalFitFunction", fitf, 0, counterWaveforms *
m_NumberofADCPoints,
251 (3 * FitFunctions.size()) + 10);
254 int FFsize = FitFunctions.size();
255 for (
int i = 0; i < FFsize; i++) {
256 TotalFitFunction->SetParameter(i, guessTime[i]);
257 TotalFitFunction->SetParameter(FFsize + i, guessBaseline[i]);
258 TotalFitFunction->SetParameter((2 * FFsize) + i, guessAmp[i]);
259 for (
int k = 0; k < 10; k++) {
260 TotalFitFunction->SetParameter((3 * FFsize) + k, ParMin11t[k + 1]);
262 TotalFitFunction->SetParLimits((3 * FFsize) + k, ParMin11t[k + 1] -
m_ParamLimitFactor * fabs(ParMin11t[k + 1]),
265 TotalFitFunction->ReleaseParameter((3 * FFsize) + k);
271 gWaveformToFit->Fit(
"TotalFitFunction",
"Q M W N 0 R",
"", 0, counterWaveforms *
m_NumberofADCPoints);
274 std::vector<int> FitResultY;
275 std::vector<int> FitResultX;
276 int maxResidualWaveformID = 0;
280 double npts = xValuesToFit.size();
281 double maxResidualOld = 0.0;
282 for (
int k = 0; k < npts; k++) {
283 double xVal = xValuesToFit[k];
284 double yVal = TotalFitFunction->Eval(xVal);
285 FitResultX.push_back(xVal);
286 FitResultY.push_back(yVal);
287 double diff = fabs(yValuesToFit[k] - yVal);
288 if (diff > maxResidual) {
291 maxResidualOld = fabs(yValuesToFit[k] / yVal);
296 if (maxResidual > resLimit) {
298 B2INFO(
"FAIL: CellID_i " << CellID_i <<
" maxResidual " << maxResidual <<
" removing entry: " <<
299 NtupleEntries[maxResidualWaveformID] <<
300 " which was waveform number " << maxResidualWaveformID <<
" resLimit was " << resLimit <<
" , resLimit started at " <<
302 B2INFO(
"Old maxResidual of Data/Fit was " << maxResidualOld);
304 B2INFO(
"Iter Time = " << std::time(0) - t << std::endl);
307 std::cout <<
"FAIL: CellID_i " << CellID_i <<
" maxResidual " << maxResidual <<
" removing entry: " <<
308 NtupleEntries[maxResidualWaveformID] <<
309 " which was waveform number " << maxResidualWaveformID <<
" resLimit was " << resLimit <<
" , resLimit started at " <<
310 resLimitOriginal << std::endl;
311 std::cout <<
"wave = [";
312 for (
int k = 0; k < npts; k++) {
313 std::cout << yValuesToFit[k];
314 if (k < (npts - 1)) {
317 std::cout <<
"]" << std::endl;
320 std::cout <<
"fitRes = [";
321 for (
int k = 0; k < npts; k++) {
322 std::cout << TotalFitFunction->Eval(xValuesToFit[k]);
323 if (k < (npts - 1)) {
326 std::cout <<
"]" << std::endl;
331 EntriesToSkip.push_back(NtupleEntries[maxResidualWaveformID]);
343 B2INFO(
"AttemptCounter reach limit: " << AttemptCounter <<
" counterWaveforms: " << counterWaveforms);
347 EntriesToSkip.clear();
353 B2INFO(
"Increasing resLimit to " << resLimit);
360 B2INFO(
"PASS: CellID_i " << CellID_i <<
" maxResidual " << maxResidual <<
" number of waveforms used was " << counterWaveforms <<
361 " resLimit was " << resLimit);
365 limitResidualArray.push_back(resLimit);
372 auto gFitResult =
new TGraph(FitResultX.size(), FitResultX.data(), FitResultY.data());
373 gFitResult->SetName(Form(
"gFitResult_%d",
int(CellID_i)));
376 cellIDArray.push_back(CellID_i);
377 maxResidualArray.push_back(maxResidual);
381 gWaveformToFit->Write();
385 float tempPhotonPar11[11];
386 tempPhotonPar11[0] = ParMin11t[0];
387 for (
unsigned int k = 0; k < 10; k++) tempPhotonPar11[k + 1] = TotalFitFunction->GetParameter((3 * FFsize) + k);
390 FitFunctions[0]->SetParameter(0, 0);
391 FitFunctions[0]->SetParameter(1, 0);
392 FitFunctions[0]->SetParameter(2, 1);
393 for (
int k = 0; k < 10; k++) {
394 FitFunctions[0]->SetParameter(4 + k, tempPhotonPar11[k + 1]);
395 FitFunctions[0]->SetParameter(10 + 4 + k, tempPhotonPar11[k + 1]);
397 FitFunctions[0]->FixParameter(24, ParMin11t[0]);
398 FitFunctions[0]->FixParameter(25, 1);
401 double MaxVal = -1.0;
402 const double cnpts = 2000;
403 for (
int k = 0; k < cnpts; k++) {
405 double yVal = FitFunctions[0]->Eval(xVal);
406 if (yVal > MaxVal) MaxVal = yVal;
408 B2INFO(
"MaxVal " << MaxVal);
409 tempPhotonPar11[0] /= MaxVal;
410 FitFunctions[0]->FixParameter(24, tempPhotonPar11[0]);
413 PhotonParameters->
setTemplateParameters(CellID_i, tempPhotonPar11, tempPhotonPar11, tempPhotonPar11);
416 for (
unsigned int k = 0; k < PhotonWaveformArray.size();
417 k++) PhotonWaveformArray[k] = FitFunctions[0]->Eval(((
double)k) * (1. / 1000.)) ;
421 for (
int w = 0; w < (int)FitFunctions.size(); w++) FitFunctions[w]->Delete();
422 TotalFitFunction->Delete() ;
423 gWaveformToFit->Delete();
429 auto gmaxResidual =
new TGraph(cellIDArray.size(), cellIDArray.data(), maxResidualArray.data());
430 gmaxResidual->SetName(
"gmaxResidual");
431 auto glimitResidualArray =
new TGraph(cellIDArray.size(), cellIDArray.data(), limitResidualArray.data());
432 glimitResidualArray->SetName(
"glimitResidualArray");
433 auto gparLimitFactorArray =
new TGraph(cellIDArray.size(), cellIDArray.data(), parLimitFactorArray.data());
434 gparLimitFactorArray->SetName(
"gparLimitFactorArray");
436 gmaxResidual->Write();
437 glimitResidualArray->Write();
438 gparLimitFactorArray->Write();
443 f_PhotonTemplateOutput->cd();
445 f_PhotonTemplateOutput->Write();
446 f_PhotonTemplateOutput->Close();
447 delete f_PhotonTemplateOutput;
451 B2INFO(
"eclWaveformTemplateCalibrationC2Algorithm: successfully stored " << Form(
"PhotonParameters_CellID%d_CellID%d",
Base class for calibration algorithms.
void saveCalibration(TClonesArray *data, const std::string &name)
Store DBArray payload with given name with default IOV.
void updateDBObjPtrs(const unsigned int event, const int run, const int experiment)
Updates any DBObjPtrs by calling update(event) for DBStore.
void setDescription(const std::string &description)
Set algorithm description (in constructor)
EResult
The result of calibration.
@ c_OK
Finished successfuly =0 in Python.
@ c_NotEnoughData
Needs more data =2 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.
Abstract base class for different kinds of events.
Struct containing exp number and run number.