329{
330 using enum Acts::AxisDirection;
331
332 ACTS_VERBOSE("Build layers: " << (type < 0 ? "NEGATIVE" : "POSITIVE")
333 << " ENDCAP");
334 std::vector<std::shared_ptr<const ActsDetectorElement>> elements =
336 std::map<std::tuple<int, int, int>, std::vector<const Acts::Surface *>>
337 initialLayers{};
338
339 for (const auto &element : elements) {
340
341 IdentityHelper id = element->identityHelper();
342 if (
id.
bec() * type <= 0) {
343 continue;
344 }
345
347 if(id.layer_disk() >= 3) continue;
348 }
350 if(id.layer_disk() <= 2) continue;
351 }
352
353 m_cfg.elementStore->push_back(element);
354
355 std::tuple<int, int, int>
key{
id.bec(),
id.layer_disk(),
id.eta_module()};
356
357 initialLayers[
key].push_back(&element->surface());
358 }
359
360 ACTS_VERBOSE("Found " << initialLayers.size() << " "
361 << (type < 0 ? "NEGATIVE" : "POSITIVE")
362 << " ENDCAP inital layers");
363
364 std::vector<Acts::ProtoLayer> protoLayers;
365 protoLayers.reserve(initialLayers.size());
366
367 for (const auto &[key, surfaces] : initialLayers) {
368 auto &pl = protoLayers.emplace_back(gctx, surfaces);
369 pl.envelope[AxisR] =
m_cfg.endcapEnvelopeR;
370 pl.envelope[AxisZ] =
m_cfg.endcapEnvelopeZ;
371 }
372
373
374 std::sort(protoLayers.begin(), protoLayers.end(),
375 [type](
const Acts::ProtoLayer &
a,
const Acts::ProtoLayer &b) {
376 double midA = (a.min(AxisZ) + a.max(AxisZ)) / 2.0;
377 double midB = (b.min(AxisZ) + b.max(AxisZ)) / 2.0;
378 if (type < 0) {
379 return midA < midB;
380 } else {
381 return midA > midB;
382 }
383 });
384
385 auto plPrintZ = [](const auto &pl) -> std::string {
386 std::stringstream
ss;
387 double zMid = (pl.min(AxisZ) + pl.max(AxisZ)) / 2.0;
388 ss <<
" < " << pl.min(AxisZ) <<
" | " << zMid <<
" | "
389 << pl.max(AxisZ) << " > ";
391 };
392 if (
logger().doPrint(Acts::Logging::VERBOSE)) {
393 for (const auto &pl : protoLayers) {
394
395 ACTS_VERBOSE(" -> at < zMin | zMid | zMax >: " << plPrintZ(pl));
396
397 ACTS_VERBOSE(" -> at rMin / rMax: " << pl.min(AxisR) << " / "
398 << pl.max(AxisR));
399 }
400 }
401
402 std::vector<Acts::ProtoLayer> mergedProtoLayers;
403
404 if (
m_cfg.doEndcapLayerMerging) {
405 mergedProtoLayers.push_back(protoLayers.front());
406 std::vector<const Acts::Surface *> surfaces;
407 for (
size_t i = 1;
i < protoLayers.size();
i++) {
408 auto &pl = protoLayers[
i];
409 auto &pl_prev = mergedProtoLayers.back();
410
411 ACTS_VERBOSE("Compare: " << plPrintZ(pl_prev) << " and " << plPrintZ(pl));
412 bool overlap = (pl.min(AxisZ) <= pl_prev.max(AxisZ) &&
413 pl.max(AxisZ) >= pl_prev.min(AxisZ));
414 ACTS_VERBOSE(" -> overlap? " << (overlap ? "yes" : "no"));
415 if (overlap) {
416 ACTS_VERBOSE(" ===> merging");
417 surfaces.clear();
418 surfaces.reserve(pl.surfaces().size() + pl_prev.surfaces().size());
419 surfaces.insert(surfaces.end(), pl.surfaces().begin(),
420 pl.surfaces().end());
421 surfaces.insert(surfaces.end(), pl_prev.surfaces().begin(),
422 pl_prev.surfaces().end());
423 mergedProtoLayers.pop_back();
424 auto &new_pl =
425 mergedProtoLayers.emplace_back(gctx, std::move(surfaces));
426 new_pl.envelope[AxisR] = pl.envelope[AxisR];
427 new_pl.envelope[AxisZ] = pl.envelope[AxisZ];
428 } else {
429 mergedProtoLayers.push_back(std::move(pl));
430 }
431 }
432
433 ACTS_VERBOSE("" << mergedProtoLayers.size() << " "
434 << (type < 0 ? "NEGATIVE" : "POSITIVE")
435 << " ENDCAP layers remain after merging");
436 } else {
437 mergedProtoLayers = std::move(protoLayers);
438 }
439
440 if (
m_cfg.objDebugOutput) {
441 for (
size_t i = 0;
i < mergedProtoLayers.size();
i++) {
442
443 std::stringstream
ss;
444 ss <<
"obj/" <<
m_cfg.mode <<
"_" << (
type < 0 ?
"neg" :
"pos")
445 <<
"_disk_" << std::setfill(
'0') << std::setw(2) <<
i <<
".obj";
446
447 std::ofstream ofs{
ss.str()};
448 Acts::ObjVisualization3D vis{};
449 Acts::ViewConfig vc = Acts::s_viewSensitive;
450 vc.quarterSegments = 200;
451 for (const auto &surface : mergedProtoLayers[i].surfaces()) {
452 Acts::GeometryView3D::drawSurface(vis, *surface, gctx,
453 Acts::Transform3::Identity(), vc);
454 }
455
456 vis.write(ofs);
457 }
458 }
459
460 std::vector<std::shared_ptr<const Surface>> ownedSurfaces;
461 for (const auto &pl : mergedProtoLayers) {
462
463 std::unique_ptr<Acts::ApproachDescriptor> approachDescriptor = nullptr;
464 std::shared_ptr<const Acts::ProtoSurfaceMaterial> materialProxy = nullptr;
465
466 double layerZ = pl.medium(AxisZ);
467 double layerHalfZ = 0.5 * pl.range(AxisZ);
468 double layerThickness = pl.range(AxisZ);
469
470 double layerZInner = layerZ - layerHalfZ;
471 double layerZOuter = layerZ + layerHalfZ;
472
473 if (std::abs(layerZInner) > std::abs(layerZOuter))
475
476 std::vector<std::shared_ptr<const Acts::Surface>> aSurfaces;
477
478 Acts::Transform3 transformNominal(Translation3(0., 0., layerZ));
479 Acts::Transform3 transformInner(Translation3(0., 0., layerZInner));
480 Acts::Transform3 transformOuter(Translation3(0., 0., layerZOuter));
481
482 std::shared_ptr<Acts::DiscSurface> innerBoundary =
483 Acts::Surface::makeShared<Acts::DiscSurface>(
484 transformInner, pl.min(AxisR), pl.max(AxisR));
485 aSurfaces.push_back(innerBoundary);
486
487 std::shared_ptr<Acts::DiscSurface> nominalSurface =
488 Acts::Surface::makeShared<Acts::DiscSurface>(
489 transformNominal, pl.min(AxisR), pl.max(AxisR));
490 aSurfaces.push_back(nominalSurface);
491
492 std::shared_ptr<Acts::DiscSurface> outerBoundary =
493 Acts::Surface::makeShared<Acts::DiscSurface>(
494 transformOuter, pl.min(AxisR), pl.max(AxisR));
495 aSurfaces.push_back(outerBoundary);
496
497 if(layerThickness > 2_mm) {
498 ACTS_VERBOSE("Wide disc layer ("<< layerThickness << ") => adding cylinder like approach surfaces");
499 Acts::Transform3
trf{Translation3{0, 0, layerZ}};
500 auto cylinderInner =
501 Acts::Surface::makeShared<Acts::CylinderSurface>(
502 trf, pl.min(AxisR), layerHalfZ);
503 aSurfaces.push_back(cylinderInner);
504
505 auto cylinderOuter =
506 Acts::Surface::makeShared<Acts::CylinderSurface>(
507 trf, pl.max(AxisR), layerHalfZ);
508 aSurfaces.push_back(cylinderOuter);
509 }
510
511
512 size_t matBinsPhi =
m_cfg.endcapMaterialBins.first;
513 size_t matBinsR =
m_cfg.endcapMaterialBins.second;
514
515 Acts::BinUtility materialBinUtil(matBinsPhi, -
M_PI,
M_PI, Acts::closed,
516 AxisPhi);
517 materialBinUtil +=
518 Acts::BinUtility(matBinsR, pl.min(AxisR), pl.max(AxisR),
519 Acts::open, AxisR, transformNominal);
520
521 materialProxy =
522 std::make_shared<const Acts::ProtoSurfaceMaterial>(materialBinUtil);
523
524 ACTS_VERBOSE("[L] Layer is marked to carry support material on Surface ( "
525 "inner=0 / center=1 / outer=2 ) : "
526 << "inner");
527 ACTS_VERBOSE("with binning: [" << matBinsPhi << ", " << matBinsR << "]");
528
529 ACTS_VERBOSE("Created ApproachSurfaces for disc layer at:");
530 ACTS_VERBOSE(" - inner: Z=" << layerZInner);
531 ACTS_VERBOSE(" - central: Z=" << layerZ);
532 ACTS_VERBOSE(" - outer: Z=" << layerZOuter);
533
534
535 innerBoundary->assignSurfaceMaterial(materialProxy);
536
537
538
542
543 std::map<int, std::set<int>> phiModuleByRing;
544
545
546 for (const auto &srf : pl.surfaces()) {
548 if (elm) {
549 auto id = elm->identityHelper();
550 int ring_number;
552 ring_number = id.eta_module();
553 }
554 else {
555 ring_number = id.layer_disk();
556 }
557 phiModuleByRing[ring_number].insert(id.phi_module());
558 }
559 }
560 size_t nModPhi = std::numeric_limits<size_t>::max();
561 for(const auto& [ring, phiModules] : phiModuleByRing) {
562 nModPhi = std::min(nModPhi, phiModules.size());
563 }
564
565 size_t nModR = phiModuleByRing.size();
566
567 ACTS_VERBOSE("Identifier reports: " << nModPhi << " is lowest for " << nModR
568 << " r-rings");
569
570 size_t nBinsPhi = nModPhi *
m_cfg.numberOfBinsFactor;
571 size_t nBinsR = nModR *
m_cfg.numberOfBinsFactor;
572
573 ACTS_VERBOSE("Creating r x phi binned layer with " << nBinsR << " x "
574 << nBinsPhi << " bins");
575
576
577 approachDescriptor =
578 std::make_unique<Acts::GenericApproachDescriptor>(aSurfaces);
579
580
581 ownedSurfaces.clear();
582 ownedSurfaces.reserve(pl.surfaces().size());
583 std::transform(pl.surfaces().begin(), pl.surfaces().end(),
584 std::back_inserter(ownedSurfaces),
585 [](const auto &s) { return s->getSharedPtr(); });
586
588 gctx, ownedSurfaces, nBinsR, nBinsPhi, pl, Transform3::Identity(),
589 std::move(approachDescriptor),
m_cfg.endcapNeighborWindow,
590 m_cfg.surfaceArrayOverfill);
591
592 layersOutput.push_back(layer);
593 }
594}
const ActsDetectorElement * getActsDetectorElement(const Acts::Surface &surf)
Attempts to retrieve the ActsDetectorElement associated to the passed ActsSurface.
void sort(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end)
Specialization of sort for DataVector/List.
void swap(ElementLinkVector< DOBJ > &lhs, ElementLinkVector< DOBJ > &rhs)