EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
ProtoLayerCreatorT.hpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file ProtoLayerCreatorT.hpp
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 
9 #pragma once
10 
29 
30 #include <iostream>
31 
32 namespace Acts {
33 
34 class LayerCreator;
35 class Surface;
36 class DetecorElementBase;
37 } // namespace Acts
38 
39 namespace ActsExamples {
40 
41 namespace Generic {
42 
46 
47 using SurfacePosition = std::pair<const Acts::Surface*, Acts::Vector3D>;
48 
51  std::vector<std::shared_ptr<const Acts::Surface>> surfaces;
52  size_t bins0;
53  size_t bins1;
54 };
55 
61 template <typename detector_element_t>
63  public:
64  using LayerStore = std::vector<std::shared_ptr<detector_element_t>>;
65 
66  using DetectorStore = std::vector<LayerStore>;
67 
71  struct Config {
76  std::pair<int, int> centralLayerBinMultipliers;
78  std::vector<double> centralLayerRadii;
80  std::vector<std::pair<double, double>> centralLayerEnvelopes;
82  std::vector<std::pair<int, int>> centralModuleBinningSchema;
84  std::vector<std::vector<Acts::Vector3D>> centralModulePositions;
86  std::vector<double> centralModuleTiltPhi;
88  std::vector<double> centralModuleHalfX;
90  std::vector<double> centralModuleHalfY;
92  std::vector<double> centralModuleThickness;
94  std::vector<size_t> centralModuleReadoutBinsX;
96  std::vector<size_t> centralModuleReadoutBinsY;
98  std::vector<int> centralModuleReadoutSide;
100  std::vector<double> centralModuleLorentzAngle;
102  std::vector<std::shared_ptr<const Acts::ISurfaceMaterial>>
105  std::vector<double> centralModuleFrontsideStereo;
107  std::vector<double> centralModuleBacksideStereo;
109  std::vector<double> centralModuleBacksideGap;
110 
113  std::pair<int, int> posnegLayerBinMultipliers;
115  std::vector<double> posnegLayerPositionsZ;
117  std::vector<double> posnegLayerEnvelopeR;
119  std::vector<std::vector<std::vector<Acts::Vector3D>>> posnegModulePositions;
121  std::vector<std::vector<size_t>> posnegModulePhiBins;
123  std::vector<std::vector<double>> posnegModuleMinHalfX;
125  std::vector<std::vector<double>> posnegModuleMaxHalfX;
127  std::vector<std::vector<double>> posnegModuleHalfY;
129  std::vector<std::vector<double>> posnegModuleThickness;
131  std::vector<std::vector<size_t>> posnegModuleReadoutBinsX;
133  std::vector<std::vector<size_t>> posnegModuleReadoutBinsY;
135  std::vector<std::vector<int>> posnegModuleReadoutSide;
137  std::vector<std::vector<double>> posnegModuleLorentzAngle;
139  std::vector<std::vector<std::shared_ptr<const Acts::ISurfaceMaterial>>>
142  std::vector<std::vector<double>> posnegModuleFrontsideStereo;
144  std::vector<std::vector<double>> posnegModuleBacksideStereo;
146  std::vector<std::vector<double>> posnegModuleBacksideGap;
147  };
148 
152  ProtoLayerCreatorT(const Config& glbConfig,
153  std::unique_ptr<const Acts::Logger> logger =
154  Acts::getDefaultLogger("ProtoLayerCreatorT",
156 
161  std::vector<ProtoLayerSurfaces> negativeProtoLayers(
162  const Acts::GeometryContext& gctx, DetectorStore& detectorStore) const;
163 
168  std::vector<ProtoLayerSurfaces> centralProtoLayers(
169  const Acts::GeometryContext& gctx, DetectorStore& detectorStore) const;
170 
175  std::vector<ProtoLayerSurfaces> positiveProtoLayers(
176  const Acts::GeometryContext& gctx, DetectorStore& detectorStore) const;
177 
178  private:
185  std::vector<ProtoLayerSurfaces> createProtoLayers(
186  const Acts::GeometryContext& gctx, DetectorStore& detectorStore,
187  int side) const;
188 
191 
193  std::unique_ptr<const Acts::Logger> m_logger;
194 
196  const Acts::Logger& logger() const { return *m_logger; }
197 };
198 
199 template <typename detector_element_t>
200 std::vector<ProtoLayerSurfaces>
202  const Acts::GeometryContext& gctx, DetectorStore& detectorStore) const {
203  // create the vector
204  std::vector<ProtoLayerSurfaces> cpLayers;
205  // create the detector store entry
206  LayerStore layerStore;
207 
208  // Count the current detector modules identifiers
209  size_t imodule = 0;
210  for (auto& eLayers : detectorStore) {
211  imodule += eLayers.size();
212  }
213  ACTS_VERBOSE("Starting with identfier " << imodule);
214 
215  // ----------------------- central layers -------------------------
216  // the central layers
217  size_t numcLayers = m_cfg.centralLayerRadii.size();
218  if (numcLayers) {
219  ACTS_DEBUG("Configured to build " << numcLayers
220  << " active central layers.");
221  cpLayers.reserve(numcLayers);
222  // loop through
223  for (size_t icl = 0; icl < numcLayers; ++icl) {
224  // layer R/Z
225  double layerR = m_cfg.centralLayerRadii.at(icl);
226  // some screen output
227  ACTS_DEBUG("Build layer " << icl << " with target radius = " << layerR);
228 
229  // prepare the Surface vector
230  std::vector<std::shared_ptr<const Acts::Surface>> sVector;
231  // assign the current envelope
232  double layerEnvelopeCoverZ =
233  m_cfg.centralLayerEnvelopes.size()
234  ? m_cfg.centralLayerEnvelopes.at(icl).second
235  : 0.;
236  // module size & tilt
237  double modulePhiTilt = m_cfg.centralModuleTiltPhi.at(icl);
238  double moduleHalfX = m_cfg.centralModuleHalfX.at(icl);
239  double moduleHalfY = m_cfg.centralModuleHalfY.at(icl);
240  double moduleThickness = m_cfg.centralModuleThickness.at(icl);
241  // create the shared module
242  std::shared_ptr<const Acts::PlanarBounds> moduleBounds(
243  new Acts::RectangleBounds(moduleHalfX, moduleHalfY));
244  size_t nCentralModules = m_cfg.centralModuleBinningSchema.at(icl).first *
245  m_cfg.centralModuleBinningSchema.at(icl).second;
246 
247  ACTS_DEBUG("- number of modules "
248  << nCentralModules << " ( from "
249  << m_cfg.centralModuleBinningSchema.at(icl).first << " x "
250  << m_cfg.centralModuleBinningSchema.at(icl).second << " )");
251 
252  sVector.reserve(nCentralModules);
253 
254  // prepartion :
255  // create digitizaiton module
256  std::shared_ptr<const Acts::DigitizationModule> moduleDigitizationPtr =
257  nullptr;
258  if (m_cfg.centralModuleReadoutBinsX.size()) {
259  // create the CartesianSegmentation
260  std::shared_ptr<const Acts::Segmentation> moduleSegmentation =
261  std::make_shared<const Acts::CartesianSegmentation>(
262  moduleBounds, m_cfg.centralModuleReadoutBinsX.at(icl),
263  m_cfg.centralModuleReadoutBinsY.at(icl));
264  // now create the digitzation module
265  moduleDigitizationPtr =
266  std::make_shared<const Acts::DigitizationModule>(
267  moduleSegmentation, 0.5 * m_cfg.centralModuleThickness.at(icl),
268  m_cfg.centralModuleReadoutSide.at(icl),
269  m_cfg.centralModuleLorentzAngle.at(icl));
270  }
271 
272  // prepartation :
273  // create the Module material from input
274  std::shared_ptr<const Acts::ISurfaceMaterial> moduleMaterialPtr = nullptr;
275  if (m_cfg.centralModuleMaterial.size()) {
276  // get the sensor material from configuration
277  moduleMaterialPtr = m_cfg.centralModuleMaterial.at(icl);
278  }
279 
280  // confirm
281  if (m_cfg.centralModulePositions.at(icl).size() != nCentralModules) {
282  ACTS_WARNING("Mismatching module numbers, configuration error!");
283  ACTS_WARNING("- Binning schema suggests : " << nCentralModules);
284  ACTS_WARNING("- Positions provided are : "
285  << m_cfg.centralModulePositions.at(icl).size());
286  }
287  // loop over the position, create the modules
288  for (auto& moduleCenter : m_cfg.centralModulePositions.at(icl)) {
289  // create the association transform
290  double modulePhi = phi(moduleCenter);
291  // the local z axis is the normal vector
292  Acts::Vector3D moduleLocalZ(cos(modulePhi + modulePhiTilt),
293  sin(modulePhi + modulePhiTilt), 0.);
294  // the local y axis is the global z axis
295  Acts::Vector3D moduleLocalY(0., 0., 1);
296  // the local x axis the normal to local y,z
297  Acts::Vector3D moduleLocalX(-sin(modulePhi + modulePhiTilt),
298  cos(modulePhi + modulePhiTilt), 0.);
299  // create the RotationMatrix
300  Acts::RotationMatrix3D moduleRotation;
301  moduleRotation.col(0) = moduleLocalX;
302  moduleRotation.col(1) = moduleLocalY;
303  moduleRotation.col(2) = moduleLocalZ;
304  // get the moduleTransform
305  std::shared_ptr<Acts::Transform3D> mutableModuleTransform =
306  std::make_shared<Acts::Transform3D>(
307  Acts::Translation3D(moduleCenter) * moduleRotation);
308  // stereo angle if necessary
309  if (m_cfg.centralModuleFrontsideStereo.size() &&
310  m_cfg.centralModuleFrontsideStereo.at(icl) != 0.) {
311  // twist by the stereo angle
312  double stereo = m_cfg.centralModuleFrontsideStereo.at(icl);
313  (*mutableModuleTransform.get()) *=
314  Acts::AngleAxis3D(-stereo, Acts::Vector3D::UnitZ());
315  }
316  // count the modules
317  Identifier moduleIdentifier = Identifier(identifier_type(imodule++));
318  // Finalize the transform
319  auto moduleTransform = std::const_pointer_cast<const Acts::Transform3D>(
320  mutableModuleTransform);
321  // create the module
322  auto module = std::make_shared<detector_element_t>(
323  moduleIdentifier, moduleTransform, moduleBounds, moduleThickness,
324  moduleMaterialPtr, moduleDigitizationPtr);
325 
326  // put the module into the detector store
327  layerStore.push_back(module);
328  // register the surface
329  sVector.push_back(module->surface().getSharedPtr());
330  // IF double modules exist
331  // and the backside one (if configured to do so)
332  if (m_cfg.centralModuleBacksideGap.size()) {
333  // create the module identifier
334  moduleIdentifier = Identifier(identifier_type(imodule++));
335  Acts::Vector3D bsModuleCenter =
336  moduleCenter +
337  m_cfg.centralModuleBacksideGap.at(icl) * moduleLocalZ;
338  mutableModuleTransform = std::make_shared<Acts::Transform3D>(
339  Acts::Translation3D(bsModuleCenter) * moduleRotation);
340  // apply the stereo
341  if (m_cfg.centralModuleBacksideStereo.size()) {
342  // twist by the stereo angle
343  double stereoBackSide = m_cfg.centralModuleBacksideStereo.at(icl);
344  (*mutableModuleTransform.get()) *=
345  Acts::AngleAxis3D(-stereoBackSide, Acts::Vector3D::UnitZ());
346  }
347  // Finalize the transform
348  moduleTransform = std::const_pointer_cast<const Acts::Transform3D>(
349  mutableModuleTransform);
350  // create the backseide moulde
351  auto bsmodule = std::make_shared<detector_element_t>(
352  moduleIdentifier, moduleTransform, moduleBounds, moduleThickness,
353  moduleMaterialPtr, moduleDigitizationPtr);
354  // everything is set for the next module
355  layerStore.push_back(std::move(bsmodule));
356  }
357  }
358 
359  size_t phiBins = m_cfg.centralModuleBinningSchema.at(icl).first;
360  phiBins *= m_cfg.centralLayerBinMultipliers.first;
361  size_t zBins = m_cfg.centralModuleBinningSchema.at(icl).second;
362  zBins *= m_cfg.centralLayerBinMultipliers.second;
363  // create the surface array - it will also fill the accesible binmember
364  // chache if avalable
365  Acts::ProtoLayer pl(gctx, sVector);
366  pl.envelope[Acts::binR] = {m_cfg.approachSurfaceEnvelope,
367  m_cfg.approachSurfaceEnvelope};
368  pl.envelope[Acts::binZ] = {layerEnvelopeCoverZ, layerEnvelopeCoverZ};
369 
370  // Record the proto layer anb dthe surfaces for the later layer building
371  ProtoLayerSurfaces pls{std::move(pl), sVector, phiBins, zBins};
372  cpLayers.push_back(std::move(pls));
373  // fill the detector store
374  detectorStore.push_back(std::move(layerStore));
375  }
376  }
377  return cpLayers;
378 }
379 
380 template <typename detector_element_t>
381 std::vector<ProtoLayerSurfaces>
383  const Acts::GeometryContext& gctx, DetectorStore& detectorStore) const {
384  return createProtoLayers(gctx, detectorStore, -1);
385 }
386 
387 template <typename detector_element_t>
388 std::vector<ProtoLayerSurfaces>
390  const Acts::GeometryContext& gctx, DetectorStore& detectorStore) const {
391  return createProtoLayers(gctx, detectorStore, 1);
392 }
393 
394 template <typename detector_element_t>
397  std::unique_ptr<const Acts::Logger> log)
398  : m_cfg(cfg), m_logger(std::move(log)) {}
399 
400 template <typename detector_element_t>
401 std::vector<ProtoLayerSurfaces>
403  const Acts::GeometryContext& gctx, DetectorStore& detectorStore,
404  int side) const {
405  // Count the current detector modules identifiers
406  size_t imodule = 0;
407  for (auto& eLayers : detectorStore) {
408  imodule += eLayers.size();
409  }
410  ACTS_VERBOSE("Starting with identfier " << imodule);
411  // the return layers
412  std::vector<ProtoLayerSurfaces> epLayers;
413  // create the detector store entry
414  LayerStore layerStore;
415  // -------------------------------- endcap type layers
416  // pos/neg layers
417  size_t numpnLayers = m_cfg.posnegLayerPositionsZ.size();
418  if (numpnLayers) {
419  ACTS_DEBUG("Configured to build 2 * "
420  << numpnLayers << " passive positive/negative side layers.");
421  epLayers.reserve(numpnLayers);
422 
424  for (size_t ipnl = 0; ipnl < numpnLayers; ++ipnl) {
425  // some screen output
426  ACTS_VERBOSE("- building layer "
427  << ipnl << " and " << numpnLayers + ipnl << " at z = "
428  << side * m_cfg.posnegLayerPositionsZ.at(ipnl));
430  // define the layer envelope
431  double layerEnvelopeR = m_cfg.posnegLayerEnvelopeR.at(ipnl);
432  // prepare for the r binning
433  std::vector<std::shared_ptr<const Acts::Surface>> esVector;
434  // now fill the vectors
435  size_t ipnR = 0;
436  for (auto& discModulePositions : m_cfg.posnegModulePositions.at(ipnl)) {
437  ACTS_VERBOSE("- building ring " << ipnR << " for this layer.");
438  // now prepare all the shared stuff
439  // (0) module specifications
440  double moduleThickness = m_cfg.posnegModuleThickness.at(ipnl).at(ipnR);
441  double moduleMinHalfX = m_cfg.posnegModuleMinHalfX.at(ipnl).at(ipnR);
442  double moduleMaxHalfX = 0.;
443  if (m_cfg.posnegModuleMaxHalfX.size() > ipnl &&
444  m_cfg.posnegModuleMaxHalfX.at(ipnl).size() > ipnR) {
445  moduleMaxHalfX = m_cfg.posnegModuleMaxHalfX.at(ipnl).at(ipnR);
446  }
447  double moduleHalfY = m_cfg.posnegModuleHalfY.at(ipnl).at(ipnR);
448  // (1) module bounds
449  // create the bounds
450  Acts::PlanarBounds* pBounds = nullptr;
451  if (moduleMaxHalfX != 0. && moduleMinHalfX != moduleMaxHalfX)
452  pBounds = new Acts::TrapezoidBounds(moduleMinHalfX, moduleMaxHalfX,
453  moduleHalfY);
454  else
455  pBounds = new Acts::RectangleBounds(moduleMinHalfX, moduleHalfY);
456  // now create the shared bounds from it
457  std::shared_ptr<const Acts::PlanarBounds> moduleBounds(pBounds);
458  // (2) create digitizaiton module
459  std::shared_ptr<const Acts::DigitizationModule> moduleDigitizationPtr =
460  nullptr;
461  if (m_cfg.posnegModuleReadoutBinsX.size()) {
462  // create the CartesianSegmentation
463  std::shared_ptr<const Acts::Segmentation> moduleSegmentation =
464  std::make_shared<const Acts::CartesianSegmentation>(
465  moduleBounds,
466  m_cfg.posnegModuleReadoutBinsX.at(ipnl).at(ipnR),
467  m_cfg.posnegModuleReadoutBinsY.at(ipnl).at(ipnR));
468  // now create the digitzation module
469  moduleDigitizationPtr =
470  std::make_shared<const Acts::DigitizationModule>(
471  moduleSegmentation, 0.5 * moduleThickness,
472  m_cfg.posnegModuleReadoutSide.at(ipnl).at(ipnR),
473  m_cfg.posnegModuleLorentzAngle.at(ipnl).at(ipnR));
474  }
475  // (3) module material
476  // create the Module material from input
477  std::shared_ptr<const Acts::ISurfaceMaterial> moduleMaterialPtr =
478  nullptr;
479  if (m_cfg.posnegModuleMaterial.size()) {
480  // and create the shared pointer
481  moduleMaterialPtr = m_cfg.posnegModuleMaterial.at(ipnl).at(ipnR);
482  }
483 
484  // low loop over the phi positions and build the stuff
485  for (auto& ringModulePosition : discModulePositions) {
486  // the module transform from the position
487  double modulePhi = phi(ringModulePosition);
488  // the center position of the modules
489  Acts::Vector3D moduleCenter(side * ringModulePosition);
490  // the rotation matrix of the module
491  Acts::Vector3D moduleLocalY(cos(modulePhi), sin(modulePhi), 0.);
492  // take different axis to have the same readout direction
493  Acts::Vector3D moduleLocalZ(0., 0., side * 1.);
494  Acts::Vector3D moduleLocalX = moduleLocalY.cross(moduleLocalZ);
495  // local rotation matrices
496  // create the RotationMatrix - negative side
497  Acts::RotationMatrix3D moduleRotation;
498  moduleRotation.col(0) = moduleLocalX;
499  moduleRotation.col(1) = moduleLocalY;
500  moduleRotation.col(2) = moduleLocalZ;
501  // the transforms for the two modules
502  std::shared_ptr<const Acts::Transform3D> moduleTransform =
503  std::make_shared<const Acts::Transform3D>(
504  Acts::Translation3D(moduleCenter) * moduleRotation);
505 
506  // reate the modules identifier
507  Identifier moduleIdentifier = Identifier(identifier_type(imodule++));
508 
509  // create the module
510  auto module = std::make_shared<detector_element_t>(
511  moduleIdentifier, moduleTransform, moduleBounds, moduleThickness,
512  moduleMaterialPtr, moduleDigitizationPtr);
513  layerStore.push_back(module);
514 
515  // now deal with the potential backside
516  if (m_cfg.posnegModuleBacksideGap.size()) {
517  // increase the counter
518  moduleIdentifier = Identifier(identifier_type(imodule++));
519  // the new centers
520  moduleCenter =
521  moduleCenter +
522  m_cfg.posnegModuleBacksideGap.at(ipnl).at(ipnR) * moduleLocalZ;
523  // the new transforms
524  auto mutableModuleTransform = std::make_shared<Acts::Transform3D>(
525  Acts::Translation3D(moduleCenter) * moduleRotation);
526  // apply the stereo
527  if (m_cfg.posnegModuleBacksideStereo.size()) {
528  // twist by the stereo angle
529  double stereoBackSide =
530  m_cfg.posnegModuleBacksideStereo.at(ipnl).at(ipnR);
531  (*mutableModuleTransform.get()) *=
532  Acts::AngleAxis3D(-stereoBackSide, Acts::Vector3D::UnitZ());
533  }
534  // Finalize the transform
535  moduleTransform = std::const_pointer_cast<const Acts::Transform3D>(
536  mutableModuleTransform);
537  // everything is set for the next module
538  auto bsmodule = std::make_shared<detector_element_t>(
539  moduleIdentifier, moduleTransform, moduleBounds,
540  moduleThickness, moduleMaterialPtr, moduleDigitizationPtr);
541  // Put into the detector store
542  layerStore.push_back(std::move(bsmodule));
543  }
544  // create the surface
545  esVector.push_back(module->surface().getSharedPtr());
546  }
547  // counter of rings
548  ++ipnR;
549  }
550  // the binning
551  size_t layerBinsR = m_cfg.posnegModulePhiBins.at(ipnl).size();
552  // never multiply 1 single r-bin, does not make sense
553  if (layerBinsR > 1) {
554  // multiply with the given bin mulitplier
555  layerBinsR *= m_cfg.posnegLayerBinMultipliers.first;
556  }
557  size_t layerBinsPhi = 0;
558  // take the minimum phi bins in that layer
559  for (unsigned int phiBins : m_cfg.posnegModulePhiBins.at(ipnl)) {
560  layerBinsPhi = phiBins < layerBinsPhi ? phiBins : layerBinsPhi;
561  layerBinsPhi *= m_cfg.posnegLayerBinMultipliers.second;
562  }
563  // create the layers with the surface arrays
564  Acts::ProtoLayer ple(gctx, esVector);
565  ple.envelope[Acts::binR] = {layerEnvelopeR, layerEnvelopeR};
566  ple.envelope[Acts::binZ] = {m_cfg.approachSurfaceEnvelope,
567  m_cfg.approachSurfaceEnvelope};
568 
569  // push it into the layer vector
570  ProtoLayerSurfaces ples{std::move(ple), esVector, layerBinsR,
571  layerBinsPhi};
572  epLayers.push_back(std::move(ples));
573  // fill the detector store
574  detectorStore.push_back(std::move(layerStore));
575  }
576  }
577  return epLayers;
578 }
579 
580 } // end of namespace Generic
581 } // end of namespace ActsExamples