Back to home page

sPhenix code displayed by LXR

 
 

    


File indexing completed on 2025-08-06 08:17:42

0001 #include "INTTZvtx.h"
0002 
0003 #include <TCanvas.h>
0004 #include <TColor.h>
0005 #include <TF1.h>
0006 #include <TFile.h>
0007 #include <TGraphErrors.h>
0008 #include <TH1.h>
0009 #include <TH2.h>
0010 #include <TLatex.h>
0011 #include <TLine.h>
0012 #include <TTree.h>
0013 
0014 #include <boost/format.hpp>
0015 
0016 #include <algorithm>
0017 #include <filesystem>
0018 #include <iostream>
0019 #include <numeric>
0020 #include <string>
0021 #include <vector>
0022 
0023 INTTZvtx::INTTZvtx(const std::string& runType,
0024                    const std::string& outFolderDirectory,
0025                    std::pair<double, double> beamOrigin,
0026                    double phiDiffCut,
0027                    std::pair<double, double> DCACut,
0028                    int NCluCutl,
0029                    int NCluCut,
0030                    unsigned int zvtxCalRequire,
0031                    std::pair<double, double> zvtxQAWidth,
0032                    bool drawEventDisplay,
0033                    bool enableQA,
0034                    bool printMessageOpt)
0035   : run_type(runType)
0036   , out_folder_directory(outFolderDirectory)
0037   , beam_origin(beamOrigin)
0038   , phi_diff_cut(phiDiffCut)
0039   , DCA_cut(DCACut)
0040   , N_clu_cut(NCluCut)
0041   , N_clu_cutl(NCluCutl)
0042   , zvtx_cal_require(zvtxCalRequire)
0043   , zvtx_QA_width(zvtxQAWidth)
0044   , draw_event_display(drawEventDisplay)
0045   , m_enable_qa(enableQA)
0046   , print_message_opt(printMessageOpt)
0047 {
0048   // SetsPhenixStyle();
0049   gErrorIgnoreLevel = kWarning;  // note : To not print the "print plot info."
0050 
0051   temp_event_zvtx_info.clear();
0052   avg_event_zvtx_vec.clear();
0053   Z_resolution_vec.clear();
0054   good_comb_id = 0;
0055   MC_z_diff_peak = -777.;
0056   MC_z_diff_width = -777.;
0057 
0058   N_group_info_detail = {-1., -1., -1., -1.};
0059 
0060   N_comb.clear();
0061   N_comb_e.clear();
0062   z_mid.clear();
0063   z_range.clear();
0064   N_comb_phi.clear();
0065   // eff_N_comb.clear(); eff_z_mid.clear(); eff_N_comb_e.clear(); eff_z_range.clear(); // note : eff_sig
0066 
0067   inner_clu_phi_map.clear();
0068   outer_clu_phi_map.clear();
0069   inner_clu_phi_map = std::vector<std::vector<std::pair<bool, clu_info>>>(360);
0070   outer_clu_phi_map = std::vector<std::vector<std::pair<bool, clu_info>>>(360);
0071 
0072   ///////////
0073   // ntuple variables
0074   out_eID = 0;
0075   bco_full_out = 0;
0076   N_cluster_inner_out = -1;
0077   N_cluster_outer_out = -1;
0078   out_ES_zvtx = -1;
0079   out_ES_zvtxE = -1;
0080   out_ES_rangeL = -1;
0081   out_ES_rangeR = -1;
0082   out_ES_N_good = -1;
0083   out_ES_width_density = -1;
0084 
0085   out_LB_Gaus_Mean_mean = -1;
0086   out_LB_Gaus_Mean_meanE = -1;
0087   out_LB_Gaus_Mean_chi2 = -1;
0088   out_LB_Gaus_Mean_width = -1;
0089 
0090   out_LB_Gaus_Width_width = -1;
0091   out_LB_Gaus_Width_size_width = -1;
0092   out_LB_Gaus_Width_offset = -1;
0093 
0094   out_mid_cut_Ngroup = -1;
0095   out_mid_cut_peak_width = -1;
0096   out_mid_cut_peak_ratio = -1;
0097 
0098   out_LB_cut_Ngroup = -1;
0099   out_LB_cut_peak_width = -1;
0100   out_LB_cut_peak_ratio = -1;
0101 
0102   out_LB_geo_mean = -1;
0103   out_good_zvtx_tag = false;
0104 
0105   MC_true_zvtx = -9999.;
0106 
0107   out_centrality_bin = -1;
0108 
0109   out_N_cluster_north = 0;
0110   out_N_cluster_south = 0;
0111 
0112   ///////////
0113   //    Init();
0114 }
0115 
0116 INTTZvtx::~INTTZvtx()
0117 {
0118   // histos for z-vertex calculation
0119   if (evt_possible_z != nullptr)
0120   {
0121     delete evt_possible_z;
0122   }
0123   if (line_breakdown_hist != nullptr)
0124   {
0125     delete line_breakdown_hist;
0126   }
0127   if (gaus_fit != nullptr)
0128   {
0129     delete gaus_fit;
0130   }
0131   if (zvtx_finder != nullptr)
0132   {
0133     delete zvtx_finder;
0134   }
0135 
0136   if (z_range_gr != nullptr)
0137   {
0138     delete z_range_gr;
0139   }
0140 
0141   if (draw_event_display)
0142   {
0143     // QA histograms
0144     // event by event
0145     delete evt_select_track_phi;
0146     delete evt_phi_diff_1D;
0147     delete evt_phi_diff_inner_phi;
0148     delete evt_inner_outer_phi;
0149     delete phi_diff_inner_phi;
0150 
0151     delete c2;
0152     // all the pads related to c2 are automatically deleted
0153     if (temp_event_xy != nullptr)
0154     {
0155       delete temp_event_xy;
0156     }
0157     if (temp_event_rz != nullptr)
0158     {
0159       delete temp_event_rz;
0160     }
0161     if (z_range_gr_draw != nullptr)
0162     {
0163       delete z_range_gr_draw;
0164     }
0165   }
0166 
0167   if (m_enable_qa)
0168   {
0169     delete c1;
0170 
0171     std::cout << "del : " << std::hex << (long) avg_event_zvtx << std::dec << std::endl;
0172     for (auto& itr : m_v_qahist)
0173     {
0174       // std::cout<<"del : "<<itr->GetTitle()<<std::endl;
0175       delete itr;
0176     }
0177   }
0178 
0179   if (draw_event_display)
0180   {
0181     delete final_fit_range_line;
0182     delete coord_line;
0183     delete ladder_line;
0184     delete bkg;
0185   }
0186 
0187   if (draw_event_display || m_enable_qa)
0188   {
0189     delete eff_sig_range_line;
0190     delete draw_text;
0191   }
0192 }
0193 
0194 void INTTZvtx::Characterize_Pad(TPad* pad, float left, float right, float top, float bottom, bool set_logY, int setgrid_bool)
0195 {
0196   if (setgrid_bool == true)
0197   {
0198     pad->SetGrid(1, 1);
0199   }
0200   pad->SetLeftMargin(left);
0201   pad->SetRightMargin(right);
0202   pad->SetTopMargin(top);
0203   pad->SetBottomMargin(bottom);
0204   pad->SetTicks(1, 1);
0205   if (set_logY == true)
0206   {
0207     pad->SetLogy(1);
0208   }
0209 }
0210 
0211 void INTTZvtx::Init()
0212 {
0213   if (!std::filesystem::exists(out_folder_directory))
0214   {
0215     std::filesystem::create_directory(out_folder_directory);
0216   }
0217 
0218   InitCanvas();
0219   InitHist();
0220   InitTreeOut();
0221   InitRest();
0222 
0223   if (draw_event_display)
0224   {
0225     c2->Print((boost::format("%s/temp_event_display.pdf") % out_folder_directory).str().c_str());
0226   }
0227 
0228   m_initialized = true;
0229 }
0230 
0231 void INTTZvtx::InitHist()
0232 {
0233   // histos for z-vertex calculation
0234   evt_possible_z = new TH1F("evt_possible_z", "evt_possible_z", 50, evt_possible_z_range.first, evt_possible_z_range.second);
0235   evt_possible_z->SetLineWidth(1);
0236   evt_possible_z->GetXaxis()->SetTitle("Z [mm]");
0237   evt_possible_z->GetYaxis()->SetTitle("Entry");
0238 
0239   int N = 1200;        // note : N bins for each side, regardless the bin at zero
0240   double width = 0.5;  // note : bin width with the unit [mm]
0241   line_breakdown_hist = new TH1F("line_breakdown_hist", "line_breakdown_hist", 2 * N + 1, -1 * (width * N + width / 2.), width * N + width / 2.);
0242   line_breakdown_hist->SetLineWidth(1);
0243   line_breakdown_hist->GetXaxis()->SetTitle("Z [mm]");
0244   line_breakdown_hist->GetYaxis()->SetTitle("Entry");
0245   if (print_message_opt == true)
0246   {
0247     std::cout << "class INTTZvtx, Line breakdown hist, range : "
0248               << line_breakdown_hist->GetXaxis()->GetXmin() << " "
0249               << line_breakdown_hist->GetXaxis()->GetXmax() << " "
0250               << line_breakdown_hist->GetBinWidth(1) << std::endl;
0251   }
0252 
0253   // QA histograms
0254   // event by event
0255   if (draw_event_display)
0256   {
0257     evt_select_track_phi = new TH1F("evt_select_track_phi", "evt_select_track_phi", 361, 0, 361);
0258     evt_select_track_phi->GetXaxis()->SetTitle("Track phi [degree]");
0259     evt_select_track_phi->GetYaxis()->SetTitle("Entry");
0260     evt_select_track_phi->GetXaxis()->SetNdivisions(505);
0261 
0262     evt_phi_diff_inner_phi = new TH2F("evt_phi_diff_inner_phi", "evt_phi_diff_inner_phi", 361, 0, 361, 100, -1.5, 1.5);
0263     evt_phi_diff_inner_phi->GetXaxis()->SetTitle("Inner phi [degree]");
0264     evt_phi_diff_inner_phi->GetYaxis()->SetTitle("Inner - Outer [degree]");
0265     evt_phi_diff_inner_phi->GetXaxis()->SetNdivisions(505);
0266 
0267     evt_inner_outer_phi = new TH2F("evt_inner_outer_phi", "evt_inner_outer_phi", 120, 0, 360, 120, 0, 360);
0268     evt_inner_outer_phi->GetXaxis()->SetTitle("Inner phi [degree]");
0269     evt_inner_outer_phi->GetYaxis()->SetTitle("Outer phi [degree]");
0270     evt_inner_outer_phi->GetXaxis()->SetNdivisions(505);
0271 
0272     evt_phi_diff_1D = new TH1F("evt_phi_diff_1D", "evt_phi_diff_1D", 100, -10, 10);
0273     evt_phi_diff_1D->GetXaxis()->SetTitle("Inner - Outer [degree]");
0274     evt_phi_diff_1D->GetYaxis()->SetTitle("Entry");
0275     evt_phi_diff_1D->GetXaxis()->SetNdivisions(505);
0276 
0277     phi_diff_inner_phi = new TH2F("phi_diff_inner_phi", "All evt phi_diff_inner_phi", 361, 0, 361, 100, -1.5, 1.5);
0278     phi_diff_inner_phi->GetXaxis()->SetTitle("Inner phi [degree]");
0279     phi_diff_inner_phi->GetYaxis()->SetTitle("Inner - Outer [degree]");
0280     phi_diff_inner_phi->GetXaxis()->SetNdivisions(505);
0281   }
0282 
0283   if (m_enable_qa)
0284   {
0285     // whole run
0286     avg_event_zvtx = new TH1F("avg_event_zvtx", "avg_event_zvtx", 100, zvtx_hist_l, zvtx_hist_r);
0287     avg_event_zvtx->SetLineColor(TColor::GetColor("#1A3947"));
0288     avg_event_zvtx->SetLineWidth(2);
0289     avg_event_zvtx->GetYaxis()->SetTitle("Entry");
0290     avg_event_zvtx->GetXaxis()->SetTitle("Z vertex position [mm]");
0291     avg_event_zvtx->GetYaxis()->SetRangeUser(0, 50);
0292     avg_event_zvtx->SetTitleSize(0.06, "X");
0293     avg_event_zvtx->SetTitleSize(0.06, "Y");
0294     avg_event_zvtx->GetXaxis()->SetTitleOffset(0.82);
0295     avg_event_zvtx->GetYaxis()->SetTitleOffset(1.1);
0296     avg_event_zvtx->GetXaxis()->CenterTitle(true);
0297     avg_event_zvtx->GetYaxis()->CenterTitle(true);
0298     avg_event_zvtx->GetXaxis()->SetNdivisions(505);
0299     m_v_qahist.push_back(avg_event_zvtx);
0300 
0301     zvtx_evt_fitError = new TH1F("zvtx_evt_fitError", "zvtx_evt_fitError", 150, 0, 50);
0302     zvtx_evt_fitError->GetXaxis()->SetTitle(" mm ");
0303     zvtx_evt_fitError->GetYaxis()->SetTitle("entry");
0304     zvtx_evt_fitError->GetXaxis()->SetNdivisions(505);
0305     m_v_qahist.push_back(zvtx_evt_fitError);
0306 
0307     zvtx_evt_fitError_corre = new TH2F("zvtx_evt_fitError_corre", "zvtx_evt_fitError_corre", 200, 0, 10000, 200, 0, 20);
0308     zvtx_evt_fitError_corre->GetXaxis()->SetTitle(" # of clusters ");
0309     zvtx_evt_fitError_corre->GetYaxis()->SetTitle(" #pm mm ");
0310     zvtx_evt_fitError_corre->GetXaxis()->SetNdivisions(505);
0311     m_v_qahist.push_back(zvtx_evt_fitError_corre);
0312 
0313     zvtx_evt_width_corre = new TH2F("zvtx_evt_width_corre", "zvtx_evt_width_corre", 200, 0, 10000, 200, 0, 300);
0314     zvtx_evt_width_corre->GetXaxis()->SetTitle(" # of clusters ");
0315     zvtx_evt_width_corre->GetYaxis()->SetTitle(" mm ");
0316     zvtx_evt_width_corre->GetXaxis()->SetNdivisions(505);
0317     m_v_qahist.push_back(zvtx_evt_width_corre);
0318 
0319     zvtx_evt_nclu_corre = new TH2F("zvtx_evt_nclu_corre", "zvtx_evt_nclu_corre", 200, 0, 10000, 200, -1000, 1000);
0320     zvtx_evt_nclu_corre->GetXaxis()->SetTitle(" # of clusters ");
0321     zvtx_evt_nclu_corre->GetYaxis()->SetTitle(" zvtx [mm] ");
0322     zvtx_evt_nclu_corre->GetXaxis()->SetNdivisions(505);
0323     m_v_qahist.push_back(zvtx_evt_nclu_corre);
0324 
0325     width_density = new TH1F("width_density", "width_density", 200, 0, 0.006);  // note : N good hits / width
0326     width_density->GetXaxis()->SetTitle(" (N good track / width) / NClus ");
0327     width_density->GetYaxis()->SetTitle(" Entry ");
0328     width_density->GetXaxis()->SetNdivisions(505);
0329     m_v_qahist.push_back(width_density);
0330 
0331     ES_width = new TH1F("ES_width", "ES_width", 200, 0, 150);
0332     ES_width->GetXaxis()->SetTitle(" Width [mm] ");
0333     ES_width->GetYaxis()->SetTitle(" Entry ");
0334     ES_width->GetXaxis()->SetNdivisions(505);
0335     m_v_qahist.push_back(ES_width);
0336 
0337     ES_width_ratio = new TH1F("ES_width_ratio", "ES_width_ratio", 200, 0, 60);
0338     ES_width_ratio->GetXaxis()->SetTitle(" NClus / Width ");
0339     ES_width_ratio->GetYaxis()->SetTitle(" Entry ");
0340     ES_width_ratio->GetXaxis()->SetNdivisions(505);
0341     m_v_qahist.push_back(ES_width_ratio);
0342 
0343     Z_resolution_Nclu = new TH2F("Z_resolution_Nclu", "Z_resolution_Nclu", 200, 0, 10000, 200, -100, 100);
0344     Z_resolution_Nclu->GetXaxis()->SetTitle(" # of clusters ");
0345     Z_resolution_Nclu->GetYaxis()->SetTitle("#Delta Z (Reco - True) [mm]");
0346     Z_resolution_Nclu->GetXaxis()->SetNdivisions(505);
0347     m_v_qahist.push_back(Z_resolution_Nclu);
0348 
0349     Z_resolution_pos = new TH2F("Z_resolution_pos", "Z_resolution_pos", 200, -350, 350, 200, -50, 50);
0350     Z_resolution_pos->GetXaxis()->SetTitle("True Zvtx [mm]");
0351     Z_resolution_pos->GetYaxis()->SetTitle("#Delta Z (Reco - True) [mm]");
0352     Z_resolution_pos->GetXaxis()->SetNdivisions(505);
0353     m_v_qahist.push_back(Z_resolution_pos);
0354 
0355     Z_resolution_pos_cut = new TH2F("Z_resolution_pos_cut", "Z_resolution_pos_cut", 200, -350, 350, 200, -50, 50);
0356     Z_resolution_pos_cut->GetXaxis()->SetTitle("True Zvtx [mm]");
0357     Z_resolution_pos_cut->GetYaxis()->SetTitle("#Delta Z (Reco - True) [mm]");
0358     Z_resolution_pos_cut->GetXaxis()->SetNdivisions(505);
0359     m_v_qahist.push_back(Z_resolution_pos_cut);
0360 
0361     Z_resolution = new TH1F("Z_resolution", "Z_resolution", 200, -30, 30);
0362     Z_resolution->GetXaxis()->SetTitle("#Delta Z (Reco - True) [mm]");
0363     Z_resolution->GetYaxis()->SetTitle(" Entry ");
0364     Z_resolution->GetXaxis()->SetNdivisions(505);
0365     m_v_qahist.push_back(Z_resolution);
0366 
0367     line_breakdown_gaus_ratio_hist = new TH1F("line_breakdown_gaus_ratio_hist", "line_breakdown_gaus_ratio_hist", 200, 0, 0.0005);
0368     line_breakdown_gaus_ratio_hist->GetXaxis()->SetTitle("(Norm. size) / width");
0369     line_breakdown_gaus_ratio_hist->GetYaxis()->SetTitle(" Entry ");
0370     line_breakdown_gaus_ratio_hist->GetXaxis()->SetNdivisions(505);
0371     m_v_qahist.push_back(line_breakdown_gaus_ratio_hist);
0372 
0373     line_breakdown_gaus_width_hist = new TH1F("line_breakdown_gaus_width_hist", "line_breakdown_gaus_width_hist", 200, 0, 100);
0374     line_breakdown_gaus_width_hist->GetXaxis()->SetTitle("Width [mm]");
0375     line_breakdown_gaus_width_hist->GetYaxis()->SetTitle(" Entry ");
0376     line_breakdown_gaus_width_hist->GetXaxis()->SetNdivisions(505);
0377     m_v_qahist.push_back(line_breakdown_gaus_width_hist);
0378 
0379     gaus_width_Nclu = new TH2F("gaus_width_Nclu", "gaus_width_Nclu", 200, 0, 10000, 200, 0, 100);
0380     gaus_width_Nclu->GetXaxis()->SetTitle(" # of clusters ");
0381     gaus_width_Nclu->GetYaxis()->SetTitle("Gaus fit width [mm]");
0382     gaus_width_Nclu->GetXaxis()->SetNdivisions(505);
0383     m_v_qahist.push_back(gaus_width_Nclu);
0384 
0385     gaus_rchi2_Nclu = new TH2F("gaus_rchi2_Nclu", "gaus_rchi2_Nclu", 200, 0, 10000, 200, 0, 1);
0386     gaus_rchi2_Nclu->GetXaxis()->SetTitle(" # of clusters ");
0387     gaus_rchi2_Nclu->GetYaxis()->SetTitle("Gaus fit #chi2^{2}/NDF");
0388     gaus_rchi2_Nclu->GetXaxis()->SetNdivisions(505);
0389     m_v_qahist.push_back(gaus_rchi2_Nclu);
0390 
0391     final_fit_width = new TH2F("final_fit_width", "final_fit_width", 200, 0, 10000, 200, 0, 400);
0392     final_fit_width->GetXaxis()->SetTitle(" # of clusters ");
0393     final_fit_width->GetYaxis()->SetTitle("Fit width [mm]");
0394     final_fit_width->GetXaxis()->SetNdivisions(505);
0395     m_v_qahist.push_back(final_fit_width);
0396 
0397     N_track_candidate_Nclu = new TH2F("N_track_candidate_Nclu", "N_track_candidate_Nclu", 200, 0, 10000, 200, 0, 13000);
0398     N_track_candidate_Nclu->GetXaxis()->SetTitle(" # of clusters ");
0399     N_track_candidate_Nclu->GetYaxis()->SetTitle("N tracklet candidates");
0400     N_track_candidate_Nclu->GetXaxis()->SetNdivisions(505);
0401     m_v_qahist.push_back(N_track_candidate_Nclu);
0402 
0403     peak_group_width_hist = new TH1F("peak_group_width_hist", "peak_group_width_hist", 100, 0, 300);
0404     peak_group_width_hist->GetXaxis()->SetTitle("Width [mm]");
0405     peak_group_width_hist->GetYaxis()->SetTitle("Entry");
0406     peak_group_width_hist->GetXaxis()->SetNdivisions(505);
0407     m_v_qahist.push_back(peak_group_width_hist);
0408 
0409     peak_group_ratio_hist = new TH1F("peak_group_ratio_hist", "peak_group_ratio_hist", 110, 0, 1.1);
0410     peak_group_ratio_hist->GetXaxis()->SetTitle("Peak group ratio");
0411     peak_group_ratio_hist->GetYaxis()->SetTitle("Entry");
0412     peak_group_ratio_hist->GetXaxis()->SetNdivisions(505);
0413     m_v_qahist.push_back(peak_group_ratio_hist);
0414 
0415     N_group_hist = new TH1F("N_group_hist", "N_group_hist", 30, 0, 30);
0416     N_group_hist->GetXaxis()->SetTitle("N group post cut");
0417     N_group_hist->GetYaxis()->SetTitle("Entry");
0418     N_group_hist->GetXaxis()->SetNdivisions(505);
0419     m_v_qahist.push_back(N_group_hist);
0420 
0421     peak_group_detail_width_hist = new TH1F("peak_group_detail_width_hist", "peak_group_detail_width_hist", 200, 0, 300);
0422     peak_group_detail_width_hist->GetXaxis()->SetTitle("Width [mm]");
0423     peak_group_detail_width_hist->GetYaxis()->SetTitle("Entry");
0424     peak_group_detail_width_hist->GetXaxis()->SetNdivisions(505);
0425     m_v_qahist.push_back(peak_group_detail_width_hist);
0426 
0427     peak_group_detail_ratio_hist = new TH1F("peak_group_detail_ratio_hist", "peak_group_detail_ratio_hist", 110, 0, 1.1);
0428     peak_group_detail_ratio_hist->GetXaxis()->SetTitle("Peak group ratio");
0429     peak_group_detail_ratio_hist->GetYaxis()->SetTitle("Entry");
0430     peak_group_detail_ratio_hist->GetXaxis()->SetNdivisions(505);
0431     m_v_qahist.push_back(peak_group_detail_ratio_hist);
0432 
0433     N_group_detail_hist = new TH1F("N_group_detail_hist", "N_group_detail_hist", 30, 0, 30);
0434     N_group_detail_hist->GetXaxis()->SetTitle("N group post cut");
0435     N_group_detail_hist->GetYaxis()->SetTitle("Entry");
0436     N_group_detail_hist->GetXaxis()->SetNdivisions(505);
0437     m_v_qahist.push_back(N_group_detail_hist);
0438 
0439     dca_inner_phi = new TH2F("dca_inner_phi", "All dca_inner_phi", 90, 0, 360, 100, -10., 10);
0440     dca_inner_phi->GetXaxis()->SetTitle("Inner phi [degree]");
0441     dca_inner_phi->GetYaxis()->SetTitle("dca [mm]");
0442     // dca_inner_phi -> GetXaxis() -> SetNdivisions(505);
0443     m_v_qahist.push_back(dca_inner_phi);
0444   }
0445 }
0446 
0447 void INTTZvtx::InitCanvas()
0448 {
0449   if (draw_event_display)
0450   {
0451     c2 = new TCanvas("", "", 4000, 1600);
0452     c2->cd();
0453     pad_xy = new TPad("pad_xy", "", 0.0, 0.5, 0.2, 1.0);
0454     Characterize_Pad(pad_xy, 0.15, 0.1, 0.1, 0.2, false, 0);
0455     pad_xy->Draw();
0456 
0457     pad_rz = new TPad("pad_rz", "", 0.2, 0.5, 0.40, 1.0);
0458     Characterize_Pad(pad_rz, 0.15, 0.1, 0.1, 0.2, false, 0);
0459     pad_rz->Draw();
0460 
0461     pad_z = new TPad("pad_z", "", 0.40, 0.5, 0.6, 1.0);
0462     Characterize_Pad(pad_z, 0.15, 0.1, 0.1, 0.2, false, 0);
0463     pad_z->Draw();
0464 
0465     pad_z_hist = new TPad("pad_z_hist", "", 0.6, 0.5, 0.8, 1.0);
0466     Characterize_Pad(pad_z_hist, 0.15, 0.1, 0.1, 0.2, false, 0);
0467     pad_z_hist->Draw();
0468 
0469     pad_z_line = new TPad("pad_z_line", "", 0.8, 0.5, 1, 1.0);
0470     Characterize_Pad(pad_z_line, 0.15, 0.1, 0.1, 0.2, false, 0);
0471     pad_z_line->Draw();
0472 
0473     pad_phi_diff = new TPad("pad_phi_diff", "", 0.0, 0.0, 0.2, 0.5);
0474     Characterize_Pad(pad_phi_diff, 0.15, 0.1, 0.1, 0.2, false, 0);
0475     pad_phi_diff->Draw();
0476 
0477     pad_track_phi = new TPad("pad_track_phi", "", 0.2, 0.0, 0.40, 0.5);
0478     Characterize_Pad(pad_track_phi, 0.15, 0.1, 0.1, 0.2, false, 0);
0479     pad_track_phi->Draw();
0480 
0481     pad_inner_outer_phi = new TPad("pad_inner_outer_phi", "", 0.4, 0.0, 0.60, 0.5);
0482     Characterize_Pad(pad_inner_outer_phi, 0.15, 0.1, 0.1, 0.2, false, 0);
0483     pad_inner_outer_phi->SetLogz(1);
0484     pad_inner_outer_phi->Draw();
0485 
0486     pad_phi_diff_1D = new TPad("pad_phi_diff_1D", "", 0.6, 0.0, 0.80, 0.5);
0487     Characterize_Pad(pad_phi_diff_1D, 0.15, 0.1, 0.1, 0.2, false, 0);
0488     // pad_phi_diff_1D -> SetLogz(1);
0489     pad_phi_diff_1D->Draw();
0490   }
0491 
0492   if (m_enable_qa)
0493   {
0494     c1 = new TCanvas("", "", 950, 800);
0495     c1->cd();
0496   }
0497 }
0498 
0499 void INTTZvtx::InitTreeOut()
0500 {
0501   if (m_enable_qa)
0502   {
0503     out_file = new TFile((boost::format("%s/INTT_zvtx.root") % out_folder_directory).str().c_str(), "RECREATE");
0504     tree_out = new TTree("tree_Z", "INTT Z info.");
0505 
0506     tree_out->Branch("eID", &out_eID);
0507     tree_out->Branch("bco_full", &bco_full_out);
0508     tree_out->Branch("nclu_inner", &N_cluster_inner_out);
0509     tree_out->Branch("nclu_outer", &N_cluster_outer_out);
0510     tree_out->Branch("nclu_south", &out_N_cluster_south);
0511     tree_out->Branch("nclu_north", &out_N_cluster_north);
0512     tree_out->Branch("ES_zvtx", &out_ES_zvtx);                                    // note : effective sigma, pol0 fit z-vertex
0513     tree_out->Branch("ES_zvtxE", &out_ES_zvtxE);                                  // note : effective sigma, pol0 fit z-vertex error
0514     tree_out->Branch("ES_rangeL", &out_ES_rangeL);                                // note : effective sigma, selected range left
0515     tree_out->Branch("ES_rangeR", &out_ES_rangeR);                                // note : effective sigma, selected range right
0516     tree_out->Branch("ES_N_good", &out_ES_N_good);                                // note : effective sigma, number of z-vertex candidates in the range
0517     tree_out->Branch("ES_Width_density", &out_ES_width_density);                  // note : effective sigma, N good z-vertex candidates divided by width
0518     tree_out->Branch("LB_Gaus_Mean_mean", &out_LB_Gaus_Mean_mean);                // note : Line break loose offset - gaus mean
0519     tree_out->Branch("LB_Gaus_Mean_meanE", &out_LB_Gaus_Mean_meanE);              // note : Line break loose offset - gaus mean error
0520     tree_out->Branch("LB_Gaus_Mean_chi2", &out_LB_Gaus_Mean_chi2);                // note : Line break loose offset - reduce chi2
0521     tree_out->Branch("LB_Gaus_Mean_width", &out_LB_Gaus_Mean_width);              // note : Line break loose offset - width
0522     tree_out->Branch("LB_Gaus_Width_width", &out_LB_Gaus_Width_width);            // note : Line break tight offset - gaus width
0523     tree_out->Branch("LB_Gaus_Width_offset", &out_LB_Gaus_Width_offset);          // note : Line break tight offset - offset
0524     tree_out->Branch("LB_Gaus_Width_size_width", &out_LB_Gaus_Width_size_width);  // note : Line break tight offset - norm. height / width
0525     tree_out->Branch("LB_geo_mean", &out_LB_geo_mean);                            // note : Line break peak position directly from the distribution (with the bin width 0.5 mm)
0526     tree_out->Branch("good_zvtx_tag", &out_good_zvtx_tag);
0527     tree_out->Branch("mid_cut_Ngroup", &out_mid_cut_Ngroup);          // note : mid cut Ngroup
0528     tree_out->Branch("mid_cut_peak_width", &out_mid_cut_peak_width);  // note : mid cut peak width
0529     tree_out->Branch("mid_cut_peak_ratio", &out_mid_cut_peak_ratio);  // note : mid cut peak ratio
0530     tree_out->Branch("LB_cut_Ngroup", &out_LB_cut_Ngroup);            // note : LB cut Ngroup
0531     tree_out->Branch("LB_cut_peak_width", &out_LB_cut_peak_width);    // note : LB cut peak width
0532     tree_out->Branch("LB_cut_peak_ratio", &out_LB_cut_peak_ratio);    // note : LB cut peak ratio
0533     tree_out->Branch("MC_true_zvtx", &MC_true_zvtx);
0534     tree_out->Branch("Centrality_bin", &out_centrality_bin);
0535   }
0536 }
0537 
0538 void INTTZvtx::InitRest()
0539 {
0540   gaus_fit = new TF1("gaus_fit", InttVertexUtil::gaus_func, evt_possible_z_range.first, evt_possible_z_range.second, 4);
0541   gaus_fit->SetLineColor(2);
0542   gaus_fit->SetLineWidth(1);
0543   gaus_fit->SetNpx(1000);
0544 
0545   zvtx_finder = new TF1("zvtx_finder", "pol0", -1, 20000);
0546   zvtx_finder->SetLineColor(2);
0547   zvtx_finder->SetLineWidth(1);
0548 
0549   if (draw_event_display)
0550   {
0551     final_fit_range_line = new TLine();
0552 
0553     coord_line = new TLine();
0554 
0555     ladder_line = new TLine();
0556 
0557     bkg = new TGraph(2);
0558   }
0559 
0560   if (draw_event_display || m_enable_qa)
0561   {
0562     eff_sig_range_line = new TLine();
0563     eff_sig_range_line->SetLineWidth(2);
0564     eff_sig_range_line->SetLineColor(TColor::GetColor("#A08144"));
0565     eff_sig_range_line->SetLineStyle(2);
0566 
0567     draw_text = new TLatex();
0568     draw_text->SetNDC();
0569     draw_text->SetTextSize(0.03);
0570   }
0571 }
0572 
0573 bool INTTZvtx::ProcessEvt(
0574     int event_i,
0575     std::vector<clu_info>& temp_sPH_inner_nocolumn_vec,
0576     std::vector<clu_info>& temp_sPH_outer_nocolumn_vec,
0577     std::vector<std::vector<double>>& temp_sPH_nocolumn_vec,
0578     std::vector<std::vector<double>>& temp_sPH_nocolumn_rz_vec,
0579     int NvtxMC,
0580     double TrigZvtxMC,
0581     bool PhiCheckTag,
0582     uint64_t bco_full,
0583     int centrality_bin)
0584 {
0585   if (!m_initialized)
0586   {
0587     std::cout << "INTTZvtx is not initialized" << std::endl;
0588     exit(1);
0589   }
0590 
0591   ////////////////////////////////////////
0592   // initialize tree variables
0593   out_eID = event_i;
0594   bco_full_out = bco_full;
0595   N_cluster_inner_out = -1;
0596   N_cluster_outer_out = -1;
0597 
0598   out_ES_zvtx = -1;
0599   out_ES_zvtxE = -1;
0600   out_ES_rangeL = -1;
0601   out_ES_rangeR = -1;
0602   out_ES_N_good = -1;
0603   out_ES_width_density = -1;
0604 
0605   out_LB_Gaus_Mean_mean = -1;
0606   out_LB_Gaus_Mean_meanE = -1;
0607   out_LB_Gaus_Mean_chi2 = -1;
0608   out_LB_Gaus_Mean_width = -1;
0609 
0610   out_LB_Gaus_Width_width = -1;
0611   out_LB_Gaus_Width_size_width = -1;
0612   out_LB_Gaus_Width_offset = -1;
0613 
0614   out_mid_cut_Ngroup = -1;
0615   out_mid_cut_peak_width = -1;
0616   out_mid_cut_peak_ratio = -1;
0617 
0618   out_LB_cut_Ngroup = -1;
0619   out_LB_cut_peak_width = -1;
0620   out_LB_cut_peak_ratio = -1;
0621 
0622   out_LB_geo_mean = -1;
0623   out_good_zvtx_tag = false;
0624 
0625   MC_true_zvtx = TrigZvtxMC * 10.;
0626 
0627   out_centrality_bin = -1;
0628 
0629   out_N_cluster_north = 0;
0630   out_N_cluster_south = 0;
0631 
0632   m_zvtxinfo.clear();
0633 
0634   good_zvtx_tag = false;
0635   good_zvtx_tag_int = 0;
0636 
0637   loose_offset_peak = -9999;   // note : unit [mm]
0638   loose_offset_peakE = -9999;  // note : unit [mm]
0639 
0640   if (event_i % 1000 == 0 && print_message_opt == true)
0641   {
0642     std::cout << "In INTTZvtx class, running event : " << event_i << std::endl;
0643   }
0644 
0645   long total_NClus = temp_sPH_inner_nocolumn_vec.size() + temp_sPH_outer_nocolumn_vec.size();
0646 
0647   if (total_NClus < zvtx_cal_require)
0648   {
0649     if (m_enable_qa)
0650     {
0651       tree_out->Fill();
0652     }
0653     std::cout << "In INTTZvtx class, event : " << event_i << " return confirmation ntotal:" << total_NClus << std::endl;
0654     return false;
0655   }
0656 
0657   if (run_type == "MC" && NvtxMC != 1)
0658   {
0659     if (m_enable_qa)
0660     {
0661       tree_out->Fill();
0662     }
0663     std::cout << "In INTTZvtx class, event : " << event_i << " return Nvtx : " << NvtxMC << " Nvtx more than one " << std::endl;
0664     return false;
0665   }
0666   if (PhiCheckTag == false)
0667   {
0668     if (m_enable_qa)
0669     {
0670       tree_out->Fill();
0671     }
0672     std::cout << "In INTTZvtx class, event : " << event_i << " return Nvtx : " << NvtxMC << " Not full phi has hits " << std::endl;
0673     return false;
0674   }
0675 
0676   //--if (   temp_sPH_inner_nocolumn_vec.size() < 10
0677   //--    || temp_sPH_outer_nocolumn_vec.size() < 10
0678   //--    || total_NClus > N_clu_cut
0679   //--    || total_NClus < N_clu_cutl)
0680   if (temp_sPH_inner_nocolumn_vec.size() < 2     // originally 5
0681       || temp_sPH_outer_nocolumn_vec.size() < 2  // originally 5
0682       || total_NClus > N_clu_cut || total_NClus < N_clu_cutl)
0683   {
0684     if (m_enable_qa)
0685     {
0686       tree_out->Fill();
0687     }
0688     std::cout << (boost::format("In INTTZvtx class, event : %i, return low clu continue, NClus : %ld %lu %lu\n") % event_i % total_NClus % temp_sPH_inner_nocolumn_vec.size() % temp_sPH_outer_nocolumn_vec.size()).str();
0689     return false;
0690   }
0691 
0692   //--std::cout<<"--1--"<<std::endl;
0693   //-----------------
0694   // cluster pair
0695   // note : put the cluster into the phi map, the first bool is for the cluster usage.
0696   // note : false means the cluster is not used
0697   double Clus_InnerPhi_Offset = 0;  // note : the vertex in XY is not at zero, so the "offset" moves the offset back to the orign which is (0,0)
0698   double Clus_OuterPhi_Offset = 0;  // note : the vertex in XY is not at zero, so the "offset" moves the offset back to the orign which is (0,0)
0699   for (auto& inner_i : temp_sPH_inner_nocolumn_vec)
0700   {
0701     Clus_InnerPhi_Offset = (inner_i.y - beam_origin.second < 0)
0702                                ? atan2(inner_i.y - beam_origin.second,
0703                                        inner_i.x - beam_origin.first) *
0704                                          (180. / TMath::Pi()) +
0705                                      360
0706                                : atan2(inner_i.y - beam_origin.second,
0707                                        inner_i.x - beam_origin.first) *
0708                                      (180. / TMath::Pi());
0709 
0710     // std::cout<<"inner clu phi : "<<Clus_InnerPhi_Offset<<" origin: "<< temp_sPH_inner_nocolumn_vec[inner_i].phi <<std::endl;
0711     // std::cout<<" ("<<Clus_InnerPhi_Offset<<", "<< temp_sPH_inner_nocolumn_vec[inner_i].phi<<")" <<std::endl;
0712     //
0713     inner_clu_phi_map[int(Clus_InnerPhi_Offset)].push_back({false, inner_i});
0714 
0715     if (inner_i.z > 0)
0716     {
0717       out_N_cluster_north += 1;
0718     }
0719     else
0720     {
0721       out_N_cluster_south += 1;
0722     }
0723   }
0724   //--std::cout<<"--2--"<<std::endl;
0725   for (auto& outer_i : temp_sPH_outer_nocolumn_vec)
0726   {
0727     Clus_OuterPhi_Offset = (outer_i.y - beam_origin.second < 0)
0728                                ? atan2(outer_i.y - beam_origin.second,
0729                                        outer_i.x - beam_origin.first) *
0730                                          (180. / TMath::Pi()) +
0731                                      360
0732                                : atan2(outer_i.y - beam_origin.second,
0733                                        outer_i.x - beam_origin.first) *
0734                                      (180. / TMath::Pi());
0735 
0736     outer_clu_phi_map[int(Clus_OuterPhi_Offset)].push_back({false, outer_i});
0737 
0738     if (outer_i.z > 0)
0739     {
0740       out_N_cluster_north += 1;
0741     }
0742     else
0743     {
0744       out_N_cluster_south += 1;
0745     }
0746   }
0747 
0748   //--std::cout<<"--3--"<<std::endl;
0749   ////
0750   // tracklet reconstruction from inner and outer clusters
0751   int good_pair_count = 0;
0752 
0753   for (int inner_phi_i = 0; inner_phi_i < 360; inner_phi_i++)  // note : each phi cell (1 degree)
0754   {
0755     // note : N cluster in this phi cell
0756     for (unsigned int inner_phi_clu_i = 0; inner_phi_clu_i < inner_clu_phi_map[inner_phi_i].size(); inner_phi_clu_i++)
0757     {
0758       if (inner_clu_phi_map[inner_phi_i][inner_phi_clu_i].first == true)
0759       {
0760         continue;
0761       }
0762 
0763       Clus_InnerPhi_Offset = (inner_clu_phi_map[inner_phi_i][inner_phi_clu_i].second.y - beam_origin.second < 0)
0764                                  ? atan2(inner_clu_phi_map[inner_phi_i][inner_phi_clu_i].second.y - beam_origin.second,
0765                                          inner_clu_phi_map[inner_phi_i][inner_phi_clu_i].second.x - beam_origin.first) *
0766                                            (180. / TMath::Pi()) +
0767                                        360
0768                                  : atan2(inner_clu_phi_map[inner_phi_i][inner_phi_clu_i].second.y - beam_origin.second,
0769                                          inner_clu_phi_map[inner_phi_i][inner_phi_clu_i].second.x - beam_origin.first) *
0770                                        (180. / TMath::Pi());
0771 
0772       // todo: change the outer phi scan range
0773       // note : the outer phi index, -1, 0, 1
0774       for (int scan_i = -1; scan_i < 2; scan_i++)
0775       {
0776         int true_scan_i = ((inner_phi_i + scan_i) < 0)     ? 360 + (inner_phi_i + scan_i)
0777                           : ((inner_phi_i + scan_i) > 359) ? (inner_phi_i + scan_i) - 360
0778                                                            : inner_phi_i + scan_i;
0779 
0780         // note : N clusters in that outer phi cell
0781         for (unsigned int outer_phi_clu_i = 0; outer_phi_clu_i < outer_clu_phi_map[true_scan_i].size(); outer_phi_clu_i++)
0782         {
0783           if (outer_clu_phi_map[true_scan_i][outer_phi_clu_i].first == true)
0784           {
0785             continue;
0786           }
0787 
0788           Clus_OuterPhi_Offset = (outer_clu_phi_map[true_scan_i][outer_phi_clu_i].second.y - beam_origin.second < 0)
0789                                      ? atan2(outer_clu_phi_map[true_scan_i][outer_phi_clu_i].second.y - beam_origin.second,
0790                                              outer_clu_phi_map[true_scan_i][outer_phi_clu_i].second.x - beam_origin.first) *
0791                                                (180. / TMath::Pi()) +
0792                                            360
0793                                      : atan2(outer_clu_phi_map[true_scan_i][outer_phi_clu_i].second.y - beam_origin.second,
0794                                              outer_clu_phi_map[true_scan_i][outer_phi_clu_i].second.x - beam_origin.first) *
0795                                            (180. / TMath::Pi());
0796 
0797           double delta_phi = get_delta_phi(Clus_InnerPhi_Offset, Clus_OuterPhi_Offset);
0798 
0799           if (draw_event_display)
0800           {
0801             evt_phi_diff_1D->Fill(delta_phi);                                       // QA
0802             evt_phi_diff_inner_phi->Fill(Clus_InnerPhi_Offset, delta_phi);          // QA
0803             evt_inner_outer_phi->Fill(Clus_InnerPhi_Offset, Clus_OuterPhi_Offset);  // QA
0804 
0805             phi_diff_inner_phi->Fill(Clus_InnerPhi_Offset, delta_phi);  // QA
0806           }
0807 
0808           if (fabs(delta_phi) < phi_diff_cut)
0809           {
0810             double DCA_sign = calculateAngleBetweenVectors(
0811                 outer_clu_phi_map[true_scan_i][outer_phi_clu_i].second.x, outer_clu_phi_map[true_scan_i][outer_phi_clu_i].second.y,
0812                 inner_clu_phi_map[inner_phi_i][inner_phi_clu_i].second.x, inner_clu_phi_map[inner_phi_i][inner_phi_clu_i].second.y,
0813                 beam_origin.first, beam_origin.second);
0814             if (m_enable_qa)
0815             {
0816               dca_inner_phi->Fill(Clus_InnerPhi_Offset, DCA_sign);
0817             }
0818 
0819             if (DCA_cut.first < DCA_sign && DCA_sign < DCA_cut.second)
0820             {
0821               good_pair_count += 1;
0822               // used_outer_check[outer_i] = 1; //note : this outer cluster was already used!
0823 
0824               // note : we basically transform the coordinate from cartesian to cylinder
0825               // note : we should set the offset first, otherwise it provides the bias
0826               // todo : which point should be used, DCA point or vertex xy ? Has to be studied
0827               std::pair<double, double> z_range_info = Get_possible_zvtx(
0828                   0.,  // get_radius(beam_origin.first,beam_origin.second),
0829                   {get_radius(inner_clu_phi_map[inner_phi_i][inner_phi_clu_i].second.x - beam_origin.first,
0830                               inner_clu_phi_map[inner_phi_i][inner_phi_clu_i].second.y - beam_origin.second),
0831                    inner_clu_phi_map[inner_phi_i][inner_phi_clu_i].second.z},  // note : unsign radius
0832                   {get_radius(outer_clu_phi_map[true_scan_i][outer_phi_clu_i].second.x - beam_origin.first,
0833                               outer_clu_phi_map[true_scan_i][outer_phi_clu_i].second.y - beam_origin.second),
0834                    outer_clu_phi_map[true_scan_i][outer_phi_clu_i].second.z}  // note : unsign radius
0835               );
0836 
0837               // note : try to remove some crazy background candidates. Can be a todo
0838               if (evt_possible_z_range.first < z_range_info.first && z_range_info.first < evt_possible_z_range.second)
0839               {
0840                 N_comb.push_back(good_comb_id);
0841                 N_comb_e.push_back(0);
0842                 N_comb_phi.push_back(get_track_phi(Clus_InnerPhi_Offset, delta_phi));
0843                 z_mid.push_back(z_range_info.first);
0844                 z_range.push_back(z_range_info.second);
0845 
0846                 evt_possible_z->Fill(z_range_info.first);  // used for calculation
0847 
0848                 // note : fill the line_breakdwon histogram as well as a vector for the width determination
0849                 line_breakdown(line_breakdown_hist,  // used for calculation
0850                                {z_range_info.first - z_range_info.second,
0851                                 z_range_info.first + z_range_info.second});
0852 
0853                 good_comb_id += 1;
0854               }
0855             }
0856           }
0857         }
0858       }  // note : end of outer clu loop
0859     }
0860 
0861   }  // note : end of inner clu loop
0862   //--std::cout<<"--4--"<<std::endl;
0863 
0864   // if (event_i == 906) {
0865   //     for (int hist_i = 0; hist_i < line_breakdown_hist->GetNbinsX(); hist_i++){
0866   //         std::cout<<line_breakdown_hist->GetBinContent(hist_i+1)<<","<<std::endl;
0867   //     }
0868   // }
0869   if (m_enable_qa)
0870   {
0871     //--std::cout<<"--4 0-- "<<total_NClus<<" "<< N_comb.size()<<std::endl;
0872     //--std::cout<<std::hex<<(long)N_track_candidate_Nclu<<std::dec<<std::endl;
0873     //--std::cout<<N_track_candidate_Nclu -> GetName()<<std::endl;
0874     N_track_candidate_Nclu->Fill(total_NClus, N_comb.size());  // QA
0875   }
0876 
0877   //--std::cout<<"--4 00--"<<std::endl;
0878   //-----------------------
0879   //
0880   // Fit histogram to determine Zvertex
0881   if (N_comb.size() > zvtx_cal_require)
0882   {
0883     //--std::cout<<"--4 1--"<<std::endl;
0884     N_group_info = find_Ngroup(evt_possible_z);
0885     N_group_info_detail = find_Ngroup(line_breakdown_hist);
0886 
0887     // note : first fit is for the width, so apply the constraints on the Gaussian offset
0888     gaus_fit->SetParameters(line_breakdown_hist->GetBinContent(line_breakdown_hist->GetMaximumBin()),
0889                             line_breakdown_hist->GetBinCenter(line_breakdown_hist->GetMaximumBin()),
0890                             40,
0891                             0);
0892     gaus_fit->SetParLimits(0, 0, 100000);  // note : size
0893     gaus_fit->SetParLimits(2, 5, 10000);   // note : Width
0894     gaus_fit->SetParLimits(3, 0, 10000);   // note : offset
0895     // todo : try to use single gaus to fit the distribution, and try to only fit the peak region (peak - 100 mm + peak + 100 mm)
0896     line_breakdown_hist->Fit(gaus_fit, "NQ", "",
0897                              line_breakdown_hist->GetBinCenter(line_breakdown_hist->GetMaximumBin()) - 90,
0898                              line_breakdown_hist->GetBinCenter(line_breakdown_hist->GetMaximumBin()) + 90);
0899     //----------------
0900     // 1st try z-vertex
0901     tight_offset_peak = gaus_fit->GetParameter(1);
0902     tight_offset_width = fabs(gaus_fit->GetParameter(2));
0903 
0904     double final_selection_widthU = (tight_offset_peak + tight_offset_width);
0905     double final_selection_widthD = (tight_offset_peak - tight_offset_width);
0906 
0907     double gaus_fit_offset = gaus_fit->GetParameter(3);
0908     gaus_fit->SetParameter(3, 0);  // note : in order to calculate the integration
0909     double gaus_ratio = (fabs(gaus_fit->GetParameter(0)) / gaus_fit->Integral(-600, 600)) / fabs(gaus_fit->GetParameter(2));
0910     gaus_fit->SetParameter(3, gaus_fit_offset);  // note : put the offset back to the function
0911 
0912     // note : second fit is for the peak position, therefore, loose the constraints on the Gaussian offset
0913     gaus_fit->SetParameters(line_breakdown_hist->GetBinContent(line_breakdown_hist->GetMaximumBin()),
0914                             line_breakdown_hist->GetBinCenter(line_breakdown_hist->GetMaximumBin()),
0915                             40,
0916                             0);
0917 
0918     gaus_fit->SetParLimits(0, 0, 100000);    // note : size
0919     gaus_fit->SetParLimits(2, 5, 10000);     // note : Width
0920     gaus_fit->SetParLimits(3, -200, 10000);  // note : offset
0921     // todo : try to use single gaus to fit the distribution, and try to only fit the peak region (peak - 100 mm + peak + 100 mm)
0922     line_breakdown_hist->Fit(gaus_fit, "NQ", "",
0923                              line_breakdown_hist->GetBinCenter(line_breakdown_hist->GetMaximumBin()) - 90,
0924                              line_breakdown_hist->GetBinCenter(line_breakdown_hist->GetMaximumBin()) + 90);
0925 
0926     // line_breakdown_hist -> Fit(gaus_fit, "NQ", "", N_group_info_detail[2]-10, N_group_info_detail[3]+10);
0927 
0928     //--std::cout<<"--5--"<<std::endl;
0929     //----------------
0930     // final z-vertex
0931     loose_offset_peak = gaus_fit->GetParameter(1);
0932     loose_offset_peakE = gaus_fit->GetParError(1);
0933 
0934     // additional QA below
0935     // note : eff sigma method, relatively sensitive to the background
0936     // note : use z-mid to do the effi_sig, because that line_breakdown takes too long time
0937     temp_event_zvtx_info = InttVertexUtil::sigmaEff_avg(z_mid, Integrate_portion);
0938 
0939     std::vector<double> eff_N_comb;    // QA
0940     std::vector<double> eff_N_comb_e;  // QA
0941     std::vector<double> eff_z_mid;     // QA
0942     std::vector<double> eff_z_range;   // QA note : eff_sig
0943     for (unsigned int track_i = 0; track_i < N_comb.size(); track_i++)
0944     {
0945       if (N_group_info[2] <= z_mid[track_i] && z_mid[track_i] <= N_group_info[3])
0946       {
0947         eff_N_comb.push_back(N_comb[track_i]);
0948         eff_N_comb_e.push_back(N_comb_e[track_i]);
0949         eff_z_mid.push_back(z_mid[track_i]);
0950         eff_z_range.push_back(z_range[track_i]);
0951       }
0952 
0953       if (draw_event_display)
0954       {
0955         if (final_selection_widthD <= z_mid[track_i] && z_mid[track_i] <= final_selection_widthU)
0956         {
0957           // note : for monitoring the the phi distribution that is used for the z vertex determination.
0958           // note : in principle, I expect it should be something uniform.
0959           evt_select_track_phi->Fill(N_comb_phi[track_i]);  // QA
0960         }
0961       }
0962     }
0963 
0964     //--std::cout<<"--6--"<<std::endl;
0965     if (z_range_gr != nullptr)
0966     {
0967       delete z_range_gr;
0968     }
0969     z_range_gr = new TGraphErrors(eff_N_comb.size(),
0970                                   &eff_N_comb[0], &eff_z_mid[0],
0971                                   &eff_N_comb_e[0], &eff_z_range[0]);
0972 
0973     z_range_gr->Fit(zvtx_finder, "NQ", "", 0, N_comb[N_comb.size() - 1]);
0974     double width_density_par = (double(eff_N_comb.size()) / fabs(temp_event_zvtx_info[2] - temp_event_zvtx_info[1]));
0975 
0976     if (zvtx_QA_width.first < tight_offset_width &&
0977         tight_offset_width < zvtx_QA_width.second &&
0978         100 < fabs(N_group_info_detail[3] - N_group_info_detail[2]) &&
0979         fabs(N_group_info_detail[3] - N_group_info_detail[2]) < 190)
0980     {
0981       if (N_group_info[0] < 4 &&
0982           N_group_info[1] >= 0.6 &&
0983           N_group_info_detail[0] < 7 &&
0984           N_group_info_detail[1] > 0.9)
0985       {
0986         good_zvtx_tag = true;
0987       }
0988       else
0989       {
0990         good_zvtx_tag = false;
0991       }
0992     }
0993     else
0994     {
0995       good_zvtx_tag = false;
0996     }
0997 
0998     good_zvtx_tag_int = (good_zvtx_tag == true) ? 1 : 0;  // note : so stupid way to convert bool to int...
0999 
1000     // note : final
1001     final_zvtx = loose_offset_peak;  // zvtx_finder -> GetParameter(0);
1002 
1003     ///////////////////////////////////
1004 
1005     //--std::cout<<"--7--"<<std::endl;
1006     if (m_enable_qa)
1007     {
1008       //
1009       // note : for the group information post the background cut
1010       peak_group_width_hist->Fill(fabs(N_group_info[3] - N_group_info[2]));
1011       peak_group_ratio_hist->Fill(N_group_info[1]);
1012       N_group_hist->Fill(N_group_info[0]);
1013       peak_group_detail_width_hist->Fill(fabs(N_group_info_detail[3] - N_group_info_detail[2]));
1014       peak_group_detail_ratio_hist->Fill(N_group_info_detail[1]);
1015       N_group_detail_hist->Fill(N_group_info_detail[0]);
1016 
1017       // note : gaus fit on the linebreak
1018       gaus_width_Nclu->Fill(total_NClus, tight_offset_width);
1019       gaus_rchi2_Nclu->Fill(total_NClus, gaus_fit->GetChisquare() / double(gaus_fit->GetNDF()));
1020       line_breakdown_gaus_ratio_hist->Fill(gaus_ratio);
1021       line_breakdown_gaus_width_hist->Fill(tight_offset_width);
1022 
1023       // note : the effi sig on the z_mid vector
1024       zvtx_evt_width_corre->Fill(total_NClus, fabs(temp_event_zvtx_info[2] - temp_event_zvtx_info[1]));
1025       width_density->Fill(width_density_par);
1026       ES_width->Fill(fabs(temp_event_zvtx_info[2] - temp_event_zvtx_info[1]));
1027       ES_width_ratio->Fill(total_NClus / fabs(temp_event_zvtx_info[2] - temp_event_zvtx_info[1]));
1028 
1029       // note : regarding to the zvtx determination, pol0 fit with error bar considered, fit range given by eff sigma method
1030       zvtx_evt_fitError->Fill(fabs(zvtx_finder->GetParError(0)));
1031       zvtx_evt_fitError_corre->Fill(total_NClus, fabs(zvtx_finder->GetParError(0)));
1032 
1033       if (good_zvtx_tag)
1034       {
1035         zvtx_evt_nclu_corre->Fill(total_NClus, final_zvtx);
1036         avg_event_zvtx->Fill(final_zvtx);
1037         avg_event_zvtx_vec.push_back(final_zvtx);
1038         if (run_type == "MC")
1039         {
1040           Z_resolution_vec.push_back(final_zvtx - (TrigZvtxMC * 10.));
1041           Z_resolution->Fill(final_zvtx - (TrigZvtxMC * 10.));
1042           Z_resolution_Nclu->Fill(total_NClus, final_zvtx - (TrigZvtxMC * 10.));
1043           Z_resolution_pos->Fill(TrigZvtxMC * 10., final_zvtx - (TrigZvtxMC * 10.));
1044           if (total_NClus > high_multi_line)
1045           {
1046             Z_resolution_pos_cut->Fill(TrigZvtxMC * 10., final_zvtx - (TrigZvtxMC * 10.));
1047           }
1048         }
1049       }
1050 
1051       final_fit_width->Fill(total_NClus, fabs(final_selection_widthU - final_selection_widthD));  // note : from LB gaus for the moment
1052 
1053       // note : output the root tree
1054       out_eID = event_i;
1055       N_cluster_inner_out = temp_sPH_inner_nocolumn_vec.size();
1056       N_cluster_outer_out = temp_sPH_outer_nocolumn_vec.size();
1057 
1058       out_ES_zvtx = zvtx_finder->GetParameter(0);
1059       out_ES_zvtxE = zvtx_finder->GetParError(0);
1060       out_ES_rangeL = temp_event_zvtx_info[1];
1061       out_ES_rangeR = temp_event_zvtx_info[2];
1062       out_ES_N_good = eff_N_comb.size();
1063       out_ES_width_density = width_density_par;
1064 
1065       out_LB_Gaus_Mean_mean = loose_offset_peak;
1066       out_LB_Gaus_Mean_meanE = gaus_fit->GetParError(1);                              // note : -> loose one
1067       out_LB_Gaus_Mean_chi2 = gaus_fit->GetChisquare() / double(gaus_fit->GetNDF());  // note : -> loose one
1068       out_LB_Gaus_Mean_width = fabs(gaus_fit->GetParameter(2));
1069 
1070       out_LB_Gaus_Width_width = tight_offset_width;
1071       out_LB_Gaus_Width_offset = gaus_fit_offset;
1072       out_LB_Gaus_Width_size_width = gaus_ratio;
1073 
1074       out_mid_cut_Ngroup = N_group_info[0];
1075       out_mid_cut_peak_ratio = N_group_info[1];
1076       out_mid_cut_peak_width = fabs(N_group_info[3] - N_group_info[2]) / 2.;
1077 
1078       out_LB_cut_Ngroup = N_group_info_detail[0];
1079       out_LB_cut_peak_ratio = N_group_info_detail[1];
1080       out_LB_cut_peak_width = fabs(N_group_info_detail[3] - N_group_info_detail[2]) / 2.;
1081 
1082       out_centrality_bin = centrality_bin;
1083 
1084       out_LB_geo_mean = LB_geo_mean(line_breakdown_hist,
1085                                     {(tight_offset_peak - tight_offset_width),
1086                                      (tight_offset_peak + tight_offset_width)},
1087                                     event_i);
1088       out_good_zvtx_tag = good_zvtx_tag;
1089       bco_full_out = bco_full;
1090       MC_true_zvtx = TrigZvtxMC * 10.;
1091 
1092       // note : if N good tracks in xy found > certain value
1093     }
1094 
1095     //--std::cout<<"--8--"<<std::endl;
1096     // drawing event display & QA histograms
1097     if (draw_event_display)
1098     {
1099       if (temp_event_xy != nullptr)
1100       {
1101         delete temp_event_xy;
1102       }
1103       temp_event_xy = new TGraph(temp_sPH_nocolumn_vec[0].size(),
1104                                  &temp_sPH_nocolumn_vec[0][0], &temp_sPH_nocolumn_vec[1][0]);
1105       temp_event_xy->SetTitle("INTT event display X-Y plane");
1106       temp_event_xy->GetXaxis()->SetLimits(-150, 150);
1107       temp_event_xy->GetYaxis()->SetRangeUser(-150, 150);
1108       temp_event_xy->GetXaxis()->SetTitle("X [mm]");
1109       temp_event_xy->GetYaxis()->SetTitle("Y [mm]");
1110       temp_event_xy->SetMarkerStyle(20);
1111       temp_event_xy->SetMarkerColor(2);
1112       temp_event_xy->SetMarkerSize(1);
1113 
1114       if (temp_event_rz != nullptr)
1115       {
1116         delete temp_event_rz;
1117       }
1118       temp_event_rz = new TGraph(temp_sPH_nocolumn_rz_vec[0].size(),
1119                                  &temp_sPH_nocolumn_rz_vec[0][0], &temp_sPH_nocolumn_rz_vec[1][0]);
1120       temp_event_rz->SetTitle("INTT event display r-Z plane");
1121       temp_event_rz->GetXaxis()->SetLimits(-500, 500);
1122       temp_event_rz->GetYaxis()->SetRangeUser(-150, 150);
1123       temp_event_rz->GetXaxis()->SetTitle("Z [mm]");
1124       temp_event_rz->GetYaxis()->SetTitle("Radius [mm]");
1125       temp_event_rz->SetMarkerStyle(20);
1126       temp_event_rz->SetMarkerColor(2);
1127       temp_event_rz->SetMarkerSize(1);
1128 
1129       // note : --------------------------------------------------------------------------------------------------------------------------
1130 
1131       // std::cout<<"pad "<<(long)pad_xy<<std::endl;
1132       // std::cout<<"bkg "<<(long)bkg<<std::endl;
1133       // std::cout<<"draw_text "<<(long)draw_text<<std::endl;
1134       pad_xy->cd();
1135       temp_event_xy->Draw("ap");
1136       // temp_event_xy -> Draw("p");
1137       draw_text->DrawLatex(0.2, 0.85,
1138                            (boost::format("eID : %i, inner Ncluster : %zu, outer Ncluster : %zu") % event_i % temp_sPH_inner_nocolumn_vec.size() % temp_sPH_outer_nocolumn_vec.size()).str().c_str());
1139 
1140       //--std::cout<<"--9--"<<std::endl;
1141       // note : --------------------------------------------------------------------------------------------------------------------------
1142 
1143       pad_rz->cd();
1144       temp_event_rz->Draw("ap");
1145       // eff_sig_range_line -> DrawLine(temp_event_zvtx_info[0],-150,temp_event_zvtx_info[0],150);
1146       coord_line->DrawLine(0, -150, 0, 150);
1147       coord_line->DrawLine(-500, 0, 500, 0);
1148       draw_text->DrawLatex(0.2, 0.85, "Negative radius : Clu_{outer} > 180^{0}");
1149       // draw_text -> DrawLatex(0.2, 0.81, (boost::format("EffSig avg : %.2f mm",temp_event_zvtx_info[0]));
1150 
1151       // note : --------------------------------------------------------------------------------------------------------------------------
1152       // std::cout<<"test tag 2-5"<<std::endl;
1153       pad_z->cd();
1154       if (z_range_gr_draw != nullptr)
1155       {
1156         delete z_range_gr_draw;
1157       }
1158       z_range_gr_draw = new TGraphErrors(N_comb.size(), &N_comb[0], &z_mid[0], &N_comb_e[0], &z_range[0]);
1159       z_range_gr_draw->GetYaxis()->SetRangeUser(-650, 650);
1160       z_range_gr_draw->GetXaxis()->SetTitle("Index");
1161       z_range_gr_draw->GetYaxis()->SetTitle("Z [mm]");
1162       z_range_gr_draw->SetMarkerStyle(20);
1163       z_range_gr_draw->Draw("ap");
1164 
1165       eff_sig_range_line->DrawLine(z_range_gr_draw->GetXaxis()->GetXmin(), N_group_info[2],
1166                                    z_range_gr_draw->GetXaxis()->GetXmax(), N_group_info[2]);
1167       eff_sig_range_line->DrawLine(z_range_gr_draw->GetXaxis()->GetXmin(), N_group_info[3],
1168                                    z_range_gr_draw->GetXaxis()->GetXmax(), N_group_info[3]);
1169       draw_text->DrawLatex(0.2, 0.82, (boost::format("#color[2]{Event Zvtx %.2f mm, error : #pm%.2f}") % zvtx_finder->GetParameter(0) % zvtx_finder->GetParError(0)).str().c_str());
1170       draw_text->DrawLatex(0.2, 0.78, (boost::format("#color[2]{Width density : %.6f}") % (width_density_par)).str().c_str());
1171       draw_text->DrawLatex(0.2, 0.74, (boost::format("#color[2]{Width (%.0f%%) : %.2f to %.2f mm #rightarrow %.2f mm}") % (Integrate_portion * 100.) % temp_event_zvtx_info[2] % temp_event_zvtx_info[1] % (std::fabs(temp_event_zvtx_info[2] - temp_event_zvtx_info[1]) / 2.)).str().c_str());
1172 
1173       // z_range_gr_draw -> Draw("p same");
1174       zvtx_finder->Draw("lsame");
1175 
1176       //--std::cout<<"--10--"<<std::endl;
1177       // note : --------------------------------------------------------------------------------------------------------------------------
1178       pad_z_hist->cd();
1179       evt_possible_z->SetMaximum(evt_possible_z->GetBinContent(evt_possible_z->GetMaximumBin()) * 1.4);
1180       evt_possible_z->Draw("hist");
1181       eff_sig_range_line->DrawLine(evt_possible_z->GetXaxis()->GetXmin(),
1182                                    evt_possible_z->GetBinContent(evt_possible_z->GetMaximumBin()) / 2.,
1183                                    evt_possible_z->GetXaxis()->GetXmax(),
1184                                    evt_possible_z->GetBinContent(evt_possible_z->GetMaximumBin()) / 2.);
1185       draw_text->DrawLatex(0.2, 0.82, (boost::format("N group : %.0f") % N_group_info[0]).str().c_str());
1186       draw_text->DrawLatex(0.2, 0.78, (boost::format("Main peak ratio : %.2f") % N_group_info[1]).str().c_str());
1187       draw_text->DrawLatex(0.2, 0.74, (boost::format("good z tag : %i") % good_zvtx_tag).str().c_str());
1188 
1189       // note : --------------------------------------------------------------------------------------------------------------------------
1190       pad_z_line->cd();
1191       line_breakdown_hist->SetMinimum(0);
1192       line_breakdown_hist->SetMaximum(line_breakdown_hist->GetBinContent(line_breakdown_hist->GetMaximumBin()) * 2);
1193       line_breakdown_hist->Draw("hist");
1194       gaus_fit->Draw("lsame");
1195       if (!good_zvtx_tag)
1196       {
1197         final_fit_range_line->DrawLine(line_breakdown_hist->GetXaxis()->GetXmin(), line_breakdown_hist->GetMaximum(),
1198                                        line_breakdown_hist->GetXaxis()->GetXmax(), line_breakdown_hist->GetMinimum());
1199       }
1200       final_fit_range_line->DrawLine(final_selection_widthD, line_breakdown_hist->GetMinimum(),
1201                                      final_selection_widthD, line_breakdown_hist->GetMaximum());
1202       final_fit_range_line->DrawLine(final_selection_widthU, line_breakdown_hist->GetMinimum(),
1203                                      final_selection_widthU, line_breakdown_hist->GetMaximum());
1204       draw_text->DrawLatex(0.2, 0.82, (boost::format("Gaus mean %.2f mm") % loose_offset_peak).str().c_str());
1205       draw_text->DrawLatex(0.2, 0.78, (boost::format("Width : %.2f mm") % tight_offset_width).str().c_str());
1206       draw_text->DrawLatex(0.2, 0.74, (boost::format("Reduced #chi2 : %.3f") % (gaus_fit->GetChisquare() / double(gaus_fit->GetNDF()))).str().c_str());
1207       draw_text->DrawLatex(0.2, 0.70, (boost::format("Norm. entry / Width : %.6f mm") % gaus_ratio).str().c_str());
1208       draw_text->DrawLatex(0.2, 0.66, (boost::format("LB Geo mean : %.3f mm") % out_LB_geo_mean).str().c_str());
1209 
1210       if (N_group_info_detail[0] != -1)
1211       {
1212         eff_sig_range_line->DrawLine(line_breakdown_hist->GetXaxis()->GetXmin(),
1213                                      line_breakdown_hist->GetBinContent(line_breakdown_hist->GetMaximumBin()) / 2.,
1214                                      line_breakdown_hist->GetXaxis()->GetXmax(),
1215                                      line_breakdown_hist->GetBinContent(line_breakdown_hist->GetMaximumBin()) / 2.);
1216         draw_text->DrawLatex(0.2, 0.62, (boost::format("N group : %.0f") % N_group_info_detail[0]).str().c_str());
1217         draw_text->DrawLatex(0.2, 0.58, (boost::format("Main peak ratio : %.2f") % N_group_info_detail[1]).str().c_str());
1218       }
1219 
1220       if (run_type == "MC")
1221       {
1222         draw_text->DrawLatex(0.2, 0.54, (boost::format("True MCz : %.3f mm") % (TrigZvtxMC * 10.)).str().c_str());
1223       }
1224 
1225       // note : --------------------------------------------------------------------------------------------------------------------------
1226       pad_phi_diff->cd();
1227       evt_phi_diff_inner_phi->Draw("colz0");
1228 
1229       // note : --------------------------------------------------------------------------------------------------------------------------
1230       pad_track_phi->cd();
1231       evt_select_track_phi->Draw("hist");
1232 
1233       // note : --------------------------------------------------------------------------------------------------------------------------
1234       pad_inner_outer_phi->cd();
1235       evt_inner_outer_phi->Draw("colz0");
1236 
1237       // note : --------------------------------------------------------------------------------------------------------------------------
1238       pad_phi_diff_1D->cd();
1239       evt_phi_diff_1D->Draw("hist");
1240       // std::cout<<"--11--"<<std::endl;
1241 
1242       if (draw_event_display && (event_i % print_rate) == 0 /*&& good_zvtx_tag == true*/)
1243       {
1244         c2->Print((boost::format("%s/temp_event_display.pdf") % out_folder_directory).str().c_str());
1245       }
1246       else if (draw_event_display && (final_zvtx > 0 || final_zvtx < -450))
1247       {
1248         std::cout << "In INTTZvtx class, event :" << event_i << " weird zvtx " << std::endl;
1249         c2->Print((boost::format("%s/temp_event_display.pdf") % out_folder_directory).str().c_str());
1250       }
1251       else if (draw_event_display && run_type == "MC" && fabs(final_zvtx - (TrigZvtxMC * 10.)) > 2. && total_NClus > 3000)
1252       {
1253         std::cout << "In INTTZvtx class, event :" << event_i << " High NClus, poor Z : " << fabs(final_zvtx - (TrigZvtxMC * 10.)) << std::endl;
1254         c2->Print((boost::format("%s/temp_event_display.pdf") % out_folder_directory).str().c_str());
1255       }
1256       else if (draw_event_display && run_type == "MC" && fabs(final_zvtx - (TrigZvtxMC * 10.)) > 2.)
1257       {
1258         std::cout << "In INTTZvtx class, event :" << event_i << " low NClus, poor Z : " << fabs(final_zvtx - (TrigZvtxMC * 10.)) << std::endl;
1259         c2->Print((boost::format("%s/temp_event_display.pdf") % out_folder_directory).str().c_str());
1260       }
1261 
1262       // std::cout<<"--12--"<<std::endl;
1263       pad_xy->Clear();
1264       pad_rz->Clear();
1265       pad_z->Clear();
1266       pad_z_hist->Clear();
1267       pad_z_line->Clear();
1268       pad_phi_diff->Clear();
1269       pad_track_phi->Clear();
1270       pad_inner_outer_phi->Clear();
1271       pad_phi_diff_1D->Clear();
1272       // std::cout<<"--13--"<<std::endl;
1273 
1274     }  // if (draw_event_display == true)
1275 
1276     m_zvtxinfo.zvtx = loose_offset_peak;
1277     m_zvtxinfo.zvtx_err = loose_offset_peakE;
1278     m_zvtxinfo.width = gaus_fit->GetParameter(2);
1279     m_zvtxinfo.chi2ndf = gaus_fit->GetChisquare() / double(gaus_fit->GetNDF());
1280     m_zvtxinfo.good = good_zvtx_tag;
1281     m_zvtxinfo.ngroup = N_group_info_detail[0];
1282     m_zvtxinfo.peakratio = N_group_info_detail[1];
1283     m_zvtxinfo.peakwidth = fabs(N_group_info_detail[3] - N_group_info_detail[2]) / 2.;
1284 
1285     std::cout << "chi2 : " << m_zvtxinfo.chi2ndf << " " << m_zvtxinfo.width << std::endl;
1286 
1287   }  // if (N_comb.size() > zvtx_cal_require)
1288 
1289   m_zvtxinfo.nclus = total_NClus;
1290   m_zvtxinfo.ntracklets = N_comb.size();
1291 
1292   ////////////////////////////////////////
1293 
1294   // std::cout<<"good pair count : "<<good_pair_count<<std::endl;
1295   std::cout << "evt : " << event_i << ", good pair count : " << N_comb.size() << " " << good_pair_count << std::endl;
1296 
1297   //--std::cout<<"--14 0--"<<std::endl;
1298   if (m_enable_qa)
1299   {
1300     tree_out->Fill();
1301   }
1302   //--std::cout<<"--14--"<<std::endl;
1303 
1304   return true;
1305 }
1306 
1307 void INTTZvtx::ClearEvt()
1308 {
1309   if (!m_initialized)
1310   {
1311     std::cout << "INTTZvtx is not initialized" << std::endl;
1312     exit(1);
1313   }
1314 
1315   good_comb_id = 0;
1316   out_N_cluster_north = 0;
1317   out_N_cluster_south = 0;
1318 
1319   // note : ultra-stupid way to avoid the errors
1320   //--z_range_gr = new TGraphErrors(); z_range_gr -> Delete();
1321 
1322   // draw_event_display
1323   // z_range_gr_draw = new TGraphErrors(); z_range_gr_draw -> Delete();
1324   // temp_event_xy = new TGraph(); temp_event_xy -> Delete();
1325   // temp_event_rz = new TGraph(); temp_event_rz -> Delete();
1326 
1327   N_comb_phi.clear();
1328   N_comb.clear();
1329   N_comb_e.clear();
1330   z_mid.clear();
1331   z_range.clear();
1332 
1333   //--eff_N_comb.clear();
1334   //--eff_z_mid.clear();
1335   //--eff_N_comb_e.clear();
1336   //--eff_z_range.clear();
1337   temp_event_zvtx_info = {0, -1000, -999.99};
1338 
1339   N_group_info.clear();
1340   N_group_info_detail = {-1., -1., -1., -1.};
1341 
1342   evt_possible_z->Reset("ICESM");
1343   line_breakdown_hist->Reset("ICESM");
1344 
1345   if (draw_event_display)
1346   {
1347     evt_phi_diff_1D->Reset("ICESM");
1348     evt_inner_outer_phi->Reset("ICESM");
1349     evt_select_track_phi->Reset("ICESM");
1350     evt_phi_diff_inner_phi->Reset("ICESM");
1351   }
1352 
1353   inner_clu_phi_map.clear();
1354   outer_clu_phi_map.clear();
1355   inner_clu_phi_map = std::vector<std::vector<std::pair<bool, clu_info>>>(360);
1356   outer_clu_phi_map = std::vector<std::vector<std::pair<bool, clu_info>>>(360);
1357 
1358   // note : this is the distribution for full run
1359   // line_breakdown_gaus_ratio_hist -> Reset("ICESM");
1360 }
1361 
1362 void INTTZvtx::PrintPlots()
1363 {
1364   if (!m_initialized)
1365   {
1366     std::cout << "INTTZvtx is not initialized" << std::endl;
1367     exit(1);
1368   }
1369 
1370   if (draw_event_display)
1371   {
1372     c2->Print((boost::format("%s/temp_event_display.pdf") % out_folder_directory).str().c_str());
1373     c2->Clear();
1374   }
1375 
1376   if (m_enable_qa)
1377   {
1378     c1->Clear();
1379 
1380     std::cout << "avg_event_zvtx_vec size : " << avg_event_zvtx_vec.size() << std::endl;
1381 
1382     TLatex* ltx = new TLatex();
1383     ltx->SetNDC();
1384     ltx->SetTextSize(0.045);
1385     ltx->SetTextAlign(31);
1386 
1387     std::string plot_text = (run_type == "MC") ? "Simulation" : "Work-in-progress";
1388     std::string inttlabel_text = (boost::format("#it{#bf{sPHENIX INTT}} %s") % plot_text).str();
1389 
1390     // note : ---------------------------------------------------------------------------------------
1391 
1392     c1->cd();
1393     std::vector<float> avg_event_zvtx_info = {0, 0, 0};
1394     if (avg_event_zvtx_vec.size() > 10)
1395     {
1396       avg_event_zvtx_info = InttVertexUtil::sigmaEff_avg(avg_event_zvtx_vec, Integrate_portion_final);
1397     }
1398 
1399     avg_event_zvtx->SetMinimum(0);
1400     avg_event_zvtx->SetMaximum(avg_event_zvtx->GetBinContent(avg_event_zvtx->GetMaximumBin()) * 1.5);
1401     avg_event_zvtx->Draw("hist");
1402 
1403     ltx->DrawLatex(1 - gPad->GetRightMargin(), 1 - gPad->GetTopMargin() + 0.01, inttlabel_text.c_str());
1404 
1405     eff_sig_range_line->DrawLine(avg_event_zvtx_info[1], 0, avg_event_zvtx_info[1], avg_event_zvtx->GetMaximum());
1406     eff_sig_range_line->DrawLine(avg_event_zvtx_info[2], 0, avg_event_zvtx_info[2], avg_event_zvtx->GetMaximum());
1407     draw_text->DrawLatex(0.21, 0.87, (boost::format("EffSig min : %.2f mm") % avg_event_zvtx_info[1]).str().c_str());
1408     draw_text->DrawLatex(0.21, 0.83, (boost::format("EffSig max : %.2f mm") % avg_event_zvtx_info[2]).str().c_str());
1409     draw_text->DrawLatex(0.21, 0.79, (boost::format("EffSig avg : %.2f mm") % avg_event_zvtx_info[0]).str().c_str());
1410     c1->Print((boost::format("%s/avg_event_zvtx.pdf") % out_folder_directory).str().c_str());
1411     c1->Clear();
1412 
1413     // note : ---------------------------------------------------------------------------------------
1414 
1415     width_density->Draw("hist");
1416     ltx->DrawLatex(1 - gPad->GetRightMargin(), 1 - gPad->GetTopMargin() + 0.01, inttlabel_text.c_str());
1417     c1->Print((boost::format("%s/width_density.pdf") % out_folder_directory).str().c_str());
1418     c1->Clear();
1419 
1420     // note : ---------------------------------------------------------------------------------------
1421 
1422     ES_width->Draw("hist");
1423     ltx->DrawLatex(1 - gPad->GetRightMargin(), 1 - gPad->GetTopMargin() + 0.01, inttlabel_text.c_str());
1424     c1->Print((boost::format("%s/ES_width.pdf") % out_folder_directory).str().c_str());
1425     c1->Clear();
1426 
1427     // note : ---------------------------------------------------------------------------------------
1428 
1429     ES_width_ratio->Draw("hist");
1430     ltx->DrawLatex(1 - gPad->GetRightMargin(), 1 - gPad->GetTopMargin() + 0.01, inttlabel_text.c_str());
1431     c1->Print((boost::format("%s/ES_width_ratio.pdf") % out_folder_directory).str().c_str());
1432     c1->Clear();
1433 
1434     // note : ---------------------------------------------------------------------------------------
1435 
1436     zvtx_evt_fitError->Draw("hist");
1437     ltx->DrawLatex(1 - gPad->GetRightMargin(), 1 - gPad->GetTopMargin() + 0.01, inttlabel_text.c_str());
1438     c1->Print((boost::format("%s/zvtx_evt_fitError.pdf") % out_folder_directory).str().c_str());
1439     c1->Clear();
1440 
1441     // note : ---------------------------------------------------------------------------------------
1442     if (run_type == "MC")
1443     {
1444       std::vector<float> Z_resolution_vec_info = InttVertexUtil::sigmaEff_avg(Z_resolution_vec, Integrate_portion_final);
1445 
1446       TF1* gaus_fit_2 = new TF1("gaus_fit_2", InttVertexUtil::gaus_func, evt_possible_z_range.first, evt_possible_z_range.second, 4);
1447       gaus_fit_2->SetLineColor(2);
1448       gaus_fit_2->SetLineWidth(2);
1449       gaus_fit_2->SetNpx(1000);
1450 
1451       gaus_fit_2->SetParameters(Z_resolution->GetBinContent(Z_resolution->GetMaximumBin()),
1452                                 Z_resolution->GetBinCenter(Z_resolution->GetMaximumBin()),
1453                                 3, 0);
1454       gaus_fit_2->SetParLimits(0, 0, 100000);  // note : size
1455       gaus_fit_2->SetParLimits(2, 0, 10000);   // note : Width
1456       gaus_fit_2->SetParLimits(3, 0, 10000);   // note : offset
1457       Z_resolution->Fit(gaus_fit_2, "NQ", "",
1458                         Z_resolution->GetBinCenter(Z_resolution->GetMaximumBin()) - (2 * Z_resolution->GetStdDev()),
1459                         Z_resolution->GetBinCenter(Z_resolution->GetMaximumBin()) + (2 * Z_resolution->GetStdDev()));
1460 
1461       Z_resolution->Draw("hist");
1462       gaus_fit_2->SetRange(gaus_fit_2->GetParameter(1) - gaus_fit_2->GetParameter(2) * 2.5,
1463                            gaus_fit_2->GetParameter(1) + gaus_fit_2->GetParameter(2) * 2.5);
1464       gaus_fit_2->Draw("lsame");
1465       eff_sig_range_line->DrawLine(Z_resolution_vec_info[1], 0, Z_resolution_vec_info[1], Z_resolution->GetMaximum());
1466       eff_sig_range_line->DrawLine(Z_resolution_vec_info[2], 0, Z_resolution_vec_info[2], Z_resolution->GetMaximum());
1467       draw_text->DrawLatex(0.21, 0.87, (boost::format("EffSig min : %.2f mm") % Z_resolution_vec_info[1]).str().c_str());
1468       draw_text->DrawLatex(0.21, 0.83, (boost::format("EffSig max : %.2f mm") % Z_resolution_vec_info[2]).str().c_str());
1469       draw_text->DrawLatex(0.21, 0.79, (boost::format("EffSig avg : %.2f mm") % Z_resolution_vec_info[0]).str().c_str());
1470       draw_text->DrawLatex(0.21, 0.71, (boost::format("Gaus mean  : %.2f mm") % gaus_fit_2->GetParameter(1)).str().c_str());
1471       draw_text->DrawLatex(0.21, 0.67, (boost::format("Gaus width : %.2f mm") % fabs(gaus_fit_2->GetParameter(2))).str().c_str());
1472       ltx->DrawLatex(1 - gPad->GetRightMargin(), 1 - gPad->GetTopMargin() + 0.01, inttlabel_text.c_str());
1473       c1->Print((boost::format("%s/Z_resolution.pdf") % out_folder_directory).str().c_str());
1474       c1->Clear();
1475 
1476       MC_z_diff_peak = gaus_fit_2->GetParameter(1);
1477       MC_z_diff_width = fabs(gaus_fit_2->GetParameter(2));
1478 
1479       delete gaus_fit_2;
1480     }
1481 
1482     // note : ---------------------------------------------------------------------------------------
1483 
1484     if (run_type == "MC")
1485     {
1486       Z_resolution_Nclu->Draw("colz0");
1487       ltx->DrawLatex(1 - gPad->GetRightMargin(), 1 - gPad->GetTopMargin() + 0.01, inttlabel_text.c_str());
1488       c1->Print((boost::format("%s/Z_resolution_Nclu.pdf") % out_folder_directory).str().c_str());
1489       c1->Clear();
1490     }
1491     // note : ---------------------------------------------------------------------------------------
1492 
1493     if (run_type == "MC")
1494     {
1495       Z_resolution_pos->Draw("colz0");
1496       ltx->DrawLatex(1 - gPad->GetRightMargin(), 1 - gPad->GetTopMargin() + 0.01, inttlabel_text.c_str());
1497       c1->Print((boost::format("%s/Z_resolution_pos.pdf") % out_folder_directory).str().c_str());
1498       c1->Clear();
1499     }
1500     // note : ---------------------------------------------------------------------------------------
1501 
1502     if (run_type == "MC")
1503     {
1504       Z_resolution_pos_cut->Draw("colz0");
1505       ltx->DrawLatex(1 - gPad->GetRightMargin(), 1 - gPad->GetTopMargin() + 0.01, inttlabel_text.c_str());
1506       c1->Print((boost::format("%s/Z_resolution_pos_cut.pdf") % out_folder_directory).str().c_str());
1507       c1->Clear();
1508     }
1509     // note : ---------------------------------------------------------------------------------------
1510 
1511     zvtx_evt_fitError_corre->Draw("colz0");
1512     ltx->DrawLatex(1 - gPad->GetRightMargin(), 1 - gPad->GetTopMargin() + 0.01, inttlabel_text.c_str());
1513     c1->Print((boost::format("%s/zvtx_evt_fitError_corre.pdf") % out_folder_directory).str().c_str());
1514     c1->Clear();
1515 
1516     // note : ---------------------------------------------------------------------------------------
1517 
1518     zvtx_evt_nclu_corre->Draw("colz0");
1519     ltx->DrawLatex(1 - gPad->GetRightMargin(), 1 - gPad->GetTopMargin() + 0.01, inttlabel_text.c_str());
1520     c1->Print((boost::format("%s/zvtx_evt_nclu_corre.pdf") % out_folder_directory).str().c_str());
1521     c1->Clear();
1522 
1523     // note : ---------------------------------------------------------------------------------------
1524 
1525     zvtx_evt_width_corre->Draw("colz0");
1526     ltx->DrawLatex(1 - gPad->GetRightMargin(), 1 - gPad->GetTopMargin() + 0.01, inttlabel_text.c_str());
1527     c1->Print((boost::format("%s/zvtx_evt_width_corre.pdf") % out_folder_directory).str().c_str());
1528     c1->Clear();
1529 
1530     // note : ---------------------------------------------------------------------------------------
1531 
1532     gaus_width_Nclu->Draw("colz0");
1533     ltx->DrawLatex(1 - gPad->GetRightMargin(), 1 - gPad->GetTopMargin() + 0.01, inttlabel_text.c_str());
1534     c1->Print((boost::format("%s/gaus_width_Nclu.pdf") % out_folder_directory).str().c_str());
1535     c1->Clear();
1536 
1537     // note : ---------------------------------------------------------------------------------------
1538 
1539     gaus_rchi2_Nclu->Draw("colz0");
1540     ltx->DrawLatex(1 - gPad->GetRightMargin(), 1 - gPad->GetTopMargin() + 0.01, inttlabel_text.c_str());
1541     c1->Print((boost::format("%s/gaus_rchi2_Nclu.pdf") % out_folder_directory).str().c_str());
1542     c1->Clear();
1543 
1544     // note : ---------------------------------------------------------------------------------------
1545 
1546     final_fit_width->Draw("colz0");
1547     ltx->DrawLatex(1 - gPad->GetRightMargin(), 1 - gPad->GetTopMargin() + 0.01, inttlabel_text.c_str());
1548     c1->Print((boost::format("%s/final_fit_width.pdf") % out_folder_directory).str().c_str());
1549     c1->Clear();
1550 
1551     // note : ---------------------------------------------------------------------------------------
1552 
1553     N_track_candidate_Nclu->Draw("colz0");
1554     ltx->DrawLatex(1 - gPad->GetRightMargin(), 1 - gPad->GetTopMargin() + 0.01, inttlabel_text.c_str());
1555     c1->Print((boost::format("%s/N_track_candidate_Nclu.pdf") % out_folder_directory).str().c_str());
1556     c1->Clear();
1557 
1558     // note : ---------------------------------------------------------------------------------------
1559     peak_group_width_hist->Draw("hist");
1560     ltx->DrawLatex(1 - gPad->GetRightMargin(), 1 - gPad->GetTopMargin() + 0.01, inttlabel_text.c_str());
1561     c1->Print((boost::format("%s/peak_group_width_hist.pdf") % out_folder_directory).str().c_str());
1562     c1->Clear();
1563 
1564     // note : ---------------------------------------------------------------------------------------
1565     peak_group_ratio_hist->Draw("hist");
1566     ltx->DrawLatex(1 - gPad->GetRightMargin(), 1 - gPad->GetTopMargin() + 0.01, inttlabel_text.c_str());
1567     c1->Print((boost::format("%s/peak_group_ratio_hist.pdf") % out_folder_directory).str().c_str());
1568     c1->Clear();
1569 
1570     // note : ---------------------------------------------------------------------------------------
1571     N_group_hist->Draw("hist");
1572     ltx->DrawLatex(1 - gPad->GetRightMargin(), 1 - gPad->GetTopMargin() + 0.01, inttlabel_text.c_str());
1573     c1->Print((boost::format("%s/N_group_hist.pdf") % out_folder_directory).str().c_str());
1574     c1->Clear();
1575 
1576     // note : ---------------------------------------------------------------------------------------
1577     peak_group_detail_width_hist->Draw("hist");
1578     ltx->DrawLatex(1 - gPad->GetRightMargin(), 1 - gPad->GetTopMargin() + 0.01, inttlabel_text.c_str());
1579     c1->Print((boost::format("%s/peak_group_detail_width_hist.pdf") % out_folder_directory).str().c_str());
1580     c1->Clear();
1581 
1582     // note : ---------------------------------------------------------------------------------------
1583     peak_group_detail_ratio_hist->Draw("hist");
1584     ltx->DrawLatex(1 - gPad->GetRightMargin(), 1 - gPad->GetTopMargin() + 0.01, inttlabel_text.c_str());
1585     c1->Print((boost::format("%s/peak_group_detail_ratio_hist.pdf") % out_folder_directory).str().c_str());
1586     c1->Clear();
1587 
1588     // note : ---------------------------------------------------------------------------------------
1589     N_group_detail_hist->Draw("hist");
1590     ltx->DrawLatex(1 - gPad->GetRightMargin(), 1 - gPad->GetTopMargin() + 0.01, inttlabel_text.c_str());
1591     c1->Print((boost::format("%s/N_group_detail_hist.pdf") % out_folder_directory).str().c_str());
1592     c1->Clear();
1593 
1594     // note : ---------------------------------------------------------------------------------------
1595     line_breakdown_gaus_ratio_hist->Draw("hist");
1596     ltx->DrawLatex(1 - gPad->GetRightMargin(), 1 - gPad->GetTopMargin() + 0.01, inttlabel_text.c_str());
1597 
1598     c1->Print((boost::format("%s/line_breakdown_gaus_ratio_hist.pdf") % out_folder_directory).str().c_str());
1599     c1->Clear();
1600 
1601     // note : ---------------------------------------------------------------------------------------
1602     gaus_fit->SetParameters(line_breakdown_gaus_width_hist->GetBinContent(line_breakdown_gaus_width_hist->GetMaximumBin()), line_breakdown_gaus_width_hist->GetBinCenter(line_breakdown_gaus_width_hist->GetMaximumBin()), 8, 0);
1603     gaus_fit->SetParLimits(0, 0, 100000);  // note : size
1604     gaus_fit->SetParLimits(2, 1, 10000);   // note : Width
1605     gaus_fit->SetParLimits(3, 0, 10000);   // note : offset
1606 
1607     // todo : try to use single gaus to fit the distribution, and try to only fit the peak region (peak - 100 mm + peak + 100 mm)
1608     line_breakdown_gaus_width_hist->Fit(gaus_fit, "NQ", "", line_breakdown_gaus_width_hist->GetBinCenter(line_breakdown_gaus_width_hist->GetMaximumBin()) - 100, line_breakdown_gaus_width_hist->GetBinCenter(line_breakdown_gaus_width_hist->GetMaximumBin()) + 100);
1609     line_breakdown_gaus_width_hist->Draw("hist");
1610     gaus_fit->Draw("lsame");
1611 
1612     draw_text->DrawLatex(0.2, 0.82, (boost::format("Gaus mean %.2f mm") % gaus_fit->GetParameter(1)).str().c_str());
1613     draw_text->DrawLatex(0.2, 0.78, (boost::format("Width : %.2f mm") % fabs(gaus_fit->GetParameter(2))).str().c_str());
1614     draw_text->DrawLatex(0.2, 0.74, (boost::format("Reduced #chi2 : %.3f") % (gaus_fit->GetChisquare() / double(gaus_fit->GetNDF()))).str().c_str());
1615     ltx->DrawLatex(1 - gPad->GetRightMargin(), 1 - gPad->GetTopMargin() + 0.01, inttlabel_text.c_str());
1616 
1617     c1->Print((boost::format("%s/line_breakdown_gaus_width_hist.pdf") % out_folder_directory).str().c_str());
1618     c1->Clear();
1619 
1620     delete ltx;
1621   }
1622 }
1623 
1624 void INTTZvtx::EndRun()
1625 {
1626   if (!m_initialized)
1627   {
1628     std::cout << "INTTZvtx is not initialized" << std::endl;
1629     exit(1);
1630   }
1631 
1632   if (m_enable_qa)
1633   {
1634     out_file->cd();
1635     tree_out->SetDirectory(out_file);
1636     tree_out->Write("", TObject::kOverwrite);
1637 
1638     for (auto& itr : m_v_qahist)
1639     {
1640       itr->Write();
1641     }
1642 
1643     out_file->Close();
1644   }
1645 }
1646 
1647 double INTTZvtx::GetZdiffPeakMC()
1648 {
1649   if (run_type == "MC" && MC_z_diff_peak != -777.)
1650   {
1651     return MC_z_diff_peak;
1652   }
1653   else
1654   {
1655     std::cout << "In INTTZvtx. Are you playing with data? The MC_z_diff_peak wasn't assigned, the value is still -777. Pleak check" << std::endl;
1656     return -777.;
1657   }
1658 }
1659 
1660 double INTTZvtx::GetZdiffWidthMC()
1661 {
1662   if (run_type == "MC" && MC_z_diff_width != -777.)
1663   {
1664     return MC_z_diff_width;
1665   }
1666   else
1667   {
1668     std::cout << "In INTTZvtx. Are you playing with data? The MC_z_diff_width wasn't assigned, the value is still -777. Pleak check" << std::endl;
1669     return -777.;
1670   }
1671 }
1672 
1673 std::vector<double> INTTZvtx::GetEvtZPeak()
1674 {
1675   return {good_zvtx_tag_int, loose_offset_peak, loose_offset_peakE};
1676 }
1677 
1678 double INTTZvtx::get_radius(double x, double y)
1679 {
1680   return sqrt(pow(x, 2) + pow(y, 2));
1681 }
1682 
1683 // note : Function to calculate the angle between two vectors in degrees using the cross product
1684 double INTTZvtx::calculateAngleBetweenVectors(double x1, double y1, double x2, double y2, double targetX, double targetY)
1685 {
1686   // Calculate the vectors vector_1 (point_1 to point_2) and vector_2 (point_1 to target)
1687   double vector1X = x2 - x1;
1688   double vector1Y = y2 - y1;
1689 
1690   double vector2X = targetX - x1;
1691   double vector2Y = targetY - y1;
1692 
1693   // Calculate the cross product of vector_1 and vector_2 (z-component)
1694   double crossProduct = vector1X * vector2Y - vector1Y * vector2X;
1695 
1696   // std::cout<<" crossProduct : "<<crossProduct<<std::endl;
1697 
1698   // Calculate the magnitudes of vector_1 and vector_2
1699   double magnitude1 = std::sqrt(vector1X * vector1X + vector1Y * vector1Y);
1700   double magnitude2 = std::sqrt(vector2X * vector2X + vector2Y * vector2Y);
1701 
1702   // Calculate the angle in radians using the inverse tangent of the cross product and dot product
1703   //--double dotProduct = vector1X * vector2X + vector1Y * vector2Y;
1704 
1705   //--double angleInRadians = std::atan2(std::abs(crossProduct), dotProduct);
1706   // Convert the angle from radians to degrees and return it
1707   //--double angleInDegrees = angleInRadians * 180.0 / M_PI;
1708 
1709   double angleInRadians_new = std::asin(crossProduct / (magnitude1 * magnitude2));
1710   //--double angleInDegrees_new = angleInRadians_new * 180.0 / M_PI;
1711 
1712   // std::cout<<"angle : "<<angleInDegrees_new<<std::endl;
1713 
1714   double DCA_distance = sin(angleInRadians_new) * magnitude2;
1715 
1716   return DCA_distance;
1717 }
1718 
1719 double INTTZvtx::Get_extrapolation(double given_y, double p0x, double p0y, double p1x, double p1y)  // note : x : z, y : r
1720 {
1721   if (fabs(p0x - p1x) < 0.00001)
1722   {  // note : the line is vertical (if z is along the x axis)
1723     return p0x;
1724   }
1725   else
1726   {
1727     double slope = (p1y - p0y) / (p1x - p0x);
1728     double yIntercept = p0y - slope * p0x;
1729     double xCoordinate = (given_y - yIntercept) / slope;
1730     return xCoordinate;
1731   }
1732 }
1733 
1734 std::pair<double, double> INTTZvtx::Get_possible_zvtx(double rvtx, std::vector<double> p0, std::vector<double> p1)  // note : inner p0, outer p1, vector {r,z}, -> {y,x}
1735 {
1736   std::vector<double> p0_z_edge = {(fabs(p0[1]) < 130) ? p0[1] - 8. : p0[1] - 10., (fabs(p0[1]) < 130) ? p0[1] + 8. : p0[1] + 10.};  // note : vector {left edge, right edge}
1737   std::vector<double> p1_z_edge = {(fabs(p1[1]) < 130) ? p1[1] - 8. : p1[1] - 10., (fabs(p1[1]) < 130) ? p1[1] + 8. : p1[1] + 10.};  // note : vector {left edge, right edge}
1738 
1739   double edge_first = Get_extrapolation(rvtx, p0_z_edge[0], p0[0], p1_z_edge[1], p1[0]);
1740   double edge_second = Get_extrapolation(rvtx, p0_z_edge[1], p0[0], p1_z_edge[0], p1[0]);
1741 
1742   double mid_point = (edge_first + edge_second) / 2.;
1743   double possible_width = fabs(edge_first - edge_second) / 2.;
1744 
1745   return {mid_point, possible_width};  // note : first : mid point, second : width
1746 }
1747 
1748 void INTTZvtx::line_breakdown(TH1* hist_in, std::pair<double, double> line_range)
1749 {
1750   int first_bin = int((line_range.first - hist_in->GetXaxis()->GetXmin()) / hist_in->GetBinWidth(1)) + 1;
1751   int last_bin = int((line_range.second - hist_in->GetXaxis()->GetXmin()) / hist_in->GetBinWidth(1)) + 1;
1752 
1753   if (first_bin < 1)
1754   {
1755     first_bin = 0;
1756   }
1757   else if (first_bin > hist_in->GetNbinsX())
1758   {
1759     first_bin = hist_in->GetNbinsX() + 1;
1760   }
1761 
1762   if (last_bin < 1)
1763   {
1764     last_bin = 0;
1765   }
1766   else if (last_bin > hist_in->GetNbinsX())
1767   {
1768     last_bin = hist_in->GetNbinsX() + 1;
1769   }
1770 
1771   // std::cout<<"Digitize the bin : "<<first_bin<<" "<<last_bin<<std::endl;
1772 
1773   // note : if first:last = (0:0) or (N+1:N+1) -> the subtraction of them euqals to zero.
1774   for (int i = 0; i < (last_bin - first_bin) + 1; i++)
1775   {
1776     hist_in->SetBinContent(first_bin + i, hist_in->GetBinContent(first_bin + i) + 1);
1777   }
1778 }
1779 
1780 // note : search_range : should be the gaus fit range
1781 double INTTZvtx::LB_geo_mean(TH1* hist_in, std::pair<double, double> search_range, int /*event_i*/)
1782 {
1783   int Highest_bin_index = hist_in->GetMaximumBin();
1784   double Highest_bin_center = hist_in->GetBinCenter(Highest_bin_index);
1785   double Highest_bin_content = hist_in->GetBinContent(Highest_bin_index);
1786   if (Highest_bin_center < search_range.first || search_range.second < Highest_bin_center)
1787   {
1788     // std::cout<<"In INTTZvtx class, event : "<<event_i<<", interesting event, different group was fit"<<std::endl;
1789     return -999.;
1790   }
1791 
1792   std::vector<float> same_height_bin;
1793   same_height_bin.clear();
1794   same_height_bin.push_back(Highest_bin_center);
1795 
1796   int search_index = 1;
1797   while ((hist_in->GetBinCenter(Highest_bin_index + search_index)) < search_range.second)
1798   {
1799     if (hist_in->GetBinContent(Highest_bin_index + search_index) == Highest_bin_content)
1800     {
1801       same_height_bin.push_back(hist_in->GetBinCenter(Highest_bin_index + search_index));
1802     }
1803     search_index++;
1804   }
1805 
1806   // std::cout<<"test, search_index right : "<<search_index<<std::endl;
1807 
1808   search_index = 1;
1809   while (search_range.first < (hist_in->GetBinCenter(Highest_bin_index - search_index)))
1810   {
1811     if (hist_in->GetBinContent(Highest_bin_index - search_index) == Highest_bin_content)
1812     {
1813       same_height_bin.push_back(hist_in->GetBinCenter(Highest_bin_index - search_index));
1814     }
1815     search_index++;
1816   }
1817 
1818   // std::cout<<"test, search_index left : "<<search_index<<std::endl;
1819   // std::cout<<"test, same_height_bin.size(): "<<same_height_bin.size()<<std::endl;
1820 
1821   return accumulate(same_height_bin.begin(), same_height_bin.end(), 0.0) / double(same_height_bin.size());
1822 }
1823 
1824 //  note : N group, group size, group tag, group width ?  // note : {group size, group entry, group tag, group widthL, group widthR}
1825 // note : {N_group, ratio (if two), peak widthL, peak widthR}
1826 std::vector<double> INTTZvtx::find_Ngroup(TH1* hist_in)
1827 {
1828   double Highest_bin_Content = hist_in->GetBinContent(hist_in->GetMaximumBin());
1829   double Highest_bin_Center = hist_in->GetBinCenter(hist_in->GetMaximumBin());
1830 
1831   int group_Nbin = 0;
1832   int peak_group_ID = 0;  // =0 added by TH 20240418
1833   double group_entry = 0;
1834   double peak_group_ratio;
1835   std::vector<int> group_Nbin_vec;
1836   group_Nbin_vec.clear();
1837   std::vector<double> group_entry_vec;
1838   group_entry_vec.clear();
1839   std::vector<double> group_widthL_vec;
1840   group_widthL_vec.clear();
1841   std::vector<double> group_widthR_vec;
1842   group_widthR_vec.clear();
1843 
1844   for (int i = 0; i < hist_in->GetNbinsX(); i++)
1845   {
1846     // todo : the background rejection is here : Highest_bin_Content/2. for the time being
1847     double bin_content = (hist_in->GetBinContent(i + 1) <= Highest_bin_Content / 2.) ? 0. : (hist_in->GetBinContent(i + 1) - Highest_bin_Content / 2.);
1848 
1849     if (bin_content != 0)
1850     {
1851       if (group_Nbin == 0)
1852       {
1853         group_widthL_vec.push_back(hist_in->GetBinCenter(i + 1) - (hist_in->GetBinWidth(i + 1) / 2.));
1854       }
1855 
1856       group_Nbin += 1;
1857       group_entry += bin_content;
1858     }
1859     else if (bin_content == 0 && group_Nbin != 0)
1860     {
1861       group_widthR_vec.push_back(hist_in->GetBinCenter(i + 1) - (hist_in->GetBinWidth(i + 1) / 2.));
1862       group_Nbin_vec.push_back(group_Nbin);
1863       group_entry_vec.push_back(group_entry);
1864       group_Nbin = 0;
1865       group_entry = 0;
1866     }
1867   }
1868   if (group_Nbin != 0)
1869   {
1870     group_Nbin_vec.push_back(group_Nbin);
1871     group_entry_vec.push_back(group_entry);
1872     group_widthR_vec.push_back(hist_in->GetXaxis()->GetXmax());
1873   }  // note : the last group at the edge
1874 
1875   // note : find the peak group
1876   for (unsigned int i = 0; i < group_Nbin_vec.size(); i++)
1877   {
1878     if (group_widthL_vec[i] < Highest_bin_Center && Highest_bin_Center < group_widthR_vec[i])
1879     {
1880       peak_group_ID = i;
1881       break;
1882     }
1883   }
1884 
1885   if (group_entry_vec.size() > 0)
1886   {
1887     peak_group_ratio = group_entry_vec[peak_group_ID] / (accumulate(group_entry_vec.begin(), group_entry_vec.end(), 0.0));
1888   }
1889   else
1890   {
1891     peak_group_ratio = 0.0;
1892   }
1893 
1894   // for (int i = 0; i < group_Nbin_vec.size(); i++)
1895   // {
1896   //     std::cout<<" "<<std::endl;
1897   //     std::cout<<"group size : "<<group_Nbin_vec[i]<<std::endl;
1898   //     std::cout<<"group entry : "<<group_entry_vec[i]<<std::endl;
1899   //     std::cout<<group_widthL_vec[i]<<" "<<group_widthR_vec[i]<<std::endl;
1900   // }
1901 
1902   // std::cout<<" "<<std::endl;
1903   // std::cout<<"N group : "<<group_Nbin_vec.size()<<std::endl;
1904   // std::cout<<"Peak group ID : "<<peak_group_ID<<std::endl;
1905   // std::cout<<"peak group width : "<<group_widthL_vec[peak_group_ID]<<" "<<group_widthR_vec[peak_group_ID]<<std::endl;
1906   // std::cout<<"ratio : "<<peak_group_ratio<<std::endl;
1907 
1908   // for the case that all bin content in the for statemene above is 0
1909   if (int(group_widthL_vec.size()) <= peak_group_ID || int(group_widthR_vec.size()) <= peak_group_ID)
1910   {  // added by Genki (Jan 2025)
1911     return {double(group_Nbin_vec.size()), peak_group_ratio, -9999, -9999};
1912   }
1913 
1914   // note : {N_group, ratio (if two), peak widthL, peak widthR}
1915   return {double(group_Nbin_vec.size()), peak_group_ratio, group_widthL_vec[peak_group_ID], group_widthR_vec[peak_group_ID]};
1916 }
1917 
1918 double INTTZvtx::get_delta_phi(double angle_1, double angle_2)
1919 {
1920   std::vector<double> vec_abs = {fabs(angle_1 - angle_2), fabs(angle_1 - angle_2 + 360), fabs(angle_1 - angle_2 - 360)};
1921   std::vector<double> vec = {(angle_1 - angle_2), (angle_1 - angle_2 + 360), (angle_1 - angle_2 - 360)};
1922   return vec[std::distance(vec_abs.begin(), std::min_element(vec_abs.begin(), vec_abs.end()))];
1923 }
1924 
1925 double INTTZvtx::get_track_phi(double inner_clu_phi_in, double delta_phi_in)
1926 {
1927   double track_phi = inner_clu_phi_in - (delta_phi_in / 2.);
1928   if (track_phi < 0)
1929   {
1930     track_phi += 360;
1931   }
1932   else if (track_phi > 360)
1933   {
1934     track_phi -= 360;
1935   }
1936   else if (track_phi == 360)
1937   {
1938     track_phi = 0;
1939   }
1940   // else {track_phi = track_phi;}
1941   return track_phi;
1942 }