Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
RootMeasurementWriter.hpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file RootMeasurementWriter.hpp
1 // This file is part of the Acts project.
2 //
3 // Copyright (C) 2020 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 
9 #pragma once
10 
28 
29 #include <array>
30 #include <memory>
31 #include <mutex>
32 #include <string>
33 #include <unordered_map>
34 #include <vector>
35 
36 #include <TTree.h>
37 
38 class TFile;
39 class TTree;
40 namespace Acts {
41 class Surface;
42 class TrackingGeometry;
43 } // namespace Acts
44 
45 namespace ActsExamples {
46 struct AlgorithmContext;
47 
59 class RootMeasurementWriter final : public WriterT<MeasurementContainer> {
60  public:
61  struct Config {
71  std::string fileMode = "RECREATE";
72 
75  std::shared_ptr<const Acts::TrackingGeometry> trackingGeometry;
76  };
77 
79  const std::array<std::string, Acts::eBoundSize> bNames = {
80  "loc0", "loc1", "phi", "theta", "qop", "time"};
81 
82  TTree* tree = nullptr;
83  // Identification parameters
84  int eventNr = 0;
85  int volumeID = 0;
86  int layerID = 0;
87  int surfaceID = 0;
88 
90  int measType = 1;
91 
94  float trueGx = 0.;
95  float trueGy = 0.;
96  float trueGz = 0.;
97  float incidentPhi = 0.;
98  float incidentTheta = 0.;
99 
103 
109  int nch = 0;
110  int cSize[2] = {};
111  std::array<std::vector<int>*, 2> chId = {nullptr, nullptr};
112  std::vector<float>* chValue = nullptr;
113 
118  void setupTree(const std::string& treeName) {
119  tree = new TTree(treeName.c_str(), treeName.c_str());
120  // Declare the branches
121  tree->Branch("event_nr", &eventNr);
122  tree->Branch("volume_id", &volumeID);
123  tree->Branch("layer_id", &layerID);
124  tree->Branch("surface_id", &surfaceID);
125  tree->Branch("measurement_type", &measType);
126  for (unsigned int ib = 0; ib < int(Acts::eBoundSize); ++ib) {
127  if (ib != int(Acts::eBoundQOverP)) {
128  tree->Branch(std::string("true_" + bNames[ib]).c_str(),
129  &trueBound[ib]);
130  }
131  }
132  tree->Branch("true_x", &trueGx);
133  tree->Branch("true_y", &trueGy);
134  tree->Branch("true_z", &trueGz);
135  tree->Branch("true_incident_phi", &incidentPhi);
136  tree->Branch("true_incident_theta", &incidentTheta);
137  }
138 
141  auto vID = geoID.volume();
142  auto lID = geoID.layer();
143  auto mID = geoID.sensitive();
144  std::string treeName = "vol" + std::to_string(vID);
145  if (lID > 0) {
146  treeName += "_lay" + std::to_string(lID);
147  }
148  if (mID > 0) {
149  treeName += "_mod" + std::to_string(mID);
150  }
151  setupTree(treeName);
152  }
153 
156  delete chId[0];
157  delete chId[1];
158  delete chValue;
159  }
160 
165  tree->Branch(std::string("rec_" + bNames[i]).c_str(), &recBound[i]);
166  tree->Branch(std::string("var_" + bNames[i]).c_str(), &varBound[i]);
167  }
168 
172  void setupClusterBranch(const std::vector<Acts::BoundIndices>& bIndices) {
173  chValue = new std::vector<float>;
174  tree->Branch("clus_size", &nch);
175  tree->Branch("channel_value", &chValue);
176  // Both are allocated, but only relevant ones are set
177  chId[0] = new std::vector<int>;
178  chId[1] = new std::vector<int>;
179  for (const auto& ib : bIndices) {
180  if (static_cast<unsigned int>(ib) < 2) {
181  tree->Branch(std::string("channel_" + bNames[ib]).c_str(), &chId[ib]);
182  tree->Branch(std::string("clus_size_" + bNames[ib]).c_str(),
183  &cSize[ib]);
184  }
185  }
186  }
187 
193  eventNr = evnt;
194  volumeID = geoId.volume();
195  layerID = geoId.layer();
196  surfaceID = geoId.sensitive();
197  }
198 
205  const Acts::Vector3& dir,
206  const std::pair<double, double> angles) {
212 
213  trueGx = xt[Acts::ePos0];
214  trueGy = xt[Acts::ePos1];
215  trueGz = xt[Acts::ePos2];
216 
217  incidentPhi = angles.first;
218  incidentTheta = angles.second;
219  }
220 
226  template <typename measurement_t>
227  void fillBoundMeasurement(const measurement_t& m) {
228  Acts::BoundVector fullVect = m.expander() * m.parameters();
234 
235  Acts::BoundSquareMatrix fullVar =
236  m.expander() * m.covariance() * m.expander().transpose();
243  }
244 
248  void fillCluster(const Cluster& c) {
249  nch = static_cast<int>(c.channels.size());
250  cSize[0] = static_cast<int>(c.sizeLoc0);
251  cSize[1] = static_cast<int>(c.sizeLoc1);
252  for (auto ch : c.channels) {
253  chId[0]->push_back(static_cast<int>(ch.bin[0]));
254  chId[1]->push_back(static_cast<int>(ch.bin[1]));
255  chValue->push_back(static_cast<float>(ch.activation));
256  }
257  }
258  };
259 
264 
266  ~RootMeasurementWriter() override;
267 
269  ProcessCode finalize() override;
270 
272  const Config& config() const { return m_cfg; }
273 
274  protected:
281  const MeasurementContainer& measurements) override;
282 
283  private:
285  std::mutex m_writeMutex;
286  TFile* m_outputFile;
289  std::unordered_map<Acts::GeometryIdentifier, const Acts::Surface*>
291 
294  this, "InputMeasurementSimHitsMap"};
296 };
297 
298 } // namespace ActsExamples