ECCE @ EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
CsvTrackingGeometryWriter.cpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file CsvTrackingGeometryWriter.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 
16 #include <Acts/Utilities/Units.hpp>
17 #include <dfe/dfe_io_dsv.hpp>
18 #include <iostream>
19 #include <sstream>
20 #include <stdexcept>
21 
23 #include "TrackMlData.hpp"
24 
25 using namespace FW;
26 
29  : m_cfg(cfg),
30  m_world(nullptr),
31  m_logger(Acts::getDefaultLogger("CsvTrackingGeometryWriter", lvl))
32 
33 {
34  if (not m_cfg.trackingGeometry) {
35  throw std::invalid_argument("Missing tracking geometry");
36  }
37  m_world = m_cfg.trackingGeometry->highestTrackingVolume();
38  if (not m_world) {
39  throw std::invalid_argument("Could not identify the world volume");
40  }
41 }
42 
43 std::string CsvTrackingGeometryWriter::name() const {
44  return "CsvTrackingGeometryWriter";
45 }
46 
47 namespace {
48 using SurfaceWriter = dfe::NamedTupleCsvWriter<SurfaceData>;
49 
51 void writeSurface(SurfaceWriter& writer, const Acts::Surface& surface,
52  const Acts::GeometryContext& geoCtx) {
54 
55  // encoded and partially decoded geometry identifier
56  data.geometry_id = surface.geoID().value();
57  data.volume_id = surface.geoID().volume();
58  data.layer_id = surface.geoID().layer();
59  data.module_id = surface.geoID().sensitive();
60  // center position
61  auto center = surface.center(geoCtx);
62  data.cx = center.x() / Acts::UnitConstants::mm;
63  data.cy = center.y() / Acts::UnitConstants::mm;
64  data.cz = center.z() / Acts::UnitConstants::mm;
65  // rotation matrix components are unit-less
66  auto transform = surface.transform(geoCtx);
67  data.rot_xu = transform(0, 0);
68  data.rot_xv = transform(0, 1);
69  data.rot_xw = transform(0, 2);
70  data.rot_yu = transform(1, 0);
71  data.rot_yv = transform(1, 1);
72  data.rot_yw = transform(1, 2);
73  data.rot_zu = transform(2, 0);
74  data.rot_zv = transform(2, 1);
75  data.rot_zw = transform(2, 2);
76 
77  // module thickness
78  if (surface.associatedDetectorElement()) {
79  const auto* detElement =
80  dynamic_cast<const Acts::IdentifiedDetectorElement*>(
81  surface.associatedDetectorElement());
82  if (detElement) {
83  data.module_t = detElement->thickness() / Acts::UnitConstants::mm;
84  }
85  }
86 
87  // bounds and pitch (if available)
88  const auto& bounds = surface.bounds();
89  const auto* planarBounds = dynamic_cast<const Acts::PlanarBounds*>(&bounds);
90  if (planarBounds) {
91  // extract limits from value store
92  auto boundValues = surface.bounds().values();
93  if (boundValues.size() == 2) {
94  data.module_minhu = boundValues[0] / Acts::UnitConstants::mm;
95  data.module_minhu = boundValues[0] / Acts::UnitConstants::mm;
96  data.module_minhu = boundValues[1] / Acts::UnitConstants::mm;
97  } else if (boundValues.size() == 3) {
98  data.module_minhu = boundValues[0] / Acts::UnitConstants::mm;
99  data.module_minhu = boundValues[0] / Acts::UnitConstants::mm;
100  data.module_minhu = boundValues[1] / Acts::UnitConstants::mm;
101  }
102  // get the pitch from the digitization module
103  const auto* detElement =
104  dynamic_cast<const Acts::IdentifiedDetectorElement*>(
105  surface.associatedDetectorElement());
106  if (detElement and detElement->digitizationModule()) {
107  auto dModule = detElement->digitizationModule();
108  // dynamic_cast to CartesianSegmentation
109  const auto* cSegmentation =
110  dynamic_cast<const Acts::CartesianSegmentation*>(
111  &(dModule->segmentation()));
112  if (cSegmentation) {
113  auto pitch = cSegmentation->pitch();
114  data.pitch_u = pitch.first / Acts::UnitConstants::mm;
115  data.pitch_u = pitch.second / Acts::UnitConstants::mm;
116  }
117  }
118  }
119 
120  writer.append(data);
121 }
122 
124 void writeVolume(SurfaceWriter& writer, const Acts::TrackingVolume& volume,
125  const Acts::GeometryContext& geoCtx) {
126  // process all layers that are directly stored within this volume
127  if (volume.confinedLayers()) {
128  for (auto layer : volume.confinedLayers()->arrayObjects()) {
129  // we jump navigation layers
130  if (layer->layerType() == Acts::navigation) {
131  continue;
132  }
133  // check for sensitive surfaces
134  if (layer->surfaceArray()) {
135  for (auto surface : layer->surfaceArray()->surfaces()) {
136  if (surface) {
137  writeSurface(writer, *surface, geoCtx);
138  }
139  }
140  }
141  }
142  }
143  // step down into hierarchy to process all child volumnes
144  if (volume.confinedVolumes()) {
145  for (auto confined : volume.confinedVolumes()->arrayObjects()) {
146  writeVolume(writer, *confined.get(), geoCtx);
147  }
148  }
149 }
150 } // namespace
151 
153  if (not m_cfg.writePerEvent) {
154  return ProcessCode::SUCCESS;
155  }
156  SurfaceWriter writer(
157  perEventFilepath(m_cfg.outputDir, "detectors.csv", ctx.eventNumber),
159  writeVolume(writer, *m_world, ctx.geoContext);
160  return ProcessCode::SUCCESS;
161 }
162 
164  SurfaceWriter writer(joinPaths(m_cfg.outputDir, "detectors.csv"),
166  writeVolume(writer, *m_world, Acts::GeometryContext());
167  return ProcessCode::SUCCESS;
168 }