Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
RootSimHitReader.cpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file RootSimHitReader.cpp
1 // This file is part of the Acts project.
2 //
3 // Copyright (C) 2023 CERN for the benefit of the Acts project
4 //
5 // This Source Code Form is subject to the terms of the Mozilla Public
6 // License, v. 2.0. If a copy of the MPL was not distributed with this
7 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 
10 
16 
17 #include <algorithm>
18 #include <cstdint>
19 #include <iostream>
20 #include <stdexcept>
21 
22 #include <TChain.h>
23 #include <TMathBase.h>
24 
28  : ActsExamples::IReader(),
29  m_cfg(config),
30  m_logger(Acts::getDefaultLogger(name(), level)) {
31  m_inputChain = new TChain(m_cfg.treeName.c_str());
32 
33  if (m_cfg.filePath.empty()) {
34  throw std::invalid_argument("Missing input filename");
35  }
36  if (m_cfg.treeName.empty()) {
37  throw std::invalid_argument("Missing tree name");
38  }
39 
41 
42  // Set the branches
43  int f = 0;
44  auto setBranches = [&](const auto& keys, auto& columns) {
45  for (auto key : keys) {
46  columns.insert({key, f++});
47  }
48  for (auto key : keys) {
49  m_inputChain->SetBranchAddress(key, &columns.at(key));
50  }
51  };
52 
53  setBranches(m_floatKeys, m_floatColumns);
54  setBranches(m_uint32Keys, m_uint32Columns);
55  setBranches(m_uint64Keys, m_uint64Columns);
56  setBranches(m_int32Keys, m_int32Columns);
57 
58  // add file to the input chain
59  m_inputChain->Add(m_cfg.filePath.c_str());
60  m_inputChain->LoadTree(0);
61  ACTS_DEBUG("Adding File " << m_cfg.filePath << " to tree '" << m_cfg.treeName
62  << "'.");
63 
64  // Because each hit is stored in a single entry in the root file, we need to
65  // scan the file first for the positions of the events in the file in order to
66  // efficiently read the events later on.
67  // TODO change the file format to store one event per entry
68 
69  // Disable all branches and only enable event-id for a first scan of the file
70  m_inputChain->SetBranchStatus("*", false);
71  m_inputChain->SetBranchStatus("event_id", true);
72 
73  auto nEntries = static_cast<std::size_t>(m_inputChain->GetEntriesFast());
74 
75  // Add the first entry
76  m_inputChain->GetEntry(0);
77  m_eventMap.push_back({m_uint32Columns.at("event_id"), 0ul, 0ul});
78 
79  // Go through all entries and store the position of new events
80  for (auto i = 1ul; i < nEntries; ++i) {
81  m_inputChain->GetEntry(i);
82  const auto evtId = m_uint32Columns.at("event_id");
83 
84  if (evtId != std::get<0>(m_eventMap.back())) {
85  std::get<2>(m_eventMap.back()) = i;
86  m_eventMap.push_back({evtId, i, i});
87  }
88  }
89 
90  std::get<2>(m_eventMap.back()) = nEntries;
91 
92  // Sort by event id
93  std::sort(m_eventMap.begin(), m_eventMap.end(),
94  [](const auto& a, const auto& b) {
95  return std::get<0>(a) < std::get<0>(b);
96  });
97 
98  // Re-Enable all branches
99  m_inputChain->SetBranchStatus("*", true);
100  ACTS_DEBUG("Event range: " << availableEvents().first << " - "
101  << availableEvents().second);
102 }
103 
105  const {
106  return {std::get<0>(m_eventMap.front()), std::get<0>(m_eventMap.back()) + 1};
107 }
108 
110  const ActsExamples::AlgorithmContext& context) {
111  auto it = std::find_if(
112  m_eventMap.begin(), m_eventMap.end(),
113  [&](const auto& a) { return std::get<0>(a) == context.eventNumber; });
114 
115  if (it == m_eventMap.end()) {
116  // explicitly warn if it happens for the first or last event as that might
117  // indicate a human error
118  if ((context.eventNumber == availableEvents().first) &&
119  (context.eventNumber == availableEvents().second - 1)) {
120  ACTS_WARNING("Reading empty event: " << context.eventNumber);
121  } else {
122  ACTS_DEBUG("Reading empty event: " << context.eventNumber);
123  }
124 
125  m_outputSimHits(context, {});
126 
127  // Return success flag
129  }
130 
131  // lock the mutex
132  std::lock_guard<std::mutex> lock(m_read_mutex);
133 
134  ACTS_DEBUG("Reading event: " << std::get<0>(*it)
135  << " stored in entries: " << std::get<1>(*it)
136  << " - " << std::get<2>(*it));
137 
138  SimHitContainer hits;
139  for (auto entry = std::get<1>(*it); entry < std::get<2>(*it); ++entry) {
140  m_inputChain->GetEntry(entry);
141 
142  auto eventId = m_uint32Columns.at("event_id");
143  if (eventId != context.eventNumber) {
144  break;
145  }
146 
147  const Acts::GeometryIdentifier geoid = m_uint64Columns.at("geometry_id");
148  const SimBarcode pid = m_uint64Columns.at("particle_id");
149  const auto index = m_int32Columns.at("index");
150 
151  const Acts::Vector4 pos4 = {
152  m_floatColumns.at("tx") * Acts::UnitConstants::mm,
153  m_floatColumns.at("ty") * Acts::UnitConstants::mm,
154  m_floatColumns.at("tz") * Acts::UnitConstants::mm,
155  m_floatColumns.at("tt") * Acts::UnitConstants::ns,
156  };
157 
158  const Acts::Vector4 before4 = {
159  m_floatColumns.at("tpx") * Acts::UnitConstants::GeV,
160  m_floatColumns.at("tpy") * Acts::UnitConstants::GeV,
161  m_floatColumns.at("tpz") * Acts::UnitConstants::GeV,
162  m_floatColumns.at("te") * Acts::UnitConstants::GeV,
163  };
164 
165  const Acts::Vector4 delta = {
166  m_floatColumns.at("deltapx") * Acts::UnitConstants::GeV,
167  m_floatColumns.at("deltapy") * Acts::UnitConstants::GeV,
168  m_floatColumns.at("deltapz") * Acts::UnitConstants::GeV,
169  m_floatColumns.at("deltae") * Acts::UnitConstants::GeV,
170  };
171 
172  SimHit hit(geoid, pid, pos4, before4, before4 + delta, index);
173 
174  hits.insert(hit);
175  }
176 
177  m_outputSimHits(context, std::move(hits));
178 
179  // Return success flag
181 }