EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
LayerCreator.cpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file LayerCreator.cpp
1 // This file is part of the Acts project.
2 //
3 // Copyright (C) 2016-2020 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 
20 #include "Acts/Utilities/Units.hpp"
21 
22 #include <cmath>
23 #include <set>
24 
27 
29  std::unique_ptr<const Logger> logger)
30  : m_cfg(lcConfig), m_logger(std::move(logger)) {}
31 
33  const Acts::LayerCreator::Config& lcConfig) {
34  // @todo check consistency
35  // copy the configuration
36  m_cfg = lcConfig;
37 }
38 
39 void Acts::LayerCreator::setLogger(std::unique_ptr<const Logger> newLogger) {
40  m_logger = std::move(newLogger);
41 }
42 
44  const GeometryContext& gctx,
45  std::vector<std::shared_ptr<const Surface>> surfaces, size_t binsPhi,
46  size_t binsZ, std::optional<ProtoLayer> _protoLayer,
47  const Transform3D& transform,
48  std::unique_ptr<ApproachDescriptor> ad) const {
49  ProtoLayer protoLayer =
50  _protoLayer ? *_protoLayer : ProtoLayer(gctx, surfaces);
51 
52  // Remaining layer parameters - they include the envelopes
53  double layerR = protoLayer.medium(binR);
54  double layerZ = protoLayer.medium(binZ);
55  double layerHalfZ = 0.5 * protoLayer.range(binZ);
56  double layerThickness = protoLayer.range(binR);
57 
58  ACTS_VERBOSE("Creating a cylindrical Layer:");
59  ACTS_VERBOSE(" - with layer R = " << layerR);
60  ACTS_VERBOSE(" - from R min/max = " << protoLayer.min(binR, false) << " / "
61  << protoLayer.max(binR, false));
62  ACTS_VERBOSE(" - with R thickness = " << layerThickness);
63  ACTS_VERBOSE(" - incl envelope = " << protoLayer.envelope[binR].first
64  << " / "
65  << protoLayer.envelope[binR].second);
66 
67  ACTS_VERBOSE(" - with z min/max = "
68  << protoLayer.min(binZ, false) << " (-"
69  << protoLayer.envelope[binZ].first << ") / "
70  << protoLayer.max(binZ, false) << " (+"
71  << protoLayer.envelope[binZ].second << ")");
72 
73  ACTS_VERBOSE(" - z center = " << layerZ);
74  ACTS_VERBOSE(" - halflength z = " << layerHalfZ);
75 
76  // create the layer transforms if not given
77  // we need to transform in case layerZ != 0, so that the layer will be
78  // correctly defined using the halflength
79  Translation3D addTranslation(0., 0., 0.);
80  if (transform.isApprox(s_idTransform)) {
81  // double shift = -(layerZ + envZShift);
82  addTranslation = Translation3D(0., 0., layerZ);
83  ACTS_VERBOSE(" - layer z shift = " << -layerZ);
84  }
85 
86  ACTS_VERBOSE(" - with phi min/max = " << protoLayer.min(binPhi, false)
87  << " / "
88  << protoLayer.max(binPhi, false));
89  ACTS_VERBOSE(" - # of modules = " << surfaces.size() << " ordered in ( "
90  << binsPhi << " x " << binsZ << ")");
91  std::unique_ptr<SurfaceArray> sArray;
92  if (!surfaces.empty()) {
93  sArray = m_cfg.surfaceArrayCreator->surfaceArrayOnCylinder(
94  gctx, std::move(surfaces), binsPhi, binsZ, protoLayer);
95 
96  checkBinning(gctx, *sArray);
97  }
98 
99  // create the layer and push it back
100  std::shared_ptr<const CylinderBounds> cBounds(
101  new CylinderBounds(layerR, layerHalfZ));
102 
103  // create the layer
105  addTranslation * transform, cBounds, std::move(sArray), layerThickness,
106  std::move(ad), active);
107 
108  if (!cLayer)
109  ACTS_ERROR("Creation of cylinder layer did not succeed!");
110  associateSurfacesToLayer(*cLayer);
111 
112  // now return
113  return cLayer;
114 }
115 
117  const GeometryContext& gctx,
118  std::vector<std::shared_ptr<const Surface>> surfaces, BinningType bTypePhi,
119  BinningType bTypeZ, std::optional<ProtoLayer> _protoLayer,
120  const Transform3D& transform,
121  std::unique_ptr<ApproachDescriptor> ad) const {
122  ProtoLayer protoLayer =
123  _protoLayer ? *_protoLayer : ProtoLayer(gctx, surfaces);
124 
125  // remaining layer parameters
126  double layerR = protoLayer.medium(binR);
127  double layerZ = protoLayer.medium(binZ);
128  double layerHalfZ = 0.5 * protoLayer.range(binZ);
129  double layerThickness = protoLayer.range(binR);
130 
131  // adjust the layer radius
132  ACTS_VERBOSE("Creating a cylindrical Layer:");
133  ACTS_VERBOSE(" - with layer R = " << layerR);
134  ACTS_VERBOSE(" - from R min/max = " << protoLayer.min(binR, false) << " / "
135  << protoLayer.max(binR, false));
136  ACTS_VERBOSE(" - with R thickness = " << layerThickness);
137  ACTS_VERBOSE(" - incl envelope = " << protoLayer.envelope[binR].first
138  << " / "
139  << protoLayer.envelope[binR].second);
140  ACTS_VERBOSE(" - with z min/max = "
141  << protoLayer.min(binZ, false) << " (-"
142  << protoLayer.envelope[binZ].first << ") / "
143  << protoLayer.max(binZ, false) << " (+"
144  << protoLayer.envelope[binZ].second << ")");
145  ACTS_VERBOSE(" - z center = " << layerZ);
146  ACTS_VERBOSE(" - halflength z = " << layerHalfZ);
147 
148  // create the layer transforms if not given
149  // we need to transform in case layerZ != 0, so that the layer will be
150  // correctly defined using the halflength
151  // create the layer transforms if not given
152  Translation3D addTranslation(0., 0., 0.);
153  if (transform.isApprox(s_idTransform) && bTypeZ == equidistant) {
154  addTranslation = Translation3D(0., 0., layerZ);
155  ACTS_VERBOSE(" - layer z shift = " << -layerZ);
156  }
157 
158  ACTS_VERBOSE(" - with phi min/max = " << protoLayer.min(binPhi, false)
159  << " / "
160  << protoLayer.max(binPhi, false));
161  ACTS_VERBOSE(" - # of modules = " << surfaces.size() << "");
162 
163  // create the surface array
164  std::unique_ptr<SurfaceArray> sArray;
165  if (!surfaces.empty()) {
166  sArray = m_cfg.surfaceArrayCreator->surfaceArrayOnCylinder(
167  gctx, std::move(surfaces), bTypePhi, bTypeZ, protoLayer);
168 
169  checkBinning(gctx, *sArray);
170  }
171 
172  // create the layer and push it back
173  std::shared_ptr<const CylinderBounds> cBounds(
174  new CylinderBounds(layerR, layerHalfZ));
175 
176  // create the layer
178  addTranslation * transform, cBounds, std::move(sArray), layerThickness,
179  std::move(ad), active);
180 
181  if (!cLayer)
182  ACTS_ERROR("Creation of cylinder layer did not succeed!");
183  associateSurfacesToLayer(*cLayer);
184 
185  // now return
186  return cLayer;
187 }
188 
190  const GeometryContext& gctx,
191  std::vector<std::shared_ptr<const Surface>> surfaces, size_t binsR,
192  size_t binsPhi, std::optional<ProtoLayer> _protoLayer,
193  const Transform3D& transform,
194  std::unique_ptr<ApproachDescriptor> ad) const {
195  ProtoLayer protoLayer =
196  _protoLayer ? *_protoLayer : ProtoLayer(gctx, surfaces);
197 
198  double layerZ = protoLayer.medium(binZ);
199  double layerThickness = protoLayer.range(binZ);
200 
201  // adjust the layer radius
202  ACTS_VERBOSE("Creating a disk Layer:");
203  ACTS_VERBOSE(" - at Z position = " << layerZ);
204  ACTS_VERBOSE(" - from Z min/max = " << protoLayer.min(binZ, false) << " / "
205  << protoLayer.max(binZ, false));
206  ACTS_VERBOSE(" - with Z thickness = " << layerThickness);
207  ACTS_VERBOSE(" - incl envelope = " << protoLayer.envelope[binZ].first
208  << " / "
209  << protoLayer.envelope[binZ].second);
210  ACTS_VERBOSE(" - with R min/max = "
211  << protoLayer.min(binR, false) << " (-"
212  << protoLayer.envelope[binR].first << ") / "
213  << protoLayer.max(binR, false) << " (+"
214  << protoLayer.envelope[binR].second << ")");
215  ACTS_VERBOSE(" - with phi min/max = " << protoLayer.min(binPhi, false)
216  << " / "
217  << protoLayer.max(binPhi, false));
218  ACTS_VERBOSE(" - # of modules = " << surfaces.size() << " ordered in ( "
219  << binsR << " x " << binsPhi << ")");
220 
221  // create the layer transforms if not given
222  Translation3D addTranslation(0., 0., 0.);
223  if (transform.isApprox(s_idTransform)) {
224  addTranslation = Translation3D(0., 0., layerZ);
225  }
226  // create the surface array
227  std::unique_ptr<SurfaceArray> sArray;
228  if (!surfaces.empty()) {
229  sArray = m_cfg.surfaceArrayCreator->surfaceArrayOnDisc(
230  gctx, std::move(surfaces), binsR, binsPhi, protoLayer, transform);
231 
232  checkBinning(gctx, *sArray);
233  }
234 
235  // create the share disc bounds
236  auto dBounds = std::make_shared<const RadialBounds>(protoLayer.min(binR),
237  protoLayer.max(binR));
238 
239  // create the layers
240  // we use the same transform here as for the layer itself
241  // for disk this is fine since we don't bin in Z, so does not matter
242  MutableLayerPtr dLayer =
243  DiscLayer::create(addTranslation * transform, dBounds, std::move(sArray),
244  layerThickness, std::move(ad), active);
245 
246  if (!dLayer)
247  ACTS_ERROR("Creation of disc layer did not succeed!");
248  associateSurfacesToLayer(*dLayer);
249  // return the layer
250  return dLayer;
251 }
252 
254  const GeometryContext& gctx,
255  std::vector<std::shared_ptr<const Surface>> surfaces, BinningType bTypeR,
256  BinningType bTypePhi, std::optional<ProtoLayer> _protoLayer,
257  const Transform3D& transform,
258  std::unique_ptr<ApproachDescriptor> ad) const {
259  ProtoLayer protoLayer =
260  _protoLayer ? *_protoLayer : ProtoLayer(gctx, surfaces);
261 
262  double layerZ = protoLayer.medium(binZ);
263  double layerThickness = protoLayer.range(binZ);
264 
265  // adjust the layer radius
266  ACTS_VERBOSE("Creating a disk Layer:");
267  ACTS_VERBOSE(" - at Z position = " << layerZ);
268  ACTS_VERBOSE(" - from Z min/max = " << protoLayer.min(binZ, false) << " / "
269  << protoLayer.max(binZ, false));
270  ACTS_VERBOSE(" - with Z thickness = " << layerThickness);
271  ACTS_VERBOSE(" - incl envelope = " << protoLayer.envelope[binZ].first
272  << " / "
273  << protoLayer.envelope[binZ].second);
274  ACTS_VERBOSE(" - with R min/max = "
275  << protoLayer.min(binR, false) << " (-"
276  << protoLayer.envelope[binR].first << ") / "
277  << protoLayer.max(binR, false) << " (+"
278  << protoLayer.envelope[binR].second << ")");
279  ACTS_VERBOSE(" - with phi min/max = " << protoLayer.min(binPhi, false)
280  << " / "
281  << protoLayer.max(binPhi, false));
282  ACTS_VERBOSE(" - # of modules = " << surfaces.size());
283 
284  // create the layer transforms if not given
285  Translation3D addTranslation(0., 0., 0.);
286  if (transform.isApprox(s_idTransform)) {
287  addTranslation = Translation3D(0., 0., layerZ);
288  }
289 
290  // create the surface array
291  std::unique_ptr<SurfaceArray> sArray;
292  if (!surfaces.empty()) {
293  sArray = m_cfg.surfaceArrayCreator->surfaceArrayOnDisc(
294  gctx, std::move(surfaces), bTypeR, bTypePhi, protoLayer, transform);
295 
296  checkBinning(gctx, *sArray);
297  }
298 
299  // create the shared disc bounds
300  auto dBounds = std::make_shared<const RadialBounds>(protoLayer.min(binR),
301  protoLayer.max(binR));
302 
303  // create the layers
304  MutableLayerPtr dLayer =
305  DiscLayer::create(addTranslation * transform, dBounds, std::move(sArray),
306  layerThickness, std::move(ad), active);
307  if (!dLayer) {
308  ACTS_ERROR("Creation of disc layer did not succeed!");
309  }
310  associateSurfacesToLayer(*dLayer);
311  // return the layer
312  return dLayer;
313 }
314 
316  const GeometryContext& gctx,
317  std::vector<std::shared_ptr<const Surface>> surfaces, size_t bins1,
318  size_t bins2, BinningValue bValue, std::optional<ProtoLayer> _protoLayer,
319  const Transform3D& transform,
320  std::unique_ptr<ApproachDescriptor> ad) const {
321  ProtoLayer protoLayer =
322  _protoLayer ? *_protoLayer : ProtoLayer(gctx, surfaces);
323 
324  // remaining layer parameters
325  double layerHalf1, layerHalf2, layerThickness;
326  switch (bValue) {
327  case BinningValue::binX: {
328  layerHalf1 = 0.5 * (protoLayer.max(binY) - protoLayer.min(binY));
329  layerHalf2 = 0.5 * (protoLayer.max(binZ) - protoLayer.min(binZ));
330  layerThickness = (protoLayer.max(binX) - protoLayer.min(binX));
331  break;
332  }
333  case BinningValue::binY: {
334  layerHalf1 = 0.5 * (protoLayer.max(binX) - protoLayer.min(binX));
335  layerHalf2 = 0.5 * (protoLayer.max(binZ) - protoLayer.min(binZ));
336  layerThickness = (protoLayer.max(binY) - protoLayer.min(binY));
337  break;
338  }
339  default: {
340  layerHalf1 = 0.5 * (protoLayer.max(binX) - protoLayer.min(binX));
341  layerHalf2 = 0.5 * (protoLayer.max(binY) - protoLayer.min(binY));
342  layerThickness = (protoLayer.max(binZ) - protoLayer.min(binZ));
343  }
344  }
345 
346  double centerX = 0.5 * (protoLayer.max(binX) + protoLayer.min(binX));
347  double centerY = 0.5 * (protoLayer.max(binY) + protoLayer.min(binY));
348  double centerZ = 0.5 * (protoLayer.max(binZ) + protoLayer.min(binZ));
349 
350  ACTS_VERBOSE("Creating a plane Layer:");
351  ACTS_VERBOSE(" - with layer center = "
352  << "(" << centerX << ", " << centerY << ", " << centerZ << ")");
353  ACTS_VERBOSE(" - from X min/max = " << protoLayer.min(binX) << " / "
354  << protoLayer.max(binX));
355  ACTS_VERBOSE(" - from Y min/max = " << protoLayer.min(binY) << " / "
356  << protoLayer.max(binY));
357  ACTS_VERBOSE(" - with Z thickness = " << layerThickness);
358 
359  // create the layer transforms if not given
360  // we need to transform in case centerX/centerY/centerZ != 0, so that the
361  // layer will be correctly defined
362  Translation3D addTranslation(0., 0., 0.);
363  if (transform.isApprox(s_idTransform)) {
364  // double shift = (layerZ + envZShift);
365  addTranslation = Translation3D(centerX, centerY, centerZ);
366  ACTS_VERBOSE(" - layer shift = "
367  << "(" << centerX << ", " << centerY << ", " << centerZ
368  << ")");
369  }
370 
371  std::unique_ptr<SurfaceArray> sArray;
372  if (!surfaces.empty()) {
373  sArray = m_cfg.surfaceArrayCreator->surfaceArrayOnPlane(
374  gctx, std::move(surfaces), bins1, bins2, bValue, protoLayer, transform);
375 
376  checkBinning(gctx, *sArray);
377  }
378 
379  // create the layer and push it back
380  std::shared_ptr<const PlanarBounds> pBounds(
381  new RectangleBounds(layerHalf1, layerHalf2));
382 
383  // create the layer
384  MutableLayerPtr pLayer =
385  PlaneLayer::create(addTranslation * transform, pBounds, std::move(sArray),
386  layerThickness, std::move(ad), active);
387 
388  if (!pLayer) {
389  ACTS_ERROR("Creation of plane layer did not succeed!");
390  }
391  associateSurfacesToLayer(*pLayer);
392 
393  // now return
394  return pLayer;
395 }
396 
398  if (layer.surfaceArray() != nullptr) {
399  auto surfaces = layer.surfaceArray()->surfaces();
400 
401  for (auto& surface : surfaces) {
402  auto mutableSurface = const_cast<Surface*>(surface);
403  mutableSurface->associateLayer(layer);
404  }
405  }
406 }
407 
409  const SurfaceArray& sArray) const {
410  // do consistency check: can we access all sensitive surfaces
411  // through the binning? If not, surfaces get lost and the binning does not
412  // work
413 
414  ACTS_VERBOSE("Performing consistency check")
415 
416  std::vector<const Surface*> surfaces = sArray.surfaces();
417  std::set<const Surface*> sensitiveSurfaces(surfaces.begin(), surfaces.end());
418  std::set<const Surface*> accessibleSurfaces;
419  size_t nEmptyBins = 0;
420  size_t nBinsChecked = 0;
421 
422  // iterate over all bins
423  size_t size = sArray.size();
424  for (size_t b = 0; b < size; ++b) {
425  std::vector<const Surface*> binContent = sArray.at(b);
426  // we don't check under/overflow bins
427  if (!sArray.isValidBin(b)) {
428  continue;
429  }
430  for (const auto& srf : binContent) {
431  accessibleSurfaces.insert(srf);
432  }
433  if (binContent.empty()) {
434  nEmptyBins++;
435  }
436  nBinsChecked++;
437  }
438 
439  std::vector<const Acts::Surface*> diff;
440  std::set_difference(sensitiveSurfaces.begin(), sensitiveSurfaces.end(),
441  accessibleSurfaces.begin(), accessibleSurfaces.end(),
442  std::inserter(diff, diff.begin()));
443 
444  ACTS_VERBOSE(" - Checked " << nBinsChecked << " valid bins");
445 
446  if (nEmptyBins > 0) {
447  ACTS_ERROR(" -- Not all bins point to surface. " << nEmptyBins << " empty");
448  } else {
449  ACTS_VERBOSE(" -- All bins point to a surface");
450  }
451 
452  if (!diff.empty()) {
453  ACTS_ERROR(
454  " -- Not all sensitive surfaces are accessible through binning. "
455  "sensitive: "
456  << sensitiveSurfaces.size()
457  << " accessible: " << accessibleSurfaces.size());
458 
459  // print all inaccessibles
460  ACTS_ERROR(" -- Inaccessible surfaces: ");
461  for (const auto& srf : diff) {
462  // have to choose BinningValue here
463  Vector3D ctr = srf->binningPosition(gctx, binR);
464  ACTS_ERROR(" Surface(x=" << ctr.x() << ", y=" << ctr.y()
465  << ", z=" << ctr.z() << ", r=" << perp(ctr)
466  << ", phi=" << phi(ctr) << ")");
467  }
468 
469  } else {
470  ACTS_VERBOSE(" -- All sensitive surfaces are accessible through binning.");
471  }
472 
473  return nEmptyBins == 0 && diff.empty();
474 }