12 #include <top/calibration/TOPLocalCalFitter.h>
22 #include <framework/logging/Logger.h>
23 #include <top/dbobjects/TOPCalChannelT0.h>
30 double crystalball_function(
double x,
double alpha,
double n,
double sigma,
double mean)
33 if (sigma < 0.)
return 0.;
34 double z = (x - mean) / sigma;
35 if (alpha < 0) z = -z;
36 double abs_alpha = std::abs(alpha);
38 return std::exp(- 0.5 * z * z);
40 double nDivAlpha = n / abs_alpha;
41 double AA = std::exp(-0.5 * abs_alpha * abs_alpha);
42 double B = nDivAlpha - abs_alpha;
43 double arg = nDivAlpha / (B - z);
44 return AA * std::pow(arg, n);
48 double crystalball_pdf(
double x,
double alpha,
double n,
double sigma,
double mean)
51 if (sigma < 0.)
return 0.;
52 if (n <= 1)
return std::numeric_limits<double>::quiet_NaN();
53 double abs_alpha = std::abs(alpha);
54 double C = n / abs_alpha * 1. / (n - 1.) * std::exp(-alpha * alpha / 2.);
55 double D = std::sqrt(M_PI / 2.) * (1. + erf(abs_alpha / std::sqrt(2.)));
56 double N = 1. / (sigma * (C + D));
57 return N * crystalball_function(x, alpha, n, sigma, mean);
63 double TTSPDF(
double x,
double time,
double deltaT,
double sigma1,
double sigma2,
double f1)
65 return f1 * TMath::Gaus(x, time, sigma1, kTRUE) + (1 - f1) * TMath::Gaus(x, time + deltaT, sigma2, kTRUE) ;
73 double laserPDF(
double* x,
double* p)
77 double fraction = p[2];
78 double deltaTLaser = p[3];
79 double sigmaRatio = p[4];
80 double deltaTTS = p[5];
84 double deltaTExtra = p[8];
85 double sigmaExtra = p[9];
86 double normExtra = p[10];
88 double deltaTBkg = p[11];
89 double sigmaBkg = p[12];
95 double mainPeak = fraction * TTSPDF(x[0], time, deltaTTS, sigma, TMath::Sqrt(sigma * sigma + sigmaRatio * sigmaRatio), f1);
96 double secondaryPeak = (1. - fraction) * TTSPDF(x[0], time + deltaTLaser, deltaTTS, sigma,
97 TMath::Sqrt(sigma * sigma + sigmaRatio * sigmaRatio), f1);
98 double extraPeak = crystalball_pdf(x[0], alpha, n, sigmaExtra, time + deltaTExtra);
99 double background = TMath::Gaus(x[0], time + deltaTBkg + deltaTTS, sigmaBkg, kTRUE);
101 return norm * (mainPeak + secondaryPeak) + normExtra * extraPeak + bkg * background;
108 "Perform the fit of the laser and pulser runs"
120 B2INFO(
"Getting the TTS parameters from " <<
m_TTSData);
132 std::cout <<
"Running in MC mode, not constraints will be set" << std::endl;
157 m_fitTree =
new TTree(
"fitTree",
"fitTree");
252 m_treeTTS->GetEntry(iChannel + 512 * iSlot);
254 double maxpos = h_profile->GetBinCenter(h_profile->GetMaximumBin());
255 h_profile->GetXaxis()->SetRangeUser(maxpos - 1, maxpos + 2.);
258 double integral = h_profile->Integral();
261 TF1 laser = TF1(
"laser", laserPDF, maxpos - 1, maxpos + 2., 16);
264 laser.SetParameter(0, maxpos);
265 laser.SetParLimits(0, maxpos - 0.06, maxpos + 0.06);
268 laser.SetParameter(1, 0.1);
269 laser.SetParLimits(1, 0.05, 0.25);
271 laser.SetParameter(1, 0.02);
272 laser.SetParLimits(1, 0., 0.04);
276 laser.SetParLimits(2, 0.5, 1.);
284 laser.SetParameter(3, -0.3);
285 laser.SetParLimits(3, -0.4, -0.2);
291 laser.FixParameter(5,
m_mean2);
293 laser.FixParameter(6,
m_f1);
295 laser.FixParameter(6, 0);
298 laser.SetParameter(7, integral * 0.005);
299 laser.SetParLimits(7, 0.2 * integral * 0.005, 2.*integral * 0.005);
302 laser.SetParameter(8, 1.);
303 laser.SetParLimits(8, 0.3, 2.);
304 laser.SetParameter(9, 0.2);
305 laser.SetParLimits(9, 0.08, 1.);
306 laser.SetParameter(10, 0.1 * integral * 0.005);
307 laser.SetParLimits(10, 0., 0.2 * integral * 0.005);
309 laser.SetParameter(14, -2.);
310 laser.SetParameter(15, 2.);
311 laser.SetParLimits(15, 1.01, 20.);
314 laser.SetParameter(11, 1.);
315 laser.SetParLimits(11, 0.1, 5.);
316 laser.SetParameter(12, 0.8);
317 laser.SetParLimits(12, 0., 5.);
318 laser.SetParameter(13, 0.01 * integral * 0.005);
319 laser.SetParLimits(13, 0., 0.2 * integral * 0.005);
336 laser.SetParameter(2, 0.8);
337 laser.SetParLimits(2, 0., 1.);
338 laser.SetParameter(3, -0.1);
339 laser.SetParLimits(3, -0.4, -0.);
341 laser.FixParameter(8, 0);
342 laser.FixParameter(9, 0.1);
343 laser.FixParameter(14, -2.);
344 laser.FixParameter(15, 2);
345 laser.FixParameter(11, 1.);
346 laser.FixParameter(12, 0.1);
347 laser.FixParameter(13, 0.);
348 laser.FixParameter(10, 0.);
358 h_profile->Fit(
"laser",
"R L Q");
362 TF1* peak1 =
new TF1(
"peak1", laserPDF, maxpos - 1, maxpos + 2., 16);
363 TF1* peak2 =
new TF1(
"peak2", laserPDF, maxpos - 1, maxpos + 2., 16);
364 TF1* extra =
new TF1(
"extra", laserPDF, maxpos - 1, maxpos + 2., 16);
365 TF1* background =
new TF1(
"background", laserPDF, maxpos - 1, maxpos + 2., 16);
366 for (
int iPar = 0; iPar < 16; iPar++) {
367 peak1->FixParameter(iPar, laser.GetParameter(iPar));
368 peak2->FixParameter(iPar, laser.GetParameter(iPar));
369 extra->FixParameter(iPar, laser.GetParameter(iPar));
370 background->FixParameter(iPar, laser.GetParameter(iPar));
372 peak1->FixParameter(2, 0.);
373 peak1->FixParameter(7, (1 - laser.GetParameter(2))*laser.GetParameter(7));
374 peak1->FixParameter(10, 0.);
375 peak1->FixParameter(13, 0.);
377 peak2->FixParameter(2, 1.);
378 peak2->FixParameter(7, laser.GetParameter(2)*laser.GetParameter(7));
379 peak2->FixParameter(10, 0.);
380 peak2->FixParameter(13, 0.);
382 extra->FixParameter(7, 0.);
383 extra->FixParameter(13, 0.);
385 background->FixParameter(7, 0.);
386 background->FixParameter(10, 0.);
388 h_profile->GetListOfFunctions()->Add(peak1);
389 h_profile->GetListOfFunctions()->Add(peak2);
390 h_profile->GetListOfFunctions()->Add(extra);
391 h_profile->GetListOfFunctions()->Add(background);
403 m_sigma = laser.GetParameter(1);
417 m_chi2 = laser.GetChisquare() / laser.GetNDF();
430 float maxpos = h_profileFirstPulser->GetBinCenter(h_profileFirstPulser->GetMaximumBin());
431 h_profileFirstPulser->GetXaxis()->SetRangeUser(maxpos - 1, maxpos + 1.);
432 if (h_profileFirstPulser->Integral() > 1000) {
433 TF1 pulser1 = TF1(
"pulser1",
"[0]*TMath::Gaus(x, [1], [2], kTRUE)", maxpos - 1, maxpos + 1.);
434 pulser1.SetParameter(0, 1.);
435 pulser1.SetParameter(1, maxpos);
436 pulser1.SetParameter(2, 0.05);
437 h_profileFirstPulser->Fit(
"pulser1",
"R Q");
440 h_profileFirstPulser->Write();
446 maxpos = h_profileSecondPulser->GetBinCenter(h_profileSecondPulser->GetMaximumBin());
447 h_profileSecondPulser->GetXaxis()->SetRangeUser(maxpos - 1, maxpos + 1.);
448 if (h_profileSecondPulser->Integral() > 1000) {
449 TF1 pulser2 = TF1(
"pulser2",
"[0]*TMath::Gaus(x, [1], [2], kTRUE)", maxpos - 1, maxpos + 1.);
450 pulser2.SetParameter(0, 1.);
451 pulser2.SetParameter(1, maxpos);
452 pulser2.SetParameter(2, 0.05);
453 h_profileSecondPulser->Fit(
"pulser2",
"R Q");
456 h_profileSecondPulser->Write();
468 if (
m_chi2 < 4 && m_sigma < 0.2 && m_yieldLaser > 1000) {
480 if (nEntries != 8192) {
481 B2ERROR(
"fitTree does not contain an entry wit a fit result for each channel. Found " << nEntries <<
482 " instead of 8192. Perhaps you tried to run the commonT0 calculation before finishing the fitting?");
489 short nCal[16] = {0};
490 for (
int i = 0; i < nEntries; i++) {
501 channelT0->suppressAverage();
508 for (
int iSlot = 1; iSlot < 17; iSlot++) {
509 B2INFO(
"--> Number of calibrated channels on Slot " << iSlot <<
" : " << nCal[iSlot - 1] <<
"/512");
510 B2INFO(
"--> Cal on ch 1, 256 and 511: " << channelT0->getT0(iSlot, 0) <<
", " << channelT0->getT0(iSlot,
511 257) <<
", " << channelT0->getT0(iSlot, 511));
512 nCalTot += nCal[iSlot - 1];
515 B2RESULT(
"Channel T0 calibration constants imported to database, calibrated channels: " << nCalTot <<
"/ 8192");
522 for (
int i = 0; i < nEntries; i++) {
526 channelT0Branch->Fill();
527 channelT0ErrBranch->Fill();
545 auto hitTree = getObjectPtr<TTree>(
"hitTree");
546 TH2F* h_hitTime =
new TH2F(
"h_hitTime",
" ", 512 * 16, 0., 512 * 16, 22000, -70, 40.);
548 float amplitude, hitTime;
551 hitTree->SetBranchAddress(
"amplitude", &litude);
552 hitTree->SetBranchAddress(
"hitTime", &hitTime);
553 hitTree->SetBranchAddress(
"channel", &channel);
554 hitTree->SetBranchAddress(
"slot", &slot);
555 hitTree->SetBranchAddress(
"refTimeValid", &refTimeValid);
558 std::vector<TH2F*> h_hitTimeLaserHistos = {};
559 for (
int iLowerEdge = 0; iLowerEdge < (int)
m_binEdges.size() - 1; iLowerEdge++) {
560 TH2F* h_hitTimeLaser =
new TH2F((
"h_hitTimeLaser_" + std::to_string(iLowerEdge + 1)).c_str(),
" ", 512 * 16, 0., 512 * 16, 14000,
562 h_hitTimeLaserHistos.push_back(h_hitTimeLaser);
565 for (
unsigned int i = 0; i < hitTree->GetEntries(); i++) {
566 auto onepc = (
unsigned int)(hitTree->GetEntries() / 100);
568 std::cout <<
"processing hit " << i <<
" of " << hitTree->GetEntries() <<
" (" << i / (onepc * 10) <<
" %)" << std::endl;
569 hitTree->GetEntry(i);
571 int iLowerEdge = std::distance(
m_binEdges.cbegin(), it) - 1;
573 if (iLowerEdge >= 0 && iLowerEdge <
static_cast<int>(
m_binEdges.size()) - 1 && refTimeValid)
574 h_hitTimeLaserHistos[iLowerEdge]->Fill(channel + (slot - 1) * 512, hitTime);
575 if (amplitude > 80. && refTimeValid)
576 h_hitTime->Fill(channel + (slot - 1) * 512, hitTime);
582 for (
short iSlot = 0; iSlot < 16; iSlot++) {
583 std::cout <<
"fitting slot " << iSlot + 1 << std::endl;
584 for (
short iChannel = 0; iChannel < 512; iChannel++) {
585 TH1D* h_profile = h_hitTime->ProjectionY((
"profile_" + std::to_string(iSlot + 1) +
"_" + std::to_string(iChannel)).c_str(),
586 iSlot * 512 + iChannel + 1, iSlot * 512 + iChannel + 1);
588 h_profile->GetXaxis()->SetRangeUser(-10, -10);
590 h_profile->GetXaxis()->SetRangeUser(-65,
597 TH1D* h_profileFirstPulser = h_hitTime->ProjectionY((
"profileFirstPulser_" + std::to_string(iSlot + 1) +
"_" + std::to_string(
598 iChannel)).c_str(), iSlot * 512 + iChannel + 1, iSlot * 512 + iChannel + 1);
599 TH1D* h_profileSecondPulser = h_hitTime->ProjectionY((
"profileSecondPulser_" + std::to_string(iSlot + 1) +
"_" + std::to_string(
600 iChannel)).c_str(), iSlot * 512 + iChannel + 1, iSlot * 512 + iChannel + 1);
601 h_profileFirstPulser->GetXaxis()->SetRangeUser(-10, 10);
602 h_profileSecondPulser->GetXaxis()->SetRangeUser(10, 40);
604 fitPulser(h_profileFirstPulser, h_profileSecondPulser);
609 h_profileFirstPulser->Write();
610 h_profileSecondPulser->Write();
622 std::cout <<
"Fitting in bins" << std::endl;
623 for (
int iLowerEdge = 0; iLowerEdge < (int)
m_binEdges.size() - 1; iLowerEdge++) {
628 for (
short iSlot = 0; iSlot < 16; iSlot++) {
629 std::cout <<
" Fitting slot " << iSlot + 1 << std::endl;
630 for (
short iChannel = 0; iChannel < 512; iChannel++) {
631 TH1D* h_profile = h_hitTimeLaserHistos[iLowerEdge]->ProjectionY((
"profile_" + std::to_string(iSlot + 1) +
"_" + std::to_string(
632 iChannel) +
"_" + std::to_string(iLowerEdge)).c_str(),
633 iSlot * 512 + iChannel + 1, iSlot * 512 + iChannel + 1);
635 h_profile->GetXaxis()->SetRangeUser(-10, -10);
637 h_profile->GetXaxis()->SetRangeUser(-65,