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