Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:12:11

0001 // This file is part of the ACTS project.
0002 //
0003 // Copyright (C) 2016 CERN for the benefit of the ACTS project
0004 //
0005 // This Source Code Form is subject to the terms of the Mozilla Public
0006 // License, v. 2.0. If a copy of the MPL was not distributed with this
0007 // file, You can obtain one at https://mozilla.org/MPL/2.0/.
0008 
0009 #pragma once
0010 
0011 #include <array>
0012 #include <string>
0013 #include <vector>
0014 
0015 #include <TCanvas.h>
0016 #include <TEfficiency.h>
0017 #include <TFile.h>
0018 #include <TTree.h>
0019 
0020 struct RecoTrackInfo {
0021   double eta;
0022   double pt;
0023   unsigned int nMajorityHits;
0024   unsigned int nMeasurements;
0025 };
0026 
0027 struct ParticleInfo {
0028   ULong64_t particleId = 0;
0029   double eta = 0;
0030   double p = 0;
0031   double pt = 0;
0032   UShort_t nHits = 0;
0033 };
0034 
0035 /// Helper for reading tree
0036 ///
0037 struct TreeReader {
0038   // The constructor
0039   explicit TreeReader(TTree* tree_) : tree(tree_) {}
0040 
0041   // Get entry
0042   void getEntry(unsigned int i) const {
0043     if (entryNumbers.size() > i) {
0044       tree->GetEntry(entryNumbers[i]);
0045     } else {
0046       tree->GetEntry(i);
0047     }
0048   };
0049 
0050   // The tree being read
0051   TTree* tree = nullptr;
0052 
0053  protected:
0054   /// The entry numbers for accessing events in increased order (there could be
0055   /// multiple entries corresponding to one event number)
0056   std::vector<long long> entryNumbers = {};
0057 };
0058 
0059 /// Struct used for reading track states written out by the
0060 /// RootTrackStatesWriter
0061 ///
0062 struct TrackStatesReader : public TreeReader {
0063   // Delete the default constructor
0064   TrackStatesReader() = delete;
0065 
0066   // The constructor
0067   TrackStatesReader(TTree* tree_, bool sortEvents) : TreeReader(tree_) {
0068     tree->SetBranchAddress("event_nr", &eventId);
0069     tree->SetBranchAddress("eLOC0_prt", &LOC0_prt);
0070     tree->SetBranchAddress("eLOC1_prt", &LOC1_prt);
0071     tree->SetBranchAddress("ePHI_prt", &PHI_prt);
0072     tree->SetBranchAddress("eTHETA_prt", &THETA_prt);
0073     tree->SetBranchAddress("eQOP_prt", &QOP_prt);
0074     tree->SetBranchAddress("eT_prt", &T_prt);
0075     tree->SetBranchAddress("eLOC0_flt", &LOC0_flt);
0076     tree->SetBranchAddress("eLOC1_flt", &LOC1_flt);
0077     tree->SetBranchAddress("ePHI_flt", &PHI_flt);
0078     tree->SetBranchAddress("eTHETA_flt", &THETA_flt);
0079     tree->SetBranchAddress("eQOP_flt", &QOP_flt);
0080     tree->SetBranchAddress("eT_flt", &T_flt);
0081     tree->SetBranchAddress("eLOC0_smt", &LOC0_smt);
0082     tree->SetBranchAddress("eLOC1_smt", &LOC1_smt);
0083     tree->SetBranchAddress("ePHI_smt", &PHI_smt);
0084     tree->SetBranchAddress("eTHETA_smt", &THETA_smt);
0085     tree->SetBranchAddress("eQOP_smt", &QOP_smt);
0086     tree->SetBranchAddress("eT_smt", &T_smt);
0087 
0088     tree->SetBranchAddress("res_eLOC0_prt", &res_LOC0_prt);
0089     tree->SetBranchAddress("res_eLOC1_prt", &res_LOC1_prt);
0090     tree->SetBranchAddress("res_ePHI_prt", &res_PHI_prt);
0091     tree->SetBranchAddress("res_eTHETA_prt", &res_THETA_prt);
0092     tree->SetBranchAddress("res_eQOP_prt", &res_QOP_prt);
0093     tree->SetBranchAddress("res_eT_prt", &res_T_prt);
0094     tree->SetBranchAddress("res_eLOC0_flt", &res_LOC0_flt);
0095     tree->SetBranchAddress("res_eLOC1_flt", &res_LOC1_flt);
0096     tree->SetBranchAddress("res_ePHI_flt", &res_PHI_flt);
0097     tree->SetBranchAddress("res_eTHETA_flt", &res_THETA_flt);
0098     tree->SetBranchAddress("res_eQOP_flt", &res_QOP_flt);
0099     tree->SetBranchAddress("res_eT_flt", &res_T_flt);
0100     tree->SetBranchAddress("res_eLOC0_smt", &res_LOC0_smt);
0101     tree->SetBranchAddress("res_eLOC1_smt", &res_LOC1_smt);
0102     tree->SetBranchAddress("res_ePHI_smt", &res_PHI_smt);
0103     tree->SetBranchAddress("res_eTHETA_smt", &res_THETA_smt);
0104     tree->SetBranchAddress("res_eQOP_smt", &res_QOP_smt);
0105     tree->SetBranchAddress("res_eT_smt", &res_T_smt);
0106 
0107     tree->SetBranchAddress("pull_eLOC0_prt", &pull_LOC0_prt);
0108     tree->SetBranchAddress("pull_eLOC1_prt", &pull_LOC1_prt);
0109     tree->SetBranchAddress("pull_ePHI_prt", &pull_PHI_prt);
0110     tree->SetBranchAddress("pull_eTHETA_prt", &pull_THETA_prt);
0111     tree->SetBranchAddress("pull_eQOP_prt", &pull_QOP_prt);
0112     tree->SetBranchAddress("pull_eT_prt", &pull_T_prt);
0113     tree->SetBranchAddress("pull_eLOC0_flt", &pull_LOC0_flt);
0114     tree->SetBranchAddress("pull_eLOC1_flt", &pull_LOC1_flt);
0115     tree->SetBranchAddress("pull_ePHI_flt", &pull_PHI_flt);
0116     tree->SetBranchAddress("pull_eTHETA_flt", &pull_THETA_flt);
0117     tree->SetBranchAddress("pull_eQOP_flt", &pull_QOP_flt);
0118     tree->SetBranchAddress("pull_eT_flt", &pull_T_flt);
0119     tree->SetBranchAddress("pull_eLOC0_smt", &pull_LOC0_smt);
0120     tree->SetBranchAddress("pull_eLOC1_smt", &pull_LOC1_smt);
0121     tree->SetBranchAddress("pull_ePHI_smt", &pull_PHI_smt);
0122     tree->SetBranchAddress("pull_eTHETA_smt", &pull_THETA_smt);
0123     tree->SetBranchAddress("pull_eQOP_smt", &pull_QOP_smt);
0124     tree->SetBranchAddress("pull_eT_smt", &pull_T_smt);
0125 
0126     tree->SetBranchAddress("g_x_prt", &g_x_prt);
0127     tree->SetBranchAddress("g_y_prt", &g_y_prt);
0128     tree->SetBranchAddress("g_z_prt", &g_z_prt);
0129     tree->SetBranchAddress("g_x_flt", &g_x_flt);
0130     tree->SetBranchAddress("g_y_flt", &g_y_flt);
0131     tree->SetBranchAddress("g_z_flt", &g_z_flt);
0132     tree->SetBranchAddress("g_x_smt", &g_x_smt);
0133     tree->SetBranchAddress("g_y_smt", &g_y_smt);
0134     tree->SetBranchAddress("g_z_smt", &g_z_smt);
0135 
0136     tree->SetBranchAddress("nStates", &nStates);
0137     tree->SetBranchAddress("nMeasurements", &nMeasurements);
0138     tree->SetBranchAddress("volume_id", &volume_id);
0139     tree->SetBranchAddress("layer_id", &layer_id);
0140     tree->SetBranchAddress("module_id", &module_id);
0141     tree->SetBranchAddress("predicted", &predicted);
0142     tree->SetBranchAddress("filtered", &filtered);
0143     tree->SetBranchAddress("smoothed", &smoothed);
0144 
0145     // It's not necessary if you just need to read one file, but please do it to
0146     // synchronize events if multiple root files are read
0147     if (sortEvents) {
0148       tree->SetEstimate(tree->GetEntries() + 1);
0149       entryNumbers.resize(tree->GetEntries());
0150       tree->Draw("event_nr", "", "goff");
0151       // Sort to get the entry numbers of the ordered events
0152       TMath::Sort(tree->GetEntries(), tree->GetV1(), entryNumbers.data(),
0153                   false);
0154     }
0155   }
0156 
0157   // The variables
0158   std::uint32_t eventId = 0;
0159   std::vector<float>* LOC0_prt =
0160       new std::vector<float>;  ///< predicted parameter local x
0161   std::vector<float>* LOC1_prt =
0162       new std::vector<float>;  ///< predicted parameter local y
0163   std::vector<float>* PHI_prt =
0164       new std::vector<float>;  ///< predicted parameter phi
0165   std::vector<float>* THETA_prt =
0166       new std::vector<float>;  ///< predicted parameter theta
0167   std::vector<float>* QOP_prt =
0168       new std::vector<float>;  ///< predicted parameter q/p
0169   std::vector<float>* T_prt =
0170       new std::vector<float>;  ///< predicted parameter t
0171   std::vector<float>* LOC0_flt =
0172       new std::vector<float>;  ///< filtered parameter local x
0173   std::vector<float>* LOC1_flt =
0174       new std::vector<float>;  ///< filtered parameter local y
0175   std::vector<float>* PHI_flt =
0176       new std::vector<float>;  ///< filtered parameter phi
0177   std::vector<float>* THETA_flt =
0178       new std::vector<float>;  ///< filtered parameter theta
0179   std::vector<float>* QOP_flt =
0180       new std::vector<float>;  ///< filtered parameter q/p
0181   std::vector<float>* T_flt = new std::vector<float>;  ///< filtered parameter t
0182   std::vector<float>* LOC0_smt =
0183       new std::vector<float>;  ///< smoothed parameter local x
0184   std::vector<float>* LOC1_smt =
0185       new std::vector<float>;  ///< smoothed parameter local y
0186   std::vector<float>* PHI_smt =
0187       new std::vector<float>;  ///< smoothed parameter phi
0188   std::vector<float>* THETA_smt =
0189       new std::vector<float>;  ///< smoothed parameter theta
0190   std::vector<float>* QOP_smt =
0191       new std::vector<float>;  ///< smoothed parameter q/p
0192   std::vector<float>* T_smt = new std::vector<float>;  ///< smoothed parameter t
0193 
0194   std::vector<float>* res_LOC0_prt =
0195       new std::vector<float>;  ///< residual of predicted parameter local x
0196   std::vector<float>* res_LOC1_prt =
0197       new std::vector<float>;  ///< residual of predicted parameter local y
0198   std::vector<float>* res_PHI_prt =
0199       new std::vector<float>;  ///< residual of predicted parameter phi
0200   std::vector<float>* res_THETA_prt =
0201       new std::vector<float>;  ///< residual of predicted parameter theta
0202   std::vector<float>* res_QOP_prt =
0203       new std::vector<float>;  ///< residual of predicted parameter q/p
0204   std::vector<float>* res_T_prt =
0205       new std::vector<float>;  ///< residual of predicted parameter t
0206   std::vector<float>* res_LOC0_flt =
0207       new std::vector<float>;  ///< residual of filtered parameter local x
0208   std::vector<float>* res_LOC1_flt =
0209       new std::vector<float>;  ///< residual of filtered parameter local y
0210   std::vector<float>* res_PHI_flt =
0211       new std::vector<float>;  ///< residual of filtered parameter phi
0212   std::vector<float>* res_THETA_flt =
0213       new std::vector<float>;  ///< residual of filtered parameter theta
0214   std::vector<float>* res_QOP_flt =
0215       new std::vector<float>;  ///< residual of filtered parameter q/p
0216   std::vector<float>* res_T_flt =
0217       new std::vector<float>;  ///< residual of filtered parameter t
0218   std::vector<float>* res_LOC0_smt =
0219       new std::vector<float>;  ///< residual of smoothed parameter local x
0220   std::vector<float>* res_LOC1_smt =
0221       new std::vector<float>;  ///< residual of smoothed parameter local y
0222   std::vector<float>* res_PHI_smt =
0223       new std::vector<float>;  ///< residual of smoothed parameter phi
0224   std::vector<float>* res_THETA_smt =
0225       new std::vector<float>;  ///< residual of smoothed parameter theta
0226   std::vector<float>* res_QOP_smt =
0227       new std::vector<float>;  ///< residual of smoothed parameter q/p
0228   std::vector<float>* res_T_smt =
0229       new std::vector<float>;  ///< residual of smoothed parameter t
0230 
0231   std::vector<float>* pull_LOC0_prt =
0232       new std::vector<float>;  ///< pull of predicted parameter local x
0233   std::vector<float>* pull_LOC1_prt =
0234       new std::vector<float>;  ///< pull of predicted parameter local y
0235   std::vector<float>* pull_PHI_prt =
0236       new std::vector<float>;  ///< pull of predicted parameter phi
0237   std::vector<float>* pull_THETA_prt =
0238       new std::vector<float>;  ///< pull of predicted parameter theta
0239   std::vector<float>* pull_QOP_prt =
0240       new std::vector<float>;  ///< pull of predicted parameter q/p
0241   std::vector<float>* pull_T_prt =
0242       new std::vector<float>;  ///< pull of predicted parameter t
0243   std::vector<float>* pull_LOC0_flt =
0244       new std::vector<float>;  ///< pull of filtered parameter local x
0245   std::vector<float>* pull_LOC1_flt =
0246       new std::vector<float>;  ///< pull of filtered parameter local y
0247   std::vector<float>* pull_PHI_flt =
0248       new std::vector<float>;  ///< pull of filtered parameter phi
0249   std::vector<float>* pull_THETA_flt =
0250       new std::vector<float>;  ///< pull of filtered parameter theta
0251   std::vector<float>* pull_QOP_flt =
0252       new std::vector<float>;  ///< pull of filtered parameter q/p
0253   std::vector<float>* pull_T_flt =
0254       new std::vector<float>;  ///< pull of filtered parameter t
0255   std::vector<float>* pull_LOC0_smt =
0256       new std::vector<float>;  ///< pull of smoothed parameter local x
0257   std::vector<float>* pull_LOC1_smt =
0258       new std::vector<float>;  ///< pull of smoothed parameter local y
0259   std::vector<float>* pull_PHI_smt =
0260       new std::vector<float>;  ///< pull of smoothed parameter phi
0261   std::vector<float>* pull_THETA_smt =
0262       new std::vector<float>;  ///< pull of smoothed parameter theta
0263   std::vector<float>* pull_QOP_smt =
0264       new std::vector<float>;  ///< pull of smoothed parameter q/p
0265   std::vector<float>* pull_T_smt =
0266       new std::vector<float>;  ///< pull of smoothed parameter t
0267 
0268   std::vector<float>* g_x_prt = new std::vector<float>;
0269   std::vector<float>* g_y_prt = new std::vector<float>;
0270   std::vector<float>* g_z_prt = new std::vector<float>;
0271   std::vector<float>* g_x_flt = new std::vector<float>;
0272   std::vector<float>* g_y_flt = new std::vector<float>;
0273   std::vector<float>* g_z_flt = new std::vector<float>;
0274   std::vector<float>* g_x_smt = new std::vector<float>;
0275   std::vector<float>* g_y_smt = new std::vector<float>;
0276   std::vector<float>* g_z_smt = new std::vector<float>;
0277 
0278   std::vector<int>* volume_id = new std::vector<int>;  ///< volume_id
0279   std::vector<int>* layer_id = new std::vector<int>;   ///< layer_id
0280   std::vector<int>* module_id = new std::vector<int>;  ///< module_id
0281 
0282   std::vector<bool>* predicted = new std::vector<bool>;  ///< prediction status
0283   std::vector<bool>* filtered = new std::vector<bool>;   ///< filtering status
0284   std::vector<bool>* smoothed = new std::vector<bool>;   ///< smoothing status
0285 
0286   unsigned int nStates = 0, nMeasurements = 0;
0287 };
0288 
0289 /// Struct used for reading track summary info written out by the
0290 /// RootTrackSummaryWriter
0291 ///
0292 struct TrackSummaryReader : public TreeReader {
0293   // Delete the default constructor
0294   TrackSummaryReader() = delete;
0295 
0296   // The constructor
0297   TrackSummaryReader(TTree* tree_, bool sortEvents) : TreeReader(tree_) {
0298     tree->SetBranchAddress("event_nr", &eventId);
0299     tree->SetBranchAddress("nStates", &nStates);
0300     tree->SetBranchAddress("nMeasurements", &nMeasurements);
0301     tree->SetBranchAddress("nOutliers", &nOutliers);
0302     tree->SetBranchAddress("nHoles", &nHoles);
0303     tree->SetBranchAddress("chi2Sum", &chi2Sum);
0304     tree->SetBranchAddress("measurementChi2", &measurementChi2);
0305     tree->SetBranchAddress("NDF", &NDF);
0306     tree->SetBranchAddress("measurementVolume", &measurementVolume);
0307     tree->SetBranchAddress("measurementLayer", &measurementLayer);
0308     tree->SetBranchAddress("outlierVolume", &outlierVolume);
0309     tree->SetBranchAddress("outlierLayer", &outlierLayer);
0310     tree->SetBranchAddress("nMajorityHits", &nMajorityHits);
0311     tree->SetBranchAddress("nSharedHits", &nSharedHits);
0312     tree->SetBranchAddress("majorityParticleId", &majorityParticleId);
0313 
0314     tree->SetBranchAddress("hasFittedParams", &hasFittedParams);
0315 
0316     tree->SetBranchAddress("t_theta", &t_theta);
0317     tree->SetBranchAddress("t_phi", &t_phi);
0318     tree->SetBranchAddress("t_eta", &t_eta);
0319     tree->SetBranchAddress("t_p", &t_p);
0320     tree->SetBranchAddress("t_pT", &t_pT);
0321     tree->SetBranchAddress("t_d0", &t_d0);
0322     tree->SetBranchAddress("t_z0", &t_z0);
0323     tree->SetBranchAddress("t_charge", &t_charge);
0324     tree->SetBranchAddress("t_time", &t_time);
0325 
0326     tree->SetBranchAddress("eLOC0_fit", &eLOC0_fit);
0327     tree->SetBranchAddress("eLOC1_fit", &eLOC1_fit);
0328     tree->SetBranchAddress("ePHI_fit", &ePHI_fit);
0329     tree->SetBranchAddress("eTHETA_fit", &eTHETA_fit);
0330     tree->SetBranchAddress("eQOP_fit", &eQOP_fit);
0331     tree->SetBranchAddress("eT_fit", &eT_fit);
0332     tree->SetBranchAddress("err_eLOC0_fit", &err_eLOC0_fit);
0333     tree->SetBranchAddress("err_eLOC1_fit", &err_eLOC1_fit);
0334     tree->SetBranchAddress("err_ePHI_fit", &err_ePHI_fit);
0335     tree->SetBranchAddress("err_eTHETA_fit", &err_eTHETA_fit);
0336     tree->SetBranchAddress("err_eQOP_fit", &err_eQOP_fit);
0337     tree->SetBranchAddress("err_eT_fit", &err_eT_fit);
0338 
0339     // It's not necessary if you just need to read one file, but please do it to
0340     // synchronize events if multiple root files are read
0341     if (sortEvents) {
0342       tree->SetEstimate(tree->GetEntries() + 1);
0343       entryNumbers.resize(tree->GetEntries());
0344       tree->Draw("event_nr", "", "goff");
0345       // Sort to get the entry numbers of the ordered events
0346       TMath::Sort(tree->GetEntries(), tree->GetV1(), entryNumbers.data(),
0347                   false);
0348     }
0349   }
0350 
0351   // The variables
0352   std::uint32_t eventId = 0;
0353   std::vector<unsigned int>* nStates = new std::vector<unsigned int>;
0354   std::vector<unsigned int>* nMeasurements = new std::vector<unsigned int>;
0355   std::vector<unsigned int>* nOutliers = new std::vector<unsigned int>;
0356   std::vector<unsigned int>* nHoles = new std::vector<unsigned int>;
0357   std::vector<unsigned int>* nSharedHits = new std::vector<unsigned int>;
0358   std::vector<float>* chi2Sum = new std::vector<float>;
0359   std::vector<unsigned int>* NDF = new std::vector<unsigned int>;
0360   std::vector<std::vector<double>>* measurementChi2 =
0361       new std::vector<std::vector<double>>;
0362   std::vector<std::vector<double>>* outlierChi2 =
0363       new std::vector<std::vector<double>>;
0364   std::vector<std::vector<double>>* measurementVolume =
0365       new std::vector<std::vector<double>>;
0366   std::vector<std::vector<double>>* measurementLayer =
0367       new std::vector<std::vector<double>>;
0368   std::vector<std::vector<double>>* outlierVolume =
0369       new std::vector<std::vector<double>>;
0370   std::vector<std::vector<double>>* outlierLayer =
0371       new std::vector<std::vector<double>>;
0372   std::vector<unsigned int>* nMajorityHits = new std::vector<unsigned int>;
0373   std::vector<std::uint64_t>* majorityParticleId =
0374       new std::vector<std::uint64_t>;
0375 
0376   std::vector<bool>* hasFittedParams = new std::vector<bool>;
0377 
0378   // True parameters
0379   std::vector<float>* t_d0 = new std::vector<float>;
0380   std::vector<float>* t_z0 = new std::vector<float>;
0381   std::vector<float>* t_phi = new std::vector<float>;
0382   std::vector<float>* t_theta = new std::vector<float>;
0383   std::vector<float>* t_eta = new std::vector<float>;
0384   std::vector<float>* t_p = new std::vector<float>;
0385   std::vector<float>* t_pT = new std::vector<float>;
0386   std::vector<float>* t_time = new std::vector<float>;
0387   std::vector<int>* t_charge = new std::vector<int>;
0388 
0389   // Estimated parameters
0390   std::vector<float>* eLOC0_fit = new std::vector<float>;
0391   std::vector<float>* eLOC1_fit = new std::vector<float>;
0392   std::vector<float>* ePHI_fit = new std::vector<float>;
0393   std::vector<float>* eTHETA_fit = new std::vector<float>;
0394   std::vector<float>* eQOP_fit = new std::vector<float>;
0395   std::vector<float>* eT_fit = new std::vector<float>;
0396 
0397   std::vector<float>* err_eLOC0_fit = new std::vector<float>;
0398   std::vector<float>* err_eLOC1_fit = new std::vector<float>;
0399   std::vector<float>* err_ePHI_fit = new std::vector<float>;
0400   std::vector<float>* err_eTHETA_fit = new std::vector<float>;
0401   std::vector<float>* err_eQOP_fit = new std::vector<float>;
0402   std::vector<float>* err_eT_fit = new std::vector<float>;
0403 };
0404 
0405 /// Struct used for reading particles written out by the
0406 /// TrackFinderNTupleWriter
0407 ///
0408 struct ParticleReader : public TreeReader {
0409   // Delete the default constructor
0410   ParticleReader() = delete;
0411 
0412   // The constructor
0413   ParticleReader(TTree* tree_, bool sortEvents) : TreeReader(tree_) {
0414     tree->SetBranchAddress("event_id", &eventId);
0415     tree->SetBranchAddress("particle_id", &particleId);
0416     tree->SetBranchAddress("particle_type", &particleType);
0417     tree->SetBranchAddress("vx", &vx);
0418     tree->SetBranchAddress("vy", &vy);
0419     tree->SetBranchAddress("vz", &vz);
0420     tree->SetBranchAddress("vt", &vt);
0421     tree->SetBranchAddress("px", &px);
0422     tree->SetBranchAddress("py", &py);
0423     tree->SetBranchAddress("pz", &pz);
0424     tree->SetBranchAddress("m", &m);
0425     tree->SetBranchAddress("q", &q);
0426     tree->SetBranchAddress("nhits", &nHits);
0427     tree->SetBranchAddress("ntracks", &nTracks);
0428     tree->SetBranchAddress("ntracks_majority", &nTracksMajority);
0429 
0430     // It's not necessary if you just need to read one file, but please do it to
0431     // synchronize events if multiple root files are read
0432     if (sortEvents) {
0433       tree->SetEstimate(tree->GetEntries() + 1);
0434       entryNumbers.resize(tree->GetEntries());
0435       tree->Draw("event_id", "", "goff");
0436       // Sort to get the entry numbers of the ordered events
0437       TMath::Sort(tree->GetEntries(), tree->GetV1(), entryNumbers.data(),
0438                   false);
0439     }
0440   }
0441 
0442   // Get all the particles with requested event id
0443   std::vector<ParticleInfo> getParticles(
0444       const std::uint32_t& eventNumber) const {
0445     // Find the start entry and the batch size for this event
0446     std::string eventNumberStr = std::to_string(eventNumber);
0447     std::string findStartEntry = "event_id<" + eventNumberStr;
0448     std::string findParticlesSize = "event_id==" + eventNumberStr;
0449     std::size_t startEntry = tree->GetEntries(findStartEntry.c_str());
0450     std::size_t nParticles = tree->GetEntries(findParticlesSize.c_str());
0451     if (nParticles == 0) {
0452       throw std::invalid_argument(
0453           "No particles found. Please check the input file.");
0454     }
0455     std::vector<ParticleInfo> particles;
0456     particles.reserve(nParticles);
0457     for (unsigned int i = 0; i < nParticles; ++i) {
0458       getEntry(startEntry + i);
0459       auto pt = std::hypot(px, py);
0460       auto p = std::hypot(pt, pz);
0461       auto eta = std::atanh(pz / p * 1.);
0462       particles.push_back({particleId, eta, p, pt, nHits});
0463     }
0464     return particles;
0465   }
0466 
0467   // The variables
0468   ULong64_t eventId = 0;
0469   ULong64_t particleId = 0;
0470   Int_t particleType = 0;
0471   float vx = 0, vy = 0, vz = 0;
0472   float vt = 0;
0473   float px = 0, py = 0, pz = 0;
0474   float m = 0;
0475   float q = 0;
0476   UShort_t nHits = 0;
0477   UShort_t nTracks = 0;
0478   UShort_t nTracksMajority = 0;
0479 };