Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
RootMeasurementWriter.cpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file RootMeasurementWriter.cpp
1 // This file is part of the Acts project.
2 //
3 // Copyright (C) 2017 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 
17 
18 #include <cstddef>
19 #include <ios>
20 #include <stdexcept>
21 #include <utility>
22 #include <variant>
23 
24 #include <TFile.h>
25 
26 namespace Acts {
27 class Surface;
28 } // namespace Acts
29 
33  : WriterT(config.inputMeasurements, "RootMeasurementWriter", level),
34  m_cfg(config) {
35  // Input container for measurements is already checked by base constructor
36  if (m_cfg.inputSimHits.empty()) {
37  throw std::invalid_argument("Missing simulated hits input collection");
38  }
39  if (m_cfg.inputMeasurementSimHitsMap.empty()) {
40  throw std::invalid_argument(
41  "Missing hit-to-simulated-hits map input collection");
42  }
43 
47 
48  if (not m_cfg.trackingGeometry) {
49  throw std::invalid_argument("Missing tracking geometry");
50  }
51  // Setup ROOT File
52  m_outputFile = TFile::Open(m_cfg.filePath.c_str(), m_cfg.fileMode.c_str());
53  if (m_outputFile == nullptr) {
54  throw std::ios_base::failure("Could not open '" + m_cfg.filePath);
55  }
56 
57  m_outputFile->cd();
58 
59  // Analyze the smearers
60  std::vector<
61  std::pair<Acts::GeometryIdentifier, std::unique_ptr<DigitizationTree>>>
62  dTrees;
63  if (not m_cfg.boundIndices.empty()) {
64  ACTS_DEBUG("Bound indices are declared, preparing trees.");
65  for (size_t ikv = 0; ikv < m_cfg.boundIndices.size(); ++ikv) {
66  auto geoID = m_cfg.boundIndices.idAt(ikv);
67  auto bIndices = m_cfg.boundIndices.valueAt(ikv);
68  auto dTree = std::make_unique<DigitizationTree>(geoID);
69  for (const auto& bIndex : bIndices) {
70  ACTS_VERBOSE("- setup branch for index: " << bIndex);
71  dTree->setupBoundRecBranch(bIndex);
72  }
73  if (not m_cfg.inputClusters.empty()) {
74  dTree->setupClusterBranch(bIndices);
75  }
76  dTrees.push_back({geoID, std::move(dTree)});
77  }
78  } else {
79  ACTS_DEBUG("Bound indices are not declared, no reco setup.")
80  }
81 
83  std::move(dTrees));
84 }
85 
87  if (m_outputFile != nullptr) {
88  m_outputFile->Close();
89  }
90 }
91 
94  m_outputFile->cd();
95  for (auto dTree = m_outputTrees.begin(); dTree != m_outputTrees.end();
96  ++dTree) {
97  (*dTree)->tree->Write();
98  }
99  m_outputFile->Close();
100 
101  return ProcessCode::SUCCESS;
102 }
103 
105  const AlgorithmContext& ctx, const MeasurementContainer& measurements) {
106  const auto& simHits = m_inputSimHits(ctx);
107  const auto& hitSimHitsMap = m_inputMeasurementSimHitsMap(ctx);
108 
110  if (not m_cfg.inputClusters.empty()) {
111  clusters = m_inputClusters(ctx);
112  }
113 
114  // Exclusive access to the tree while writing
115  std::lock_guard<std::mutex> lock(m_writeMutex);
116 
117  for (Index hitIdx = 0u; hitIdx < measurements.size(); ++hitIdx) {
118  const auto& meas = measurements[hitIdx];
119 
120  std::visit(
121  [&](const auto& m) {
123  m.sourceLink().template get<IndexSourceLink>().geometryId();
124  // find the corresponding surface
125  const Acts::Surface* surfacePtr =
126  m_cfg.trackingGeometry->findSurface(geoId);
127  if (not surfacePtr) {
128  return;
129  }
130  const Acts::Surface& surface = *surfacePtr;
131  // find the corresponding output tree
132  auto dTreeItr = m_outputTrees.find(geoId);
133  if (dTreeItr == m_outputTrees.end()) {
134  return;
135  }
136  auto& dTree = *dTreeItr;
137 
138  // Fill the identification
139  dTree->fillIdentification(ctx.eventNumber, geoId);
140 
141  // Find the contributing simulated hits
142  auto indices = makeRange(hitSimHitsMap.equal_range(hitIdx));
143  // Use average truth in the case of multiple contributing sim hits
144  auto [local, pos4, dir] = averageSimHits(ctx.geoContext, surface,
145  simHits, indices, logger());
147  surface
148  .referenceFrame(ctx.geoContext, pos4.segment<3>(Acts::ePos0),
149  dir)
150  .inverse();
151  std::pair<double, double> angles =
153  dTree->fillTruthParameters(local, pos4, dir, angles);
154  dTree->fillBoundMeasurement(m);
155  if (not clusters.empty()) {
156  const auto& c = clusters[hitIdx];
157  dTree->fillCluster(c);
158  }
159  dTree->tree->Fill();
160  if (dTree->chValue != nullptr) {
161  dTree->chValue->clear();
162  }
163  if (dTree->chId[0] != nullptr) {
164  dTree->chId[0]->clear();
165  }
166  if (dTree->chId[1] != nullptr) {
167  dTree->chId[1]->clear();
168  }
169  },
170  meas);
171  }
172 
174 }