Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
TGeoLayerBuilder.cpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file TGeoLayerBuilder.cpp
1 // This file is part of the Acts project.
2 //
3 // Copyright (C) 2017-2018 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 
11 #include "Acts/Geometry/Extent.hpp"
21 
22 #include <ostream>
23 #include <stdexcept>
24 
25 #include "TGeoManager.h"
26 #include "TGeoMatrix.h"
27 
28 namespace Acts {
29 class ISurfaceMaterial;
30 } // namespace Acts
31 
34  std::unique_ptr<const Logger> logger)
35  : m_cfg(), m_logger(std::move(logger)) {
36  setConfiguration(config);
37 }
38 
40 
43  m_cfg = config;
44 }
45 
47  std::unique_ptr<const Logger> newLogger) {
48  m_logger = std::move(newLogger);
49 }
50 
52  const GeometryContext& gctx) const {
53  // @todo Remove this hack once the m_elementStore mess is sorted out
54  auto mutableThis = const_cast<TGeoLayerBuilder*>(this);
55  LayerVector nVector;
56  mutableThis->buildLayers(gctx, nVector, -1);
57  return nVector;
58 }
59 
61  const GeometryContext& gctx) const {
62  // @todo Remove this hack once the m_elementStore mess is sorted out
63  auto mutableThis = const_cast<TGeoLayerBuilder*>(this);
64  LayerVector cVector;
65  mutableThis->buildLayers(gctx, cVector, 0);
66  return cVector;
67 }
68 
70  const GeometryContext& gctx) const {
71  // @todo Remove this hack once the m_elementStore mess is sorted out
72  auto mutableThis = const_cast<TGeoLayerBuilder*>(this);
73  LayerVector pVector;
74  mutableThis->buildLayers(gctx, pVector, 1);
75  return pVector;
76 }
77 
79  LayerVector& layers, int type) {
80  // Bail out if you have no gGeoManager
81  if (gGeoManager == nullptr) {
82  ACTS_WARNING("No gGeoManager found - bailing out.");
83  return;
84  }
85 
86  using LayerSurfaceVector = std::vector<std::shared_ptr<const Surface>>;
87  LayerSurfaceVector layerSurfaces;
88 
89  std::vector<LayerConfig> layerConfigs = m_cfg.layerConfigurations[type + 1];
90  std::string layerType = m_layerTypes[type + 1];
91 
92  // Appropriate screen output
93  std::string addonOutput = m_cfg.layerSplitToleranceR[type + 1] > 0.
94  ? std::string(", splitting in r")
95  : std::string("");
96  addonOutput += m_cfg.layerSplitToleranceZ[type + 1] > 0.
97  ? std::string(", splitting in z")
98  : std::string("");
99  addonOutput += std::string(".");
100 
101  // Screen output of the configuration
102  ACTS_DEBUG(layerType << " layers : found " << layerConfigs.size()
103  << " configuration(s)" + addonOutput);
104 
105  // Helper function to fill the layer
106  auto fillLayer = [&](const LayerSurfaceVector& lSurfaces,
107  const LayerConfig& lCfg,
108  unsigned int pl_id = 0) -> void {
109  int nb0 = 0, nt0 = 0;
110  bool is_autobinning = ((lCfg.binning0.size() == 1) and
111  (std::get<int>(lCfg.binning0.at(0)) <= 0));
112  if (!is_autobinning and std::get<int>(lCfg.binning0.at(pl_id)) <= 0) {
113  throw std::invalid_argument(
114  "Incorrect binning configuration found for loc0 protolayer #" +
115  std::to_string(pl_id) +
116  ". Layer is autobinned: No mixed binning (manual and auto) for loc0 "
117  "possible between layers in a single subvolume. Quitting");
118  }
119  if (is_autobinning) {
120  // Set binning by hand if nb0 > 0 and nb1 > 0
121  nb0 = std::get<int>(lCfg.binning0.at(0));
122  // Read the binning type
123  nt0 = std::get<BinningType>(lCfg.binning0.at(0));
124  } else if (pl_id < lCfg.binning0.size()) {
125  // Set binning by hand if nb0 > 0 and nb1 > 0
126  nb0 = std::get<int>(lCfg.binning0.at(pl_id));
127  }
128 
129  int nb1 = 0, nt1 = 0;
130  is_autobinning = (lCfg.binning1.size() == 1) and
131  (std::get<int>(lCfg.binning1.at(0)) <= 0);
132  if (!is_autobinning and std::get<int>(lCfg.binning1.at(pl_id)) <= 0) {
133  throw std::invalid_argument(
134  "Incorrect binning configuration found for loc1 protolayer #" +
135  std::to_string(pl_id) +
136  ". Layer is autobinned: No mixed binning (manual and auto) for loc1 "
137  "possible between layers in a single subvolume. Quitting");
138  }
139  if (is_autobinning) {
140  // Set binning by hand if nb0 > 0 and nb1 > 0
141  nb1 = std::get<int>(lCfg.binning1.at(0));
142  // For a binning type
143  nt1 = std::get<BinningType>(lCfg.binning1.at(0));
144  } else if (pl_id < lCfg.binning1.size()) {
145  // Set binning by hand if nb0 > 0 and nb1 > 0
146  nb1 = std::get<int>(lCfg.binning1.at(pl_id));
147  }
148 
149  if (type == 0) {
150  ProtoLayer pl(gctx, lSurfaces);
151  ACTS_DEBUG("- creating CylinderLayer with "
152  << lSurfaces.size() << " surfaces at r = " << pl.medium(binR));
153 
154  pl.envelope[Acts::binR] = {lCfg.envelope.first, lCfg.envelope.second};
155  pl.envelope[Acts::binZ] = {lCfg.envelope.second, lCfg.envelope.second};
156  if (nb0 >= 0 and nb1 >= 0) {
157  layers.push_back(
158  m_cfg.layerCreator->cylinderLayer(gctx, lSurfaces, nb0, nb1, pl));
159  } else {
160  layers.push_back(
161  m_cfg.layerCreator->cylinderLayer(gctx, lSurfaces, nt0, nt1, pl));
162  }
163  } else {
164  ProtoLayer pl(gctx, lSurfaces);
165  ACTS_DEBUG("- creating DiscLayer with "
166  << lSurfaces.size() << " surfaces at z = " << pl.medium(binZ));
167 
168  pl.envelope[Acts::binR] = {lCfg.envelope.first, lCfg.envelope.second};
169  pl.envelope[Acts::binZ] = {lCfg.envelope.second, lCfg.envelope.second};
170  if (nb0 >= 0 and nb1 >= 0) {
171  layers.push_back(
172  m_cfg.layerCreator->discLayer(gctx, lSurfaces, nb0, nb1, pl));
173  } else {
174  layers.push_back(
175  m_cfg.layerCreator->discLayer(gctx, lSurfaces, nt0, nt1, pl));
176  }
177  }
178  };
179 
180  for (auto layerCfg : layerConfigs) {
181  ACTS_DEBUG("- layer configuration found for layer " << layerCfg.volumeName
182  << " with sensors ");
183  for (auto& sensor : layerCfg.sensorNames) {
184  ACTS_DEBUG(" - sensor: " << sensor);
185  }
186  if (not layerCfg.parseRanges.empty()) {
187  for (const auto& pRange : layerCfg.parseRanges) {
188  ACTS_DEBUG("- layer parsing restricted in "
189  << binningValueNames()[pRange.first] << " to ["
190  << pRange.second.first << "/" << pRange.second.second
191  << "].");
192  }
193  }
194  if (not layerCfg.splitConfigs.empty()) {
195  for (const auto& sConfig : layerCfg.splitConfigs) {
196  ACTS_DEBUG("- layer splitting attempt in "
197  << binningValueNames()[sConfig.first] << " with tolerance "
198  << sConfig.second << ".");
199  }
200  }
201 
202  // Either pick the configured volume or take the top level volume
203  TGeoVolume* tVolume =
204  gGeoManager->FindVolumeFast(layerCfg.volumeName.c_str());
205  if (tVolume == nullptr) {
206  tVolume = gGeoManager->GetTopVolume();
207  ACTS_DEBUG("- search volume is TGeo top volume");
208  } else {
209  ACTS_DEBUG("- setting search volume to " << tVolume->GetName());
210  }
211 
212  if (tVolume != nullptr) {
213  TGeoParser::Options tgpOptions;
214  tgpOptions.volumeNames = {layerCfg.volumeName};
215  tgpOptions.targetNames = layerCfg.sensorNames;
216  tgpOptions.parseRanges = layerCfg.parseRanges;
217  tgpOptions.unit = m_cfg.unit;
218  TGeoParser::State tgpState;
219  tgpState.volume = tVolume;
220 
221  ACTS_DEBUG("- applying " << layerCfg.parseRanges.size()
222  << " search restrictions.");
223  for (const auto& prange : layerCfg.parseRanges) {
224  ACTS_VERBOSE(" - range " << binningValueNames()[prange.first]
225  << " within [ " << prange.second.first << ", "
226  << prange.second.second << "]");
227  }
228 
229  TGeoParser::select(tgpState, tgpOptions);
230 
231  ACTS_DEBUG("- number of selected nodes found : "
232  << tgpState.selectedNodes.size());
233 
234  for (auto& snode : tgpState.selectedNodes) {
235  auto identifier =
236  m_cfg.identifierProvider != nullptr
237  ? m_cfg.identifierProvider->identify(gctx, *snode.node)
238  : Identifier();
239 
240  auto tgElement =
241  m_cfg.elementFactory(identifier, *snode.node, *snode.transform,
242  layerCfg.localAxes, m_cfg.unit, nullptr);
243 
244  std::vector<std::shared_ptr<const Acts::TGeoDetectorElement>>
245  tgElements =
246  (m_cfg.detectorElementSplitter == nullptr)
247  ? std::vector<std::shared_ptr<
248  const Acts::TGeoDetectorElement>>{tgElement}
249  : m_cfg.detectorElementSplitter->split(gctx, tgElement);
250 
251  for (const auto& tge : tgElements) {
252  m_elementStore.push_back(tge);
253  layerSurfaces.push_back(tge->surface().getSharedPtr());
254  }
255  }
256 
257  ACTS_DEBUG("- created TGeoDetectorElements : " << layerSurfaces.size());
258 
259  if (m_cfg.protoLayerHelper != nullptr and
260  not layerCfg.splitConfigs.empty()) {
261  auto protoLayers = m_cfg.protoLayerHelper->protoLayers(
262  gctx, unpack_shared_vector(layerSurfaces), layerCfg.splitConfigs);
263  ACTS_DEBUG("- splitting into " << protoLayers.size() << " layers.");
264 
265  // Number of options mismatch and has not been configured for
266  // auto-binning
267  const bool is_loc0_n_config =
268  layerCfg.binning0.size() == protoLayers.size();
269  const bool is_loc0_autobinning =
270  (layerCfg.binning0.size() == 1) and
271  (std::get<int>(layerCfg.binning0.at(0)) <= 0);
272  const bool is_loc1_n_config =
273  layerCfg.binning1.size() == protoLayers.size();
274  const bool is_loc1_autobinning =
275  (layerCfg.binning1.size() == 1) and
276  (std::get<int>(layerCfg.binning1.at(0)) <= 0);
277  if ((!is_loc0_n_config and !is_loc0_autobinning) or
278  (!is_loc1_n_config and !is_loc1_autobinning)) {
279  throw std::invalid_argument(
280  "Incorrect binning configuration found: Number of configurations "
281  "does not match number of protolayers in subvolume " +
282  layerCfg.volumeName + ". Quitting.");
283  }
284  unsigned int layer_id = 0;
285  for (auto& pLayer : protoLayers) {
286  layerSurfaces.clear();
287 
288  for (const auto& lsurface : pLayer.surfaces()) {
289  layerSurfaces.push_back(lsurface->getSharedPtr());
290  }
291  fillLayer(layerSurfaces, layerCfg, layer_id);
292  layer_id++;
293  }
294  } else {
295  fillLayer(layerSurfaces, layerCfg);
296  }
297  }
298  }
299  return;
300 }
301 
302 std::shared_ptr<Acts::TGeoDetectorElement>
304  const Identifier& identifier, const TGeoNode& tGeoNode,
305  const TGeoMatrix& tGeoMatrix, const std::string& axes, double scalor,
306  std::shared_ptr<const Acts::ISurfaceMaterial> material) {
307  return std::make_shared<TGeoDetectorElement>(
308  identifier, tGeoNode, tGeoMatrix, axes, scalor, std::move(material));
309 }