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