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/LayerCreator.hpp"
20 #include "Acts/Geometry/ProtoLayer.hpp"
21 #include "Acts/Material/ProtoSurfaceMaterial.hpp"
22 #include "Acts/Surfaces/CylinderSurface.hpp"
23 #include "Acts/Surfaces/DiscSurface.hpp"
24 #include "Acts/Utilities/BinningType.hpp"
25 #include "Acts/Surfaces/AnnulusBounds.hpp"
27 #include "Acts/Visualization/GeometryView3D.hpp"
28 #include "Acts/Visualization/ObjVisualization3D.hpp"
31 #include <unordered_map>
34 using Acts::Transform3;
35 using Acts::Translation3;
37 using namespace Acts::UnitLiterals;
40 std::unique_ptr<const Acts::Logger>
logger)
42 m_logger(std::move(
logger))
45 throw std::invalid_argument(
"ALB mode is undefined");
49 const Acts::LayerVector
51 ACTS_VERBOSE(
"Building negative layers");
52 Acts::LayerVector nVector;
57 const Acts::LayerVector
59 ACTS_VERBOSE(
"Building central layers");
60 Acts::LayerVector cVector;
65 const Acts::LayerVector
67 ACTS_VERBOSE(
"Building positive layers");
68 Acts::LayerVector pVector;
73 std::vector<std::shared_ptr<const ActsDetectorElement>>
75 ACTS_VERBOSE(
"Retrieving detector elements from detector manager");
77 ACTS_ERROR(
"Manager is null");
78 throw std::runtime_error{
"Detector manager is null"};
81 ACTS_VERBOSE(
"Detector manager has "
83 siDetMng->getDetectorElementEnd())
86 std::vector<std::shared_ptr<const ActsDetectorElement>> elements;
88 InDetDD::SiDetectorElementCollection::const_iterator iter;
89 for (iter = siDetMng->getDetectorElementBegin();
90 iter != siDetMng->getDetectorElementEnd(); ++iter) {
93 if (siDetElement ==
nullptr) {
94 ACTS_ERROR(
"Detector element was nullptr");
95 throw std::runtime_error{
"Corrupt detector element collection"};
98 std::make_shared<const ActsDetectorElement>(*siDetElement));
100 ACTS_VERBOSE(
"Retrieved " << elements.size() <<
" elements");
106 Acts::LayerVector &layersOutput)
const {
108 ACTS_VERBOSE(
"Build layers: BARREL");
109 std::vector<std::shared_ptr<const ActsDetectorElement>> elements =
112 std::map<int, std::vector<std::shared_ptr<const Acts::Surface>>>
layers{};
114 for (
const auto &element : elements) {
121 if(
id.layer_disk() >= 2)
continue;
124 if(
id.layer_disk() <= 1)
continue;
130 elementLayer =
id.layer_disk();
132 layers[elementLayer].push_back(element->surface().getSharedPtr());
138 for (
auto &[
key, layerSurfaces] :
layers) {
140 std::stringstream
name;
144 name <<
"obj/" <<
m_cfg.
mode <<
"_brl_" << std::setfill(
'0') << std::setw(2)
148 std::ofstream ofs{
name.str()};
149 Acts::ObjVisualization3D vis{};
150 Acts::ViewConfig vc = Acts::s_viewSensitive;
152 for (
const auto &surface : layerSurfaces) {
153 Acts::GeometryView3D::drawSurface(vis, *surface, gctx,
154 Acts::Transform3::Identity(), vc);
161 ACTS_VERBOSE(
"Found " <<
layers.size() <<
" barrel layers");
165 for (
const auto &[
key, surfaces] :
layers) {
166 Acts::ProtoLayer pl(gctx, surfaces);
167 ACTS_VERBOSE(
"Layer #" <<
n <<
" with layerKey: (" <<
key <<
")");
168 ACTS_VERBOSE(
" -> at rMin / rMax: " << pl.min(
Acts::binR) <<
" / "
170 ACTS_VERBOSE(
" -> at zMin / zMax: " << pl.min(
Acts::binZ) <<
" / "
177 for (
const auto &[
key, surfaces] :
layers) {
179 std::unique_ptr<Acts::ApproachDescriptor> approachDescriptor =
nullptr;
180 std::shared_ptr<const Acts::ProtoSurfaceMaterial> materialProxy =
nullptr;
183 Acts::ProtoLayer pl(gctx, surfaces);
188 double layerHalfZ = 0.5 * pl.range(
Acts::binZ);
190 Acts::Transform3
transform(Translation3(0., 0., -layerZ));
193 std::shared_ptr<Acts::CylinderSurface> innerBoundary =
194 Acts::Surface::makeShared<Acts::CylinderSurface>(
197 std::shared_ptr<Acts::CylinderSurface> outerBoundary =
198 Acts::Surface::makeShared<Acts::CylinderSurface>(
201 std::shared_ptr<Acts::CylinderSurface> centralSurface =
202 Acts::Surface::makeShared<Acts::CylinderSurface>(
211 materialBinUtil += Acts::BinUtility(
binsZ, -layerHalfZ, layerHalfZ,
215 std::make_shared<const Acts::ProtoSurfaceMaterial>(materialBinUtil);
217 ACTS_VERBOSE(
"[L] Layer is marked to carry support material on Surface ( "
218 "inner=0 / center=1 / outer=2 ) : "
220 ACTS_VERBOSE(
"with binning: [" << binsPhi <<
", " <<
binsZ <<
"]");
222 ACTS_VERBOSE(
"Created ApproachSurfaces for cylinder layer at:");
223 ACTS_VERBOSE(
" - inner: R=" << pl.min(
Acts::binR));
226 ACTS_VERBOSE(
" - outer: R=" << pl.max(
Acts::binR));
229 innerBoundary->assignSurfaceMaterial(materialProxy);
231 std::vector<std::shared_ptr<const Acts::Surface>> aSurfaces;
232 aSurfaces.push_back(std::move(innerBoundary));
233 aSurfaces.push_back(std::move(centralSurface));
234 aSurfaces.push_back(std::move(outerBoundary));
237 std::make_unique<Acts::GenericApproachDescriptor>(std::move(aSurfaces));
240 auto phiEqual = [
this](
const Acts::Surface &
a,
241 const Acts::Surface &
b) {
242 Acts::GeometryContext gctx;
247 auto zEqual = [
this](
const Acts::Surface &
a,
248 const Acts::Surface &
b) {
249 Acts::GeometryContext gctx;
256 auto& xsurfaces = surfaces;
257 auto countKey = [&xsurfaces](
auto equal) ->
size_t {
258 std::vector<const Acts::Surface *> keySurfaces;
259 for (
const auto &surface : xsurfaces) {
261 for (
const auto* existing : keySurfaces) {
262 if (
equal(*surface, *existing)) {
268 keySurfaces.push_back(surface.get());
271 return keySurfaces.size();
274 size_t nModPhi = countKey(phiEqual);
275 size_t nModZ = countKey(zEqual);
277 ACTS_VERBOSE(
"Found " << nModPhi <<
" modules in phi " << nModZ
280 std::shared_ptr<Acts::Layer>
layer;
288 size_t nBinsPhi = nModPhi /
f;
289 size_t nBinsZ = nModZ /
f;
292 std::move(approachDescriptor));
299 size_t nBinsPhi = nModPhi /
f;
300 size_t nBinsZ = nModZ /
f;
303 std::move(approachDescriptor));
307 std::move(approachDescriptor));
310 layersOutput.push_back(
layer);
315 Acts::LayerVector &layersOutput,
int type)
const
318 ACTS_VERBOSE(
"Build layers: " << (
type < 0 ?
"NEGATIVE" :
"POSITIVE")
320 std::vector<std::shared_ptr<const ActsDetectorElement>> elements =
322 std::map<std::tuple<int, int, int>, std::vector<const Acts::Surface *>>
325 for (
const auto &element : elements) {
333 if(
id.layer_disk() >= 3)
continue;
336 if(
id.layer_disk() <= 2)
continue;
341 std::tuple<int, int, int>
key{
id.bec(),
id.layer_disk(),
id.eta_module()};
343 initialLayers[
key].push_back(&element->surface());
346 ACTS_VERBOSE(
"Found " << initialLayers.size() <<
" "
347 << (
type < 0 ?
"NEGATIVE" :
"POSITIVE")
348 <<
" ENDCAP inital layers");
350 std::vector<Acts::ProtoLayer> protoLayers;
351 protoLayers.reserve(initialLayers.size());
353 for (
const auto &[
key, surfaces] : initialLayers) {
354 auto &pl = protoLayers.emplace_back(gctx, surfaces);
360 std::sort(protoLayers.begin(), protoLayers.end(),
361 [
type](
const Acts::ProtoLayer &
a,
const Acts::ProtoLayer &
b) {
362 double midA = (a.min(Acts::binZ) + a.max(Acts::binZ)) / 2.0;
363 double midB = (b.min(Acts::binZ) + b.max(Acts::binZ)) / 2.0;
371 auto plPrintZ = [](
const auto &pl) -> std::string {
372 std::stringstream
ss;
374 ss <<
" < " << pl.min(
Acts::binZ) <<
" | " << zMid <<
" | "
379 for (
const auto &pl : protoLayers) {
381 ACTS_VERBOSE(
" -> at < zMin | zMid | zMax >: " << plPrintZ(pl));
383 ACTS_VERBOSE(
" -> at rMin / rMax: " << pl.min(
Acts::binR) <<
" / "
388 std::vector<Acts::ProtoLayer> mergedProtoLayers;
390 if (m_cfg.doEndcapLayerMerging) {
391 mergedProtoLayers.push_back(protoLayers.front());
392 std::vector<const Acts::Surface *> surfaces;
393 for (
size_t i = 1;
i < protoLayers.size();
i++) {
394 auto &pl = protoLayers[
i];
395 auto &pl_prev = mergedProtoLayers.back();
397 ACTS_VERBOSE(
"Compare: " << plPrintZ(pl_prev) <<
" and " << plPrintZ(pl));
400 ACTS_VERBOSE(
" -> overlap? " << (overlap ?
"yes" :
"no"));
402 ACTS_VERBOSE(
" ===> merging");
404 surfaces.reserve(pl.surfaces().size() + pl_prev.surfaces().size());
405 surfaces.insert(surfaces.end(), pl.surfaces().begin(),
406 pl.surfaces().end());
407 surfaces.insert(surfaces.end(), pl_prev.surfaces().begin(),
408 pl_prev.surfaces().end());
409 mergedProtoLayers.pop_back();
411 mergedProtoLayers.emplace_back(gctx, std::move(surfaces));
415 mergedProtoLayers.push_back(std::move(pl));
419 ACTS_VERBOSE(
"" << mergedProtoLayers.size() <<
" "
420 << (
type < 0 ?
"NEGATIVE" :
"POSITIVE")
421 <<
" ENDCAP layers remain after merging");
423 mergedProtoLayers = protoLayers;
426 if (m_cfg.objDebugOutput) {
427 for (
size_t i = 0;
i < mergedProtoLayers.size();
i++) {
429 std::stringstream
ss;
430 ss <<
"obj/" << m_cfg.mode <<
"_" << (
type < 0 ?
"neg" :
"pos")
431 <<
"_disk_" << std::setfill(
'0') << std::setw(2) <<
i <<
".obj";
433 std::ofstream ofs{
ss.str()};
434 Acts::ObjVisualization3D vis{};
435 Acts::ViewConfig vc = Acts::s_viewSensitive;
437 for (
const auto &surface : mergedProtoLayers[
i].surfaces()) {
438 Acts::GeometryView3D::drawSurface(vis, *surface, gctx,
439 Acts::Transform3::Identity(), vc);
446 std::vector<std::shared_ptr<const Surface>> ownedSurfaces;
447 for (
const auto &pl : mergedProtoLayers) {
449 std::unique_ptr<Acts::ApproachDescriptor> approachDescriptor =
nullptr;
450 std::shared_ptr<const Acts::ProtoSurfaceMaterial> materialProxy =
nullptr;
453 double layerHalfZ = 0.5 * pl.range(
Acts::binZ);
456 double layerZInner = layerZ - layerHalfZ;
457 double layerZOuter = layerZ + layerHalfZ;
459 if (std::abs(layerZInner) > std::abs(layerZOuter))
462 std::vector<std::shared_ptr<const Acts::Surface>> aSurfaces;
464 Acts::Transform3 transformNominal(Translation3(0., 0., layerZ));
465 Acts::Transform3 transformInner(Translation3(0., 0., layerZInner));
466 Acts::Transform3 transformOuter(Translation3(0., 0., layerZOuter));
468 std::shared_ptr<Acts::DiscSurface> innerBoundary =
469 Acts::Surface::makeShared<Acts::DiscSurface>(
471 aSurfaces.push_back(innerBoundary);
473 std::shared_ptr<Acts::DiscSurface> nominalSurface =
474 Acts::Surface::makeShared<Acts::DiscSurface>(
476 aSurfaces.push_back(nominalSurface);
478 std::shared_ptr<Acts::DiscSurface> outerBoundary =
479 Acts::Surface::makeShared<Acts::DiscSurface>(
481 aSurfaces.push_back(outerBoundary);
483 if(layerThickness > 2_mm) {
484 ACTS_VERBOSE(
"Wide disc layer ("<< layerThickness <<
") => adding cylinder like approach surfaces");
485 Acts::Transform3
trf{Translation3{0, 0, layerZ}};
487 Acts::Surface::makeShared<Acts::CylinderSurface>(
489 aSurfaces.push_back(cylinderInner);
492 Acts::Surface::makeShared<Acts::CylinderSurface>(
494 aSurfaces.push_back(cylinderOuter);
498 size_t matBinsPhi = m_cfg.endcapMaterialBins.first;
499 size_t matBinsR = m_cfg.endcapMaterialBins.second;
508 std::make_shared<const Acts::ProtoSurfaceMaterial>(materialBinUtil);
510 ACTS_VERBOSE(
"[L] Layer is marked to carry support material on Surface ( "
511 "inner=0 / center=1 / outer=2 ) : "
513 ACTS_VERBOSE(
"with binning: [" << matBinsPhi <<
", " << matBinsR <<
"]");
515 ACTS_VERBOSE(
"Created ApproachSurfaces for disc layer at:");
516 ACTS_VERBOSE(
" - inner: Z=" << layerZInner);
517 ACTS_VERBOSE(
" - central: Z=" << layerZ);
518 ACTS_VERBOSE(
" - outer: Z=" << layerZOuter);
521 innerBoundary->assignSurfaceMaterial(materialProxy);
525 bool isITk = m_cfg.mode == Mode::ITkPixelInner ||
526 m_cfg.mode == Mode::ITkPixelOuter ||
527 m_cfg.mode == Mode::ITkStrip;
529 std::map<int, std::set<int>> phiModuleByRing;
532 for (
const auto &srf : pl.surfaces()) {
534 srf->associatedDetectorElement());
538 if(m_cfg.mode == Mode::ITkStrip || !isITk) {
542 ring_number =
id.layer_disk();
544 phiModuleByRing[ring_number].insert(
id.phi_module());
548 for(
const auto& [ring, phiModules] : phiModuleByRing) {
549 nModPhi =
std::min(nModPhi, phiModules.size());
552 size_t nModR = phiModuleByRing.size();
554 ACTS_VERBOSE(
"Identifier reports: " << nModPhi <<
" is lowest for " << nModR
557 size_t nBinsPhi = nModPhi;
558 size_t nBinsR = nModR;
568 if(m_cfg.mode == Mode::ITkStrip) {
573 ACTS_VERBOSE(
"Creating r x phi binned layer with " << nBinsR <<
" x "
574 << nBinsPhi <<
" bins");
578 std::make_unique<Acts::GenericApproachDescriptor>(aSurfaces);
581 ownedSurfaces.clear();
582 ownedSurfaces.reserve(pl.surfaces().size());
584 std::back_inserter(ownedSurfaces),
585 [](
const auto &
s) { return s->getSharedPtr(); });
587 auto layer = m_cfg.layerCreator->discLayer(gctx, ownedSurfaces, nBinsR,
588 nBinsPhi, pl, transformNominal,
589 std::move(approachDescriptor));
591 layersOutput.push_back(
layer);
611 case Mode::ITkPixelInner:
612 os <<
"ITkPixelInner";
614 case Mode::ITkPixelOuter:
615 os <<
"ITkPixelOuter";