ATLAS Offline Software
TruthNtupleTool.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3 */
4 
6 // TruthNtupleTool.cxx
7 // Source file for class TruthNtupleTool
9 // (c) ATLAS Detector software
11 // Sebastian.Fleischmann@cern.ch
13 
14 // Trk
17 // Truth
19 
20 #include "AtlasHepMC/GenParticle.h"
21 #include "AtlasHepMC/GenVertex.h"
22 
23 // root
24 #include "TTree.h"
25 #include <TH1D.h>
26 #include <TGraphAsymmErrors.h>
27 
28 
29 #include <cmath>
30 
31 
32 // constructor
34  const std::string& t,
35  const std::string& n,
36  const IInterface* p )
37  :
38  AthAlgTool(t,n,p),
39  m_fillJets(false),
40  m_histSvc("THistSvc", n),
41  m_nt(nullptr),
42  m_numberOfTreeEntries(0),
43  m_runNumber{},
44  m_eventNumber{},
45  m_TrackLinkIndex{},
46  m_mc_prob{},
47  m_classifications{},
48  m_mc_d0{},
49  m_mc_z0{},
50  m_mc_phi0{},
51  m_mc_theta{},
52  m_mc_qOverP{},
53  m_mc_qOverPt{},
54  m_mc_eta{},
55 
56  m_mc_particleID{},
57  m_mc_uniqueID{},
58  m_mc_energy{},
59  m_mc_jetLinkIndex{},
60  m_mc_prodR{},
61  m_mc_prodz{}
62 {
63  declareInterface<ITruthNtupleTool>(this);
64 
65  m_etaBins.push_back(0.0);
66  m_etaBins.push_back(0.8);
67  m_etaBins.push_back(1.6);
68  m_etaBins.push_back(2.5);
69  // Declare the properties
70  declareProperty("NtupleFileName", m_ntupleFileName = "TRKVAL/Validation", "Ntuple file handle");
71  declareProperty("NtupleTreeName", m_ntupleTreeName = "Truth", "Name of the ntuple tree");
72 }
73 
74 // destructor
76 
77 
78 
79 
80 // initialize
82 
83  ATH_CHECK( m_evt.initialize() );
84 
85  if (m_etaBins.size()<2) {
86  ATH_MSG_ERROR ("Vector of eta bins too small");
87  return StatusCode::FAILURE;
88  }
89 
90  // ---------------------------
91  // retrieve pointer to THistSvc
92  ATH_CHECK( m_histSvc.retrieve() );
93 
94  // ---------------------------
95  // create tree and register it to THistSvc
96  m_nt = new TTree(TString(m_ntupleTreeName), "Track Validation Truth");
97  // NB: we must not delete the tree, this is done by THistSvc
98  std::string fullNtupleName = "/"+m_ntupleFileName+"/"+m_ntupleTreeName;
99  ATH_CHECK( m_histSvc->regTree(fullNtupleName, m_nt) );
100 
101  //-----------------
102  // add items
103  // event info:
104  m_nt->Branch( "RunNumber", &m_runNumber );
105  m_nt->Branch( "EventNumber", &m_eventNumber );
106  m_nt->Branch( "truth_d0", &m_mc_d0 );
107  m_nt->Branch( "truth_z0", &m_mc_z0 );
108  m_nt->Branch( "truth_phi0", &m_mc_phi0 );
109  m_nt->Branch( "truth_theta", &m_mc_theta );
110  m_nt->Branch( "truth_qOverP", &m_mc_qOverP );
111  m_nt->Branch( "truth_qOverPt", &m_mc_qOverPt );
112  m_nt->Branch( "truth_eta", &m_mc_eta );
113  m_nt->Branch( "truth_particleID", &m_mc_particleID );
114  m_nt->Branch( "truth_barcode", &m_mc_uniqueID ); // TODO Update variable name to be consistent
115  m_nt->Branch( "truth_energy", &m_mc_energy );
116  m_nt->Branch( "truth_prod_R", &m_mc_prodR );
117  m_nt->Branch( "truth_prod_z", &m_mc_prodz );
118 
119  ATH_MSG_VERBOSE ("added items to ntuple");
120 
121  return StatusCode::SUCCESS;
122 
123 }
124 
125 StatusCode Trk::TruthNtupleTool::initBranches(const std::vector<const Trk::ITrackTruthClassifier*>& classifiers, bool fillJets, const std::vector<std::string> trackCollectionNames) {
126  m_trackTruthClassifiers = classifiers;
127  m_classifications.resize(classifiers.size(), 0);
128  m_recoTrackCounts.resize(classifiers.size());
129  m_truthTrackCounts.resize(classifiers.size());
130  m_fillJets = fillJets;
131 
132  if (m_fillJets)
133  m_nt->Branch("JetLinkIndex", &m_mc_jetLinkIndex );// link to MC jets
134 
135  double etaBins[100];
136  for (unsigned int bin = 0; bin < m_etaBins.size(); ++bin ) {
137  etaBins[bin] = m_etaBins[bin];
138  }
139  for (unsigned int classifierIndex = 0; classifierIndex < classifiers.size(); ++classifierIndex ) {
140  if (!(classifiers[classifierIndex])) {
141  ATH_MSG_ERROR ("Got NULL pointer to truth classifier tool!");
142  return StatusCode::FAILURE;
143  }
144  std::string classifierName = classifiers[classifierIndex]->nameOfClassifier();
145  // add branch for classifier
146  ATH_MSG_INFO ("using classifier " << classifierName);
147  std::string branchName = "Class_" + classifierName;
148  std::string branchDescription = "Class_" + classifierName + "/I";
149  m_nt->Branch(branchName.c_str(), &(m_classifications[classifierIndex]), branchDescription.c_str());
150  // init statistic counters
151  for (unsigned int clIndex = 0; clIndex < classifiers[classifierIndex]->numberOfClassifiers(); clIndex++) {
152  m_truthTrackCounts[classifierIndex].push_back( new TH1D(
153  ("true"+classifiers[classifierIndex]->classificationAsString(clIndex)).c_str(),
154  ("true"+classifiers[classifierIndex]->classificationAsString(clIndex)).c_str(),
155  m_etaBins.size()-1,
156  etaBins
157  ) );
158  // TODO: do statistics for each input track collection
159  m_recoTrackCounts[classifierIndex].push_back( new TH1D(
160  ("reco"+classifiers[classifierIndex]->classificationAsString(clIndex)).c_str(),
161  ("reco"+classifiers[classifierIndex]->classificationAsString(clIndex)).c_str(),
162  m_etaBins.size()-1,
163  etaBins
164  ) );
165  }
166  }
167 
168  // add branches with links to the reconstructed tracks:
169  if (!m_TrackLinkIndex.empty()) {
170  ATH_MSG_ERROR ("Track links seem to be already initialized! Do NOT call initBranches() twice!");
171  return StatusCode::FAILURE;
172  }
173  m_TrackLinkIndex.resize(trackCollectionNames.size(), nullptr);
174  m_mc_prob.resize(trackCollectionNames.size(), nullptr);
175  for (unsigned int trackColIndex = 0; trackColIndex < trackCollectionNames.size(); ++trackColIndex ) {
176  m_TrackLinkIndex[trackColIndex] = new std::vector<unsigned int>();
177  std::string branchName = "TrackLinkIndex_" + trackCollectionNames[trackColIndex];
178  m_nt->Branch(branchName.c_str(), &(m_TrackLinkIndex[trackColIndex])); // link to tracks
179  m_mc_prob[trackColIndex] = new std::vector<float>();
180  branchName = "truth_prob_" + trackCollectionNames[trackColIndex];
181  m_nt->Branch(branchName.c_str(), &(m_mc_prob[trackColIndex])); // matching probability
182  }
183  return StatusCode::SUCCESS;
184 }
185 
190 
191  ATH_MSG_INFO ("start finalize() in " << name());
192 
193  ATH_MSG_INFO ( "Efficiencies:" );
194 
195  //Double_t* efficiencyValues;
196  for (unsigned int classifierIndex = 0; classifierIndex < m_trackTruthClassifiers.size(); ++classifierIndex ) {
197  for (unsigned int clIndex = 0; clIndex < m_trackTruthClassifiers[classifierIndex]->numberOfClassifiers(); clIndex++) {
198  // output:
199 
200  msg() << std::resetiosflags(std::ios::right) << std::setiosflags(std::ios::left) << std::setw(15) << m_trackTruthClassifiers[classifierIndex]->classificationAsString(clIndex);
201  msg() << std::resetiosflags(std::ios::left) << std::setiosflags(std::ios::right);
202  for (int etaBin = 0; etaBin < m_recoTrackCounts[classifierIndex][clIndex]->GetNbinsX(); etaBin++) {
203  double truth = m_truthTrackCounts[classifierIndex][clIndex]->GetBinContent(etaBin+1);
204  double reco = m_recoTrackCounts[classifierIndex][clIndex]->GetBinContent(etaBin+1);
205  msg() << std::resetiosflags(std::ios::fixed | std::ios::showpoint) << std::setprecision(8) << std::setw(8) << reco << "/" << std::setw(8) << truth;
206  msg() << std::setiosflags(std::ios::fixed | std::ios::showpoint | std::ios::right ) << std::setw(7)
207  << " (" << std::setprecision(4) << (truth>0. ? reco/truth : 0.) << ")";
208  }
209  // calc efficiency:
210  TGraphAsymmErrors* effPlot = new TGraphAsymmErrors(m_recoTrackCounts[classifierIndex][clIndex], m_truthTrackCounts[classifierIndex][clIndex], "");
211  // add graph to ROOT file
212  std::string graphName = "trackEff_" + m_trackTruthClassifiers[classifierIndex]->classificationAsString(clIndex);
213  effPlot->SetNameTitle(graphName.c_str(), graphName.c_str());
214  StatusCode sc = m_histSvc->regGraph("/"+m_ntupleFileName+"/"+graphName, effPlot);
215  if(sc.isFailure()){
216  ATH_MSG_ERROR ("ROOT Graph registration failed");
217  return sc;
218  }
219  msg() << "\n";
220  delete m_recoTrackCounts[classifierIndex][clIndex];
221  m_recoTrackCounts[classifierIndex][clIndex] = nullptr;
222  delete m_truthTrackCounts[classifierIndex][clIndex];
223  m_truthTrackCounts[classifierIndex][clIndex] = nullptr;
224  }
225  }
226  msg() << endmsg;
227 
228  // delete track links and probs
229  for (unsigned int trackColIndex = 0; trackColIndex < m_TrackLinkIndex.size(); ++trackColIndex ) {
230  delete m_TrackLinkIndex[trackColIndex];
231  delete m_mc_prob[trackColIndex];
232  }
233  return StatusCode::SUCCESS;
234 }
235 
240  const std::vector< Trk::ValidationTrackTruthData >& truthData) {
241 
242  ATH_MSG_DEBUG ("in writeTruthData(...) with ValTrackTruthData size = "<<truthData.size());
243  // ---------------------------------------
244  // fill event data
246  if (!evt.isValid()) {
247  ATH_MSG_WARNING ("Could not retrieve event info");
248  return StatusCode::FAILURE;
249  }
250 
251  m_runNumber=evt->runNumber();
252  m_eventNumber=evt->eventNumber();
253 
254  HepMC::ConstGenParticlePtr genParticle{nullptr};
255  const Trk::TrackParameters* truePerigee = nullptr;
256  for (unsigned int index = 0; index < truthData.size(); index++) {
257  genParticle = truthData[index].genParticle;
258  truePerigee = truthData[index].truthPerigee;
259  if (genParticle==nullptr || truePerigee==nullptr) {
260  if (genParticle==nullptr) ATH_MSG_WARNING ("NULL pointer to gen particle at index "<<index<<
261  ", problem with truth selection logic?");
262  else ATH_MSG_DEBUG ("NULL pointer perigee from TruthToTrack. Index is "<<index);
263  m_mc_uniqueID = HepMC::UNDEFINED_ID;
264  for (unsigned int trackColIndex = 0; trackColIndex < m_mc_prob.size(); ++trackColIndex ) {
265  (m_mc_prob[trackColIndex])->clear();
266  (m_TrackLinkIndex[trackColIndex])->clear();
267  }
268  //m_classifications->clear(); do not clear! vector needs to be the same
269  m_mc_particleID = 0;
270  m_mc_energy = 0.;
271 
272  m_mc_d0 = 0.;
273  m_mc_z0 = 0.;
274  m_mc_phi0 = 0.;
275  m_mc_theta = 0.;
276  m_mc_qOverP = 0.;
277  m_mc_qOverPt = 0.;
278  m_mc_eta = 0.;
279  m_mc_prodR = 0.;
280  m_mc_prodz = 0.;
281  } else {
282  m_mc_uniqueID = HepMC::uniqueID(genParticle);
283  m_mc_particleID = genParticle->pdg_id();
284  m_mc_energy = genParticle->momentum().e();
285 
286  m_mc_d0 = truePerigee->parameters()[Trk::d0];
287  m_mc_z0 = truePerigee->parameters()[Trk::z0];
288  m_mc_phi0 = truePerigee->parameters()[Trk::phi0];
289  m_mc_theta = truePerigee->parameters()[Trk::theta];
290  m_mc_qOverP = truePerigee->parameters()[Trk::qOverP];
291  m_mc_qOverPt = (std::sin( m_mc_theta ) != 0.) ? m_mc_qOverP / std::sin( m_mc_theta ) : 0.;
292  m_mc_eta = truePerigee->eta();
293  m_mc_prodR = fabs(genParticle->production_vertex()->position().perp());
294  m_mc_prodz = fabs(genParticle->production_vertex()->position().z());
295 
296  for (unsigned int trackColIndex = 0; trackColIndex < truthData[index].truthToTrackIndices.size(); ++trackColIndex ) {
297  (*(m_TrackLinkIndex[trackColIndex])) = truthData[index].truthToTrackIndices[trackColIndex];
298  (*(m_mc_prob[trackColIndex])) = truthData[index].truthToTrackMatchingProbabilities[trackColIndex];
299  }
300  // get classification
301  m_classifications = truthData[index].classifications;
302 
303  if (m_fillJets)
304  m_mc_jetLinkIndex = truthData[index].truthToJetIndex;
305 
306  // do statistics:
307  for (unsigned int classIndex = 0; classIndex < m_classifications.size(); ++classIndex ) {
308  m_truthTrackCounts[classIndex][m_classifications[classIndex]]->Fill(std::fabs(m_mc_eta));
309  if (!truthData[index].truthToTrackIndices[0].empty()) {
310  // TODO: do statistics for each input track collection
311  m_recoTrackCounts[classIndex][m_classifications[classIndex]]->Fill(std::fabs(m_mc_eta));
312  }
313 
314  }
315 
316  }
317  m_nt->Fill();
318  m_numberOfTreeEntries++;
319  }
320  ATH_MSG_DEBUG ("filled " << m_numberOfTreeEntries << " entries, returning...");
321  return StatusCode::SUCCESS;
322 }
323 
324 
326  return m_numberOfTreeEntries;
327 }
TrackParameters.h
Trk::TruthNtupleTool::getNumberOfTreeRecords
virtual unsigned int getNumberOfTreeRecords() const
Definition: TruthNtupleTool.cxx:325
ATH_MSG_INFO
#define ATH_MSG_INFO(x)
Definition: AthMsgStreamMacros.h:31
SG::ReadHandle
Definition: StoreGate/StoreGate/ReadHandle.h:70
index
Definition: index.py:1
GenVertex.h
ConvertOldUJHistosToNewHistos.etaBins
list etaBins
Definition: ConvertOldUJHistosToNewHistos.py:145
bin
Definition: BinsDiffFromStripMedian.h:43
Trk::z0
@ z0
Definition: ParamDefs.h:64
LArG4FSStartPointFilter.evt
evt
Definition: LArG4FSStartPointFilter.py:42
read_hist_ntuple.t
t
Definition: read_hist_ntuple.py:5
ATH_MSG_VERBOSE
#define ATH_MSG_VERBOSE(x)
Definition: AthMsgStreamMacros.h:28
Trk::TruthNtupleTool::writeTruthData
virtual StatusCode writeTruthData(const std::vector< Trk::ValidationTrackTruthData > &truthData)
write track data to ntuple
Definition: TruthNtupleTool.cxx:239
empty
bool empty(TH1 *h)
Definition: computils.cxx:294
GenParticle.h
Trk::TruthNtupleTool::initBranches
virtual StatusCode initBranches(const std::vector< const Trk::ITrackTruthClassifier * > &classifiers, bool, const std::vector< std::string > trackCollectionNames)
Definition: TruthNtupleTool.cxx:125
AthenaPoolTestRead.sc
sc
Definition: AthenaPoolTestRead.py:27
Trk::TruthNtupleTool::TruthNtupleTool
TruthNtupleTool(const std::string &, const std::string &, const IInterface *)
Definition: TruthNtupleTool.cxx:33
xAOD::etaBin
setSAddress setEtaMS setDirPhiMS setDirZMS setBarrelRadius setEndcapAlpha setEndcapRadius setInterceptInner setEtaMap etaBin
Definition: L2StandAloneMuon_v1.cxx:148
python.utils.AtlRunQueryDQUtils.p
p
Definition: AtlRunQueryDQUtils.py:210
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
beamspotman.n
n
Definition: beamspotman.py:731
Trk::theta
@ theta
Definition: ParamDefs.h:66
endmsg
#define endmsg
Definition: AnalysisConfig_Ntuple.cxx:63
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
xAOD::JetTests::fillJets
void fillJets(JetContainer &jetCont, const std::vector< xAOD::JetFourMom_t > &jet4moms)
Fill input JetContainer with new jets which 4-momentum are given by jet4moms.
Definition: JetFactory.h:78
HepMC::uniqueID
int uniqueID(const T &p)
Definition: MagicNumbers.h:109
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
Trk::ParametersBase
Definition: ParametersBase.h:55
HepMC::UNDEFINED_ID
constexpr int UNDEFINED_ID
Definition: MagicNumbers.h:55
HepMC::ConstGenParticlePtr
const GenParticle * ConstGenParticlePtr
Definition: GenParticle.h:38
TrackTruth.h
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:221
Trk::d0
@ d0
Definition: ParamDefs.h:63
plotBeamSpotVxVal.bin
int bin
Definition: plotBeamSpotVxVal.py:83
Trk::TruthNtupleTool::~TruthNtupleTool
~TruthNtupleTool()
DeMoScan.index
string index
Definition: DeMoScan.py:364
VKalVrtAthena::varHolder_detail::clear
void clear(T &var)
Definition: NtupleVars.h:48
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
Trk::qOverP
@ qOverP
perigee
Definition: ParamDefs.h:67
Trk::TruthNtupleTool::initialize
StatusCode initialize()
Definition: TruthNtupleTool.cxx:81
Trk::ParametersBase::eta
double eta() const
Access method for pseudorapidity - from momentum.
drawFromPickle.sin
sin
Definition: drawFromPickle.py:36
AthAlgTool
Definition: AthAlgTool.h:26
Trk::TruthNtupleTool::finalize
StatusCode finalize()
finalize
Definition: TruthNtupleTool.cxx:189
TruthNtupleTool.h
python.AutoConfigFlags.msg
msg
Definition: AutoConfigFlags.py:7
Trk::phi0
@ phi0
Definition: ParamDefs.h:65
MuonSegmentReaderConfig.reco
reco
Definition: MuonSegmentReaderConfig.py:133