34 #include <boost/algorithm/string.hpp>
39 std::unique_ptr<const Logger>
logger)
54 std::unique_ptr<const Logger> newLogger) {
58 std::shared_ptr<Acts::TrackingVolume>
64 ACTS_DEBUG(
"- will wrap/enclose : " << existingVolume->volumeName());
82 if (
m_cfg.layerBuilder) {
84 negativeLayers =
m_cfg.layerBuilder->negativeLayers(gctx);
86 centralLayers =
m_cfg.layerBuilder->centralLayers(gctx);
88 positiveLayers =
m_cfg.layerBuilder->positiveLayers(gctx);
94 if (
m_cfg.ctVolumeBuilder) {
95 centralVolumes =
m_cfg.ctVolumeBuilder->centralVolumes();
101 if (existingVolume) {
104 &existingVolume->volumeBounds());
112 existingVolume->center().z() -
115 existingVolume->center().z() +
122 if (externalBounds) {
126 if (ocvBounds !=
nullptr) {
160 wConfig.
nVolumeConfig = analyzeContent(gctx, negativeLayers, {});
161 wConfig.
cVolumeConfig = analyzeContent(gctx, centralLayers, centralVolumes);
162 wConfig.
pVolumeConfig = analyzeContent(gctx, positiveLayers, {});
169 ACTS_INFO(
"No layers present, returning nullptr");
176 ACTS_VERBOSE(
"Negative layers are present: rmin, rmax | zmin, zmax = "
178 std::vector<std::string> centers;
180 std::back_inserter(centers), [&](
const auto&
layer) {
182 layer->surfaceRepresentation().center(gctx)[
eZ]);
186 layerConfiguration +=
" Negative Endcap |";
190 ACTS_VERBOSE(
"Central layers are present: rmin, rmax | zmin, zmax = "
192 std::vector<std::string> centers;
194 std::back_inserter(centers), [&](
const auto&
layer) {
196 layer->surfaceRepresentation().center(gctx)));
200 layerConfiguration +=
" Barrel |";
204 ACTS_VERBOSE(
"Positive layers are present: rmin, rmax | zmin, zmax = "
206 std::vector<std::string> centers;
208 std::back_inserter(centers), [&](
const auto&
layer) {
210 layer->surfaceRepresentation().center(gctx)[
eZ]);
214 layerConfiguration +=
" Positive Endcap |";
217 ACTS_DEBUG(
"Layer configuration is : " << layerConfiguration);
221 ACTS_VERBOSE(
"Configurations after layer parsing " <<
'\n'
225 ACTS_VERBOSE(
"Configuration after container synchronisation "
231 ACTS_VERBOSE(
"Configuration after wrapping, insertion, attachment "
242 auto tvHelper =
m_cfg.trackingVolumeHelper;
246 ? tvHelper->createTrackingVolume(
251 m_cfg.volumeName +
"::Barrel")
261 if (not endcapConfig) {
265 if (
m_cfg.checkRingLayout) {
266 ACTS_DEBUG(
"Configured to check for ring layout - parsing layers.");
268 std::vector<double> innerRadii = {};
269 std::vector<double> outerRadii = {};
270 for (
const auto& elay : endcapConfig.layers) {
272 &(elay->surfaceRepresentation().bounds()));
273 if (discBounds !=
nullptr) {
276 double rMin = discBounds->rMin();
277 auto innerSearch = std::find_if(
278 innerRadii.begin(), innerRadii.end(), [&](
double reference) {
279 return std::abs(rMin - reference) <
tolerance;
281 if (innerSearch == innerRadii.end()) {
282 innerRadii.push_back(rMin);
285 double rMax = discBounds->rMax();
286 auto outerSearch = std::find_if(
287 outerRadii.begin(), outerRadii.end(), [&](
double reference) {
288 return std::abs(rMax - reference) <
tolerance;
290 if (outerSearch == outerRadii.end()) {
291 outerRadii.push_back(rMax);
298 std::sort(innerRadii.begin(), innerRadii.end());
299 std::sort(outerRadii.begin(), outerRadii.end());
302 std::stringstream ss;
303 for (
double f : innerRadii) {
310 std::stringstream ss;
311 for (
double f : outerRadii) {
317 if (innerRadii.size() == outerRadii.size() and not innerRadii.empty()) {
318 bool consistent =
true;
321 std::vector<double> interRadii = {};
322 for (
int ir = 1; ir < int(innerRadii.size()); ++ir) {
325 "or #" << ir - 1 <<
" < ir #" << ir <<
": " << outerRadii[ir - 1]
326 <<
" < " << innerRadii[ir] <<
", ok: "
327 << (outerRadii[ir - 1] < innerRadii[ir] ?
"yes" :
"no"));
328 if (outerRadii[ir - 1] < innerRadii[ir]) {
329 interRadii.push_back(0.5 * (outerRadii[ir - 1] + innerRadii[ir]));
337 ACTS_DEBUG(
"Ring layout detection: " << innerRadii.size()
340 std::vector<std::pair<double, double>> volumeRminRmax = {};
341 for (
unsigned int ii = 0; ii < interRadii.size(); ++ii) {
343 volumeRminRmax.push_back({endcapConfig.rMin, interRadii[ii]});
345 if (ii + 1 < interRadii.size()) {
346 volumeRminRmax.push_back({interRadii[ii], interRadii[ii + 1]});
348 volumeRminRmax.push_back({interRadii[ii], endcapConfig.rMax});
352 std::vector<LayerVector>(innerRadii.size(),
LayerVector());
354 for (
const auto& elay : endcapConfig.layers) {
357 elay->surfaceRepresentation().binningPositionValue(gctx,
binR);
359 auto ringVolume = std::find_if(
360 volumeRminRmax.begin(), volumeRminRmax.end(),
361 [&](
const auto& reference) {
362 return (test > reference.first and test < reference.second);
364 if (ringVolume != volumeRminRmax.end()) {
365 unsigned int ringBin =
367 ringLayers[ringBin].push_back(elay);
373 std::vector<TrackingVolumePtr> endcapContainer;
375 for (
auto& rLayers : ringLayers) {
376 ACTS_DEBUG(
" - ring volume " << ir <<
" with " << rLayers.size()
377 <<
" layers, and rmin/rmax = "
378 << volumeRminRmax[ir].first <<
"/"
379 << volumeRminRmax[ir].second);
380 endcapContainer.push_back(tvHelper->createTrackingVolume(
381 gctx, rLayers, centralConfig.
volumes,
m_cfg.volumeMaterial,
382 volumeRminRmax[ir].first, volumeRminRmax[ir].second,
383 endcapConfig.zMin, endcapConfig.zMax,
389 return tvHelper->createContainerTrackingVolume(gctx, endcapContainer);
391 ACTS_DEBUG(
"Ring radii found to be inconsistent");
394 ACTS_DEBUG(
"Have " << innerRadii.size() <<
" inner radii and "
395 << outerRadii.size() <<
" outer radii");
400 return tvHelper->createTrackingVolume(
401 gctx, endcapConfig.layers, centralConfig.
volumes,
m_cfg.volumeMaterial,
402 endcapConfig.rMin, endcapConfig.rMax, endcapConfig.zMin,
403 endcapConfig.zMax,
m_cfg.volumeName + endcapName);
421 std::vector<TrackingVolumePtr> volumesContainer;
423 volumesContainer.push_back(nEndcap);
426 if (not
m_cfg.buildToRadiusZero) {
427 volume->assignBoundaryMaterial(
m_cfg.boundaryMaterial[0],
430 volume->assignBoundaryMaterial(
m_cfg.boundaryMaterial[1],
432 volume->assignBoundaryMaterial(
m_cfg.boundaryMaterial[2],
434 volume->assignBoundaryMaterial(
m_cfg.boundaryMaterial[3],
439 volumesContainer.push_back(barrel);
442 if (not
m_cfg.buildToRadiusZero) {
443 volume->assignBoundaryMaterial(
m_cfg.boundaryMaterial[0],
446 volume->assignBoundaryMaterial(
m_cfg.boundaryMaterial[1],
448 volume->assignBoundaryMaterial(
m_cfg.boundaryMaterial[3],
450 volume->assignBoundaryMaterial(
m_cfg.boundaryMaterial[4],
454 volumesContainer.push_back(pEndcap);
457 if (not
m_cfg.buildToRadiusZero) {
458 volume->assignBoundaryMaterial(
m_cfg.boundaryMaterial[0],
461 volume->assignBoundaryMaterial(
m_cfg.boundaryMaterial[1],
463 volume->assignBoundaryMaterial(
m_cfg.boundaryMaterial[4],
465 volume->assignBoundaryMaterial(
m_cfg.boundaryMaterial[5],
470 volumesContainer.size() > 1
471 ? tvHelper->createContainerTrackingVolume(gctx, volumesContainer)
475 volume = nEndcap ? nEndcap : (barrel ? barrel : pEndcap);
481 if (existingVolumeCp) {
483 std::vector<TrackingVolumePtr> existingContainer;
486 auto fGap = tvHelper->createGapTrackingVolume(
490 false,
m_cfg.volumeName +
"::fGap");
492 existingContainer.push_back(fGap);
494 existingContainer.push_back(existingVolumeCp);
497 auto sGap = tvHelper->createGapTrackingVolume(
501 false,
m_cfg.volumeName +
"::sGap");
503 existingContainer.push_back(sGap);
508 existingContainer.size() > 1
509 ? tvHelper->createContainerTrackingVolume(gctx, existingContainer)
514 existingContainer.clear();
516 existingContainer.push_back(existingVolumeCp);
517 existingContainer.push_back(barrel);
519 existingContainer.push_back(barrel);
520 existingContainer.push_back(existingVolumeCp);
524 !existingContainer.empty()
525 ? tvHelper->createContainerTrackingVolume(gctx, existingContainer)
528 std::vector<TrackingVolumePtr> totalContainer;
534 totalContainer.push_back(nEndcap);
536 totalContainer.push_back(existingVolumeCp);
538 totalContainer.push_back(pEndcap);
541 totalContainer.push_back(volume);
542 totalContainer.push_back(existingVolumeCp);
544 totalContainer.push_back(existingVolumeCp);
545 totalContainer.push_back(volume);
547 ACTS_ERROR(
"Misconfiguration in volume building detected.");
551 volume = tvHelper->createContainerTrackingVolume(gctx, totalContainer);
566 if (!lVector.empty() || !mtvVector.empty()) {
570 for (
auto&
layer : lVector) {
574 const Vector3& center =
layer->surfaceRepresentation().center(gctx);
578 if (cLayer !=
nullptr) {
592 std::max(lConfig.
rMax, rMaxC +
m_cfg.layerEnvelopeR.second);
596 std::max(lConfig.
zMax, center.z() + hZ +
m_cfg.layerEnvelopeZ);
600 &(
layer->surfaceRepresentation().bounds()));
601 if (dBounds !=
nullptr) {
603 double rMinD = dBounds->
rMin();
604 double rMaxD = dBounds->
rMax();
605 double zMinD = center.z() - 0.5 *
thickness;
606 double zMaxD = center.z() + 0.5 *
thickness;
610 std::max(lConfig.
rMax, rMaxD +
m_cfg.layerEnvelopeR.second);
611 lConfig.
rMin = std::max(0.0, lConfig.
rMin);
613 lConfig.
zMax = std::max(lConfig.
zMax, zMaxD +
m_cfg.layerEnvelopeZ);
616 for (
auto& volume : mtvVector) {
619 if (cvBounds !=
nullptr) {
626 lConfig.
zMax = std::max(
637 if (
m_cfg.buildToRadiusZero) {
638 ACTS_VERBOSE(
"This layer builder is configured to build to the beamline.");