372 m_treeTTS->GetEntry(iChannel + 512 * iSlot);
374 double maxpos = h_profile->GetBinCenter(h_profile->GetMaximumBin());
375 h_profile->GetXaxis()->SetRangeUser(maxpos - 1, maxpos + 2.);
378 double integral = h_profile->Integral();
381 TF1 laser = TF1(
"laser", laserPDF, maxpos - 1, maxpos + 2., 16);
384 laser.SetParameter(0, maxpos);
385 laser.SetParLimits(0, maxpos - 0.06, maxpos + 0.06);
388 laser.SetParameter(1, 0.1);
389 laser.SetParLimits(1, 0.05, 0.25);
391 laser.SetParameter(1, 0.02);
392 laser.SetParLimits(1, 0., 0.04);
397 laser.SetParLimits(2, 0.5, 1.);
399 laser.FixParameter(2, frac);
408 laser.SetParameter(3, -0.3);
409 laser.SetParLimits(3, -0.4, -0.2);
415 laser.FixParameter(5,
m_mean2);
417 laser.FixParameter(6,
m_f1);
419 laser.FixParameter(6, 0);
422 const double binw = h_profile->GetXaxis()->GetBinWidth(1);
423 laser.SetParameter(7, integral * binw);
424 laser.SetParLimits(7, 0.2 * integral * binw, 2.*integral * binw);
427 laser.SetParameter(8, 1.);
428 laser.SetParLimits(8, 0.3, 2.);
429 laser.SetParameter(9, 0.2);
430 laser.SetParLimits(9, 0.08, 1.);
431 laser.SetParameter(10, 0.1 * integral * binw);
432 laser.SetParLimits(10, 0., 0.2 * integral * binw);
434 laser.SetParameter(14, -2.);
435 laser.SetParameter(15, 2.);
436 laser.SetParLimits(15, 1.01, 20.);
439 laser.SetParameter(11, 1.);
440 laser.SetParLimits(11, 0.1, 5.);
441 laser.SetParameter(12, 0.8);
442 laser.SetParLimits(12, 0., 5.);
443 laser.SetParameter(13, 0.01 * integral * binw);
444 laser.SetParLimits(13, 0., 0.2 * integral * binw);
460 laser.SetParameter(2, 0.8);
461 laser.SetParLimits(2, 0., 1.);
462 laser.SetParameter(3, -0.1);
463 laser.SetParLimits(3, -0.4, -0.);
465 laser.FixParameter(8, 0);
466 laser.FixParameter(9, 0.1);
467 laser.FixParameter(14, -2.);
468 laser.FixParameter(15, 2);
469 laser.FixParameter(11, 1.);
470 laser.FixParameter(12, 0.1);
471 laser.FixParameter(13, 0.);
472 laser.FixParameter(10, 0.);
479 h_profile->Fit(
"laser",
"R L Q");
482 TF1* peak1 =
new TF1(
"peak1", laserPDF, maxpos - 1, maxpos + 2., 16);
483 TF1* peak2 =
new TF1(
"peak2", laserPDF, maxpos - 1, maxpos + 2., 16);
484 TF1* extra =
new TF1(
"extra", laserPDF, maxpos - 1, maxpos + 2., 16);
485 TF1* background =
new TF1(
"background", laserPDF, maxpos - 1, maxpos + 2., 16);
486 for (
int iPar = 0; iPar < 16; iPar++) {
487 peak1->FixParameter(iPar, laser.GetParameter(iPar));
488 peak2->FixParameter(iPar, laser.GetParameter(iPar));
489 extra->FixParameter(iPar, laser.GetParameter(iPar));
490 background->FixParameter(iPar, laser.GetParameter(iPar));
492 peak1->FixParameter(2, 0.);
493 peak1->FixParameter(7, (1 - laser.GetParameter(2))*laser.GetParameter(7));
494 peak1->FixParameter(10, 0.);
495 peak1->FixParameter(13, 0.);
496 peak2->FixParameter(2, 1.);
497 peak2->FixParameter(7, laser.GetParameter(2)*laser.GetParameter(7));
498 peak2->FixParameter(10, 0.);
499 peak2->FixParameter(13, 0.);
500 extra->FixParameter(7, 0.);
501 extra->FixParameter(13, 0.);
502 background->FixParameter(7, 0.);
503 background->FixParameter(10, 0.);
505 h_profile->GetListOfFunctions()->Add(peak1);
506 h_profile->GetListOfFunctions()->Add(peak2);
507 h_profile->GetListOfFunctions()->Add(extra);
508 h_profile->GetListOfFunctions()->Add(background);
520 m_sigma = laser.GetParameter(1);
534 m_chi2 = laser.GetChisquare() / laser.GetNDF();
660 float amplitude, width, hitTime;
663 hitTree->SetBranchAddress(
"event", &event);
664 hitTree->SetBranchAddress(
"amplitude", &litude);
665 hitTree->SetBranchAddress(
"width", &width);
666 hitTree->SetBranchAddress(
"hitTime", &hitTime);
667 hitTree->SetBranchAddress(
"channel", &channel);
670 hitTree->SetBranchAddress(
"slot", &slot);
671 hitTree->SetBranchAddress(
"refTimeValid", &refTimeValid);
674 TH2F* h_hitTime =
new TH2F(
"h_hitTime",
" ", 512 * 16, 0., 512 * 16, 22000, -70, 40.);
675 TH2F* h_amplitude2D =
new TH2F(
"h_amplitude",
" ", 512 * 16, 0., 512 * 16, 600, 0, 2200.);
676 TH2F* h_width2D =
new TH2F(
"h_width",
" ", 512 * 16, 0., 512 * 16, 1000, 0, 2.);
681 std::vector<TH2F*> h_hitTimeLaserHistos = {};
682 for (
int iLowerEdge = 0; iLowerEdge < (int)
m_binEdges.size() - 1; iLowerEdge++) {
683 TH2F* h_hitTimeLaser =
new TH2F((
"h_hitTimeLaser_" + std::to_string(iLowerEdge + 1)).c_str(),
" ",
684 512 * 16, 0., 512 * 16, 14000, -70, 0.);
685 h_hitTimeLaserHistos.push_back(h_hitTimeLaser);
697 std::vector<Hit> evtHits;
701 int prev_evt = std::numeric_limits<int>::min();
704 const float conv = 1.f / (0.3989f * 2.35f);
707 const float fracMin = 0.25f;
708 const float dtMax = 0.30f;
709 const float epsQ = 1e-6f;
713 TH2F* h_hitTime_noXtalk =
new TH2F(
"h_hitTime_noXtalk",
" ", 512 * 16, 0., 512 * 16, 22000, -70, 40.);
714 TH2F* h_amplitude2D_noXtalk =
new TH2F(
"h_amplitude2D_noXtalk",
" ", 512 * 16, 0., 512 * 16, 600, 0, 2200.);
715 TH2F* h_width2D_noXtalk =
new TH2F(
"h_width2D_noXtalk",
" ", 512 * 16, 0., 512 * 16, 1000, 0, 2.);
718 Long64_t nhits = hitTree->GetEntries();
719 const Long64_t step = std::max<Long64_t>(1, nhits / 100);
722 for (Long64_t i = 0; i < nhits; i++) {
726 std::cout <<
"Processing hit " << i <<
" of " << nhits <<
" ("
727 << std::setprecision(3) << (100. * i) / nhits <<
" %)" << std::endl;
731 hitTree->GetEntry(i);
736 int iLowerEdge = std::distance(
m_binEdges.cbegin(), it) - 1;
737 if (iLowerEdge >= 0 && iLowerEdge <
static_cast<int>(
m_binEdges.size()) - 1 && refTimeValid)
738 h_hitTimeLaserHistos[iLowerEdge]->Fill(channel + (slot - 1) * 512, hitTime);
742 if (amplitude > 80. && refTimeValid) {
745 h_hitTime->Fill(channel + (slot - 1) * 512, hitTime);
748 if ((hitTime > -65) && (hitTime < -10)) {
751 h_amplitude2D->Fill(channel + (slot - 1) * 512, amplitude);
752 h_width2D->Fill(channel + (slot - 1) * 512, width);
757 const int curr_evt = event;
760 if (curr_evt != prev_evt && !evtHits.empty()) {
763 std::vector<char> isXtalk(evtHits.size(), 0);
764 for (
size_t ii = 0; ii + 1 < evtHits.size(); ++ii) {
765 const auto& hi = evtHits[ii];
766 for (
size_t jj = ii + 1; jj < evtHits.size(); ++jj) {
767 const auto& hj = evtHits[jj];
770 if (hi.slot != hj.slot)
continue;
774 if (std::fabs(hi.t - hj.t) > dtMax)
continue;
777 const float qsum = hi.q + hj.q;
778 if (qsum <= epsQ)
continue;
779 const float f_q0 = hi.q / qsum;
781 if (f_q0 < fracMin || f_q0 > (1.f - fracMin)) {
801 for (
size_t kk = 0; kk < evtHits.size(); ++kk) {
802 if (isXtalk[kk])
continue;
803 const auto& h = evtHits[kk];
804 const int gch = h.ch + (h.slot - 1) * 512;
805 h_hitTime_noXtalk->Fill(gch, h.t);
806 h_amplitude2D_noXtalk->Fill(gch, h.a);
807 h_width2D_noXtalk->Fill(gch, h.w);
814 evtHits.push_back(
Hit{slot, channel, hitTime, amplitude, width, conv* amplitude * width});
825 std::vector<char> isXtalk(evtHits.size(), 0);
826 for (
size_t ll = 0; ll + 1 < evtHits.size(); ++ll) {
827 const auto& hi = evtHits[ll];
828 for (
size_t mm = ll + 1; mm < evtHits.size(); ++mm) {
829 const auto& hj = evtHits[mm];
830 if (hi.slot != hj.slot)
continue;
832 if (std::fabs(hi.t - hj.t) > dtMax)
continue;
833 const float qsum = hi.q + hj.q;
834 if (qsum <= epsQ)
continue;
835 const float f_q0 = hi.q / qsum;
836 if (f_q0 < fracMin || f_q0 > (1.f - fracMin)) {
852 for (
size_t nn = 0; nn < evtHits.size(); ++nn) {
853 if (isXtalk[nn])
continue;
854 const auto& h = evtHits[nn];
855 const int gch = h.ch + (h.slot - 1) * 512;
856 h_hitTime_noXtalk->Fill(gch, h.t);
857 h_amplitude2D_noXtalk->Fill(gch, h.a);
858 h_width2D_noXtalk->Fill(gch, h.w);
865 std::cout <<
"Writing crosstalkTree (candidate crosstalk channel pairs) to output file" << std::endl;
876 for (
short iSlot = 0; iSlot < 16; iSlot++) {
877 std::cout <<
"fitting slot " << iSlot + 1 << std::endl;
878 for (
short iChannel = 0; iChannel < 512; iChannel++) {
881 TH1D* h_profile = h_hitTime->ProjectionY(
882 (
"profile_" + std::to_string(iSlot + 1) +
"_" + std::to_string(iChannel)).c_str(),
883 iSlot * 512 + iChannel + 1, iSlot * 512 + iChannel + 1
889 h_profile->GetXaxis()->SetRangeUser(-65, -1);
891 h_profile->GetXaxis()->SetRangeUser(-65, -5);
898 TH1D* h_profileFirstPulser = h_hitTime->ProjectionY(
899 (
"profileFirstPulser_" + std::to_string(iSlot + 1) +
"_" + std::to_string(
900 iChannel)).c_str(), iSlot * 512 + iChannel + 1, iSlot * 512 + iChannel + 1
902 TH1D* h_profileSecondPulser = h_hitTime->ProjectionY(
903 (
"profileSecondPulser_" + std::to_string(iSlot + 1) +
"_" + std::to_string(
904 iChannel)).c_str(), iSlot * 512 + iChannel + 1, iSlot * 512 + iChannel + 1
906 h_profileFirstPulser->GetXaxis()->SetRangeUser(-10, 10);
907 h_profileSecondPulser->GetXaxis()->SetRangeUser(10, 40);
908 fitPulser(h_profileFirstPulser, h_profileSecondPulser);
912 TH1D* h_amplitude = h_amplitude2D->ProjectionY(
913 (
"AmpProfile_" + std::to_string(iSlot + 1) +
"_" + std::to_string(iChannel)).c_str(),
914 iSlot * 512 + iChannel + 1, iSlot * 512 + iChannel + 1
916 TH1D* h_width = h_width2D->ProjectionY(
917 (
"WidthProfile_" + std::to_string(iSlot + 1) +
"_" + std::to_string(iChannel)).c_str(),
918 iSlot * 512 + iChannel + 1, iSlot * 512 + iChannel + 1
924 h_width->GetQuantiles(1, &
m_width, &q);
928 h_profileFirstPulser->Write();
929 h_profileSecondPulser->Write();
930 h_amplitude->Write();
935 delete h_profileFirstPulser;
936 delete h_profileSecondPulser;
956 std::cout <<
"Fitting in bins of pulse heigth" << std::endl;
958 for (
short iSlot = 0; iSlot < 16; iSlot++) {
959 std::cout <<
" Fitting slot " << iSlot + 1 << std::endl;
960 for (
short iChannel = 0; iChannel < 512; iChannel++) {
964 TH1D* h_profile_full = h_hitTime->ProjectionY(
965 (
"profile_" + std::to_string(iSlot + 1) +
"_" + std::to_string(iChannel)).c_str(),
966 iSlot * 512 + iChannel + 1, iSlot * 512 + iChannel + 1
971 delete h_profile_full;
974 for (
int iLowerEdge = 0; iLowerEdge < (int)
m_binEdges.size() - 1; iLowerEdge++) {
982 TH1D* h_profile = h_hitTimeLaserHistos[iLowerEdge]->ProjectionY(
983 (
"profile_" + std::to_string(iSlot + 1) +
"_" + std::to_string(
984 iChannel) +
"_" + std::to_string(iLowerEdge)).c_str(),
985 iSlot * 512 + iChannel + 1, iSlot * 512 + iChannel + 1
989 h_profile->GetXaxis()->SetRangeUser(-10, -10);
991 h_profile->GetXaxis()->SetRangeUser(-65, -5);
995 fitChannel(iSlot, iChannel, h_profile,
true, ff);
1000 TH1D* h_amplitude = h_amplitude2D->ProjectionY(
1001 (
"AmpProfile_" + std::to_string(iSlot + 1) +
1002 "_" + std::to_string(iChannel) +
1003 "_" + std::to_string(iLowerEdge)).c_str(),
1004 iSlot * 512 + iChannel + 1, iSlot * 512 + iChannel + 1
1006 TH1D* h_width = h_width2D->ProjectionY(
1007 (
"WidthProfile_" + std::to_string(iSlot + 1) +
1008 "_" + std::to_string(iChannel) +
1009 "_" + std::to_string(iLowerEdge)).c_str(),
1010 iSlot * 512 + iChannel + 1, iSlot * 512 + iChannel + 1
1016 h_width->GetQuantiles(1, &
m_width, &q);
1021 h_amplitude->Write();
1037 std::cout <<
"Fitting channels with no crosstalk detected" << std::endl;
1038 for (
short iSlot = 0; iSlot < 16; iSlot++) {
1039 std::cout <<
" Fitting slot " << iSlot + 1 << std::endl;
1040 for (
short iChannel = 0; iChannel < 512; iChannel++) {
1042 TH1D* h_profile = h_hitTime_noXtalk->ProjectionY(
1043 (
"profile_" + std::to_string(iSlot + 1) +
"_" + std::to_string(iChannel)).c_str(),
1044 iSlot * 512 + iChannel + 1, iSlot * 512 + iChannel + 1
1050 h_profile->GetXaxis()->SetRangeUser(-65, -1);
1052 h_profile->GetXaxis()->SetRangeUser(-65, -5);
1059 TH1D* h_amplitude = h_amplitude2D_noXtalk->ProjectionY(
1060 (
"AmpProfile_" + std::to_string(iSlot + 1) +
"_" + std::to_string(iChannel)).c_str(),
1061 iSlot * 512 + iChannel + 1, iSlot * 512 + iChannel + 1
1063 TH1D* h_width = h_width2D_noXtalk->ProjectionY(
1064 (
"WidthProfile_" + std::to_string(iSlot + 1) +
"_" + std::to_string(iChannel)).c_str(),
1065 iSlot * 512 + iChannel + 1, iSlot * 512 + iChannel + 1
1071 h_width->GetQuantiles(1, &
m_width, &q);
1075 h_amplitude->Write();