Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-04-11 07:57:20

0001 // This file is part of the ACTS project.
0002 //
0003 // Copyright (C) 2016 CERN for the benefit of the ACTS project
0004 //
0005 // This Source Code Form is subject to the terms of the Mozilla Public
0006 // License, v. 2.0. If a copy of the MPL was not distributed with this
0007 // file, You can obtain one at https://mozilla.org/MPL/2.0/.
0008 
0009 #include "ActsExamples/GenericDetector/ProtoLayerCreator.hpp"
0010 
0011 using Acts::VectorHelpers::phi;
0012 
0013 namespace ActsExamples::Generic {
0014 
0015 std::vector<ProtoLayerSurfaces> ProtoLayerCreator::centralProtoLayers(
0016     const Acts::GeometryContext& gctx) const {
0017   // create the vector
0018   std::vector<ProtoLayerSurfaces> cpLayers;
0019 
0020   // ----------------------- central layers -------------------------
0021   // the central layers
0022   std::size_t numcLayers = m_cfg.centralLayerRadii.size();
0023   if (numcLayers != 0u) {
0024     ACTS_DEBUG("Configured to build " << numcLayers
0025                                       << " active central layers.");
0026     cpLayers.reserve(numcLayers);
0027     // loop through
0028     for (std::size_t icl = 0; icl < numcLayers; ++icl) {
0029       // layer R/Z
0030       double layerR = m_cfg.centralLayerRadii.at(icl);
0031       // some screen output
0032       ACTS_DEBUG("Build layer " << icl << " with target radius = " << layerR);
0033 
0034       // prepare the Surface vector
0035       std::vector<std::shared_ptr<const Acts::Surface>> sVector;
0036       // assign the current envelope
0037       double layerEnvelopeCoverZ =
0038           !m_cfg.centralLayerEnvelopes.empty()
0039               ? m_cfg.centralLayerEnvelopes.at(icl).second
0040               : 0.;
0041       // module size & tilt
0042       double modulePhiTilt = m_cfg.centralModuleTiltPhi.at(icl);
0043       double moduleHalfX = m_cfg.centralModuleHalfX.at(icl);
0044       double moduleHalfY = m_cfg.centralModuleHalfY.at(icl);
0045       double moduleThickness = m_cfg.centralModuleThickness.at(icl);
0046       // create the shared module
0047       auto moduleBounds =
0048           std::make_shared<Acts::RectangleBounds>(moduleHalfX, moduleHalfY);
0049       std::size_t nCentralModules =
0050           m_cfg.centralModuleBinningSchema.at(icl).first *
0051           m_cfg.centralModuleBinningSchema.at(icl).second;
0052 
0053       ACTS_DEBUG("- number of modules "
0054                  << nCentralModules << " ( from "
0055                  << m_cfg.centralModuleBinningSchema.at(icl).first << " x "
0056                  << m_cfg.centralModuleBinningSchema.at(icl).second << " )");
0057 
0058       sVector.reserve(nCentralModules);
0059 
0060       // prepartation :
0061       // create the Module material from input
0062       std::shared_ptr<const Acts::ISurfaceMaterial> moduleMaterialPtr = nullptr;
0063       if (!m_cfg.centralModuleMaterial.empty()) {
0064         // get the sensor material from configuration
0065         moduleMaterialPtr = m_cfg.centralModuleMaterial.at(icl);
0066       }
0067 
0068       // confirm
0069       if (m_cfg.centralModulePositions.at(icl).size() != nCentralModules) {
0070         ACTS_WARNING("Mismatching module numbers, configuration error!");
0071         ACTS_WARNING("- Binning schema suggests : " << nCentralModules);
0072         ACTS_WARNING("- Positions provided are  : "
0073                      << m_cfg.centralModulePositions.at(icl).size());
0074       }
0075       // loop over the position, create the modules
0076       for (auto& moduleCenter : m_cfg.centralModulePositions.at(icl)) {
0077         // create the association transform
0078         double modulePhi = phi(moduleCenter);
0079         // the local z axis is the normal vector
0080         Acts::Vector3 moduleLocalZ(cos(modulePhi + modulePhiTilt),
0081                                    sin(modulePhi + modulePhiTilt), 0.);
0082         // the local y axis is the global z axis
0083         Acts::Vector3 moduleLocalY(0., 0., 1);
0084         // the local x axis the normal to local y,z
0085         Acts::Vector3 moduleLocalX(-sin(modulePhi + modulePhiTilt),
0086                                    cos(modulePhi + modulePhiTilt), 0.);
0087         // create the RotationMatrix
0088         Acts::RotationMatrix3 moduleRotation;
0089         moduleRotation.col(0) = moduleLocalX;
0090         moduleRotation.col(1) = moduleLocalY;
0091         moduleRotation.col(2) = moduleLocalZ;
0092         // get the moduleTransform
0093         std::shared_ptr<Acts::Transform3> mutableModuleTransform =
0094             std::make_shared<Acts::Transform3>(
0095                 Acts::Translation3(moduleCenter) * moduleRotation);
0096         // stereo angle if necessary
0097         if (!m_cfg.centralModuleFrontsideStereo.empty() &&
0098             m_cfg.centralModuleFrontsideStereo.at(icl) != 0.) {
0099           // twist by the stereo angle
0100           double stereo = m_cfg.centralModuleFrontsideStereo.at(icl);
0101           (*mutableModuleTransform) *=
0102               Acts::AngleAxis3(-stereo, Acts::Vector3::UnitZ());
0103         }
0104 
0105         // Finalize the transform
0106         auto moduleTransform = std::const_pointer_cast<const Acts::Transform3>(
0107             mutableModuleTransform);
0108         // create the module
0109         auto moduleElement = m_cfg.detectorElementFactory(
0110             moduleTransform, moduleBounds, moduleThickness, moduleMaterialPtr);
0111 
0112         // register the surface
0113         sVector.push_back(moduleElement->surface().getSharedPtr());
0114         // IF double modules exist
0115         // and the backside one (if configured to do so)
0116         if (!m_cfg.centralModuleBacksideGap.empty()) {
0117           // create the module identifier
0118 
0119           Acts::Vector3 bsModuleCenter =
0120               moduleCenter +
0121               m_cfg.centralModuleBacksideGap.at(icl) * moduleLocalZ;
0122           mutableModuleTransform = std::make_shared<Acts::Transform3>(
0123               Acts::Translation3(bsModuleCenter) * moduleRotation);
0124           // apply the stereo
0125           if (!m_cfg.centralModuleBacksideStereo.empty()) {
0126             // twist by the stereo angle
0127             double stereoBackSide = m_cfg.centralModuleBacksideStereo.at(icl);
0128             (*mutableModuleTransform) *=
0129                 Acts::AngleAxis3(-stereoBackSide, Acts::Vector3::UnitZ());
0130           }
0131           // Finalize the transform
0132           moduleTransform = std::const_pointer_cast<const Acts::Transform3>(
0133               mutableModuleTransform);
0134           // create the backseide moulde
0135           auto bsModuleElement =
0136               m_cfg.detectorElementFactory(moduleTransform, moduleBounds,
0137                                            moduleThickness, moduleMaterialPtr);
0138         }
0139       }
0140 
0141       std::size_t phiBins = m_cfg.centralModuleBinningSchema.at(icl).first;
0142       phiBins *= m_cfg.centralLayerBinMultipliers.first;
0143       std::size_t zBins = m_cfg.centralModuleBinningSchema.at(icl).second;
0144       zBins *= m_cfg.centralLayerBinMultipliers.second;
0145       // create the surface array - it will also fill the accessible binmember
0146       // cache if available
0147       Acts::ProtoLayer pl(gctx, sVector);
0148       pl.envelope[Acts::AxisDirection::AxisR] = {m_cfg.approachSurfaceEnvelope,
0149                                                  m_cfg.approachSurfaceEnvelope};
0150       pl.envelope[Acts::AxisDirection::AxisZ] = {layerEnvelopeCoverZ,
0151                                                  layerEnvelopeCoverZ};
0152 
0153       // Record the proto layer and the surfaces for the later layer building
0154       ProtoLayerSurfaces pls{std::move(pl), sVector, phiBins, zBins};
0155       cpLayers.push_back(std::move(pls));
0156     }
0157   }
0158   return cpLayers;
0159 }
0160 
0161 std::vector<ProtoLayerSurfaces> ProtoLayerCreator::negativeProtoLayers(
0162     const Acts::GeometryContext& gctx) const {
0163   return createProtoLayers(gctx, -1);
0164 }
0165 
0166 std::vector<ProtoLayerSurfaces> ProtoLayerCreator::positiveProtoLayers(
0167     const Acts::GeometryContext& gctx) const {
0168   return createProtoLayers(gctx, 1);
0169 }
0170 
0171 ProtoLayerCreator::ProtoLayerCreator(const ProtoLayerCreator::Config& cfg,
0172                                      std::unique_ptr<const Acts::Logger> log)
0173     : m_cfg(cfg), m_logger(std::move(log)) {
0174   if (!m_cfg.detectorElementFactory) {
0175     throw std::invalid_argument("Detector element factory is not set");
0176   }
0177 }
0178 
0179 std::vector<ProtoLayerSurfaces> ProtoLayerCreator::createProtoLayers(
0180     const Acts::GeometryContext& gctx, int side) const {
0181   // Count the current detector modules identifiers
0182   // the return layers
0183   std::vector<ProtoLayerSurfaces> epLayers;
0184   // -------------------------------- endcap type layers
0185   // pos/neg layers
0186   std::size_t numpnLayers = m_cfg.posnegLayerPositionsZ.size();
0187   if (numpnLayers != 0u) {
0188     ACTS_DEBUG("Configured to build 2 * "
0189                << numpnLayers << " passive positive/negative side layers.");
0190     epLayers.reserve(numpnLayers);
0191 
0192     /// this is the loop over the layer positions
0193     for (std::size_t ipnl = 0; ipnl < numpnLayers; ++ipnl) {
0194       // some screen output
0195       ACTS_VERBOSE("- building layer "
0196                    << ipnl << " and " << numpnLayers + ipnl << " at z = "
0197                    << side * m_cfg.posnegLayerPositionsZ.at(ipnl));
0198       /// some preparation work
0199       // define the layer envelope
0200       double layerEnvelopeR = m_cfg.posnegLayerEnvelopeR.at(ipnl);
0201       // prepare for the r binning
0202       std::vector<std::shared_ptr<const Acts::Surface>> esVector;
0203       // now fill the vectors
0204       std::size_t ipnR = 0;
0205       for (auto& discModulePositions : m_cfg.posnegModulePositions.at(ipnl)) {
0206         ACTS_VERBOSE("- building ring " << ipnR << " for this layer.");
0207         // now prepare all the shared stuff
0208         // (0) module specifications
0209         double moduleThickness = m_cfg.posnegModuleThickness.at(ipnl).at(ipnR);
0210         double moduleMinHalfX = m_cfg.posnegModuleMinHalfX.at(ipnl).at(ipnR);
0211         double moduleMaxHalfX = 0.;
0212         if (m_cfg.posnegModuleMaxHalfX.size() > ipnl &&
0213             m_cfg.posnegModuleMaxHalfX.at(ipnl).size() > ipnR) {
0214           moduleMaxHalfX = m_cfg.posnegModuleMaxHalfX.at(ipnl).at(ipnR);
0215         }
0216         double moduleHalfY = m_cfg.posnegModuleHalfY.at(ipnl).at(ipnR);
0217         // (1) module bounds
0218         // create the bounds
0219         std::shared_ptr<const Acts::PlanarBounds> moduleBounds;
0220         if (moduleMaxHalfX != 0. && moduleMinHalfX != moduleMaxHalfX) {
0221           moduleBounds = std::make_shared<Acts::TrapezoidBounds>(
0222               moduleMinHalfX, moduleMaxHalfX, moduleHalfY);
0223         } else {
0224           moduleBounds = std::make_shared<Acts::RectangleBounds>(moduleMinHalfX,
0225                                                                  moduleHalfY);
0226         }
0227         // (2)) module material
0228         // create the Module material from input
0229         std::shared_ptr<const Acts::ISurfaceMaterial> moduleMaterialPtr =
0230             nullptr;
0231         if (!m_cfg.posnegModuleMaterial.empty()) {
0232           // and create the shared pointer
0233           moduleMaterialPtr = m_cfg.posnegModuleMaterial.at(ipnl).at(ipnR);
0234         }
0235 
0236         // low loop over the phi positions and build the stuff
0237         for (auto& ringModulePosition : discModulePositions) {
0238           // the module transform from the position
0239           double modulePhi = phi(ringModulePosition);
0240           // the center position of the modules
0241           Acts::Vector3 moduleCenter(ringModulePosition);
0242           moduleCenter.z() *= side;
0243           // the rotation matrix of the module
0244           Acts::Vector3 moduleLocalY(cos(modulePhi), sin(modulePhi), 0.);
0245           // take different axis to have the same readout direction
0246           Acts::Vector3 moduleLocalZ(0., 0., side * 1.);
0247           Acts::Vector3 moduleLocalX = moduleLocalY.cross(moduleLocalZ);
0248           // local rotation matrices
0249           // create the RotationMatrix - negative side
0250           Acts::RotationMatrix3 moduleRotation;
0251           moduleRotation.col(0) = moduleLocalX;
0252           moduleRotation.col(1) = moduleLocalY;
0253           moduleRotation.col(2) = moduleLocalZ;
0254           // the transforms for the two modules
0255           std::shared_ptr<const Acts::Transform3> moduleTransform =
0256               std::make_shared<const Acts::Transform3>(
0257                   Acts::Translation3(moduleCenter) * moduleRotation);
0258 
0259           // create the module
0260           auto moduleElement =
0261               m_cfg.detectorElementFactory(moduleTransform, moduleBounds,
0262                                            moduleThickness, moduleMaterialPtr);
0263 
0264           // now deal with the potential backside
0265           if (!m_cfg.posnegModuleBacksideGap.empty()) {
0266             // the new centers
0267             moduleCenter =
0268                 moduleCenter +
0269                 m_cfg.posnegModuleBacksideGap.at(ipnl).at(ipnR) * moduleLocalZ;
0270             // the new transforms
0271             auto mutableModuleTransform = std::make_shared<Acts::Transform3>(
0272                 Acts::Translation3(moduleCenter) * moduleRotation);
0273             // apply the stereo
0274             if (!m_cfg.posnegModuleBacksideStereo.empty()) {
0275               // twist by the stereo angle
0276               double stereoBackSide =
0277                   m_cfg.posnegModuleBacksideStereo.at(ipnl).at(ipnR);
0278               (*mutableModuleTransform) *=
0279                   Acts::AngleAxis3(-stereoBackSide, Acts::Vector3::UnitZ());
0280             }
0281             // Finalize the transform
0282             moduleTransform = std::const_pointer_cast<const Acts::Transform3>(
0283                 mutableModuleTransform);
0284             // everything is set for the next module
0285             auto bsModuleElement = m_cfg.detectorElementFactory(
0286                 moduleTransform, moduleBounds, moduleThickness,
0287                 moduleMaterialPtr);
0288           }
0289           // create the surface
0290           esVector.push_back(moduleElement->surface().getSharedPtr());
0291         }
0292         // counter of rings
0293         ++ipnR;
0294       }
0295       // the binning
0296       std::size_t layerBinsR = m_cfg.posnegModulePhiBins.at(ipnl).size();
0297       // never multiply 1 single r-bin, does not make sense
0298       if (layerBinsR > 1) {
0299         // multiply with the given bin multiplier
0300         layerBinsR *= m_cfg.posnegLayerBinMultipliers.first;
0301       }
0302       std::size_t layerBinsPhi = 0;
0303       // take the minimum phi bins in that layer
0304       for (unsigned int phiBins : m_cfg.posnegModulePhiBins.at(ipnl)) {
0305         layerBinsPhi = phiBins < layerBinsPhi ? phiBins : layerBinsPhi;
0306         layerBinsPhi *= m_cfg.posnegLayerBinMultipliers.second;
0307       }
0308       // create the layers with the surface arrays
0309       Acts::ProtoLayer ple(gctx, esVector);
0310       ple.envelope[Acts::AxisDirection::AxisR] = {layerEnvelopeR,
0311                                                   layerEnvelopeR};
0312       ple.envelope[Acts::AxisDirection::AxisZ] = {
0313           m_cfg.approachSurfaceEnvelope, m_cfg.approachSurfaceEnvelope};
0314 
0315       // push it into the layer vector
0316       ProtoLayerSurfaces ples{std::move(ple), esVector, layerBinsR,
0317                               layerBinsPhi};
0318       epLayers.push_back(std::move(ples));
0319     }
0320   }
0321   return epLayers;
0322 }
0323 
0324 }  // namespace ActsExamples::Generic