363 m_treeTTS->GetEntry(iChannel + 512 * iSlot);
365 double maxpos = h_profile->GetBinCenter(h_profile->GetMaximumBin());
366 h_profile->GetXaxis()->SetRangeUser(maxpos - 1, maxpos + 2.);
369 double integral = h_profile->Integral();
372 TF1 laser = TF1(
"laser", laserPDF, maxpos - 1, maxpos + 2., 16);
375 laser.SetParameter(0, maxpos);
376 laser.SetParLimits(0, maxpos - 0.06, maxpos + 0.06);
379 laser.SetParameter(1, 0.1);
380 laser.SetParLimits(1, 0.05, 0.25);
382 laser.SetParameter(1, 0.02);
383 laser.SetParLimits(1, 0., 0.04);
388 laser.SetParLimits(2, 0.5, 1.);
390 laser.FixParameter(2, frac);
399 laser.SetParameter(3, -0.3);
400 laser.SetParLimits(3, -0.4, -0.2);
406 laser.FixParameter(5,
m_mean2);
408 laser.FixParameter(6,
m_f1);
410 laser.FixParameter(6, 0);
413 const double binw = h_profile->GetXaxis()->GetBinWidth(1);
414 laser.SetParameter(7, integral * binw);
415 laser.SetParLimits(7, 0.2 * integral * binw, 2.*integral * binw);
418 laser.SetParameter(8, 1.);
419 laser.SetParLimits(8, 0.3, 2.);
420 laser.SetParameter(9, 0.2);
421 laser.SetParLimits(9, 0.08, 1.);
422 laser.SetParameter(10, 0.1 * integral * binw);
423 laser.SetParLimits(10, 0., 0.2 * integral * binw);
425 laser.SetParameter(14, -2.);
426 laser.SetParameter(15, 2.);
427 laser.SetParLimits(15, 1.01, 20.);
430 laser.SetParameter(11, 1.);
431 laser.SetParLimits(11, 0.1, 5.);
432 laser.SetParameter(12, 0.8);
433 laser.SetParLimits(12, 0., 5.);
434 laser.SetParameter(13, 0.01 * integral * binw);
435 laser.SetParLimits(13, 0., 0.2 * integral * binw);
451 laser.SetParameter(2, 0.8);
452 laser.SetParLimits(2, 0., 1.);
453 laser.SetParameter(3, -0.1);
454 laser.SetParLimits(3, -0.4, -0.);
456 laser.FixParameter(8, 0);
457 laser.FixParameter(9, 0.1);
458 laser.FixParameter(14, -2.);
459 laser.FixParameter(15, 2);
460 laser.FixParameter(11, 1.);
461 laser.FixParameter(12, 0.1);
462 laser.FixParameter(13, 0.);
463 laser.FixParameter(10, 0.);
470 h_profile->Fit(
"laser",
"R L Q");
473 TF1* peak1 =
new TF1(
"peak1", laserPDF, maxpos - 1, maxpos + 2., 16);
474 TF1* peak2 =
new TF1(
"peak2", laserPDF, maxpos - 1, maxpos + 2., 16);
475 TF1* extra =
new TF1(
"extra", laserPDF, maxpos - 1, maxpos + 2., 16);
476 TF1* background =
new TF1(
"background", laserPDF, maxpos - 1, maxpos + 2., 16);
477 for (
int iPar = 0; iPar < 16; iPar++) {
478 peak1->FixParameter(iPar, laser.GetParameter(iPar));
479 peak2->FixParameter(iPar, laser.GetParameter(iPar));
480 extra->FixParameter(iPar, laser.GetParameter(iPar));
481 background->FixParameter(iPar, laser.GetParameter(iPar));
483 peak1->FixParameter(2, 0.);
484 peak1->FixParameter(7, (1 - laser.GetParameter(2))*laser.GetParameter(7));
485 peak1->FixParameter(10, 0.);
486 peak1->FixParameter(13, 0.);
487 peak2->FixParameter(2, 1.);
488 peak2->FixParameter(7, laser.GetParameter(2)*laser.GetParameter(7));
489 peak2->FixParameter(10, 0.);
490 peak2->FixParameter(13, 0.);
491 extra->FixParameter(7, 0.);
492 extra->FixParameter(13, 0.);
493 background->FixParameter(7, 0.);
494 background->FixParameter(10, 0.);
496 h_profile->GetListOfFunctions()->Add(peak1);
497 h_profile->GetListOfFunctions()->Add(peak2);
498 h_profile->GetListOfFunctions()->Add(extra);
499 h_profile->GetListOfFunctions()->Add(background);
510 m_sigma = laser.GetParameter(1);
524 m_chi2 = laser.GetChisquare() / laser.GetNDF();
650 float amplitude, width, hitTime;
653 hitTree->SetBranchAddress(
"event", &event);
654 hitTree->SetBranchAddress(
"amplitude", &litude);
655 hitTree->SetBranchAddress(
"width", &width);
656 hitTree->SetBranchAddress(
"hitTime", &hitTime);
657 hitTree->SetBranchAddress(
"channel", &channel);
660 hitTree->SetBranchAddress(
"slot", &slot);
661 hitTree->SetBranchAddress(
"refTimeValid", &refTimeValid);
664 TH2F* h_hitTime =
new TH2F(
"h_hitTime",
" ", 512 * 16, 0., 512 * 16, 22000, -70, 40.);
665 TH2F* h_amplitude2D =
new TH2F(
"h_amplitude",
" ", 512 * 16, 0., 512 * 16, 600, 0, 2200.);
666 TH2F* h_width2D =
new TH2F(
"h_width",
" ", 512 * 16, 0., 512 * 16, 1000, 0, 2.);
671 std::vector<TH2F*> h_hitTimeLaserHistos = {};
672 for (
int iLowerEdge = 0; iLowerEdge < (int)
m_binEdges.size() - 1; iLowerEdge++) {
673 TH2F* h_hitTimeLaser =
new TH2F((
"h_hitTimeLaser_" + std::to_string(iLowerEdge + 1)).c_str(),
" ",
674 512 * 16, 0., 512 * 16, 14000, -70, 0.);
675 h_hitTimeLaserHistos.push_back(h_hitTimeLaser);
687 std::vector<Hit> evtHits;
691 int prev_evt = std::numeric_limits<int>::min();
694 const float conv = 1.f / (0.3989f * 2.35f);
697 const float fracMin = 0.25f;
698 const float dtMax = 0.30f;
699 const float epsQ = 1e-6f;
703 TH2F* h_hitTime_noXtalk =
new TH2F(
"h_hitTime_noXtalk",
" ", 512 * 16, 0., 512 * 16, 22000, -70, 40.);
704 TH2F* h_amplitude2D_noXtalk =
new TH2F(
"h_amplitude2D_noXtalk",
" ", 512 * 16, 0., 512 * 16, 600, 0, 2200.);
705 TH2F* h_width2D_noXtalk =
new TH2F(
"h_width2D_noXtalk",
" ", 512 * 16, 0., 512 * 16, 1000, 0, 2.);
708 Long64_t nhits = hitTree->GetEntries();
709 const Long64_t step = std::max<Long64_t>(1, nhits / 100);
712 for (Long64_t i = 0; i < nhits; i++) {
716 std::cout <<
"Processing hit " << i <<
" of " << nhits <<
" ("
717 << std::setprecision(3) << (100. * i) / nhits <<
" %)" << std::endl;
721 hitTree->GetEntry(i);
726 int iLowerEdge = std::distance(
m_binEdges.cbegin(), it) - 1;
727 if (iLowerEdge >= 0 && iLowerEdge <
static_cast<int>(
m_binEdges.size()) - 1 && refTimeValid)
728 h_hitTimeLaserHistos[iLowerEdge]->Fill(channel + (slot - 1) * 512, hitTime);
732 if (amplitude > 80. && refTimeValid) {
735 h_hitTime->Fill(channel + (slot - 1) * 512, hitTime);
738 if ((hitTime > -65) && (hitTime < -10)) {
741 h_amplitude2D->Fill(channel + (slot - 1) * 512, amplitude);
742 h_width2D->Fill(channel + (slot - 1) * 512, width);
747 const int curr_evt = event;
750 if (curr_evt != prev_evt && !evtHits.empty()) {
753 std::vector<char> isXtalk(evtHits.size(), 0);
754 for (
size_t ii = 0; ii + 1 < evtHits.size(); ++ii) {
755 const auto& hi = evtHits[ii];
756 for (
size_t jj = ii + 1; jj < evtHits.size(); ++jj) {
757 const auto& hj = evtHits[jj];
760 if (hi.slot != hj.slot)
continue;
764 if (std::fabs(hi.t - hj.t) > dtMax)
continue;
767 const float qsum = hi.q + hj.q;
768 if (qsum <= epsQ)
continue;
769 const float f_q0 = hi.q / qsum;
771 if (f_q0 < fracMin || f_q0 > (1.f - fracMin)) {
791 for (
size_t kk = 0; kk < evtHits.size(); ++kk) {
792 if (isXtalk[kk])
continue;
793 const auto& h = evtHits[kk];
794 const int gch = h.ch + (h.slot - 1) * 512;
795 h_hitTime_noXtalk->Fill(gch, h.t);
796 h_amplitude2D_noXtalk->Fill(gch, h.a);
797 h_width2D_noXtalk->Fill(gch, h.w);
804 evtHits.push_back(
Hit{slot, channel, hitTime, amplitude, width, conv* amplitude * width});
815 std::vector<char> isXtalk(evtHits.size(), 0);
816 for (
size_t ll = 0; ll + 1 < evtHits.size(); ++ll) {
817 const auto& hi = evtHits[ll];
818 for (
size_t mm = ll + 1; mm < evtHits.size(); ++mm) {
819 const auto& hj = evtHits[mm];
820 if (hi.slot != hj.slot)
continue;
822 if (std::fabs(hi.t - hj.t) > dtMax)
continue;
823 const float qsum = hi.q + hj.q;
824 if (qsum <= epsQ)
continue;
825 const float f_q0 = hi.q / qsum;
826 if (f_q0 < fracMin || f_q0 > (1.f - fracMin)) {
842 for (
size_t nn = 0; nn < evtHits.size(); ++nn) {
843 if (isXtalk[nn])
continue;
844 const auto& h = evtHits[nn];
845 const int gch = h.ch + (h.slot - 1) * 512;
846 h_hitTime_noXtalk->Fill(gch, h.t);
847 h_amplitude2D_noXtalk->Fill(gch, h.a);
848 h_width2D_noXtalk->Fill(gch, h.w);
855 std::cout <<
"Writing crosstalkTree (candidate crosstalk channel pairs) to output file" << std::endl;
866 for (
short iSlot = 0; iSlot < 16; iSlot++) {
867 std::cout <<
"fitting slot " << iSlot + 1 << std::endl;
868 for (
short iChannel = 0; iChannel < 512; iChannel++) {
871 TH1D* h_profile = h_hitTime->ProjectionY(
872 (
"profile_" + std::to_string(iSlot + 1) +
"_" + std::to_string(iChannel)).c_str(),
873 iSlot * 512 + iChannel + 1, iSlot * 512 + iChannel + 1
879 h_profile->GetXaxis()->SetRangeUser(-65, -1);
881 h_profile->GetXaxis()->SetRangeUser(-65, -5);
888 TH1D* h_profileFirstPulser = h_hitTime->ProjectionY(
889 (
"profileFirstPulser_" + std::to_string(iSlot + 1) +
"_" + std::to_string(
890 iChannel)).c_str(), iSlot * 512 + iChannel + 1, iSlot * 512 + iChannel + 1
892 TH1D* h_profileSecondPulser = h_hitTime->ProjectionY(
893 (
"profileSecondPulser_" + std::to_string(iSlot + 1) +
"_" + std::to_string(
894 iChannel)).c_str(), iSlot * 512 + iChannel + 1, iSlot * 512 + iChannel + 1
896 h_profileFirstPulser->GetXaxis()->SetRangeUser(-10, 10);
897 h_profileSecondPulser->GetXaxis()->SetRangeUser(10, 40);
898 fitPulser(h_profileFirstPulser, h_profileSecondPulser);
902 TH1D* h_amplitude = h_amplitude2D->ProjectionY(
903 (
"AmpProfile_" + std::to_string(iSlot + 1) +
"_" + std::to_string(iChannel)).c_str(),
904 iSlot * 512 + iChannel + 1, iSlot * 512 + iChannel + 1
906 TH1D* h_width = h_width2D->ProjectionY(
907 (
"WidthProfile_" + std::to_string(iSlot + 1) +
"_" + std::to_string(iChannel)).c_str(),
908 iSlot * 512 + iChannel + 1, iSlot * 512 + iChannel + 1
914 h_width->GetQuantiles(1, &
m_width, &q);
918 h_profileFirstPulser->Write();
919 h_profileSecondPulser->Write();
920 h_amplitude->Write();
925 delete h_profileFirstPulser;
926 delete h_profileSecondPulser;
946 std::cout <<
"Fitting in bins of pulse heigth" << std::endl;
948 for (
short iSlot = 0; iSlot < 16; iSlot++) {
949 std::cout <<
" Fitting slot " << iSlot + 1 << std::endl;
950 for (
short iChannel = 0; iChannel < 512; iChannel++) {
954 TH1D* h_profile_full = h_hitTime->ProjectionY(
955 (
"profile_" + std::to_string(iSlot + 1) +
"_" + std::to_string(iChannel)).c_str(),
956 iSlot * 512 + iChannel + 1, iSlot * 512 + iChannel + 1
961 delete h_profile_full;
964 for (
int iLowerEdge = 0; iLowerEdge < (int)
m_binEdges.size() - 1; iLowerEdge++) {
972 TH1D* h_profile = h_hitTimeLaserHistos[iLowerEdge]->ProjectionY(
973 (
"profile_" + std::to_string(iSlot + 1) +
"_" + std::to_string(
974 iChannel) +
"_" + std::to_string(iLowerEdge)).c_str(),
975 iSlot * 512 + iChannel + 1, iSlot * 512 + iChannel + 1
979 h_profile->GetXaxis()->SetRangeUser(-10, -10);
981 h_profile->GetXaxis()->SetRangeUser(-65, -5);
985 fitChannel(iSlot, iChannel, h_profile,
true, ff);
990 TH1D* h_amplitude = h_amplitude2D->ProjectionY(
991 (
"AmpProfile_" + std::to_string(iSlot + 1) +
992 "_" + std::to_string(iChannel) +
993 "_" + std::to_string(iLowerEdge)).c_str(),
994 iSlot * 512 + iChannel + 1, iSlot * 512 + iChannel + 1
996 TH1D* h_width = h_width2D->ProjectionY(
997 (
"WidthProfile_" + std::to_string(iSlot + 1) +
998 "_" + std::to_string(iChannel) +
999 "_" + std::to_string(iLowerEdge)).c_str(),
1000 iSlot * 512 + iChannel + 1, iSlot * 512 + iChannel + 1
1006 h_width->GetQuantiles(1, &
m_width, &q);
1011 h_amplitude->Write();
1027 std::cout <<
"Fitting channels with no crosstalk detected" << std::endl;
1028 for (
short iSlot = 0; iSlot < 16; iSlot++) {
1029 std::cout <<
" Fitting slot " << iSlot + 1 << std::endl;
1030 for (
short iChannel = 0; iChannel < 512; iChannel++) {
1032 TH1D* h_profile = h_hitTime_noXtalk->ProjectionY(
1033 (
"profile_" + std::to_string(iSlot + 1) +
"_" + std::to_string(iChannel)).c_str(),
1034 iSlot * 512 + iChannel + 1, iSlot * 512 + iChannel + 1
1040 h_profile->GetXaxis()->SetRangeUser(-65, -1);
1042 h_profile->GetXaxis()->SetRangeUser(-65, -5);
1049 TH1D* h_amplitude = h_amplitude2D_noXtalk->ProjectionY(
1050 (
"AmpProfile_" + std::to_string(iSlot + 1) +
"_" + std::to_string(iChannel)).c_str(),
1051 iSlot * 512 + iChannel + 1, iSlot * 512 + iChannel + 1
1053 TH1D* h_width = h_width2D_noXtalk->ProjectionY(
1054 (
"WidthProfile_" + std::to_string(iSlot + 1) +
"_" + std::to_string(iChannel)).c_str(),
1055 iSlot * 512 + iChannel + 1, iSlot * 512 + iChannel + 1
1061 h_width->GetQuantiles(1, &
m_width, &q);
1065 h_amplitude->Write();