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);
222 B2INFO(
"eclWaveformTemplateCalibrationC2Algorithm: warning total entries for cell ID " << CellID_i <<
" is only: " <<
224 EntriesToSkip.clear();
226 B2INFO(
"eclWaveformTemplateCalibrationC2Algorithm: warning " << CellID_i <<
" resLimit is doubled to" << resLimit <<
" start was "
227 << resLimitOriginal);
232 auto gWaveformToFit =
new TGraph(xValuesToFit.size(), xValuesToFit.data(), yValuesToFit.data());
233 gWaveformToFit->SetName(Form(
"gWaveformToFit_%d",
int(CellID_i)));
238 FitFunctions.clear();
239 for (
int i = 0; i < counterWaveforms; i++) {
240 FitFunctions.push_back(
new TF1(Form(
"Shp_%d", i), Belle2::ECL::WaveFuncTwoComponent, 0, 30.5, 26));
241 FitFunctions[i]->SetNpx(10000);
242 FitFunctions[i]->FixParameter(3, 0);
243 for (
int k = 0; k < 10; k++) {
244 FitFunctions[i]->SetParameter(4 + k, ParMin11t[k + 1]);
245 FitFunctions[i]->FixParameter(10 + 4 + k, ParMin11t[k + 1]);
247 FitFunctions[i]->FixParameter(24, ParMin11t[0]);
248 FitFunctions[i]->FixParameter(25, 1);
252 TF1* TotalFitFunction =
new TF1(
"TotalFitFunction", fitf, 0, counterWaveforms *
m_NumberofADCPoints,
253 (3 * FitFunctions.size()) + 10);
256 int FFsize = FitFunctions.size();
257 for (
int i = 0; i < FFsize; i++) {
258 TotalFitFunction->SetParameter(i, guessTime[i]);
259 TotalFitFunction->SetParameter(FFsize + i, guessBaseline[i]);
260 TotalFitFunction->SetParameter((2 * FFsize) + i, guessAmp[i]);
261 for (
int k = 0; k < 10; k++) {
262 TotalFitFunction->SetParameter((3 * FFsize) + k, ParMin11t[k + 1]);
264 TotalFitFunction->SetParLimits((3 * FFsize) + k, ParMin11t[k + 1] -
m_ParamLimitFactor * fabs(ParMin11t[k + 1]),
267 TotalFitFunction->ReleaseParameter((3 * FFsize) + k);
273 gWaveformToFit->Fit(
"TotalFitFunction",
"Q M W N 0 R",
"", 0, counterWaveforms *
m_NumberofADCPoints);
276 std::vector<int> FitResultY;
277 std::vector<int> FitResultX;
278 int maxResidualWaveformID = 0;
282 double npts = xValuesToFit.size();
283 double maxResidualOld = 0.0;
284 for (
int k = 0; k < npts; k++) {
285 double xVal = xValuesToFit[k];
286 double yVal = TotalFitFunction->Eval(xVal);
287 FitResultX.push_back(xVal);
288 FitResultY.push_back(yVal);
289 double diff = fabs(yValuesToFit[k] - yVal);
290 if (diff > maxResidual) {
293 maxResidualOld = fabs(yValuesToFit[k] / yVal);
298 if (maxResidual > resLimit) {
300 B2INFO(
"FAIL: CellID_i " << CellID_i <<
" maxResidual " << maxResidual <<
" removing entry: " <<
301 NtupleEntries[maxResidualWaveformID] <<
302 " which was waveform number " << maxResidualWaveformID <<
" resLimit was " << resLimit <<
" , resLimit started at " <<
304 B2INFO(
"Old maxResidual of Data/Fit was " << maxResidualOld);
306 B2INFO(
"Iter Time = " << std::time(0) - t << std::endl);
309 std::cout <<
"FAIL: CellID_i " << CellID_i <<
" maxResidual " << maxResidual <<
" removing entry: " <<
310 NtupleEntries[maxResidualWaveformID] <<
311 " which was waveform number " << maxResidualWaveformID <<
" resLimit was " << resLimit <<
" , resLimit started at " <<
312 resLimitOriginal << std::endl;
313 std::cout <<
"wave = [";
314 for (
int k = 0; k < npts; k++) {
315 std::cout << yValuesToFit[k];
316 if (k < (npts - 1)) {
319 std::cout <<
"]" << std::endl;
322 std::cout <<
"fitRes = [";
323 for (
int k = 0; k < npts; k++) {
324 std::cout << TotalFitFunction->Eval(xValuesToFit[k]);
325 if (k < (npts - 1)) {
328 std::cout <<
"]" << std::endl;
333 EntriesToSkip.push_back(NtupleEntries[maxResidualWaveformID]);
345 B2INFO(
"AttemptCounter reach limit: " << AttemptCounter <<
" counterWaveforms: " << counterWaveforms);
349 EntriesToSkip.clear();
355 B2INFO(
"Increasing resLimit to " << resLimit);
362 B2INFO(
"PASS: CellID_i " << CellID_i <<
" maxResidual " << maxResidual <<
" number of waveforms used was " << counterWaveforms <<
363 " resLimit was " << resLimit);
367 limitResidualArray.push_back(resLimit);
374 auto gFitResult =
new TGraph(FitResultX.size(), FitResultX.data(), FitResultY.data());
375 gFitResult->SetName(Form(
"gFitResult_%d",
int(CellID_i)));
378 cellIDArray.push_back(CellID_i);
379 maxResidualArray.push_back(maxResidual);
383 gWaveformToFit->Write();
387 float tempPhotonPar11[11];
388 tempPhotonPar11[0] = ParMin11t[0];
389 for (
unsigned int k = 0; k < 10; k++) tempPhotonPar11[k + 1] = TotalFitFunction->GetParameter((3 * FFsize) + k);
392 FitFunctions[0]->SetParameter(0, 0);
393 FitFunctions[0]->SetParameter(1, 0);
394 FitFunctions[0]->SetParameter(2, 1);
395 for (
int k = 0; k < 10; k++) {
396 FitFunctions[0]->SetParameter(4 + k, tempPhotonPar11[k + 1]);
397 FitFunctions[0]->SetParameter(10 + 4 + k, tempPhotonPar11[k + 1]);
399 FitFunctions[0]->FixParameter(24, ParMin11t[0]);
400 FitFunctions[0]->FixParameter(25, 1);
403 double MaxVal = -1.0;
404 const double cnpts = 2000;
405 for (
int k = 0; k < cnpts; k++) {
407 double yVal = FitFunctions[0]->Eval(xVal);
408 if (yVal > MaxVal) MaxVal = yVal;
410 B2INFO(
"MaxVal " << MaxVal);
411 tempPhotonPar11[0] /= MaxVal;
412 FitFunctions[0]->FixParameter(24, tempPhotonPar11[0]);
415 PhotonParameters->
setTemplateParameters(CellID_i, tempPhotonPar11, tempPhotonPar11, tempPhotonPar11);
418 for (
unsigned int k = 0; k < PhotonWaveformArray.size();
419 k++) PhotonWaveformArray[k] = FitFunctions[0]->Eval(((
double)k) * (1. / 1000.)) ;
423 for (
int w = 0; w < (int)FitFunctions.size(); w++) FitFunctions[w]->Delete();
424 TotalFitFunction->Delete() ;
425 gWaveformToFit->Delete();
431 auto gmaxResidual =
new TGraph(cellIDArray.size(), cellIDArray.data(), maxResidualArray.data());
432 gmaxResidual->SetName(
"gmaxResidual");
433 auto glimitResidualArray =
new TGraph(cellIDArray.size(), cellIDArray.data(), limitResidualArray.data());
434 glimitResidualArray->SetName(
"glimitResidualArray");
435 auto gparLimitFactorArray =
new TGraph(cellIDArray.size(), cellIDArray.data(), parLimitFactorArray.data());
436 gparLimitFactorArray->SetName(
"gparLimitFactorArray");
438 gmaxResidual->Write();
439 glimitResidualArray->Write();
440 gparLimitFactorArray->Write();
445 f_PhotonTemplateOutput->cd();
447 f_PhotonTemplateOutput->Write();
448 f_PhotonTemplateOutput->Close();
449 delete f_PhotonTemplateOutput;
453 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.
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.