ATLAS Offline Software
Loading...
Searching...
No Matches
ActsCaloTrackingVolumeBuilder.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4
8
11#include "CaloDetDescr/CaloDetDescrElement.h"
13
14#include "Acts/Geometry/TrackingVolume.hpp"
15#include "Acts/Geometry/VolumeBounds.hpp"
16#include "Acts/Geometry/GlueVolumesDescriptor.hpp"
17
18// ACTS
19#include "Acts/Geometry/GenericCuboidVolumeBounds.hpp"
20#include "Acts/Geometry/CutoutCylinderVolumeBounds.hpp"
21#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"
26
27#include <fstream>
28
29using Box = Acts::Volume::BoundingBox; // shortcut
30
31using CVBBV = Acts::CylinderVolumeBounds::BoundValues;
32using CCVBBV = Acts::CutoutCylinderVolumeBounds::BoundValues;
33
34
35StatusCode
37{
38 m_caloMgr = detStore()->tryConstRetrieve<CaloDetDescrManager>(caloMgrStaticKey);
39 if(!m_caloMgr) {
40 std::unique_ptr<CaloDetDescrManager> caloMgrPtr = buildCaloDetDescrNoAlign(serviceLocator()
42 ATH_CHECK(detStore()->record(std::move(caloMgrPtr), caloMgrStaticKey));
43 ATH_CHECK(detStore()->retrieve(m_caloMgr, caloMgrStaticKey));
44 }
45 return StatusCode::SUCCESS;
46}
47
48std::shared_ptr<Acts::TrackingVolume>
50 const Acts::GeometryContext& gctx,
51 std::shared_ptr<const Acts::TrackingVolume> insideVolume,
52 std::shared_ptr<const Acts::VolumeBounds> /*outsideBounds*/) const
53{
54
55
56 // generate the calo cell volume description
57 std::vector<std::unique_ptr<Acts::Volume>> cells;
58 cells = cellFactory();
59
60 ATH_MSG_VERBOSE("Collected " << cells.size() << " calo cells");
61
62
63 // we need to turn the cells into boundary boxes
64 std::vector<std::unique_ptr<Box>> boxStore;
65 std::vector<Box*> prims;
66 for (const auto& cell : cells) {
67 boxStore.push_back(
68 std::make_unique<Box>(cell->boundingBox({0.1, 0.1, 0.1})));
69 prims.push_back(boxStore.back().get());
70 }
71
72 ATH_MSG_VERBOSE("Generated Bounding Boxes");
73
74
75 ATH_MSG_VERBOSE("Figure out dimensions of wrapping volume");
76
77 std::shared_ptr<Acts::CutoutCylinderVolumeBounds> caloVolBounds
78 = makeCaloVolumeBounds(gctx, boxStore, std::move(insideVolume));
79
80 // build a BVH octree for the bounding boxes
81 // but only AFTER we've built the calo volume bounds
82 // Box* top;
83 // top = Acts::make_octree(boxStore, prims, 1, 0.1);
84
85 // Create Tracking Volume that coutains the Calo
86 // This needs to own the Abstract Volumes (cells), but we
87 // need to up-cast them to Volume, since that's what TrackingVolume can own
88 std::vector<std::unique_ptr<const Acts::Volume>> cellVols;
89 cellVols.reserve(cells.size());
90 for(auto& cell : cells) {
91 std::unique_ptr<const Acts::Volume> up;
92 // release, up-cast, then immediately pack again
93 up = std::unique_ptr<const Acts::Volume>(dynamic_cast<const Acts::Volume*>(cell.release()));
94 cellVols.push_back(std::move(up));
95 }
96
97 // This was removed in https://github.com/acts-project/acts/pull/3029
98 // To be reimplemented using new geometry model instead of explicit TrackingVolume content
99 (void)gctx; // suppress compiler warning
100 throw std::runtime_error{"Calo building for ACTS currently disabled"};
101
102 /***** TODO START *****
103 std::shared_ptr<Acts::TrackingVolume> calo;
104 // = Acts::TrackingVolume::create(Acts::Transform3::Identity(),
105 // caloVolBounds,
106 // std::move(boxStore),
107 // std::move(cellVols),
108 // top,
109 // nullptr, // no material for now
110 // "Calo");
111
112 // We need to interglue all the volumes together
113 std::shared_ptr<Acts::TrackingVolume> mutInsideVolume
114 = std::const_pointer_cast<Acts::TrackingVolume>(insideVolume);
115 auto idBounds = dynamic_cast<const Acts::CylinderVolumeBounds*>(&insideVolume->volumeBounds());
116 if (idBounds == nullptr) { // protection against nullptr
117 ATH_MSG_ERROR("Unable to dynamic cast volume bounds to Acts::CylinderVolumeBounds");
118 throw std::runtime_error("Error casting to CylinderVolumeBounds");
119 }
120
121 // we want gap volumes at pos and neg xy face, and at outer cyl cover
122 // which will include the solenoid area
123
124 auto trackingVolumeArrayCreator
125 = std::make_shared<const Acts::TrackingVolumeArrayCreator>(
126 Acts::TrackingVolumeArrayCreator::Config{},
127 makeActsAthenaLogger(this, std::string("TrkVolArrCrtr"), std::string("ActsTGSvc")));
128 Acts::CylinderVolumeHelper::Config cvhCfg;
129 cvhCfg.trackingVolumeArrayCreator = trackingVolumeArrayCreator;
130 Acts::CylinderVolumeHelper cvh(cvhCfg, makeActsAthenaLogger(this, std::string("ACaloTrkVB"), std::string("CylVolHlp")));
131
132 std::vector<double> lPos = {};
133 std::vector<std::shared_ptr<Acts::TrackingVolume>> noVolumes;
134
135 ATH_MSG_VERBOSE("Creating gap volume to extend ID");
136 // positive xy gap
137 auto idGapPosXY = cvh.createGapTrackingVolume(gctx,
138 noVolumes,
139 nullptr,
140 idBounds->get(CVBBV::eMinR),
141 idBounds->get(CVBBV::eMaxR),
142 idBounds->get(CVBBV::eHalfLengthZ),
143 caloVolBounds->get(CCVBBV::eHalfLengthZcutout),
144 lPos,
145 false,
146 "ID::PositiveGap"
147 );
148 // negative xy gap
149 auto idGapNegXY = cvh.createGapTrackingVolume(gctx,
150 noVolumes,
151 nullptr,
152 idBounds->get(CVBBV::eMinR),
153 idBounds->get(CVBBV::eMaxR),
154 -caloVolBounds->get(CCVBBV::eHalfLengthZcutout),
155 -idBounds->get(CVBBV::eHalfLengthZ),
156 lPos,
157 false,
158 "ID::NegativeGap"
159 );
160 // outer cover gap
161 auto idGapCylOuter = cvh.createGapTrackingVolume(gctx,
162 noVolumes,
163 nullptr,
164 idBounds->get(CVBBV::eMaxR),
165 caloVolBounds->get(CCVBBV::eMedR),
166 -caloVolBounds->get(CCVBBV::eHalfLengthZcutout),
167 +caloVolBounds->get(CCVBBV::eHalfLengthZcutout),
168 lPos,
169 false,
170 "ID::CylOutGap"
171 );
172
173 ATH_MSG_VERBOSE("Create container volume to contain ID and gap volumes");
174 auto idContainerZ = cvh.createContainerTrackingVolume(gctx, {idGapNegXY, mutInsideVolume, idGapPosXY});
175 auto idContainer = cvh.createContainerTrackingVolume(gctx, {idContainerZ, idGapCylOuter});
176
177
178 ATH_MSG_VERBOSE("Begin volume glueing");
179
180 const Acts::GlueVolumesDescriptor& gvd
181 = idContainer->glueVolumesDescriptor();
182 // let's see what the GVD says is on the inner cover of the ID
183 const auto& tVolArrPos = gvd.glueVolumes(Acts::positiveFaceXY);
184 const auto& tVolArrNeg = gvd.glueVolumes(Acts::negativeFaceXY);
185
186 std::cout << "POSITIVE: " << std::endl;
187 for(const auto& subvol : tVolArrPos->arrayObjects()) {
188 std::cout << subvol->volumeName() << std::endl;
189 std::cout << *subvol << std::endl;
190 }
191
192 std::cout << "NEGATIVE: " << std::endl;
193 for(const auto& subvol : tVolArrNeg->arrayObjects()) {
194 std::cout << subvol->volumeName() << std::endl;
195 std::cout << *subvol << std::endl;
196 }
197
198 using BoundarySurface = Acts::BoundarySurfaceT<Acts::TrackingVolume>;
199
200
201 // Glue outer radial cover of ID to inner cover of Calo cutout
202 auto idOutVolArray = gvd.glueVolumes(Acts::tubeOuterCover);
203 // Attach that volume array to the calo inner cover
204 ATH_MSG_VERBOSE("Glueing " << calo->volumeName() << " inner cover to " << idOutVolArray->arrayObjects().size() << " volumes");
205 std::const_pointer_cast<BoundarySurface>(calo->boundarySurfaces().at(Acts::tubeInnerCover))
206 ->attachVolumeArray(idOutVolArray, Acts::Direction::Backward);
207 // Loop through the array and attach their boundary surfaces to the calo
208 for(const auto& idVol : idOutVolArray->arrayObjects()){
209 ATH_MSG_VERBOSE("Glueing outer cover of " << idVol->volumeName()
210 << " to inner cover of " << calo->volumeName());
211 std::const_pointer_cast<BoundarySurface>(idVol->boundarySurfaces().at(Acts::tubeOuterCover))
212 ->attachVolume(calo.get(), Acts::Direction::Forward);
213 }
214
215 // Glue positive XY face of ID to inner positive XY face of Calo.
216 // ID has multiple, Calo has only one
217 auto idPosXYVolArray = gvd.glueVolumes(Acts::positiveFaceXY);
218 ATH_MSG_VERBOSE("Glueing " << calo->volumeName() << " positive inner cutout disc to "
219 << idPosXYVolArray->arrayObjects().size() << " volumes");
220 std::const_pointer_cast<BoundarySurface>(calo->boundarySurfaces().at(Acts::index5))
221 ->attachVolumeArray(idPosXYVolArray, Acts::Direction::Backward);
222 // Other way round, attach ID volumes to calo
223 for(const auto& idVol : idPosXYVolArray->arrayObjects()){
224 ATH_MSG_VERBOSE("Glueing positive XY face of " << idVol->volumeName()
225 << " to positive inner coutout disc of " << calo->volumeName());
226 std::const_pointer_cast<BoundarySurface>(idVol->boundarySurfaces().at(Acts::positiveFaceXY))
227 ->attachVolume(calo.get(), Acts::Direction::Forward);
228 }
229
230 // Glue negative XY face of ID to inner negative XY face of Calo.
231 // ID has multiple, Calo has only one
232 auto idNegXYVolArray = gvd.glueVolumes(Acts::negativeFaceXY);
233 ATH_MSG_VERBOSE("Glueing " << calo->volumeName() << " negative inner cutout disc to "
234 << idNegXYVolArray->arrayObjects().size() << " volumes");
235 std::const_pointer_cast<BoundarySurface>(calo->boundarySurfaces().at(Acts::index4))
236 ->attachVolumeArray(idNegXYVolArray, Acts::Direction::Forward);
237 // Other way round, attach ID volumes to calo
238 for(const auto& idVol : idNegXYVolArray->arrayObjects()){
239 ATH_MSG_VERBOSE("Glueing negative XY face of " << idVol->volumeName()
240 << " to negative inner coutout disc of " << calo->volumeName());
241 std::const_pointer_cast<BoundarySurface>(idVol->boundarySurfaces().at(Acts::negativeFaceXY))
242 ->attachVolume(calo.get(), Acts::Direction::Backward);
243 }
244
245 // For navigational purposes we need to create three pseudo container cylinders.
246 // One for the middle, which includes the central part of the Calo and the ID, and
247 // two that fit cleanly at the +- XY face that then only include the Calo
248
249 // Construct track vol array for use in positive and negative pseudocontainer.
250 // This will only contain the calo
251
252 double caloRMin = caloVolBounds->get(CCVBBV::eMinR);
253 double caloRMed = caloVolBounds->get(CCVBBV::eMedR);
254 double caloRMax = caloVolBounds->get(CCVBBV::eMaxR);
255 double caloDZ1 = caloVolBounds->get(CCVBBV::eHalfLengthZ);
256 double caloDZ2 = caloVolBounds->get(CCVBBV::eHalfLengthZcutout);
257
258 Acts::Vector3 caloChokeRPos
259 = {caloRMin + (caloRMax - caloRMin)/2., 0, 0};
260
261 std::vector<Acts::TrackingVolumeOrderPosition> tVolOrdPosNeg;
262 tVolOrdPosNeg.push_back(std::make_pair(calo, caloChokeRPos));
263 std::vector<float> posNegBoundaries
264 = {float(caloRMin), float(caloRMax)};
265 auto binUtilityPosNeg = std::make_unique<const Acts::BinUtility>(posNegBoundaries,
266 Acts::open, Acts::AxisDirection::AxisR);
267
268 auto tVolArrPosNeg
269 = std::make_shared<const Acts::BinnedArrayXD<Acts::TrackingVolumePtr>>(
270 tVolOrdPosNeg, std::move(binUtilityPosNeg));
271
272 double chokeZOffset = caloDZ2 + (caloDZ1 - caloDZ2)/2.;
273 Acts::Transform3 posTrf(Acts::Translation3(Acts::Vector3::UnitZ() * chokeZOffset));
274 Acts::Transform3 negTrf(Acts::Translation3(Acts::Vector3::UnitZ()* -1 *chokeZOffset));
275
276 auto posNegCylBounds = std::make_shared<Acts::CylinderVolumeBounds>(
277 caloRMin, caloRMax, (caloDZ1 - caloDZ2) / 2.);
278
279 // they share the same bounds and tvol array
280 auto posContainer = std::make_shared<Acts::TrackingVolume>(
281 posTrf,
282 posNegCylBounds,
283 nullptr, nullptr,
284 tVolArrPosNeg,
285 Acts::MutableTrackingVolumeVector{});
286 ATH_MSG_VERBOSE("Built positive container " << *posContainer);
287 ATH_MSG_VERBOSE(" - containing: " << calo->volumeName());
288 auto negContainer = std::make_shared<Acts::TrackingVolume>(
289 negTrf,
290 posNegCylBounds,
291 nullptr, nullptr,
292 tVolArrPosNeg,
293 Acts::MutableTrackingVolumeVector{});
294 ATH_MSG_VERBOSE("Built negative container " << *negContainer);
295 ATH_MSG_VERBOSE(" - containing: " << calo->volumeName());
296
297 // now build the central pseudocontainer
298 std::vector<Acts::TrackingVolumeOrderPosition> tVolOrderedCtr;
299 tVolOrderedCtr.push_back(std::make_pair(idContainer, Acts::Vector3(caloRMed / 2., 0, 0)));
300 tVolOrderedCtr.push_back(std::make_pair(calo,
301 Acts::Vector3(caloRMed +
302 (caloRMax- caloRMed) / 2., 0, 0)));
303
304 std::vector<float> ctrBoundaries = {0, float(caloRMed), float(caloRMax)};
305 auto binUtilityCtr
306 = std::make_unique<const Acts::BinUtility>(
307 ctrBoundaries,
308 Acts::open, Acts::AxisDirection::AxisR);
309
310 auto tVolArrCtr
311 = std::make_shared<const Acts::BinnedArrayXD<Acts::TrackingVolumePtr>>(
312 tVolOrderedCtr, std::move(binUtilityCtr));
313
314
315 auto ctrContainer = std::make_shared<Acts::TrackingVolume>(Acts::Transform3::Identity(),
316 std::make_shared<Acts::CylinderVolumeBounds>(
317 caloRMin, caloRMax, caloDZ2),
318 nullptr, nullptr,
319 tVolArrCtr,
320 Acts::MutableTrackingVolumeVector{}
321 );
322
323 ATH_MSG_VERBOSE("Built central container " << *ctrContainer);
324 ATH_MSG_VERBOSE("- containing: " << idContainer->volumeName() << ", " << calo->volumeName());
325
326 // and now combine those together into another one
327 Acts::TrackingVolumeArrayCreator tvac{Acts::TrackingVolumeArrayCreator::Config{}};
328
329 auto mainContainer = std::make_shared<Acts::TrackingVolume>(Acts::Transform3::Identity(),
330 std::make_shared<Acts::CylinderVolumeBounds>(
331 caloRMin, caloRMax, caloDZ1),
332 nullptr, nullptr,
333 tvac.trackingVolumeArray(gctx, {negContainer, ctrContainer, posContainer},
334 Acts::AxisDirection::AxisZ),
335 Acts::MutableTrackingVolumeVector{}
336 );
337
338
339 ATH_MSG_VERBOSE("Built main container: " << *mainContainer);
340
341 return mainContainer;
342 ***** TODO END *****/
343}
344
345std::shared_ptr<Acts::CutoutCylinderVolumeBounds>
347 const Acts::GeometryContext& gctx,
348 const std::vector<std::unique_ptr<Box>>& boxStore,
349 std::shared_ptr<const Acts::TrackingVolume> insideVolume) const
350{
351 using namespace Acts::VectorHelpers;
352
353 // determine the dimensions of the
354 double rmin_at_center = std::numeric_limits<double>::max();
355 double rmin_at_choke = std::numeric_limits<double>::max();
356 double rmax = std::numeric_limits<double>::lowest();
357 double zmin = std::numeric_limits<double>::max();
358 double zmax = std::numeric_limits<double>::lowest();
359 double cutout_zmin_abs = std::numeric_limits<double>::max();
360
361 // We need to figure out what the size of the inner cutout cylinder is
362 // so we can make sure everything worked fine!
363 // We check what the min radius at small z, and then we turn it around and
364 // check z bounds at lower radii.
365 for (const auto& box : boxStore) {
366 Acts::Vector3 vmin = box->min().cast<double>();
367 Acts::Vector3 vmax = box->max().cast<double>();
368
369 double vrmin = perp(vmin);
370 double vrmax = perp(vmax);
371
372 rmin_at_choke = std::min(rmin_at_choke, std::min(vrmin, vrmax));
373
374 rmax = std::max(rmax, std::max(vrmin, vrmax));
375 zmin = std::min(zmin, std::min(vmin.z(), vmax.z()));
376 zmax = std::max(zmax, std::max(vmin.z(), vmax.z()));
377
378 if (std::abs(vmin.z()) < 100) {
379 rmin_at_center = std::min(vrmin, rmin_at_center);
380 }
381 if (std::abs(vmax.z()) < 100) {
382 rmin_at_center = std::min(vrmax, rmin_at_center);
383 }
384 }
385
386 for (const auto& box : boxStore) {
387 Acts::Vector3 vmin = box->min().cast<double>();
388 Acts::Vector3 vmax = box->max().cast<double>();
389 double vrmin = perp(vmin);
390 double vrmax = perp(vmax);
391
392 if (vrmin < rmin_at_center * 0.9) {
393 cutout_zmin_abs = std::min(cutout_zmin_abs, std::abs(vmin.z()));
394 }
395 if (vrmax < rmin_at_center * 0.9) {
396 cutout_zmin_abs = std::min(cutout_zmin_abs, std::abs(vmax.z()));
397 }
398 }
399
400 double dz1 = (zmax - zmin) / 2.;
401 double dz2 = cutout_zmin_abs;
402
403 // envelopes
404 double envZ = 5;
405 double envR = 5;
406 dz1 += envZ;
407 dz2 -= envZ;
408 rmax += envR;
409 if(rmin_at_choke > envR) rmin_at_choke -= envR;
410 rmin_at_center -= envR;
411
412
413 ATH_MSG_VERBOSE("rmin_at_center: " << rmin_at_center
414 << " rmin at choke: " << rmin_at_choke
415 << " rmax: " << rmax << " zmin: " << zmin << " zmax: " << zmax
416 << " coutout_zmin_abs: " << cutout_zmin_abs);
417
418 // Ok now let's analyse what we're wrapping the calo around: the ID
419 // The ID will have to be built already.
420
421 // We need to figure out the dimensions of the ID.
422 // Assuming the wrapping volume is a cylinder.
423 auto idCylBds
424 = dynamic_cast<const Acts::CylinderVolumeBounds*>(&insideVolume->volumeBounds());
425 if (idCylBds == nullptr) { // protection against nullptr
426 ATH_MSG_ERROR("Unable to dynamic cast volume bounds to Acts::CylinderVolumeBounds");
427 throw std::runtime_error("Error casting to CylinderVolumeBounds");
428 }
429
430 double idRMax = idCylBds->get(CVBBV::eMaxR);
431 double idRMin = idCylBds->get(CVBBV::eMinR);
432 double idHlZ = idCylBds->get(CVBBV::eHalfLengthZ);
433
434 ATH_MSG_VERBOSE("ID volume bounds:\n" << *idCylBds);
435
436 ATH_MSG_VERBOSE("Inside volume transform: \n" <<Amg::toString(insideVolume->localToGlobalTransform(gctx)));
437
438 const auto& trf = insideVolume->localToGlobalTransform(gctx);
439
440 if (!trf.isApprox(Acts::Transform3::Identity())) {
441 ATH_MSG_VERBOSE("Inside volume transform is not unity.");
442 // transformation matrix is NOT unity. Let's check:
443 // - Rotation is approximate unity
444 // - Translation is only along z axis
445
446 Acts::RotationMatrix3 rot = trf.rotation();
447 bool unityRot = rot.isApprox(Acts::RotationMatrix3::Identity());
448
449 ATH_MSG_VERBOSE("\n" << rot);
450
451 // dot product with Z axis is about 1 => ok
452 const Acts::Vector3 trl = trf.translation();
453 bool transZOnly = std::abs(1 - std::abs(Acts::Vector3::UnitZ().dot(trl.normalized()))) < 1e-6;
454
455 ATH_MSG_VERBOSE("TRL "<< trl.transpose());
456 ATH_MSG_VERBOSE("TRL "<< trl.normalized().dot(Acts::Vector3::UnitZ()));
457
458 if(!unityRot || !transZOnly) {
459 ATH_MSG_ERROR("The ID appears to be shifted from the origin. I cannot handle this.");
460 ATH_MSG_ERROR("(I'm not building the Calo!)");
461 throw std::runtime_error("Error building calo");
462 }
463 else {
464 ATH_MSG_VERBOSE("Checked: non unitarity is ONLY due to shift along z axis: that's ok");
465 double prevIdHlZ = idHlZ;
466 idHlZ += std::abs(trl.z());
467 ATH_MSG_VERBOSE("Modifying effective half length of ID cylinder: " << prevIdHlZ << " => " << idHlZ);
468 }
469 }
470
471 // make sure we can fit the ID inside the calo cutout
472 if (idRMax > rmin_at_center || idHlZ > dz2 || (idRMin > rmin_at_choke && idRMin != 0.)) {
473 ATH_MSG_ERROR("Cannot fit ID inside the Calo");
474 ATH_MSG_ERROR("This can be because the ID overlaps into the calo volume");
475 ATH_MSG_ERROR("Or because the Calo choke radius is SMALLER than the ID inner radius");
476 ATH_MSG_ERROR("Currently, I can only make the choke radius smaller, I can not make it larger");
477 ATH_MSG_ERROR("nor can I manipulate the ID volume bounds at this point.");
478 ATH_MSG_ERROR("ID rMax: " << idRMax << " Calo rMin@center: " << rmin_at_center);
479 ATH_MSG_ERROR("ID hlZ: " << idHlZ << " Calo inner Z hl: " << dz2);
480 ATH_MSG_ERROR("ID rMin: " << idRMin << " Calo rMin@choke: " << rmin_at_choke);
481 ATH_MSG_ERROR("(I'm not building the Calo!)");
482 throw std::runtime_error("Error building calo");
483 }
484
485 // Let's harmonize the sizes, so we have a exact wrap of the ID
486 // Choke is now exactly as wide as space inside the ID.
487 // We can fit the beam pipe in there later.
488 rmin_at_choke = idRMin;
489
490 std::shared_ptr<Acts::CutoutCylinderVolumeBounds> volBds = nullptr;
491 volBds = std::make_shared<Acts::CutoutCylinderVolumeBounds>(
492 rmin_at_choke, rmin_at_center, rmax, dz1, dz2);
493
494 ATH_MSG_VERBOSE(*volBds);
495
496 return volBds;
497}
498
499
500namespace {
501 double
502 eta_to_theta(double eta)
503 {
504 return 2 * std::atan(std::exp(-eta));
505 }
506}
507
508Acts::Volume
510 double dz,
511 double eta,
512 double deta,
513 double phi,
514 double dphi) const
515{
516 double eta_max = eta + deta * 0.5;
517 double eta_min = eta - deta * 0.5;
518 double theta_max = eta_to_theta(eta_max);
519 double theta = eta_to_theta(eta);
520 double theta_min = eta_to_theta(eta_min);
521 double phi_max = phi + dphi * 0.5;
522 double phi_min = phi - dphi * 0.5;
523 double z_min = z - dz;
524 double z_max = z + dz;
525
526 double r_min, r_max;
527
528 // inner face
529 r_min = std::tan(theta_min) * z_min;
530 r_max = std::tan(theta_max) * z_min;
531
532 Acts::Vector3 p1(r_min * std::cos(phi_min), r_min * std::sin(phi_min), z_min);
533 Acts::Vector3 p2(r_min * std::cos(phi_max), r_min * std::sin(phi_max), z_min);
534 Acts::Vector3 p3(r_max * std::cos(phi_max), r_max * std::sin(phi_max), z_min);
535 Acts::Vector3 p4(r_max * std::cos(phi_min), r_max * std::sin(phi_min), z_min);
536
537 // outer face
538 r_min = std::tan(theta_min) * z_max;
539 r_max = std::tan(theta_max) * z_max;
540
541 Acts::Vector3 p5(r_min * std::cos(phi_min), r_min * std::sin(phi_min), z_max);
542 Acts::Vector3 p6(r_min * std::cos(phi_max), r_min * std::sin(phi_max), z_max);
543 Acts::Vector3 p7(r_max * std::cos(phi_max), r_max * std::sin(phi_max), z_max);
544 Acts::Vector3 p8(r_max * std::cos(phi_min), r_max * std::sin(phi_min), z_max);
545
546 double r_mid = std::tan(theta) * z_min;
547 Acts::Vector3 center;
548 center.x() = r_mid * std::cos(phi);
549 center.y() = r_mid * std::sin(phi);
550 center.z() = z;
551
552 Acts::Transform3 glob2vol = Acts::Transform3::Identity();
553 glob2vol *= Acts::AngleAxis3(-phi, Acts::Vector3::UnitZ());
554 glob2vol *= Acts::AngleAxis3(
555 -theta, Acts::Vector3::UnitZ().cross(center).normalized());
556 glob2vol
557 *= Acts::Translation3(-(p1 + p2 + p3 + p4 + p5 + p6 + p7 + p8) / 8.);
558
559 p1 = glob2vol * p1;
560 p2 = glob2vol * p2;
561 p3 = glob2vol * p3;
562 p4 = glob2vol * p4;
563 p5 = glob2vol * p5;
564 p6 = glob2vol * p6;
565 p7 = glob2vol * p7;
566 p8 = glob2vol * p8;
567
568 auto globalToLocal = glob2vol.inverse();
569
570 auto cubo = std::make_shared<Acts::GenericCuboidVolumeBounds>(
571 std::array<Acts::Vector3, 8>({{p1, p2, p3, p4, p5, p6, p7, p8}}));
572 Acts::Volume vol(globalToLocal, std::move(cubo));
573
574 return vol;
575}
576
577
578Acts::Volume
580 double dr,
581 double eta,
582 double deta,
583 double phi,
584 double dphi) const
585{
586 // std::cout << "build barrel" << std::endl;
587 double eta_max = eta + deta * 0.5;
588 double eta_min = eta - deta * 0.5;
589 double theta = eta_to_theta(eta);
590 double theta_max = eta_to_theta(eta_max);
591 double theta_min = eta_to_theta(eta_min);
592 double phi_max = phi + dphi * 0.5;
593 double phi_min = phi - dphi * 0.5;
594
595 double r_min = r - dr;
596 double r_max = r + dr;
597
598 double z_min, z_max;
599
600 // inner face
601 z_min = r_min / std::tan(theta_min);
602 z_max = r_min / std::tan(theta_max);
603
604 Acts::Vector3 p1(r_min * std::cos(phi_min), r_min * std::sin(phi_min), z_min);
605 Acts::Vector3 p2(r_min * std::cos(phi_min), r_min * std::sin(phi_min), z_max);
606 Acts::Vector3 p3(r_min * std::cos(phi_max), r_min * std::sin(phi_max), z_max);
607 Acts::Vector3 p4(r_min * std::cos(phi_max), r_min * std::sin(phi_max), z_min);
608
609 // outer face
610 z_min = r_max / std::tan(theta_min);
611 z_max = r_max / std::tan(theta_max);
612
613 Acts::Vector3 p5(r_max * std::cos(phi_min), r_max * std::sin(phi_min), z_min);
614 Acts::Vector3 p6(r_max * std::cos(phi_min), r_max * std::sin(phi_min), z_max);
615 Acts::Vector3 p7(r_max * std::cos(phi_max), r_max * std::sin(phi_max), z_max);
616 Acts::Vector3 p8(r_max * std::cos(phi_max), r_max * std::sin(phi_max), z_min);
617
618 Acts::Vector3 center;
619 center.x() = r * std::cos(phi);
620 center.y() = r * std::sin(phi);
621 center.z() = r / std::tan(theta);
622
623 Acts::Transform3 glob2vol = Acts::Transform3::Identity();
624 glob2vol *= Acts::AngleAxis3(-phi, Acts::Vector3::UnitZ());
625 glob2vol *= Acts::AngleAxis3(
626 -theta, Acts::Vector3::UnitZ().cross(center).normalized());
627 glob2vol
628 *= Acts::Translation3(-(p1 + p2 + p3 + p4 + p5 + p6 + p7 + p8) / 8.);
629
630 p1 = glob2vol * p1;
631 p2 = glob2vol * p2;
632 p3 = glob2vol * p3;
633 p4 = glob2vol * p4;
634 p5 = glob2vol * p5;
635 p6 = glob2vol * p6;
636 p7 = glob2vol * p7;
637 p8 = glob2vol * p8;
638
639 auto globalToLocal = glob2vol.inverse();
640
641 auto cubo = std::make_shared<Acts::GenericCuboidVolumeBounds>(
642 std::array<Acts::Vector3, 8>({{p1, p2, p3, p4, p5, p6, p7, p8}}));
643
644 Acts::Volume vol(globalToLocal, std::move(cubo));
645
646 return vol;
647}
648
649Acts::Volume
650ActsCaloTrackingVolumeBuilder::build_box(double x, double dx, double y, double dy, double z, double dz) const
651{
652 // std::cout << "build box" << std::endl;
653
654 double x_min, x_max, y_min, y_max, z_min, z_max;
655 x_min = x - dx;
656 x_max = x + dx;
657 y_min = y - dy;
658 y_max = y + dy;
659 z_min = z - dz;
660 z_max = z + dz;
661
662 // inner face
663 Acts::Vector3 p1(x_min, y_min, z_min);
664 Acts::Vector3 p2(x_min, y_max, z_min);
665 Acts::Vector3 p3(x_max, y_max, z_min);
666 Acts::Vector3 p4(x_max, y_min, z_min);
667
668 // outer face
669 Acts::Vector3 p5(x_min, y_min, z_max);
670 Acts::Vector3 p6(x_min, y_max, z_max);
671 Acts::Vector3 p7(x_max, y_max, z_max);
672 Acts::Vector3 p8(x_max, y_min, z_max);
673
674 Acts::Transform3 glob2vol = Acts::Transform3::Identity();
675 glob2vol
676 *= Acts::Translation3(-(p1 + p2 + p3 + p4 + p5 + p6 + p7 + p8) / 8.);
677
678 p1 = glob2vol * p1;
679 p2 = glob2vol * p2;
680 p3 = glob2vol * p3;
681 p4 = glob2vol * p4;
682 p5 = glob2vol * p5;
683 p6 = glob2vol * p6;
684 p7 = glob2vol * p7;
685 p8 = glob2vol * p8;
686
687 auto globalToLocal = glob2vol.inverse();
688
689 auto cubo = std::make_shared<Acts::GenericCuboidVolumeBounds>(
690 std::array<Acts::Vector3, 8>({{p1, p2, p3, p4, p5, p6, p7, p8}}));
691 Acts::Volume vol(globalToLocal, std::move(cubo));
692
693 return vol;
694}
695
696std::vector<std::unique_ptr<Acts::Volume>>
698{
699 //Acts::ply_helper<double> ply_lar;
700 //Acts::ply_helper<double> ply_tile;
701 //Acts::ply_helper<double> ply_fcal;
702
703 //float x, y, z, r, phi_raw, eta_raw, dphi, deta, dr, dx, dy, dz;
704 float z, dz, eta_raw, deta, phi_raw, dphi, r, dr, x, y, dx, dy;
705 size_t calosample;
706 float scale;
707
708 // storage of cells we will produce
709 std::vector<std::unique_ptr<Acts::Volume>> cells;
710 cells.reserve(m_caloMgr->element_size()); // about 180k
711
712 for(auto it = m_caloMgr->element_begin();it < m_caloMgr->element_end();++it) {
713 const CaloDetDescrElement* cde = *it;
714
715 z = cde->z();
716 dz = cde->dz();
717 eta_raw = cde->eta_raw();
718 deta = cde->deta();
719 phi_raw = cde->phi_raw();
720 dphi = cde->dphi();
721 r = cde->r();
722 dr = cde->dr();
723 x = cde->x();
724 y = cde->y();
725 dx = cde->dx();
726 dy = cde->dy();
727
728 calosample = cde->getSampling();
729
730 scale = 1.;
731 if (calosample >= 12 && calosample <= 20) {
732 scale = 0.5;
733 }
734
735 //Acts::ply_helper<double>* ply;
736 //if (calosample <= 11) {
737 //ply = &ply_lar;
738 //} else if (calosample <= 20) {
739 //ply = &ply_tile;
740 //} else {
741 //ply = &ply_fcal;
742 //}
743
744
745 switch (calosample) {
746 case 4:
747 case 5:
748 case 6:
749 case 7:
750 case 8:
751 case 9:
752 case 10:
753 case 11:
754 case 17:
755 dz *= scale;
756 cells.push_back(std::make_unique<Acts::Volume>(
757 build_endcap(z, dz, eta_raw, deta, phi_raw, dphi)));
758 break;
759 case 0:
760 case 1:
761 case 2:
762 case 3:
763 case 12:
764 case 13:
765 case 14:
766 case 15:
767 case 16:
768 case 18:
769 case 19:
770 case 20:
771 dr *= scale;
772 cells.push_back(std::make_unique<Acts::Volume>(
773 build_barrel(r, dr, eta_raw, deta, phi_raw, dphi)));
774 break;
775 case 21:
776 case 22:
777 case 23:
778 scale = 1.;
779 dx *= scale;
780 dy *= scale;
781 // dz *= scale;
782 cells.push_back(std::make_unique<Acts::Volume>(
783 build_box(x, dx, y, dy, z, dz)));
784 break;
785 default:
786 std::stringstream ss;
787 ss << "Unkown calo sample " << calosample;
788 std::runtime_error(ss.str());
789 }
790
791 //cells.back()->boundingBox({0.1, 0.1, 0.1}).draw(*ply);
792 //auto cvb = dynamic_cast<const
793 //Acts::GenericCuboidVolumeBounds*>(&cells.back()->volumeBounds());
794 //cvb->draw(*ply, cells.back()->transform());
795 }
796
797 //std::ofstream os("lar.ply");
798 //os << ply_lar << std::flush;
799 //os.close();
800
801 //os = std::ofstream("tile.ply");
802 //os << ply_tile << std::flush;
803 //os.close();
804
805 //os = std::ofstream("fcal.ply");
806 //os << ply_fcal << std::flush;
807 //os.close();
808
809 return cells;
810}
Acts::CutoutCylinderVolumeBounds::BoundValues CCVBBV
Acts::CylinderVolumeBounds::BoundValues CVBBV
Acts::Volume::BoundingBox Box
Scalar eta() const
pseudorapidity method
Scalar perp() const
perp method - perpendicular length
Scalar phi() const
phi method
Scalar theta() const
theta method
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_VERBOSE(x)
std::unique_ptr< CaloDetDescrManager > buildCaloDetDescrNoAlign(ISvcLocator *svcLocator, IMessageSvc *msgSvc)
Definition of CaloDetDescrManager.
static constexpr const char * caloMgrStaticKey
static Double_t ss
Handle class for reading from StoreGate.
#define y
#define x
#define z
std::shared_ptr< Acts::TrackingVolume > trackingVolume(const Acts::GeometryContext &gctx, std::shared_ptr< const Acts::TrackingVolume > insideVolume=nullptr, std::shared_ptr< const Acts::VolumeBounds > outsideBounds=nullptr) const override
std::vector< std::unique_ptr< Acts::Volume > > cellFactory() const
std::shared_ptr< Acts::CutoutCylinderVolumeBounds > makeCaloVolumeBounds(const Acts::GeometryContext &gctx, const std::vector< std::unique_ptr< Acts::Volume::BoundingBox > > &boxStore, std::shared_ptr< const Acts::TrackingVolume > insideVolume) const
Acts::Volume build_box(double x, double dx, double y, double dy, double z, double dz) const
Acts::Volume build_barrel(double r, double dr, double eta, double deta, double phi, double dphi) const
Acts::Volume build_endcap(double z, double dz, double eta, double deta, double phi, double dphi) const
This class groups all DetDescr information related to a CaloCell.
CaloCell_ID::CaloSample getSampling() const
cell sampling
This class provides the client interface for accessing the detector description information common to...
int r
Definition globals.cxx:22
std::string toString(const Translation3D &translation, int precision=4)
GeoPrimitvesToStringConverter.
IMessageSvc * getMessageSvc(bool quiet=false)
Definition dot.py:1