Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
MappingMaterialDecorator.hpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file MappingMaterialDecorator.hpp
1 // This file is part of the Acts project.
2 //
3 // Copyright (C) 2017-2022 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 
22 
23 #include <fstream>
24 #include <map>
25 #include <mutex>
26 
27 // Convenience shorthand
28 
29 namespace Acts {
30 
38  public:
39  using BinningMap = std::map<uint64_t, std::pair<int, int>>;
40 
41  using VolumeMaterialMap =
42  std::map<GeometryIdentifier, std::shared_ptr<const IVolumeMaterial>>;
43 
46  bool clearSurfaceMaterial = true,
47  bool clearVolumeMaterial = true)
48  : m_clearSurfaceMaterial(clearSurfaceMaterial),
49  m_clearVolumeMaterial(clearVolumeMaterial),
50  m_logger{getDefaultLogger("MappingMaterialDecorator", level)} {
51  volumeLoop(tGeometry.highestTrackingVolume());
52  }
53 
57  void decorate(Surface& surface) const final {
58  ACTS_VERBOSE("Processing surface: " << surface.geometryId());
59  // Clear the material if registered to do so
61  ACTS_VERBOSE("-> Clearing surface material");
62  surface.assignSurfaceMaterial(nullptr);
63  }
64  // Try to find the surface in the map
65  auto bins = m_binningMap.find(surface.geometryId().value());
66  if (bins != m_binningMap.end()) {
67  ACTS_VERBOSE("-> Found material for surface, assigning");
68  surface.assignSurfaceMaterial(
69  binnedSurfaceMaterial(surface.getSharedPtr()));
70  }
71  }
72 
76  void decorate(TrackingVolume& volume) const final {
77  ACTS_VERBOSE("Processing volume: " << volume.geometryId());
78  // Clear the material if registered to do so
80  ACTS_VERBOSE("-> Clearing volume material");
81  volume.assignVolumeMaterial(nullptr);
82  }
83  // Try to find the volume in the map
84  auto vMaterial = m_volumeMaterialMap.find(volume.geometryId());
85  if (vMaterial != m_volumeMaterialMap.end()) {
86  ACTS_VERBOSE("-> Found material for volume, assigning");
87  volume.assignVolumeMaterial(vMaterial->second);
88  }
89  }
90 
95  void volumeLoop(const Acts::TrackingVolume* tVolume) {
96  auto sameId =
97  [tVolume](
98  const std::pair<Acts::GeometryIdentifier,
99  std::shared_ptr<const IVolumeMaterial>>& pair) {
100  return (tVolume->geometryId() == pair.first);
101  };
102  if (std::find_if(m_volumeMaterialMap.begin(), m_volumeMaterialMap.end(),
103  sameId) != m_volumeMaterialMap.end()) {
104  // this volume was already visited
105  return;
106  }
107  if (tVolume->volumeMaterial() != nullptr) {
108  m_volumeMaterialMap.insert(
109  {tVolume->geometryId(), tVolume->volumeMaterialSharedPtr()});
110  }
111  // there are confined volumes
112  if (tVolume->confinedVolumes() != nullptr) {
113  // get through the volumes
114  auto& volumes = tVolume->confinedVolumes()->arrayObjects();
115  // loop over the volumes
116  for (auto& vol : volumes) {
117  // recursive call
118  volumeLoop(vol.get());
119  }
120  }
121  // there are dense volumes
122  if (!tVolume->denseVolumes().empty()) {
123  // loop over the volumes
124  for (auto& vol : tVolume->denseVolumes()) {
125  // recursive call
126  volumeLoop(vol.get());
127  }
128  }
129  if (tVolume->confinedLayers() != nullptr) {
130  // get the layers
131  auto& layers = tVolume->confinedLayers()->arrayObjects();
132  // loop over the layers
133  for (auto& lay : layers) {
134  auto& layRep = lay->surfaceRepresentation();
135  if (layRep.surfaceMaterial() != nullptr &&
136  layRep.geometryId() != GeometryIdentifier()) {
137  m_binningMap.insert(
138  {layRep.geometryId().value(), std::make_pair(1, 1)});
139  }
140  if (lay->approachDescriptor() != nullptr) {
141  for (auto& asf : lay->approachDescriptor()->containedSurfaces()) {
142  if (asf->surfaceMaterial() != nullptr) {
143  m_binningMap.insert(
144  {asf->geometryId().value(), std::make_pair(1, 1)});
145  }
146  }
147  }
148  if (lay->surfaceArray() != nullptr) {
149  for (auto& ssf : lay->surfaceArray()->surfaces()) {
150  if (ssf->surfaceMaterial() != nullptr) {
151  m_binningMap.insert(
152  {ssf->geometryId().value(), std::make_pair(1, 1)});
153  }
154  }
155  }
156  }
157  }
158  // Let's finally check the boundaries
159  for (auto& bsurf : tVolume->boundarySurfaces()) {
160  // the surface representation
161  auto& bssfRep = bsurf->surfaceRepresentation();
162  if (bssfRep.geometryId().volume() == tVolume->geometryId().volume()) {
163  if (bssfRep.surfaceMaterial() != nullptr) {
164  m_binningMap.insert(
165  {bssfRep.geometryId().value(), std::make_pair(1, 1)});
166  }
167  }
168  }
169  }
170 
174  std::shared_ptr<const Acts::ISurfaceMaterial> binnedSurfaceMaterial(
175  const std::shared_ptr<const Acts::Surface>& surface) const {
176  auto bin = m_binningMap.find(surface->geometryId().value());
177  Acts::BinUtility bUtility;
178  if (bin == m_binningMap.end()) {
179  ACTS_ERROR("No corresponding binning in the map to surface "
180  << surface->geometryId());
181  } else {
182  auto binning = bin->second;
183  // Check which type of bounds is associated to the surface
184  const Acts::SurfaceBounds& surfaceBounds = surface->bounds();
185  const Acts::RadialBounds* radialBounds =
186  dynamic_cast<const Acts::RadialBounds*>(&surfaceBounds);
187  const Acts::CylinderBounds* cylinderBounds =
188  dynamic_cast<const Acts::CylinderBounds*>(&surfaceBounds);
189  const Acts::AnnulusBounds* annulusBounds =
190  dynamic_cast<const Acts::AnnulusBounds*>(&surfaceBounds);
191  const Acts::RectangleBounds* rectangleBounds =
192  dynamic_cast<const Acts::RectangleBounds*>(&surfaceBounds);
193  const Acts::TrapezoidBounds* trapezoidBounds =
194  dynamic_cast<const Acts::TrapezoidBounds*>(&surfaceBounds);
195 
196  if (radialBounds != nullptr) {
197  bUtility += Acts::BinUtility(
198  binning.first,
199  radialBounds->get(Acts::RadialBounds::eAveragePhi) -
201  radialBounds->get(Acts::RadialBounds::eAveragePhi) +
203  (radialBounds->get(Acts::RadialBounds::eHalfPhiSector) - M_PI) <
205  ? Acts::closed
206  : Acts::open,
207  Acts::binPhi);
208  bUtility +=
209  Acts::BinUtility(binning.second, radialBounds->rMin(),
210  radialBounds->rMax(), Acts::open, Acts::binR);
211  }
212  if (cylinderBounds != nullptr) {
213  bUtility += Acts::BinUtility(
214  binning.first,
215  cylinderBounds->get(Acts::CylinderBounds::eAveragePhi) -
216  cylinderBounds->get(Acts::CylinderBounds::eHalfPhiSector),
217  cylinderBounds->get(Acts::CylinderBounds::eAveragePhi) +
218  cylinderBounds->get(Acts::CylinderBounds::eHalfPhiSector),
219  (cylinderBounds->get(Acts::CylinderBounds::eHalfPhiSector) - M_PI) <
221  ? Acts::closed
222  : Acts::open,
223  Acts::binPhi);
224  bUtility += Acts::BinUtility(
225  binning.second,
226  -1 * cylinderBounds->get(Acts::CylinderBounds::eHalfLengthZ),
228  Acts::binZ);
229  }
230  if (annulusBounds != nullptr) {
231  bUtility += Acts::BinUtility(
232  binning.first, annulusBounds->get(Acts::AnnulusBounds::eMinPhiRel),
234  Acts::binPhi);
235  bUtility +=
236  Acts::BinUtility(binning.second, annulusBounds->rMin(),
237  annulusBounds->rMax(), Acts::open, Acts::binR);
238  }
239  if (rectangleBounds != nullptr) {
240  bUtility += Acts::BinUtility(
241  binning.first, rectangleBounds->get(Acts::RectangleBounds::eMinX),
242  rectangleBounds->get(Acts::RectangleBounds::eMaxX), Acts::open,
243  Acts::binX);
244  bUtility += Acts::BinUtility(
245  binning.second, rectangleBounds->get(Acts::RectangleBounds::eMinY),
246  rectangleBounds->get(Acts::RectangleBounds::eMaxY), Acts::open,
247  Acts::binY);
248  }
249  if (trapezoidBounds != nullptr) {
250  double halfLengthX = std::max(
252  trapezoidBounds->get(Acts::TrapezoidBounds::eHalfLengthXposY));
253  bUtility += Acts::BinUtility(binning.first, -1 * halfLengthX,
254  halfLengthX, Acts::open, Acts::binX);
255  bUtility += Acts::BinUtility(
256  binning.second,
257  -1 * trapezoidBounds->get(Acts::TrapezoidBounds::eHalfLengthY),
258  trapezoidBounds->get(Acts::TrapezoidBounds::eHalfLengthY),
260  }
261  }
262  return std::make_shared<Acts::ProtoSurfaceMaterial>(bUtility);
263  }
264 
267 
270  m_binningMap = std::move(binningMap);
271  }
272 
273  private:
275 
277 
280 
281  std::unique_ptr<const Logger> m_logger;
282 
283  const Logger& logger() const { return *m_logger; }
284 };
285 } // namespace Acts