Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
CsvPlanarClusterWriter.cpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file CsvPlanarClusterWriter.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 
26 
27 #include <ostream>
28 #include <stdexcept>
29 #include <utility>
30 #include <vector>
31 
32 #include <dfe/dfe_io_dsv.hpp>
33 
34 #include "CsvOutputData.hpp"
35 
39  : WriterT(config.inputClusters, "CsvPlanarClusterWriter", level),
40  m_cfg(config) {
41  // inputClusters is already checked by base constructor
42  if (m_cfg.inputSimHits.empty()) {
43  throw std::invalid_argument("Missing simulated hits input collection");
44  }
45  if (not m_cfg.trackingGeometry) {
46  throw std::invalid_argument("Missing tracking geometry");
47  }
48 
50 }
51 
53  const AlgorithmContext& ctx,
55  clusters) {
56  // retrieve simulated hits
57  const auto& simHits = m_inputSimHits(ctx);
58 
59  // open per-event file for all components
60  std::string pathHits =
61  perEventFilepath(m_cfg.outputDir, "hits.csv", ctx.eventNumber);
62  std::string pathCells =
63  perEventFilepath(m_cfg.outputDir, "cells.csv", ctx.eventNumber);
64  std::string pathTruth =
65  perEventFilepath(m_cfg.outputDir, "truth.csv", ctx.eventNumber);
66 
67  dfe::NamedTupleCsvWriter<HitData> writerHits(pathHits, m_cfg.outputPrecision);
68  dfe::NamedTupleCsvWriter<CellDataLegacy> writerCells(pathCells,
69  m_cfg.outputPrecision);
70  dfe::NamedTupleCsvWriter<TruthHitData> writerTruth(pathTruth,
71  m_cfg.outputPrecision);
72 
73  HitData hit;
74  CellDataLegacy cell;
75  TruthHitData truth;
76  // will be reused as hit counter
77  hit.hit_id = 0;
78 
79  for (auto [moduleGeoId, moduleClusters] : groupByModule(clusters)) {
80  const Acts::Surface* surfacePtr =
81  m_cfg.trackingGeometry->findSurface(moduleGeoId);
82  if (surfacePtr == nullptr) {
83  ACTS_ERROR("Could not find surface for " << moduleGeoId);
84  return ProcessCode::ABORT;
85  }
86 
87  // encoded geometry identifier. same for all hits on the module
88  hit.geometry_id = moduleGeoId.value();
89 
90  for (const auto& entry : moduleClusters) {
91  const Acts::PlanarModuleCluster& cluster = entry.second;
92  // local cluster information
93  const auto& parameters = cluster.parameters();
94  Acts::Vector2 localPos(parameters[0], parameters[1]);
95  Acts::Vector3 globalFakeMom(1, 1, 1);
96  Acts::Vector3 globalPos =
97  surfacePtr->localToGlobal(ctx.geoContext, localPos, globalFakeMom);
98 
99  // write global hit information
100  hit.x = globalPos.x() / Acts::UnitConstants::mm;
101  hit.y = globalPos.y() / Acts::UnitConstants::mm;
102  hit.z = globalPos.z() / Acts::UnitConstants::mm;
104  writerHits.append(hit);
105 
106  // write local cell information
107  cell.hit_id = hit.hit_id;
108  for (auto& c : cluster.digitizationCells()) {
109  cell.channel0 = c.channel0;
110  cell.channel1 = c.channel1;
111  // TODO store digital timestamp once added to the cell definition
112  cell.timestamp = 0;
113  cell.value = c.data;
114  writerCells.append(cell);
115  }
116 
117  // write hit-particle truth association
118  // each hit can have multiple particles, e.g. in a dense environment
119  truth.hit_id = hit.hit_id;
120  truth.geometry_id = hit.geometry_id;
121  const auto& sl = cluster.sourceLink().get<Acts::DigitizationSourceLink>();
122  for (auto idx : sl.indices()) {
123  auto it = simHits.nth(idx);
124  if (it == simHits.end()) {
125  ACTS_FATAL("Simulation hit with index " << idx << " does not exist");
126  return ProcessCode::ABORT;
127  }
128 
129  const auto& simHit = *it;
130  truth.particle_id = simHit.particleId().value();
131  // hit position
132  truth.tx = simHit.position().x() / Acts::UnitConstants::mm;
133  truth.ty = simHit.position().y() / Acts::UnitConstants::mm;
134  truth.tz = simHit.position().z() / Acts::UnitConstants::mm;
135  truth.tt = simHit.time() / Acts::UnitConstants::ns;
136  // particle four-momentum before interaction
137  truth.tpx = simHit.momentum4Before().x() / Acts::UnitConstants::GeV;
138  truth.tpy = simHit.momentum4Before().y() / Acts::UnitConstants::GeV;
139  truth.tpz = simHit.momentum4Before().z() / Acts::UnitConstants::GeV;
140  truth.te = simHit.momentum4Before().w() / Acts::UnitConstants::GeV;
141  // particle four-momentum change due to interaction
142  const auto delta4 = simHit.momentum4After() - simHit.momentum4Before();
143  truth.deltapx = delta4.x() / Acts::UnitConstants::GeV;
144  truth.deltapy = delta4.y() / Acts::UnitConstants::GeV;
145  truth.deltapz = delta4.z() / Acts::UnitConstants::GeV;
146  truth.deltae = delta4.w() / Acts::UnitConstants::GeV;
147  // TODO write hit index along the particle trajectory
148  truth.index = simHit.index();
149  writerTruth.append(truth);
150  }
151 
152  // increase hit id for next iteration
153  hit.hit_id += 1;
154  }
155  }
156 
158 }