14 #include "Acts/Definitions/Algebra.hpp"
15 #include "Acts/Definitions/Units.hpp"
16 #include "Acts/Geometry/ApproachDescriptor.hpp"
17 #include "Acts/Geometry/GenericApproachDescriptor.hpp"
18 #include "Acts/Geometry/GeometryContext.hpp"
19 #include "Acts/Geometry/CylinderLayer.hpp"
20 #include "Acts/Geometry/LayerCreator.hpp"
21 #include "Acts/Geometry/ProtoLayer.hpp"
22 #include "Acts/Material/ProtoSurfaceMaterial.hpp"
23 #include "Acts/Surfaces/CylinderSurface.hpp"
24 #include "Acts/Surfaces/DiscSurface.hpp"
25 #include "Acts/Utilities/BinningType.hpp"
26 #include "Acts/Surfaces/AnnulusBounds.hpp"
28 #include "Acts/Visualization/GeometryView3D.hpp"
29 #include "Acts/Visualization/ObjVisualization3D.hpp"
31 #include <Acts/Utilities/AxisDefinitions.hpp>
33 #include <unordered_map>
37 using Acts::Transform3;
38 using Acts::Translation3;
40 using namespace Acts::UnitLiterals;
43 std::unique_ptr<const Acts::Logger>
logger)
45 m_logger(std::move(
logger))
48 throw std::invalid_argument(
"ALB mode is undefined");
52 const Acts::LayerVector
54 ACTS_VERBOSE(
"Building negative layers");
55 Acts::LayerVector nVector;
60 const Acts::LayerVector
62 ACTS_VERBOSE(
"Building central layers");
63 Acts::LayerVector cVector;
68 const Acts::LayerVector
70 ACTS_VERBOSE(
"Building positive layers");
71 Acts::LayerVector pVector;
76 std::vector<std::shared_ptr<const ActsDetectorElement>>
78 ACTS_VERBOSE(
"Retrieving detector elements from detector manager");
80 ACTS_ERROR(
"Manager is null");
81 throw std::runtime_error{
"Detector manager is null"};
84 ACTS_VERBOSE(
"Detector manager has "
86 siDetMng->getDetectorElementEnd())
89 std::vector<std::shared_ptr<const ActsDetectorElement>> elements;
91 InDetDD::SiDetectorElementCollection::const_iterator iter;
92 for (iter = siDetMng->getDetectorElementBegin();
93 iter != siDetMng->getDetectorElementEnd(); ++iter) {
96 if (siDetElement ==
nullptr) {
97 ACTS_ERROR(
"Detector element was nullptr");
98 throw std::runtime_error{
"Corrupt detector element collection"};
101 std::make_shared<const ActsDetectorElement>(*siDetElement));
103 ACTS_VERBOSE(
"Retrieved " << elements.size() <<
" elements");
109 Acts::LayerVector &layersOutput)
const {
110 using enum Acts::AxisDirection;
112 ACTS_VERBOSE(
"Build layers: BARREL");
113 std::vector<std::shared_ptr<const ActsDetectorElement>> elements =
116 std::map<int, std::vector<std::shared_ptr<const Acts::Surface>>>
layers{};
118 for (
const auto &element : elements) {
125 if(
id.layer_disk() >= 2)
continue;
128 if(
id.layer_disk() <= 1)
continue;
134 elementLayer =
id.layer_disk();
136 layers[elementLayer].push_back(element->surface().getSharedPtr());
142 for (
auto &[
key, layerSurfaces] :
layers) {
144 std::stringstream
name;
148 name <<
"obj/" <<
m_cfg.
mode <<
"_brl_" << std::setfill(
'0') << std::setw(2)
152 std::ofstream ofs{
name.str()};
153 Acts::ObjVisualization3D vis{};
154 Acts::ViewConfig vc = Acts::s_viewSensitive;
155 vc.quarterSegments = 200;
156 for (
const auto &surface : layerSurfaces) {
157 Acts::GeometryView3D::drawSurface(vis, *surface, gctx,
158 Acts::Transform3::Identity(), vc);
165 ACTS_VERBOSE(
"Found " <<
layers.size() <<
" barrel layers");
169 for (
const auto &[
key, surfaces] :
layers) {
170 Acts::ProtoLayer pl(gctx, surfaces);
171 ACTS_VERBOSE(
"Layer #" <<
n <<
" with layerKey: (" <<
key <<
")");
172 ACTS_VERBOSE(
" -> at rMin / rMax: " << pl.min(AxisR) <<
" / "
174 ACTS_VERBOSE(
" -> at zMin / zMax: " << pl.min(AxisZ) <<
" / "
181 for (
const auto &[
key, surfaces] :
layers) {
183 std::unique_ptr<Acts::ApproachDescriptor> approachDescriptor =
nullptr;
184 std::shared_ptr<const Acts::ProtoSurfaceMaterial> materialProxy =
nullptr;
187 Acts::ProtoLayer pl(gctx, surfaces);
191 double layerZ = pl.medium(AxisZ,
true);
192 double layerHalfZ = 0.5 * pl.range(AxisZ);
194 Acts::Transform3
transform(Translation3(0., 0., -layerZ));
197 std::shared_ptr<Acts::CylinderSurface> innerBoundary =
198 Acts::Surface::makeShared<Acts::CylinderSurface>(
201 std::shared_ptr<Acts::CylinderSurface> outerBoundary =
202 Acts::Surface::makeShared<Acts::CylinderSurface>(
205 std::shared_ptr<Acts::CylinderSurface> centralSurface =
206 Acts::Surface::makeShared<Acts::CylinderSurface>(
207 transform, (pl.min(AxisR) + pl.max(AxisR)) / 2.,
215 materialBinUtil += Acts::BinUtility(
binsZ, -layerHalfZ, layerHalfZ,
219 std::make_shared<const Acts::ProtoSurfaceMaterial>(materialBinUtil);
221 ACTS_VERBOSE(
"[L] Layer is marked to carry support material on Surface ( "
222 "inner=0 / center=1 / outer=2 ) : "
224 ACTS_VERBOSE(
"with binning: [" << binsPhi <<
", " <<
binsZ <<
"]");
226 ACTS_VERBOSE(
"Created ApproachSurfaces for cylinder layer at:");
227 ACTS_VERBOSE(
" - inner: R=" << pl.min(AxisR));
228 ACTS_VERBOSE(
" - central: R=" << (pl.min(AxisR) + pl.max(AxisR)) /
230 ACTS_VERBOSE(
" - outer: R=" << pl.max(AxisR));
233 innerBoundary->assignSurfaceMaterial(materialProxy);
235 std::vector<std::shared_ptr<const Acts::Surface>> aSurfaces;
236 aSurfaces.push_back(std::move(innerBoundary));
237 aSurfaces.push_back(std::move(centralSurface));
238 aSurfaces.push_back(std::move(outerBoundary));
241 std::make_unique<Acts::GenericApproachDescriptor>(std::move(aSurfaces));
244 auto phiEqual = [
this](
const Acts::Surface &
a,
245 const Acts::Surface &
b) {
246 Acts::GeometryContext gctx;
250 auto zEqual = [
this](
const Acts::Surface &
a,
251 const Acts::Surface &
b) {
252 Acts::GeometryContext gctx;
258 auto& xsurfaces = surfaces;
259 auto countKey = [&xsurfaces](
auto equal) ->
size_t {
260 std::vector<const Acts::Surface *> keySurfaces;
261 for (
const auto &surface : xsurfaces) {
263 for (
const auto* existing : keySurfaces) {
264 if (
equal(*surface, *existing)) {
270 keySurfaces.push_back(surface.get());
273 return keySurfaces.size();
276 size_t nModPhi = countKey(phiEqual);
277 size_t nModZ = countKey(zEqual);
279 ACTS_VERBOSE(
"Found " << nModPhi <<
" modules in phi " << nModZ
282 std::shared_ptr<Acts::Layer>
layer;
290 size_t nBinsPhi = nModPhi /
f;
291 size_t nBinsZ = nModZ /
f;
294 std::move(approachDescriptor));
301 size_t nBinsPhi = nModPhi /
f;
302 size_t nBinsZ = nModZ /
f;
305 std::move(approachDescriptor));
309 std::move(approachDescriptor));
312 layersOutput.push_back(
layer);
317 ACTS_DEBUG(
"Configured to build " << numPassiveLayers <<
" passive central layers.");
318 if (numPassiveLayers != 0
u) {
319 for (std::size_t icl = 0; icl < numPassiveLayers; ++icl) {
320 ACTS_VERBOSE(
"- build layer " << icl
326 auto cBounds = std::make_shared<const Acts::CylinderBounds>(
330 std::shared_ptr<Acts::Layer>
layer =
333 layersOutput.push_back(
layer);
339 Acts::LayerVector &layersOutput,
int type)
const
341 using enum Acts::AxisDirection;
343 ACTS_VERBOSE(
"Build layers: " << (
type < 0 ?
"NEGATIVE" :
"POSITIVE")
345 std::vector<std::shared_ptr<const ActsDetectorElement>> elements =
347 std::map<std::tuple<int, int, int>, std::vector<const Acts::Surface *>>
350 for (
const auto &element : elements) {
358 if(
id.layer_disk() >= 3)
continue;
361 if(
id.layer_disk() <= 2)
continue;
366 std::tuple<int, int, int>
key{
id.bec(),
id.layer_disk(),
id.eta_module()};
368 initialLayers[
key].push_back(&element->surface());
371 ACTS_VERBOSE(
"Found " << initialLayers.size() <<
" "
372 << (
type < 0 ?
"NEGATIVE" :
"POSITIVE")
373 <<
" ENDCAP inital layers");
375 std::vector<Acts::ProtoLayer> protoLayers;
376 protoLayers.reserve(initialLayers.size());
378 for (
const auto &[
key, surfaces] : initialLayers) {
379 auto &pl = protoLayers.emplace_back(gctx, surfaces);
385 std::sort(protoLayers.begin(), protoLayers.end(),
386 [
type](
const Acts::ProtoLayer &
a,
const Acts::ProtoLayer &
b) {
387 double midA = (a.min(AxisZ) + a.max(AxisZ)) / 2.0;
388 double midB = (b.min(AxisZ) + b.max(AxisZ)) / 2.0;
396 auto plPrintZ = [](
const auto &pl) -> std::string {
397 std::stringstream
ss;
398 double zMid = (pl.min(AxisZ) + pl.max(AxisZ)) / 2.0;
399 ss <<
" < " << pl.min(AxisZ) <<
" | " << zMid <<
" | "
400 << pl.max(AxisZ) <<
" > ";
404 for (
const auto &pl : protoLayers) {
406 ACTS_VERBOSE(
" -> at < zMin | zMid | zMax >: " << plPrintZ(pl));
408 ACTS_VERBOSE(
" -> at rMin / rMax: " << pl.min(AxisR) <<
" / "
413 std::vector<Acts::ProtoLayer> mergedProtoLayers;
415 if (m_cfg.doEndcapLayerMerging) {
416 mergedProtoLayers.push_back(protoLayers.front());
417 std::vector<const Acts::Surface *> surfaces;
418 for (
size_t i = 1;
i < protoLayers.size();
i++) {
419 auto &pl = protoLayers[
i];
420 auto &pl_prev = mergedProtoLayers.back();
422 ACTS_VERBOSE(
"Compare: " << plPrintZ(pl_prev) <<
" and " << plPrintZ(pl));
423 bool overlap = (pl.min(AxisZ) <= pl_prev.max(AxisZ) &&
424 pl.max(AxisZ) >= pl_prev.min(AxisZ));
425 ACTS_VERBOSE(
" -> overlap? " << (overlap ?
"yes" :
"no"));
427 ACTS_VERBOSE(
" ===> merging");
429 surfaces.reserve(pl.surfaces().size() + pl_prev.surfaces().size());
430 surfaces.insert(surfaces.end(), pl.surfaces().begin(),
431 pl.surfaces().end());
432 surfaces.insert(surfaces.end(), pl_prev.surfaces().begin(),
433 pl_prev.surfaces().end());
434 mergedProtoLayers.pop_back();
436 mergedProtoLayers.emplace_back(gctx, std::move(surfaces));
437 new_pl.envelope[AxisR] = pl.envelope[AxisR];
438 new_pl.envelope[AxisZ] = pl.envelope[AxisZ];
440 mergedProtoLayers.push_back(std::move(pl));
444 ACTS_VERBOSE(
"" << mergedProtoLayers.size() <<
" "
445 << (
type < 0 ?
"NEGATIVE" :
"POSITIVE")
446 <<
" ENDCAP layers remain after merging");
448 mergedProtoLayers = protoLayers;
451 if (m_cfg.objDebugOutput) {
452 for (
size_t i = 0;
i < mergedProtoLayers.size();
i++) {
454 std::stringstream
ss;
455 ss <<
"obj/" << m_cfg.mode <<
"_" << (
type < 0 ?
"neg" :
"pos")
456 <<
"_disk_" << std::setfill(
'0') << std::setw(2) <<
i <<
".obj";
458 std::ofstream ofs{
ss.str()};
459 Acts::ObjVisualization3D vis{};
460 Acts::ViewConfig vc = Acts::s_viewSensitive;
461 vc.quarterSegments = 200;
462 for (
const auto &surface : mergedProtoLayers[
i].surfaces()) {
463 Acts::GeometryView3D::drawSurface(vis, *surface, gctx,
464 Acts::Transform3::Identity(), vc);
471 std::vector<std::shared_ptr<const Surface>> ownedSurfaces;
472 for (
const auto &pl : mergedProtoLayers) {
474 std::unique_ptr<Acts::ApproachDescriptor> approachDescriptor =
nullptr;
475 std::shared_ptr<const Acts::ProtoSurfaceMaterial> materialProxy =
nullptr;
477 double layerZ = pl.medium(AxisZ);
478 double layerHalfZ = 0.5 * pl.range(AxisZ);
479 double layerThickness = pl.range(AxisZ);
481 double layerZInner = layerZ - layerHalfZ;
482 double layerZOuter = layerZ + layerHalfZ;
484 if (std::abs(layerZInner) > std::abs(layerZOuter))
487 std::vector<std::shared_ptr<const Acts::Surface>> aSurfaces;
489 Acts::Transform3 transformNominal(Translation3(0., 0., layerZ));
490 Acts::Transform3 transformInner(Translation3(0., 0., layerZInner));
491 Acts::Transform3 transformOuter(Translation3(0., 0., layerZOuter));
493 std::shared_ptr<Acts::DiscSurface> innerBoundary =
494 Acts::Surface::makeShared<Acts::DiscSurface>(
495 transformInner, pl.min(AxisR), pl.max(AxisR));
496 aSurfaces.push_back(innerBoundary);
498 std::shared_ptr<Acts::DiscSurface> nominalSurface =
499 Acts::Surface::makeShared<Acts::DiscSurface>(
500 transformNominal, pl.min(AxisR), pl.max(AxisR));
501 aSurfaces.push_back(nominalSurface);
503 std::shared_ptr<Acts::DiscSurface> outerBoundary =
504 Acts::Surface::makeShared<Acts::DiscSurface>(
505 transformOuter, pl.min(AxisR), pl.max(AxisR));
506 aSurfaces.push_back(outerBoundary);
508 if(layerThickness > 2_mm) {
509 ACTS_VERBOSE(
"Wide disc layer ("<< layerThickness <<
") => adding cylinder like approach surfaces");
510 Acts::Transform3
trf{Translation3{0, 0, layerZ}};
512 Acts::Surface::makeShared<Acts::CylinderSurface>(
513 trf, pl.min(AxisR), layerHalfZ);
514 aSurfaces.push_back(cylinderInner);
517 Acts::Surface::makeShared<Acts::CylinderSurface>(
518 trf, pl.max(AxisR), layerHalfZ);
519 aSurfaces.push_back(cylinderOuter);
523 size_t matBinsPhi = m_cfg.endcapMaterialBins.first;
524 size_t matBinsR = m_cfg.endcapMaterialBins.second;
529 Acts::BinUtility(matBinsR, pl.min(AxisR), pl.max(AxisR),
533 std::make_shared<const Acts::ProtoSurfaceMaterial>(materialBinUtil);
535 ACTS_VERBOSE(
"[L] Layer is marked to carry support material on Surface ( "
536 "inner=0 / center=1 / outer=2 ) : "
538 ACTS_VERBOSE(
"with binning: [" << matBinsPhi <<
", " << matBinsR <<
"]");
540 ACTS_VERBOSE(
"Created ApproachSurfaces for disc layer at:");
541 ACTS_VERBOSE(
" - inner: Z=" << layerZInner);
542 ACTS_VERBOSE(
" - central: Z=" << layerZ);
543 ACTS_VERBOSE(
" - outer: Z=" << layerZOuter);
546 innerBoundary->assignSurfaceMaterial(materialProxy);
550 bool isITk = m_cfg.mode == Mode::ITkPixelInner ||
551 m_cfg.mode == Mode::ITkPixelOuter ||
552 m_cfg.mode == Mode::ITkStrip;
554 std::map<int, std::set<int>> phiModuleByRing;
557 for (
const auto &srf : pl.surfaces()) {
559 srf->associatedDetectorElement());
563 if(m_cfg.mode == Mode::ITkStrip || !isITk) {
567 ring_number =
id.layer_disk();
569 phiModuleByRing[ring_number].insert(
id.phi_module());
573 for(
const auto& [ring, phiModules] : phiModuleByRing) {
574 nModPhi =
std::min(nModPhi, phiModules.size());
577 size_t nModR = phiModuleByRing.size();
579 ACTS_VERBOSE(
"Identifier reports: " << nModPhi <<
" is lowest for " << nModR
582 size_t nBinsPhi = nModPhi;
583 size_t nBinsR = nModR;
593 if(m_cfg.mode == Mode::ITkStrip) {
598 ACTS_VERBOSE(
"Creating r x phi binned layer with " << nBinsR <<
" x "
599 << nBinsPhi <<
" bins");
603 std::make_unique<Acts::GenericApproachDescriptor>(aSurfaces);
606 ownedSurfaces.clear();
607 ownedSurfaces.reserve(pl.surfaces().size());
609 std::back_inserter(ownedSurfaces),
610 [](
const auto &
s) { return s->getSharedPtr(); });
612 auto layer = m_cfg.layerCreator->discLayer(gctx, ownedSurfaces, nBinsR,
613 nBinsPhi, pl, transformNominal,
614 std::move(approachDescriptor));
616 layersOutput.push_back(
layer);
636 case Mode::ITkPixelInner:
637 os <<
"ITkPixelInner";
639 case Mode::ITkPixelOuter:
640 os <<
"ITkPixelOuter";