10 #include "CaloDetDescr/CaloDetDescrElement.h"
13 #include "Acts/Geometry/TrackingVolume.hpp"
14 #include "Acts/Geometry/VolumeBounds.hpp"
15 #include "Acts/Geometry/GlueVolumesDescriptor.hpp"
18 #include "Acts/Geometry/GenericCuboidVolumeBounds.hpp"
19 #include "Acts/Geometry/CutoutCylinderVolumeBounds.hpp"
20 #include "Acts/Geometry/CylinderVolumeBounds.hpp"
22 #include "Acts/Utilities/Helpers.hpp"
23 #include "Acts/Geometry/TrackingVolumeArrayCreator.hpp"
24 #include "Acts/Utilities/BinnedArrayXD.hpp"
25 #include "Acts/Geometry/CylinderVolumeHelper.hpp"
29 using Box = Acts::Volume::BoundingBox;
31 using CVBBV = Acts::CylinderVolumeBounds::BoundValues;
32 using CCVBBV = Acts::CutoutCylinderVolumeBounds::BoundValues;
35 const std::string&
name,
52 return StatusCode::SUCCESS;
55 std::shared_ptr<Acts::TrackingVolume>
57 const Acts::GeometryContext& gctx,
58 std::shared_ptr<const Acts::TrackingVolume> insideVolume,
59 std::shared_ptr<const Acts::VolumeBounds> )
const
64 std::vector<std::unique_ptr<Acts::Volume>>
cells;
71 std::vector<std::unique_ptr<Box>> boxStore;
72 std::vector<Box*> prims;
75 std::make_unique<Box>(
cell->boundingBox({0.1, 0.1, 0.1})));
76 prims.push_back(boxStore.back().get());
84 std::shared_ptr<Acts::CutoutCylinderVolumeBounds> caloVolBounds
95 std::vector<std::unique_ptr<const Acts::Volume>> cellVols;
96 cellVols.reserve(
cells.size());
98 std::unique_ptr<const Acts::Volume>
up;
100 up = std::unique_ptr<const Acts::Volume>(
dynamic_cast<const Acts::Volume*
>(
cell.release()));
101 cellVols.push_back(std::move(
up));
106 throw std::runtime_error{
"Calo building for ACTS currently disabled"};
107 std::shared_ptr<Acts::TrackingVolume> calo;
117 std::shared_ptr<Acts::TrackingVolume> mutInsideVolume
118 = std::const_pointer_cast<Acts::TrackingVolume>(insideVolume);
119 auto idBounds =
dynamic_cast<const Acts::CylinderVolumeBounds*
>(&insideVolume->volumeBounds());
120 if (idBounds ==
nullptr) {
121 ATH_MSG_ERROR(
"Unable to dynamic cast volume bounds to Acts::CylinderVolumeBounds");
122 throw std::runtime_error(
"Error casting to CylinderVolumeBounds");
128 auto trackingVolumeArrayCreator
129 = std::make_shared<const Acts::TrackingVolumeArrayCreator>(
130 Acts::TrackingVolumeArrayCreator::Config{},
132 Acts::CylinderVolumeHelper::Config cvhCfg;
133 cvhCfg.trackingVolumeArrayCreator = trackingVolumeArrayCreator;
134 Acts::CylinderVolumeHelper cvh(cvhCfg,
makeActsAthenaLogger(
this, std::string(
"ACaloTrkVB"), std::string(
"CylVolHlp")));
136 std::vector<double> lPos = {};
137 std::vector<std::shared_ptr<Acts::TrackingVolume>> noVolumes;
141 auto idGapPosXY = cvh.createGapTrackingVolume(gctx,
144 idBounds->get(CVBBV::eMinR),
145 idBounds->get(CVBBV::eMaxR),
146 idBounds->get(CVBBV::eHalfLengthZ),
147 caloVolBounds->get(CCVBBV::eHalfLengthZcutout),
153 auto idGapNegXY = cvh.createGapTrackingVolume(gctx,
156 idBounds->get(CVBBV::eMinR),
157 idBounds->get(CVBBV::eMaxR),
158 -caloVolBounds->get(CCVBBV::eHalfLengthZcutout),
159 -idBounds->get(CVBBV::eHalfLengthZ),
165 auto idGapCylOuter = cvh.createGapTrackingVolume(gctx,
168 idBounds->get(CVBBV::eMaxR),
169 caloVolBounds->get(CCVBBV::eMedR),
170 -caloVolBounds->get(CCVBBV::eHalfLengthZcutout),
171 +caloVolBounds->get(CCVBBV::eHalfLengthZcutout),
177 ATH_MSG_VERBOSE(
"Create container volume to contain ID and gap volumes");
178 auto idContainerZ = cvh.createContainerTrackingVolume(gctx, {idGapNegXY, mutInsideVolume, idGapPosXY});
179 auto idContainer = cvh.createContainerTrackingVolume(gctx, {idContainerZ, idGapCylOuter});
184 const Acts::GlueVolumesDescriptor& gvd
185 = idContainer->glueVolumesDescriptor();
190 std::cout <<
"POSITIVE: " << std::endl;
191 for(
const auto& subvol : tVolArrPos->arrayObjects()) {
192 std::cout << subvol->volumeName() << std::endl;
193 std::cout << *subvol << std::endl;
196 std::cout <<
"NEGATIVE: " << std::endl;
197 for(
const auto& subvol : tVolArrNeg->arrayObjects()) {
198 std::cout << subvol->volumeName() << std::endl;
199 std::cout << *subvol << std::endl;
202 using BoundarySurface = Acts::BoundarySurfaceT<Acts::TrackingVolume>;
208 ATH_MSG_VERBOSE(
"Glueing " << calo->volumeName() <<
" inner cover to " << idOutVolArray->arrayObjects().size() <<
" volumes");
210 ->attachVolumeArray(idOutVolArray, Acts::Direction::Backward);
212 for(
const auto& idVol : idOutVolArray->arrayObjects()){
214 <<
" to inner cover of " << calo->volumeName());
216 ->attachVolume(calo.get(), Acts::Direction::Forward);
222 ATH_MSG_VERBOSE(
"Glueing " << calo->volumeName() <<
" positive inner cutout disc to "
223 << idPosXYVolArray->arrayObjects().size() <<
" volumes");
224 std::const_pointer_cast<BoundarySurface>(calo->boundarySurfaces().at(
Acts::index5))
225 ->attachVolumeArray(idPosXYVolArray, Acts::Direction::Backward);
227 for(
const auto& idVol : idPosXYVolArray->arrayObjects()){
229 <<
" to positive inner coutout disc of " << calo->volumeName());
231 ->attachVolume(calo.get(), Acts::Direction::Forward);
237 ATH_MSG_VERBOSE(
"Glueing " << calo->volumeName() <<
" negative inner cutout disc to "
238 << idNegXYVolArray->arrayObjects().size() <<
" volumes");
239 std::const_pointer_cast<BoundarySurface>(calo->boundarySurfaces().at(
Acts::index4))
240 ->attachVolumeArray(idNegXYVolArray, Acts::Direction::Forward);
242 for(
const auto& idVol : idNegXYVolArray->arrayObjects()){
244 <<
" to negative inner coutout disc of " << calo->volumeName());
246 ->attachVolume(calo.get(), Acts::Direction::Backward);
256 double caloRMin = caloVolBounds->get(CCVBBV::eMinR);
257 double caloRMed = caloVolBounds->get(CCVBBV::eMedR);
258 double caloRMax = caloVolBounds->get(CCVBBV::eMaxR);
259 double caloDZ1 = caloVolBounds->get(CCVBBV::eHalfLengthZ);
260 double caloDZ2 = caloVolBounds->get(CCVBBV::eHalfLengthZcutout);
262 Acts::Vector3 caloChokeRPos
263 = {caloRMin + (caloRMax - caloRMin)/2., 0, 0};
265 std::vector<Acts::TrackingVolumeOrderPosition> tVolOrdPosNeg;
266 tVolOrdPosNeg.push_back(std::make_pair(calo, caloChokeRPos));
267 std::vector<float> posNegBoundaries
269 auto binUtilityPosNeg = std::make_unique<const Acts::BinUtility>(posNegBoundaries,
273 = std::make_shared<const Acts::BinnedArrayXD<Acts::TrackingVolumePtr>>(
274 tVolOrdPosNeg, std::move(binUtilityPosNeg));
276 double chokeZOffset = caloDZ2 + (caloDZ1 - caloDZ2)/2.;
277 Acts::Transform3 posTrf(Acts::Translation3(Acts::Vector3::UnitZ() * chokeZOffset));
278 Acts::Transform3 negTrf(Acts::Translation3(Acts::Vector3::UnitZ()* -1 *chokeZOffset));
280 auto posNegCylBounds = std::make_shared<Acts::CylinderVolumeBounds>(
281 caloRMin, caloRMax, (caloDZ1 - caloDZ2) / 2.);
284 auto posContainer = std::make_shared<Acts::TrackingVolume>(
289 Acts::MutableTrackingVolumeVector{});
292 auto negContainer = std::make_shared<Acts::TrackingVolume>(
297 Acts::MutableTrackingVolumeVector{});
302 std::vector<Acts::TrackingVolumeOrderPosition> tVolOrderedCtr;
303 tVolOrderedCtr.push_back(std::make_pair(idContainer, Acts::Vector3(caloRMed / 2., 0, 0)));
304 tVolOrderedCtr.push_back(std::make_pair(calo,
305 Acts::Vector3(caloRMed +
306 (caloRMax- caloRMed) / 2., 0, 0)));
308 std::vector<float> ctrBoundaries = {0,
float(caloRMed),
float(caloRMax)};
310 = std::make_unique<const Acts::BinUtility>(
315 = std::make_shared<const Acts::BinnedArrayXD<Acts::TrackingVolumePtr>>(
316 tVolOrderedCtr, std::move(binUtilityCtr));
319 auto ctrContainer = std::make_shared<Acts::TrackingVolume>(Acts::Transform3::Identity(),
320 std::make_shared<Acts::CylinderVolumeBounds>(
321 caloRMin, caloRMax, caloDZ2),
324 Acts::MutableTrackingVolumeVector{}
328 ATH_MSG_VERBOSE(
"- containing: " << idContainer->volumeName() <<
", " << calo->volumeName());
331 Acts::TrackingVolumeArrayCreator tvac{Acts::TrackingVolumeArrayCreator::Config{}};
333 auto mainContainer = std::make_shared<Acts::TrackingVolume>(Acts::Transform3::Identity(),
334 std::make_shared<Acts::CylinderVolumeBounds>(
335 caloRMin, caloRMax, caloDZ1),
337 tvac.trackingVolumeArray(gctx, {negContainer, ctrContainer, posContainer},
339 Acts::MutableTrackingVolumeVector{}
345 return mainContainer;
348 std::shared_ptr<Acts::CutoutCylinderVolumeBounds>
350 std::shared_ptr<const Acts::TrackingVolume> insideVolume)
const
352 using namespace Acts::VectorHelpers;
357 double rmax = std::numeric_limits<double>::lowest();
359 double zmax = std::numeric_limits<double>::lowest();
366 for (
const auto& box : boxStore) {
367 Acts::Vector3
vmin = box->min().cast<
double>();
368 Acts::Vector3
vmax = box->max().cast<
double>();
379 if (std::abs(
vmin.z()) < 100) {
380 rmin_at_center =
std::min(vrmin, rmin_at_center);
382 if (std::abs(
vmax.z()) < 100) {
383 rmin_at_center =
std::min(vrmax, rmin_at_center);
387 for (
const auto& box : boxStore) {
388 Acts::Vector3
vmin = box->min().cast<
double>();
389 Acts::Vector3
vmax = box->max().cast<
double>();
393 if (vrmin < rmin_at_center * 0.9) {
394 cutout_zmin_abs =
std::min(cutout_zmin_abs, std::abs(
vmin.z()));
396 if (vrmax < rmin_at_center * 0.9) {
397 cutout_zmin_abs =
std::min(cutout_zmin_abs, std::abs(
vmax.z()));
402 double dz2 = cutout_zmin_abs;
410 if(rmin_at_choke > envR) rmin_at_choke -= envR;
411 rmin_at_center -= envR;
415 <<
" rmin at choke: " << rmin_at_choke
416 <<
" rmax: " << rmax <<
" zmin: " <<
zmin <<
" zmax: " <<
zmax
417 <<
" coutout_zmin_abs: " << cutout_zmin_abs);
425 =
dynamic_cast<const Acts::CylinderVolumeBounds*
>(&insideVolume->volumeBounds());
426 if (idCylBds ==
nullptr) {
427 ATH_MSG_ERROR(
"Unable to dynamic cast volume bounds to Acts::CylinderVolumeBounds");
428 throw std::runtime_error(
"Error casting to CylinderVolumeBounds");
431 double idRMax = idCylBds->get(CVBBV::eMaxR);
432 double idRMin = idCylBds->get(CVBBV::eMinR);
433 double idHlZ = idCylBds->get(CVBBV::eHalfLengthZ);
437 ATH_MSG_VERBOSE(
"Inside volume transform: \n" << insideVolume->transform().matrix());
439 if (!insideVolume->transform().isApprox(Acts::Transform3::Identity())) {
445 const auto&
trf = insideVolume->transform();
447 Acts::RotationMatrix3 rot =
trf.rotation();
448 bool unityRot = rot.isApprox(Acts::RotationMatrix3::Identity());
453 const Acts::Vector3 trl =
trf.translation();
454 bool transZOnly = std::abs(1 - std::abs(Acts::Vector3::UnitZ().
dot(trl.normalized()))) < 1
e-6;
457 ATH_MSG_VERBOSE(
"TRL "<< trl.normalized().dot(Acts::Vector3::UnitZ()));
459 if(!unityRot || !transZOnly) {
460 ATH_MSG_ERROR(
"The ID appears to be shifted from the origin. I cannot handle this.");
462 throw std::runtime_error(
"Error building calo");
465 ATH_MSG_VERBOSE(
"Checked: non unitarity is ONLY due to shift along z axis: that's ok");
466 double prevIdHlZ = idHlZ;
467 idHlZ += std::abs(trl.z());
468 ATH_MSG_VERBOSE(
"Modifying effective half length of ID cylinder: " << prevIdHlZ <<
" => " << idHlZ);
473 if (idRMax > rmin_at_center || idHlZ > dz2 || (idRMin > rmin_at_choke && idRMin != 0.)) {
475 ATH_MSG_ERROR(
"This can be because the ID overlaps into the calo volume");
476 ATH_MSG_ERROR(
"Or because the Calo choke radius is SMALLER than the ID inner radius");
477 ATH_MSG_ERROR(
"Currently, I can only make the choke radius smaller, I can not make it larger");
478 ATH_MSG_ERROR(
"nor can I manipulate the ID volume bounds at this point.");
479 ATH_MSG_ERROR(
"ID rMax: " << idRMax <<
" Calo rMin@center: " << rmin_at_center);
480 ATH_MSG_ERROR(
"ID hlZ: " << idHlZ <<
" Calo inner Z hl: " << dz2);
481 ATH_MSG_ERROR(
"ID rMin: " << idRMin <<
" Calo rMin@choke: " << rmin_at_choke);
483 throw std::runtime_error(
"Error building calo");
489 rmin_at_choke = idRMin;
491 std::shared_ptr<Acts::CutoutCylinderVolumeBounds> volBds =
nullptr;
492 volBds = std::make_shared<Acts::CutoutCylinderVolumeBounds>(
493 rmin_at_choke, rmin_at_center, rmax, dz1, dz2);
503 eta_to_theta(
double eta)
517 double eta_max =
eta + deta * 0.5;
518 double eta_min =
eta - deta * 0.5;
519 double theta_max = eta_to_theta(eta_max);
521 double theta_min = eta_to_theta(eta_min);
522 double phi_max =
phi + dphi * 0.5;
523 double phi_min =
phi - dphi * 0.5;
524 double z_min =
z - dz;
525 double z_max =
z + dz;
530 r_min =
std::tan(theta_min) * z_min;
531 r_max =
std::tan(theta_max) * z_min;
536 Acts::Vector3 p4(r_max *
std::cos(phi_min), r_max *
std::sin(phi_min), z_min);
539 r_min =
std::tan(theta_min) * z_max;
540 r_max =
std::tan(theta_max) * z_max;
542 Acts::Vector3 p5(r_min *
std::cos(phi_min), r_min *
std::sin(phi_min), z_max);
543 Acts::Vector3 p6(r_min *
std::cos(phi_max), r_min *
std::sin(phi_max), z_max);
544 Acts::Vector3 p7(r_max *
std::cos(phi_max), r_max *
std::sin(phi_max), z_max);
545 Acts::Vector3 p8(r_max *
std::cos(phi_min), r_max *
std::sin(phi_min), z_max);
548 Acts::Vector3 center;
553 Acts::Transform3 glob2vol = Acts::Transform3::Identity();
554 glob2vol *= Acts::AngleAxis3(-
phi, Acts::Vector3::UnitZ());
555 glob2vol *= Acts::AngleAxis3(
556 -
theta, Acts::Vector3::UnitZ().cross(center).normalized());
558 *= Acts::Translation3(-(
p1 +
p2 +
p3 + p4 + p5 + p6 + p7 + p8) / 8.);
571 auto cubo = std::make_shared<Acts::GenericCuboidVolumeBounds>(
572 std::array<Acts::Vector3, 8>({{
p1,
p2,
p3, p4, p5, p6, p7, p8}}));
588 double eta_max =
eta + deta * 0.5;
589 double eta_min =
eta - deta * 0.5;
591 double theta_max = eta_to_theta(eta_max);
592 double theta_min = eta_to_theta(eta_min);
593 double phi_max =
phi + dphi * 0.5;
594 double phi_min =
phi - dphi * 0.5;
596 double r_min =
r -
dr;
597 double r_max =
r +
dr;
602 z_min = r_min /
std::tan(theta_min);
603 z_max = r_min /
std::tan(theta_max);
608 Acts::Vector3 p4(r_min *
std::cos(phi_max), r_min *
std::sin(phi_max), z_min);
611 z_min = r_max /
std::tan(theta_min);
612 z_max = r_max /
std::tan(theta_max);
614 Acts::Vector3 p5(r_max *
std::cos(phi_min), r_max *
std::sin(phi_min), z_min);
615 Acts::Vector3 p6(r_max *
std::cos(phi_min), r_max *
std::sin(phi_min), z_max);
616 Acts::Vector3 p7(r_max *
std::cos(phi_max), r_max *
std::sin(phi_max), z_max);
617 Acts::Vector3 p8(r_max *
std::cos(phi_max), r_max *
std::sin(phi_max), z_min);
619 Acts::Vector3 center;
624 Acts::Transform3 glob2vol = Acts::Transform3::Identity();
625 glob2vol *= Acts::AngleAxis3(-
phi, Acts::Vector3::UnitZ());
626 glob2vol *= Acts::AngleAxis3(
627 -
theta, Acts::Vector3::UnitZ().cross(center).normalized());
629 *= Acts::Translation3(-(
p1 +
p2 +
p3 + p4 + p5 + p6 + p7 + p8) / 8.);
642 auto cubo = std::make_shared<Acts::GenericCuboidVolumeBounds>(
643 std::array<Acts::Vector3, 8>({{
p1,
p2,
p3, p4, p5, p6, p7, p8}}));
655 double x_min, x_max, y_min, y_max, z_min, z_max;
664 Acts::Vector3
p1(x_min, y_min, z_min);
665 Acts::Vector3
p2(x_min, y_max, z_min);
666 Acts::Vector3
p3(x_max, y_max, z_min);
667 Acts::Vector3 p4(x_max, y_min, z_min);
670 Acts::Vector3 p5(x_min, y_min, z_max);
671 Acts::Vector3 p6(x_min, y_max, z_max);
672 Acts::Vector3 p7(x_max, y_max, z_max);
673 Acts::Vector3 p8(x_max, y_min, z_max);
675 Acts::Transform3 glob2vol = Acts::Transform3::Identity();
677 *= Acts::Translation3(-(
p1 +
p2 +
p3 + p4 + p5 + p6 + p7 + p8) / 8.);
690 auto cubo = std::make_shared<Acts::GenericCuboidVolumeBounds>(
691 std::array<Acts::Vector3, 8>({{
p1,
p2,
p3, p4, p5, p6, p7, p8}}));
697 std::vector<std::unique_ptr<Acts::Volume>>
705 float z, dz, eta_raw, deta, phi_raw, dphi,
r,
dr,
x,
y,
dx,
dy;
710 std::vector<std::unique_ptr<Acts::Volume>>
cells;
732 if (calosample >= 12 && calosample <= 20) {
746 switch (calosample) {
757 cells.push_back(std::make_unique<Acts::Volume>(
773 cells.push_back(std::make_unique<Acts::Volume>(
783 cells.push_back(std::make_unique<Acts::Volume>(
787 std::stringstream
ss;
788 ss <<
"Unkown calo sample " << calosample;
789 std::runtime_error(
ss.str());