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