Analysis Software
Documentation for sPHENIX simulation 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 
28 
29 #include <iostream>
30 
31 namespace Acts {
32 
33 class LayerCreator;
34 class Surface;
35 class DetecorElementBase;
36 } // namespace Acts
37 
38 namespace ActsExamples {
39 
40 namespace Generic {
41 
45 
46 using SurfacePosition = std::pair<const Acts::Surface*, Acts::Vector3>;
47 
50  std::vector<std::shared_ptr<const Acts::Surface>> surfaces;
51  size_t bins0;
52  size_t bins1;
53 };
54 
60 template <typename detector_element_t>
62  public:
63  using LayerStore = std::vector<std::shared_ptr<detector_element_t>>;
64 
65  using DetectorStore = std::vector<LayerStore>;
66 
70  struct Config {
75  std::pair<int, int> centralLayerBinMultipliers;
77  std::vector<double> centralLayerRadii;
79  std::vector<std::pair<double, double>> centralLayerEnvelopes;
81  std::vector<std::pair<int, int>> centralModuleBinningSchema;
83  std::vector<std::vector<Acts::Vector3>> centralModulePositions;
85  std::vector<double> centralModuleTiltPhi;
87  std::vector<double> centralModuleHalfX;
89  std::vector<double> centralModuleHalfY;
91  std::vector<double> centralModuleThickness;
93  std::vector<size_t> centralModuleReadoutBinsX;
95  std::vector<size_t> centralModuleReadoutBinsY;
97  std::vector<int> centralModuleReadoutSide;
99  std::vector<double> centralModuleLorentzAngle;
101  std::vector<std::shared_ptr<const Acts::ISurfaceMaterial>>
104  std::vector<double> centralModuleFrontsideStereo;
106  std::vector<double> centralModuleBacksideStereo;
108  std::vector<double> centralModuleBacksideGap;
109 
112  std::pair<int, int> posnegLayerBinMultipliers;
114  std::vector<double> posnegLayerPositionsZ;
116  std::vector<double> posnegLayerEnvelopeR;
118  std::vector<std::vector<std::vector<Acts::Vector3>>> posnegModulePositions;
120  std::vector<std::vector<size_t>> posnegModulePhiBins;
122  std::vector<std::vector<double>> posnegModuleMinHalfX;
124  std::vector<std::vector<double>> posnegModuleMaxHalfX;
126  std::vector<std::vector<double>> posnegModuleHalfY;
128  std::vector<std::vector<double>> posnegModuleThickness;
130  std::vector<std::vector<size_t>> posnegModuleReadoutBinsX;
132  std::vector<std::vector<size_t>> posnegModuleReadoutBinsY;
134  std::vector<std::vector<int>> posnegModuleReadoutSide;
136  std::vector<std::vector<double>> posnegModuleLorentzAngle;
138  std::vector<std::vector<std::shared_ptr<const Acts::ISurfaceMaterial>>>
141  std::vector<std::vector<double>> posnegModuleFrontsideStereo;
143  std::vector<std::vector<double>> posnegModuleBacksideStereo;
145  std::vector<std::vector<double>> posnegModuleBacksideGap;
146  };
147 
152  std::unique_ptr<const Acts::Logger> logger =
153  Acts::getDefaultLogger("ProtoLayerCreatorT",
155 
160  std::vector<ProtoLayerSurfaces> negativeProtoLayers(
161  const Acts::GeometryContext& gctx, DetectorStore& detectorStore) const;
162 
167  std::vector<ProtoLayerSurfaces> centralProtoLayers(
168  const Acts::GeometryContext& gctx, DetectorStore& detectorStore) const;
169 
174  std::vector<ProtoLayerSurfaces> positiveProtoLayers(
175  const Acts::GeometryContext& gctx, DetectorStore& detectorStore) const;
176 
177  private:
184  std::vector<ProtoLayerSurfaces> createProtoLayers(
185  const Acts::GeometryContext& gctx, DetectorStore& detectorStore,
186  int side) const;
187 
190 
192  std::unique_ptr<const Acts::Logger> m_logger;
193 
195  const Acts::Logger& logger() const { return *m_logger; }
196 };
197 
198 template <typename detector_element_t>
199 std::vector<ProtoLayerSurfaces>
201  const Acts::GeometryContext& gctx, DetectorStore& detectorStore) const {
202  // create the vector
203  std::vector<ProtoLayerSurfaces> cpLayers;
204  // create the detector store entry
205  LayerStore layerStore;
206 
207  // Count the current detector modules identifiers
208  size_t imodule = 0;
209  for (auto& eLayers : detectorStore) {
210  imodule += eLayers.size();
211  }
212  ACTS_VERBOSE("Starting with identifier " << imodule);
213 
214  // ----------------------- central layers -------------------------
215  // the central layers
216  size_t numcLayers = m_cfg.centralLayerRadii.size();
217  if (numcLayers != 0u) {
218  ACTS_DEBUG("Configured to build " << numcLayers
219  << " active central layers.");
220  cpLayers.reserve(numcLayers);
221  // loop through
222  for (size_t icl = 0; icl < numcLayers; ++icl) {
223  // layer R/Z
224  double layerR = m_cfg.centralLayerRadii.at(icl);
225  // some screen output
226  ACTS_DEBUG("Build layer " << icl << " with target radius = " << layerR);
227 
228  // prepare the Surface vector
229  std::vector<std::shared_ptr<const Acts::Surface>> sVector;
230  // assign the current envelope
231  double layerEnvelopeCoverZ =
232  !m_cfg.centralLayerEnvelopes.empty()
233  ? m_cfg.centralLayerEnvelopes.at(icl).second
234  : 0.;
235  // module size & tilt
236  double modulePhiTilt = m_cfg.centralModuleTiltPhi.at(icl);
237  double moduleHalfX = m_cfg.centralModuleHalfX.at(icl);
238  double moduleHalfY = m_cfg.centralModuleHalfY.at(icl);
239  double moduleThickness = m_cfg.centralModuleThickness.at(icl);
240  // create the shared module
241  std::shared_ptr<const Acts::PlanarBounds> moduleBounds(
242  new Acts::RectangleBounds(moduleHalfX, moduleHalfY));
243  size_t nCentralModules = m_cfg.centralModuleBinningSchema.at(icl).first *
244  m_cfg.centralModuleBinningSchema.at(icl).second;
245 
246  ACTS_DEBUG("- number of modules "
247  << nCentralModules << " ( from "
248  << m_cfg.centralModuleBinningSchema.at(icl).first << " x "
249  << m_cfg.centralModuleBinningSchema.at(icl).second << " )");
250 
251  sVector.reserve(nCentralModules);
252 
253  // preparation :
254  // create digitizaiton module
255  std::shared_ptr<const Acts::DigitizationModule> moduleDigitizationPtr =
256  nullptr;
257  if (!m_cfg.centralModuleReadoutBinsX.empty()) {
258  // create the CartesianSegmentation
259  std::shared_ptr<const Acts::Segmentation> moduleSegmentation =
260  std::make_shared<const Acts::CartesianSegmentation>(
261  moduleBounds, m_cfg.centralModuleReadoutBinsX.at(icl),
262  m_cfg.centralModuleReadoutBinsY.at(icl));
263  // now create the digitzation module
264  moduleDigitizationPtr =
265  std::make_shared<const Acts::DigitizationModule>(
266  moduleSegmentation, 0.5 * m_cfg.centralModuleThickness.at(icl),
267  m_cfg.centralModuleReadoutSide.at(icl),
268  m_cfg.centralModuleLorentzAngle.at(icl));
269  }
270 
271  // prepartation :
272  // create the Module material from input
273  std::shared_ptr<const Acts::ISurfaceMaterial> moduleMaterialPtr = nullptr;
274  if (!m_cfg.centralModuleMaterial.empty()) {
275  // get the sensor material from configuration
276  moduleMaterialPtr = m_cfg.centralModuleMaterial.at(icl);
277  }
278 
279  // confirm
280  if (m_cfg.centralModulePositions.at(icl).size() != nCentralModules) {
281  ACTS_WARNING("Mismatching module numbers, configuration error!");
282  ACTS_WARNING("- Binning schema suggests : " << nCentralModules);
283  ACTS_WARNING("- Positions provided are : "
284  << m_cfg.centralModulePositions.at(icl).size());
285  }
286  // loop over the position, create the modules
287  for (auto& moduleCenter : m_cfg.centralModulePositions.at(icl)) {
288  // create the association transform
289  double modulePhi = phi(moduleCenter);
290  // the local z axis is the normal vector
291  Acts::Vector3 moduleLocalZ(cos(modulePhi + modulePhiTilt),
292  sin(modulePhi + modulePhiTilt), 0.);
293  // the local y axis is the global z axis
294  Acts::Vector3 moduleLocalY(0., 0., 1);
295  // the local x axis the normal to local y,z
296  Acts::Vector3 moduleLocalX(-sin(modulePhi + modulePhiTilt),
297  cos(modulePhi + modulePhiTilt), 0.);
298  // create the RotationMatrix
299  Acts::RotationMatrix3 moduleRotation;
300  moduleRotation.col(0) = moduleLocalX;
301  moduleRotation.col(1) = moduleLocalY;
302  moduleRotation.col(2) = moduleLocalZ;
303  // get the moduleTransform
304  std::shared_ptr<Acts::Transform3> mutableModuleTransform =
305  std::make_shared<Acts::Transform3>(
306  Acts::Translation3(moduleCenter) * moduleRotation);
307  // stereo angle if necessary
308  if (!m_cfg.centralModuleFrontsideStereo.empty() &&
309  m_cfg.centralModuleFrontsideStereo.at(icl) != 0.) {
310  // twist by the stereo angle
311  double stereo = m_cfg.centralModuleFrontsideStereo.at(icl);
312  (*mutableModuleTransform.get()) *=
313  Acts::AngleAxis3(-stereo, Acts::Vector3::UnitZ());
314  }
315  // count the modules
316  Identifier moduleIdentifier = Identifier(identifier_type(imodule++));
317  // Finalize the transform
318  auto moduleTransform = std::const_pointer_cast<const Acts::Transform3>(
319  mutableModuleTransform);
320  // create the module
321  auto module = std::make_shared<detector_element_t>(
322  moduleIdentifier, moduleTransform, moduleBounds, moduleThickness,
323  moduleMaterialPtr, moduleDigitizationPtr);
324 
325  // put the module into the detector store
326  layerStore.push_back(module);
327  // register the surface
328  sVector.push_back(module->surface().getSharedPtr());
329  // IF double modules exist
330  // and the backside one (if configured to do so)
331  if (!m_cfg.centralModuleBacksideGap.empty()) {
332  // create the module identifier
333  moduleIdentifier = Identifier(identifier_type(imodule++));
334  Acts::Vector3 bsModuleCenter =
335  moduleCenter +
336  m_cfg.centralModuleBacksideGap.at(icl) * moduleLocalZ;
337  mutableModuleTransform = std::make_shared<Acts::Transform3>(
338  Acts::Translation3(bsModuleCenter) * moduleRotation);
339  // apply the stereo
340  if (!m_cfg.centralModuleBacksideStereo.empty()) {
341  // twist by the stereo angle
342  double stereoBackSide = m_cfg.centralModuleBacksideStereo.at(icl);
343  (*mutableModuleTransform.get()) *=
344  Acts::AngleAxis3(-stereoBackSide, Acts::Vector3::UnitZ());
345  }
346  // Finalize the transform
347  moduleTransform = std::const_pointer_cast<const Acts::Transform3>(
348  mutableModuleTransform);
349  // create the backseide moulde
350  auto bsmodule = std::make_shared<detector_element_t>(
351  moduleIdentifier, moduleTransform, moduleBounds, moduleThickness,
352  moduleMaterialPtr, moduleDigitizationPtr);
353  // everything is set for the next module
354  layerStore.push_back(std::move(bsmodule));
355  }
356  }
357 
358  size_t phiBins = m_cfg.centralModuleBinningSchema.at(icl).first;
359  phiBins *= m_cfg.centralLayerBinMultipliers.first;
360  size_t zBins = m_cfg.centralModuleBinningSchema.at(icl).second;
361  zBins *= m_cfg.centralLayerBinMultipliers.second;
362  // create the surface array - it will also fill the accessible binmember
363  // cache if available
364  Acts::ProtoLayer pl(gctx, sVector);
365  pl.envelope[Acts::binR] = {m_cfg.approachSurfaceEnvelope,
366  m_cfg.approachSurfaceEnvelope};
367  pl.envelope[Acts::binZ] = {layerEnvelopeCoverZ, layerEnvelopeCoverZ};
368 
369  // Record the proto layer and the 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 identifier " << 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 != 0u) {
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  }
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.empty()) {
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.empty()) {
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::Vector3 moduleCenter(ringModulePosition);
490  moduleCenter.z() *= side;
491  // the rotation matrix of the module
492  Acts::Vector3 moduleLocalY(cos(modulePhi), sin(modulePhi), 0.);
493  // take different axis to have the same readout direction
494  Acts::Vector3 moduleLocalZ(0., 0., side * 1.);
495  Acts::Vector3 moduleLocalX = moduleLocalY.cross(moduleLocalZ);
496  // local rotation matrices
497  // create the RotationMatrix - negative side
498  Acts::RotationMatrix3 moduleRotation;
499  moduleRotation.col(0) = moduleLocalX;
500  moduleRotation.col(1) = moduleLocalY;
501  moduleRotation.col(2) = moduleLocalZ;
502  // the transforms for the two modules
503  std::shared_ptr<const Acts::Transform3> moduleTransform =
504  std::make_shared<const Acts::Transform3>(
505  Acts::Translation3(moduleCenter) * moduleRotation);
506 
507  // create the modules identifier
508  Identifier moduleIdentifier = Identifier(identifier_type(imodule++));
509 
510  // create the module
511  auto module = std::make_shared<detector_element_t>(
512  moduleIdentifier, moduleTransform, moduleBounds, moduleThickness,
513  moduleMaterialPtr, moduleDigitizationPtr);
514  layerStore.push_back(module);
515 
516  // now deal with the potential backside
517  if (!m_cfg.posnegModuleBacksideGap.empty()) {
518  // increase the counter
519  moduleIdentifier = Identifier(identifier_type(imodule++));
520  // the new centers
521  moduleCenter =
522  moduleCenter +
523  m_cfg.posnegModuleBacksideGap.at(ipnl).at(ipnR) * moduleLocalZ;
524  // the new transforms
525  auto mutableModuleTransform = std::make_shared<Acts::Transform3>(
526  Acts::Translation3(moduleCenter) * moduleRotation);
527  // apply the stereo
528  if (!m_cfg.posnegModuleBacksideStereo.empty()) {
529  // twist by the stereo angle
530  double stereoBackSide =
531  m_cfg.posnegModuleBacksideStereo.at(ipnl).at(ipnR);
532  (*mutableModuleTransform.get()) *=
533  Acts::AngleAxis3(-stereoBackSide, Acts::Vector3::UnitZ());
534  }
535  // Finalize the transform
536  moduleTransform = std::const_pointer_cast<const Acts::Transform3>(
537  mutableModuleTransform);
538  // everything is set for the next module
539  auto bsmodule = std::make_shared<detector_element_t>(
540  moduleIdentifier, moduleTransform, moduleBounds,
541  moduleThickness, moduleMaterialPtr, moduleDigitizationPtr);
542  // Put into the detector store
543  layerStore.push_back(std::move(bsmodule));
544  }
545  // create the surface
546  esVector.push_back(module->surface().getSharedPtr());
547  }
548  // counter of rings
549  ++ipnR;
550  }
551  // the binning
552  size_t layerBinsR = m_cfg.posnegModulePhiBins.at(ipnl).size();
553  // never multiply 1 single r-bin, does not make sense
554  if (layerBinsR > 1) {
555  // multiply with the given bin multiplier
556  layerBinsR *= m_cfg.posnegLayerBinMultipliers.first;
557  }
558  size_t layerBinsPhi = 0;
559  // take the minimum phi bins in that layer
560  for (unsigned int phiBins : m_cfg.posnegModulePhiBins.at(ipnl)) {
561  layerBinsPhi = phiBins < layerBinsPhi ? phiBins : layerBinsPhi;
562  layerBinsPhi *= m_cfg.posnegLayerBinMultipliers.second;
563  }
564  // create the layers with the surface arrays
565  Acts::ProtoLayer ple(gctx, esVector);
566  ple.envelope[Acts::binR] = {layerEnvelopeR, layerEnvelopeR};
567  ple.envelope[Acts::binZ] = {m_cfg.approachSurfaceEnvelope,
568  m_cfg.approachSurfaceEnvelope};
569 
570  // push it into the layer vector
571  ProtoLayerSurfaces ples{std::move(ple), esVector, layerBinsR,
572  layerBinsPhi};
573  epLayers.push_back(std::move(ples));
574  // fill the detector store
575  detectorStore.push_back(std::move(layerStore));
576  }
577  }
578  return epLayers;
579 }
580 
581 } // end of namespace Generic
582 } // end of namespace ActsExamples