9 #include <top/calibration/TOPLocalCalFitter.h>
19 #include <framework/logging/Logger.h>
20 #include <top/dbobjects/TOPCalChannelT0.h>
27 double crystalball_function(
double x,
double alpha,
double n,
double sigma,
double mean)
30 if (sigma < 0.)
return 0.;
31 double z = (x - mean) / sigma;
32 if (alpha < 0) z = -z;
33 double abs_alpha = std::abs(alpha);
35 return std::exp(- 0.5 * z * z);
37 double nDivAlpha = n / abs_alpha;
38 double AA = std::exp(-0.5 * abs_alpha * abs_alpha);
39 double B = nDivAlpha - abs_alpha;
40 double arg = nDivAlpha / (B - z);
41 return AA * std::pow(arg, n);
45 double crystalball_pdf(
double x,
double alpha,
double n,
double sigma,
double mean)
48 if (sigma < 0.)
return 0.;
49 if (n <= 1)
return std::numeric_limits<double>::quiet_NaN();
50 double abs_alpha = std::abs(alpha);
51 double C = n / abs_alpha * 1. / (n - 1.) * std::exp(-alpha * alpha / 2.);
52 double D = std::sqrt(M_PI / 2.) * (1. + erf(abs_alpha / std::sqrt(2.)));
53 double N = 1. / (sigma * (C + D));
54 return N * crystalball_function(x, alpha, n, sigma, mean);
60 double TTSPDF(
double x,
double time,
double deltaT,
double sigma1,
double sigma2,
double f1)
62 return f1 * TMath::Gaus(x, time, sigma1, kTRUE) + (1 - f1) * TMath::Gaus(x, time + deltaT, sigma2, kTRUE) ;
70 double laserPDF(
double* x,
double* p)
74 double fraction = p[2];
75 double deltaTLaser = p[3];
76 double sigmaRatio = p[4];
77 double deltaTTS = p[5];
81 double deltaTExtra = p[8];
82 double sigmaExtra = p[9];
83 double normExtra = p[10];
85 double deltaTBkg = p[11];
86 double sigmaBkg = p[12];
92 double mainPeak = fraction * TTSPDF(x[0], time, deltaTTS, sigma, TMath::Sqrt(sigma * sigma + sigmaRatio * sigmaRatio), f1);
93 double secondaryPeak = (1. - fraction) * TTSPDF(x[0], time + deltaTLaser, deltaTTS, sigma,
94 TMath::Sqrt(sigma * sigma + sigmaRatio * sigmaRatio), f1);
95 double extraPeak = crystalball_pdf(x[0], alpha, n, sigmaExtra, time + deltaTExtra);
96 double background = TMath::Gaus(x[0], time + deltaTBkg + deltaTTS, sigmaBkg, kTRUE);
98 return norm * (mainPeak + secondaryPeak) + normExtra * extraPeak + bkg * background;
105 "Perform the fit of the laser and pulser runs"
117 B2INFO(
"Getting the TTS parameters from " <<
m_TTSData);
129 std::cout <<
"Running in MC mode, not constraints will be set" << std::endl;
154 m_fitTree =
new TTree(
"fitTree",
"fitTree");
249 m_treeTTS->GetEntry(iChannel + 512 * iSlot);
251 double maxpos = h_profile->GetBinCenter(h_profile->GetMaximumBin());
252 h_profile->GetXaxis()->SetRangeUser(maxpos - 1, maxpos + 2.);
255 double integral = h_profile->Integral();
258 TF1 laser = TF1(
"laser", laserPDF, maxpos - 1, maxpos + 2., 16);
261 laser.SetParameter(0, maxpos);
262 laser.SetParLimits(0, maxpos - 0.06, maxpos + 0.06);
265 laser.SetParameter(1, 0.1);
266 laser.SetParLimits(1, 0.05, 0.25);
268 laser.SetParameter(1, 0.02);
269 laser.SetParLimits(1, 0., 0.04);
273 laser.SetParLimits(2, 0.5, 1.);
281 laser.SetParameter(3, -0.3);
282 laser.SetParLimits(3, -0.4, -0.2);
288 laser.FixParameter(5,
m_mean2);
290 laser.FixParameter(6,
m_f1);
292 laser.FixParameter(6, 0);
295 laser.SetParameter(7, integral * 0.005);
296 laser.SetParLimits(7, 0.2 * integral * 0.005, 2.*integral * 0.005);
299 laser.SetParameter(8, 1.);
300 laser.SetParLimits(8, 0.3, 2.);
301 laser.SetParameter(9, 0.2);
302 laser.SetParLimits(9, 0.08, 1.);
303 laser.SetParameter(10, 0.1 * integral * 0.005);
304 laser.SetParLimits(10, 0., 0.2 * integral * 0.005);
306 laser.SetParameter(14, -2.);
307 laser.SetParameter(15, 2.);
308 laser.SetParLimits(15, 1.01, 20.);
311 laser.SetParameter(11, 1.);
312 laser.SetParLimits(11, 0.1, 5.);
313 laser.SetParameter(12, 0.8);
314 laser.SetParLimits(12, 0., 5.);
315 laser.SetParameter(13, 0.01 * integral * 0.005);
316 laser.SetParLimits(13, 0., 0.2 * integral * 0.005);
333 laser.SetParameter(2, 0.8);
334 laser.SetParLimits(2, 0., 1.);
335 laser.SetParameter(3, -0.1);
336 laser.SetParLimits(3, -0.4, -0.);
338 laser.FixParameter(8, 0);
339 laser.FixParameter(9, 0.1);
340 laser.FixParameter(14, -2.);
341 laser.FixParameter(15, 2);
342 laser.FixParameter(11, 1.);
343 laser.FixParameter(12, 0.1);
344 laser.FixParameter(13, 0.);
345 laser.FixParameter(10, 0.);
355 h_profile->Fit(
"laser",
"R L Q");
359 TF1* peak1 =
new TF1(
"peak1", laserPDF, maxpos - 1, maxpos + 2., 16);
360 TF1* peak2 =
new TF1(
"peak2", laserPDF, maxpos - 1, maxpos + 2., 16);
361 TF1* extra =
new TF1(
"extra", laserPDF, maxpos - 1, maxpos + 2., 16);
362 TF1* background =
new TF1(
"background", laserPDF, maxpos - 1, maxpos + 2., 16);
363 for (
int iPar = 0; iPar < 16; iPar++) {
364 peak1->FixParameter(iPar, laser.GetParameter(iPar));
365 peak2->FixParameter(iPar, laser.GetParameter(iPar));
366 extra->FixParameter(iPar, laser.GetParameter(iPar));
367 background->FixParameter(iPar, laser.GetParameter(iPar));
369 peak1->FixParameter(2, 0.);
370 peak1->FixParameter(7, (1 - laser.GetParameter(2))*laser.GetParameter(7));
371 peak1->FixParameter(10, 0.);
372 peak1->FixParameter(13, 0.);
374 peak2->FixParameter(2, 1.);
375 peak2->FixParameter(7, laser.GetParameter(2)*laser.GetParameter(7));
376 peak2->FixParameter(10, 0.);
377 peak2->FixParameter(13, 0.);
379 extra->FixParameter(7, 0.);
380 extra->FixParameter(13, 0.);
382 background->FixParameter(7, 0.);
383 background->FixParameter(10, 0.);
385 h_profile->GetListOfFunctions()->Add(peak1);
386 h_profile->GetListOfFunctions()->Add(peak2);
387 h_profile->GetListOfFunctions()->Add(extra);
388 h_profile->GetListOfFunctions()->Add(background);
400 m_sigma = laser.GetParameter(1);
414 m_chi2 = laser.GetChisquare() / laser.GetNDF();
427 float maxpos = h_profileFirstPulser->GetBinCenter(h_profileFirstPulser->GetMaximumBin());
428 h_profileFirstPulser->GetXaxis()->SetRangeUser(maxpos - 1, maxpos + 1.);
429 if (h_profileFirstPulser->Integral() > 1000) {
430 TF1 pulser1 = TF1(
"pulser1",
"[0]*TMath::Gaus(x, [1], [2], kTRUE)", maxpos - 1, maxpos + 1.);
431 pulser1.SetParameter(0, 1.);
432 pulser1.SetParameter(1, maxpos);
433 pulser1.SetParameter(2, 0.05);
434 h_profileFirstPulser->Fit(
"pulser1",
"R Q");
437 h_profileFirstPulser->Write();
443 maxpos = h_profileSecondPulser->GetBinCenter(h_profileSecondPulser->GetMaximumBin());
444 h_profileSecondPulser->GetXaxis()->SetRangeUser(maxpos - 1, maxpos + 1.);
445 if (h_profileSecondPulser->Integral() > 1000) {
446 TF1 pulser2 = TF1(
"pulser2",
"[0]*TMath::Gaus(x, [1], [2], kTRUE)", maxpos - 1, maxpos + 1.);
447 pulser2.SetParameter(0, 1.);
448 pulser2.SetParameter(1, maxpos);
449 pulser2.SetParameter(2, 0.05);
450 h_profileSecondPulser->Fit(
"pulser2",
"R Q");
453 h_profileSecondPulser->Write();
465 if (
m_chi2 < 4 && m_sigma < 0.2 && m_yieldLaser > 1000) {
477 if (nEntries != 8192) {
478 B2ERROR(
"fitTree does not contain an entry wit a fit result for each channel. Found " << nEntries <<
479 " instead of 8192. Perhaps you tried to run the commonT0 calculation before finishing the fitting?");
486 short nCal[16] = {0};
487 for (
int i = 0; i < nEntries; i++) {
498 channelT0->suppressAverage();
505 for (
int iSlot = 1; iSlot < 17; iSlot++) {
506 B2INFO(
"--> Number of calibrated channels on Slot " << iSlot <<
" : " << nCal[iSlot - 1] <<
"/512");
507 B2INFO(
"--> Cal on ch 1, 256 and 511: " << channelT0->getT0(iSlot, 0) <<
", " << channelT0->getT0(iSlot,
508 257) <<
", " << channelT0->getT0(iSlot, 511));
509 nCalTot += nCal[iSlot - 1];
512 B2RESULT(
"Channel T0 calibration constants imported to database, calibrated channels: " << nCalTot <<
"/ 8192");
519 for (
int i = 0; i < nEntries; i++) {
523 channelT0Branch->Fill();
524 channelT0ErrBranch->Fill();
542 auto hitTree = getObjectPtr<TTree>(
"hitTree");
543 TH2F* h_hitTime =
new TH2F(
"h_hitTime",
" ", 512 * 16, 0., 512 * 16, 22000, -70, 40.);
545 float amplitude, hitTime;
548 hitTree->SetBranchAddress(
"amplitude", &litude);
549 hitTree->SetBranchAddress(
"hitTime", &hitTime);
550 hitTree->SetBranchAddress(
"channel", &channel);
551 hitTree->SetBranchAddress(
"slot", &slot);
552 hitTree->SetBranchAddress(
"refTimeValid", &refTimeValid);
555 std::vector<TH2F*> h_hitTimeLaserHistos = {};
556 for (
int iLowerEdge = 0; iLowerEdge < (int)
m_binEdges.size() - 1; iLowerEdge++) {
557 TH2F* h_hitTimeLaser =
new TH2F((
"h_hitTimeLaser_" + std::to_string(iLowerEdge + 1)).c_str(),
" ", 512 * 16, 0., 512 * 16, 14000,
559 h_hitTimeLaserHistos.push_back(h_hitTimeLaser);
562 for (
unsigned int i = 0; i < hitTree->GetEntries(); i++) {
563 auto onepc = (
unsigned int)(hitTree->GetEntries() / 100);
565 std::cout <<
"processing hit " << i <<
" of " << hitTree->GetEntries() <<
" (" << i / (onepc * 10) <<
" %)" << std::endl;
566 hitTree->GetEntry(i);
568 int iLowerEdge = std::distance(
m_binEdges.cbegin(), it) - 1;
570 if (iLowerEdge >= 0 && iLowerEdge <
static_cast<int>(
m_binEdges.size()) - 1 && refTimeValid)
571 h_hitTimeLaserHistos[iLowerEdge]->Fill(channel + (slot - 1) * 512, hitTime);
572 if (amplitude > 80. && refTimeValid)
573 h_hitTime->Fill(channel + (slot - 1) * 512, hitTime);
579 for (
short iSlot = 0; iSlot < 16; iSlot++) {
580 std::cout <<
"fitting slot " << iSlot + 1 << std::endl;
581 for (
short iChannel = 0; iChannel < 512; iChannel++) {
582 TH1D* h_profile = h_hitTime->ProjectionY((
"profile_" + std::to_string(iSlot + 1) +
"_" + std::to_string(iChannel)).c_str(),
583 iSlot * 512 + iChannel + 1, iSlot * 512 + iChannel + 1);
585 h_profile->GetXaxis()->SetRangeUser(-10, -10);
587 h_profile->GetXaxis()->SetRangeUser(-65,
594 TH1D* h_profileFirstPulser = h_hitTime->ProjectionY((
"profileFirstPulser_" + std::to_string(iSlot + 1) +
"_" + std::to_string(
595 iChannel)).c_str(), iSlot * 512 + iChannel + 1, iSlot * 512 + iChannel + 1);
596 TH1D* h_profileSecondPulser = h_hitTime->ProjectionY((
"profileSecondPulser_" + std::to_string(iSlot + 1) +
"_" + std::to_string(
597 iChannel)).c_str(), iSlot * 512 + iChannel + 1, iSlot * 512 + iChannel + 1);
598 h_profileFirstPulser->GetXaxis()->SetRangeUser(-10, 10);
599 h_profileSecondPulser->GetXaxis()->SetRangeUser(10, 40);
601 fitPulser(h_profileFirstPulser, h_profileSecondPulser);
606 h_profileFirstPulser->Write();
607 h_profileSecondPulser->Write();
619 std::cout <<
"Fitting in bins" << std::endl;
620 for (
int iLowerEdge = 0; iLowerEdge < (int)
m_binEdges.size() - 1; iLowerEdge++) {
625 for (
short iSlot = 0; iSlot < 16; iSlot++) {
626 std::cout <<
" Fitting slot " << iSlot + 1 << std::endl;
627 for (
short iChannel = 0; iChannel < 512; iChannel++) {
628 TH1D* h_profile = h_hitTimeLaserHistos[iLowerEdge]->ProjectionY((
"profile_" + std::to_string(iSlot + 1) +
"_" + std::to_string(
629 iChannel) +
"_" + std::to_string(iLowerEdge)).c_str(),
630 iSlot * 512 + iChannel + 1, iSlot * 512 + iChannel + 1);
632 h_profile->GetXaxis()->SetRangeUser(-10, -10);
634 h_profile->GetXaxis()->SetRangeUser(-65,
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.
Channel T0 calibration constants for all 512 channels of 16 modules.
short m_fitStatus
Fit quality flag, propagated to the constants.
float m_yieldLaserErr
Statistical error on yield.
float m_binLowerEdge
Lower edge of the amplitude bin in which this fit is performed.
void fitChannel(short, short, TH1 *)
Fits the laser light on one channel.
float m_nExtraConstraints
parameter n of the tail of the extra peak
float m_chi2
Reduced chi2 of the fit.
float m_timeExtraConstraints
Position of the guassian used to describe the extra peak on the timing distribution tail.
float m_f1
Fraction of the first gaussian on the TTS parametrization.
float m_fraction
Fraction of events in the secondary peak.
float m_sigmaExtra
Gaussian sigma of the extra peak in the timing tail
float m_secondPulserSigma
Time resolution from the fit of the first electronic pulse, from a Gaussian fit.
float m_yieldLaserBackground
Integral of the background gaussian.
TOPLocalCalFitter()
Constructor.
float m_sigma
Gaussian time resolution, fitted.
float m_peakTimeMC
Time of the main peak in teh MC simulation, i.e.
std::string m_output
Name of the output file.
float m_timeBackground
Position of the gaussian used to describe the background, w/ respect to peakTime.
void loadMCInfoTrees()
loads the TTS parameters and the MC truth info
float m_deltaTMC
Time difference between the main peak and the secondary peak in the MC simulation.
float m_peakTimeErr
Statistical error on peakTime.
short m_channel
Channel number (0-511)
float m_channelT0Err
Statistical error on channelT0.
std::string m_TTSData
File with the Fit constraints and MC info.
std::vector< float > m_binEdges
Amplitude bins.
float m_sigmaBackground
Sigma of the gaussian used to describe the background.
float m_peakTime
Fitted time of the main (i.e.
float m_fractionErr
Statistical error on fraction.
bool m_isFitInAmplitudeBins
Enables the fit in amplitude bins.
void calculateChennelT0()
Calculates the commonT0 calibration after the fits have been done.
float m_alphaExtra
alpha parameter of the tail of the extra peak.
float m_rms
RMS of the histogram used for the fit.
float m_mean2
Position of the second gaussian of the TTS parametrization with respect to the first one.
std::string m_fitConstraints
File with the TTS parametrization.
TTree * m_timewalkTree
Output of the fitter.
short m_pixelCol
Pixel column.
float m_yieldLaser
Total number of laser hits from the fitting function integral.
TFile * m_inputTTS
File containing m_treeTTS.
float m_nExtra
parameter n of the tail of the extra peak
float m_alphaExtraConstraints
alpha parameter of the tail of the extra peak.
float m_channelT0
Raw, channelT0 calibration, defined as peakTime-peakTimeMC.
float m_sigmaErr
Statistical error on sigma.
std::string m_fitterMode
Fit mode.
float m_binUpperEdge
Upper edge of the amplitude bin in which this fit is performed.
TFile * m_histFile
Output of the fitter.
TTree * m_treeConstraints
Input to the fitter.
float m_sigmaExtraConstraints
Width of the guassian used to describe the extra peak on the timing distribution tail.
float m_firstPulserSigma
Time resolution from the fit of the first electronic pulse, from a Gaussian fit.
float m_deltaT
Time difference between the main peak and the secondary peak.
TTree * m_fitTree
Output of the fitter.
short m_slot
Slot ID (1-16)
float m_f2
Fraction of the second gaussian on the TTS parametrization.
void determineFitStatus()
determines if the constant obtained by the fit are good or not
short m_pixelRow
Pixel row.
float m_secondPulserTime
Average time of the second electronic pulse respect to the reference pulse, from a gaussian fit.
float m_peakTimeConstraints
Time of the main laser peak in the MC simulation (aka MC correction)
float m_sigma1
Width of the first gaussian on the TTS parametrization.
float m_fractionMC
Fraction of events in the secondary peak form the MC simulation.
float m_sigmaBackgroundConstraints
Sigma of the gaussian used to describe the background.
virtual EResult calibrate() override
Runs the algorithm on events.
TTree * m_treeTTS
Input to the fitter.
void setupOutputTreeAndFile()
prepares the output tree
float m_timeBackgroundConstraints
Position of the gaussian used to describe the background, w/ respect to peakTime.
TFile * m_inputConstraints
File containing m_treeConstraints.
float m_deltaTErr
Statistical error on deltaT.
float m_firstPulserTime
Average time of the first electronic pulse respect to the reference pulse, from a Gaussian fit.
float m_histoIntegral
Integral of the fitted histogram.
float m_yieldLaserExtra
Integral of the extra peak.
float m_sigma2
Width of the second gaussian on the TTS parametrization.
void fitPulser(TH1 *, TH1 *)
Fits the two pulsers.
float m_timeExtra
Position of the extra peak seen in the timing tail, w/ respect to peakTime.
float m_fractionConstraints
Fraction of the main peak.
float m_deltaTConstraints
Distance between the main and the secondary laser peak.
Abstract base class for different kinds of events.