ECCE @ 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 
11 #include <iostream>
12 
31 
32 namespace Acts {
33 
34 class LayerCreator;
35 class Surface;
36 class DetecorElementBase;
37 } // namespace Acts
38 
39 namespace FW {
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.envR = {m_cfg.approachSurfaceEnvelope, m_cfg.approachSurfaceEnvelope};
367  pl.envZ = {layerEnvelopeCoverZ, layerEnvelopeCoverZ};
368 
369  // Record the proto layer anb dthe surfaces for the later layer building
370  ProtoLayerSurfaces pls{std::move(pl), sVector, phiBins, zBins};
371  cpLayers.push_back(std::move(pls));
372  // fill the detector store
373  detectorStore.push_back(std::move(layerStore));
374  }
375  }
376  return cpLayers;
377 }
378 
379 template <typename detector_element_t>
380 std::vector<ProtoLayerSurfaces>
382  const Acts::GeometryContext& gctx, DetectorStore& detectorStore) const {
383  return createProtoLayers(gctx, detectorStore, -1);
384 }
385 
386 template <typename detector_element_t>
387 std::vector<ProtoLayerSurfaces>
389  const Acts::GeometryContext& gctx, DetectorStore& detectorStore) const {
390  return createProtoLayers(gctx, detectorStore, 1);
391 }
392 
393 template <typename detector_element_t>
396  std::unique_ptr<const Acts::Logger> log)
397  : m_cfg(cfg), m_logger(std::move(log)) {}
398 
399 template <typename detector_element_t>
400 std::vector<ProtoLayerSurfaces>
402  const Acts::GeometryContext& gctx, DetectorStore& detectorStore,
403  int side) const {
404  // Count the current detector modules identifiers
405  size_t imodule = 0;
406  for (auto& eLayers : detectorStore) {
407  imodule += eLayers.size();
408  }
409  ACTS_VERBOSE("Starting with identfier " << imodule);
410  // the return layers
411  std::vector<ProtoLayerSurfaces> epLayers;
412  // create the detector store entry
413  LayerStore layerStore;
414  // -------------------------------- endcap type layers
415  // pos/neg layers
416  size_t numpnLayers = m_cfg.posnegLayerPositionsZ.size();
417  if (numpnLayers) {
418  ACTS_DEBUG("Configured to build 2 * "
419  << numpnLayers << " passive positive/negative side layers.");
420  epLayers.reserve(numpnLayers);
421 
423  for (size_t ipnl = 0; ipnl < numpnLayers; ++ipnl) {
424  // some screen output
425  ACTS_VERBOSE("- building layer "
426  << ipnl << " and " << numpnLayers + ipnl << " at z = "
427  << side * m_cfg.posnegLayerPositionsZ.at(ipnl));
429  // define the layer envelope
430  double layerEnvelopeR = m_cfg.posnegLayerEnvelopeR.at(ipnl);
431  // prepare for the r binning
432  std::vector<std::shared_ptr<const Acts::Surface>> esVector;
433  // now fill the vectors
434  size_t ipnR = 0;
435  for (auto& discModulePositions : m_cfg.posnegModulePositions.at(ipnl)) {
436  ACTS_VERBOSE("- building ring " << ipnR << " for this layer.");
437  // now prepare all the shared stuff
438  // (0) module specifications
439  double moduleThickness = m_cfg.posnegModuleThickness.at(ipnl).at(ipnR);
440  double moduleMinHalfX = m_cfg.posnegModuleMinHalfX.at(ipnl).at(ipnR);
441  double moduleMaxHalfX = 0.;
442  if (m_cfg.posnegModuleMaxHalfX.size() > ipnl &&
443  m_cfg.posnegModuleMaxHalfX.at(ipnl).size() > ipnR) {
444  moduleMaxHalfX = m_cfg.posnegModuleMaxHalfX.at(ipnl).at(ipnR);
445  }
446  double moduleHalfY = m_cfg.posnegModuleHalfY.at(ipnl).at(ipnR);
447  // (1) module bounds
448  // create the bounds
449  Acts::PlanarBounds* pBounds = nullptr;
450  if (moduleMaxHalfX != 0. && moduleMinHalfX != moduleMaxHalfX)
451  pBounds = new Acts::TrapezoidBounds(moduleMinHalfX, moduleMaxHalfX,
452  moduleHalfY);
453  else
454  pBounds = new Acts::RectangleBounds(moduleMinHalfX, moduleHalfY);
455  // now create the shared bounds from it
456  std::shared_ptr<const Acts::PlanarBounds> moduleBounds(pBounds);
457  // (2) create digitizaiton module
458  std::shared_ptr<const Acts::DigitizationModule> moduleDigitizationPtr =
459  nullptr;
460  if (m_cfg.posnegModuleReadoutBinsX.size()) {
461  // create the CartesianSegmentation
462  std::shared_ptr<const Acts::Segmentation> moduleSegmentation =
463  std::make_shared<const Acts::CartesianSegmentation>(
464  moduleBounds,
465  m_cfg.posnegModuleReadoutBinsX.at(ipnl).at(ipnR),
466  m_cfg.posnegModuleReadoutBinsY.at(ipnl).at(ipnR));
467  // now create the digitzation module
468  moduleDigitizationPtr =
469  std::make_shared<const Acts::DigitizationModule>(
470  moduleSegmentation, 0.5 * moduleThickness,
471  m_cfg.posnegModuleReadoutSide.at(ipnl).at(ipnR),
472  m_cfg.posnegModuleLorentzAngle.at(ipnl).at(ipnR));
473  }
474  // (3) module material
475  // create the Module material from input
476  std::shared_ptr<const Acts::ISurfaceMaterial> moduleMaterialPtr =
477  nullptr;
478  if (m_cfg.posnegModuleMaterial.size()) {
479  // and create the shared pointer
480  moduleMaterialPtr = m_cfg.posnegModuleMaterial.at(ipnl).at(ipnR);
481  }
482 
483  // low loop over the phi positions and build the stuff
484  for (auto& ringModulePosition : discModulePositions) {
485  // the module transform from the position
486  double modulePhi = phi(ringModulePosition);
487  // the center position of the modules
488  Acts::Vector3D moduleCenter(side * ringModulePosition);
489  // the rotation matrix of the module
490  Acts::Vector3D moduleLocalY(cos(modulePhi), sin(modulePhi), 0.);
491  // take different axis to have the same readout direction
492  Acts::Vector3D moduleLocalZ(0., 0., side * 1.);
493  Acts::Vector3D moduleLocalX = moduleLocalY.cross(moduleLocalZ);
494  // local rotation matrices
495  // create the RotationMatrix - negative side
496  Acts::RotationMatrix3D moduleRotation;
497  moduleRotation.col(0) = moduleLocalX;
498  moduleRotation.col(1) = moduleLocalY;
499  moduleRotation.col(2) = moduleLocalZ;
500  // the transforms for the two modules
501  std::shared_ptr<const Acts::Transform3D> moduleTransform =
502  std::make_shared<const Acts::Transform3D>(
503  Acts::Translation3D(moduleCenter) * moduleRotation);
504 
505  // reate the modules identifier
506  Identifier moduleIdentifier = Identifier(identifier_type(imodule++));
507 
508  // create the module
509  auto module = std::make_shared<detector_element_t>(
510  moduleIdentifier, moduleTransform, moduleBounds, moduleThickness,
511  moduleMaterialPtr, moduleDigitizationPtr);
512  layerStore.push_back(module);
513 
514  // now deal with the potential backside
515  if (m_cfg.posnegModuleBacksideGap.size()) {
516  // increase the counter
517  moduleIdentifier = Identifier(identifier_type(imodule++));
518  // the new centers
519  moduleCenter =
520  moduleCenter +
521  m_cfg.posnegModuleBacksideGap.at(ipnl).at(ipnR) * moduleLocalZ;
522  // the new transforms
523  auto mutableModuleTransform = std::make_shared<Acts::Transform3D>(
524  Acts::Translation3D(moduleCenter) * moduleRotation);
525  // apply the stereo
526  if (m_cfg.posnegModuleBacksideStereo.size()) {
527  // twist by the stereo angle
528  double stereoBackSide =
529  m_cfg.posnegModuleBacksideStereo.at(ipnl).at(ipnR);
530  (*mutableModuleTransform.get()) *=
531  Acts::AngleAxis3D(-stereoBackSide, Acts::Vector3D::UnitZ());
532  }
533  // Finalize the transform
534  moduleTransform = std::const_pointer_cast<const Acts::Transform3D>(
535  mutableModuleTransform);
536  // everything is set for the next module
537  auto bsmodule = std::make_shared<detector_element_t>(
538  moduleIdentifier, moduleTransform, moduleBounds,
539  moduleThickness, moduleMaterialPtr, moduleDigitizationPtr);
540  // Put into the detector store
541  layerStore.push_back(std::move(bsmodule));
542  }
543  // create the surface
544  esVector.push_back(module->surface().getSharedPtr());
545  }
546  // counter of rings
547  ++ipnR;
548  }
549  // the binning
550  size_t layerBinsR = m_cfg.posnegModulePhiBins.at(ipnl).size();
551  // never multiply 1 single r-bin, does not make sense
552  if (layerBinsR > 1) {
553  // multiply with the given bin mulitplier
554  layerBinsR *= m_cfg.posnegLayerBinMultipliers.first;
555  }
556  size_t layerBinsPhi = 0;
557  // take the minimum phi bins in that layer
558  for (unsigned int phiBins : m_cfg.posnegModulePhiBins.at(ipnl)) {
559  layerBinsPhi = phiBins < layerBinsPhi ? phiBins : layerBinsPhi;
560  layerBinsPhi *= m_cfg.posnegLayerBinMultipliers.second;
561  }
562  // create the layers with the surface arrays
563  Acts::ProtoLayer ple(gctx, esVector);
564  ple.envR = {layerEnvelopeR, layerEnvelopeR};
565  ple.envZ = {m_cfg.approachSurfaceEnvelope, m_cfg.approachSurfaceEnvelope};
566 
567  // push it into the layer vector
568  ProtoLayerSurfaces ples{std::move(ple), esVector, layerBinsR,
569  layerBinsPhi};
570  epLayers.push_back(std::move(ples));
571  // fill the detector store
572  detectorStore.push_back(std::move(layerStore));
573  }
574  }
575  return epLayers;
576 }
577 
578 } // end of namespace Generic
579 } // end of namespace FW