ATLAS Offline Software
Loading...
Searching...
No Matches
CaloBlueprintNodeBuilder.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4
6
8
9#include "Acts/Geometry/Blueprint.hpp"
10#include "Acts/Geometry/PortalShell.hpp"
11#include "Acts/Geometry/Volume.hpp"
12#include "Acts/Geometry/StaticBlueprintNode.hpp"
13#include "Acts/Geometry/GeometryIdentifierBlueprintNode.hpp"
14#include <Acts/Navigation/SurfaceArrayNavigationPolicy.hpp>
15#include <Acts/Navigation/TryAllNavigationPolicy.hpp>
16#include <Acts/Utilities/AxisDefinitions.hpp>
17#include <Acts/Geometry/ContainerBlueprintNode.hpp>
18#include <Acts/Geometry/Extent.hpp>
19#include <Acts/Definitions/Units.hpp>
20#include <Acts/Geometry/LayerBlueprintNode.hpp>
21#include <Acts/Geometry/VolumeResizeStrategy.hpp>
22#include <Acts/Geometry/VolumeAttachmentStrategy.hpp>
23#include <Acts/Geometry/TrackingVolume.hpp>
24#include <Acts/Geometry/CylinderVolumeBounds.hpp>
25
27
28#include <Acts/Surfaces/SurfaceArray.hpp>
30
31using namespace Acts;
32using namespace Acts::Experimental;
33using namespace Acts::UnitLiterals;
34using AttachmentStrategy = Acts::VolumeAttachmentStrategy;
35using ResizeStrategy = Acts::VolumeResizeStrategy;
36
37using namespace ActsTrk::detail::GeoVolIds;
38
40 ATH_MSG_DEBUG("Initializing CaloBlueprintNodeBuilder");
41
43
44 return StatusCode::SUCCESS;
45}
46
47std::shared_ptr<BlueprintNode> ActsTrk::CaloBlueprintNodeBuilder::buildBlueprintNode(const GeometryContext& /*gctx*/,
48 std::shared_ptr<BlueprintNode>&& childNode) {
49
50
51 std::map<caloRegion, caloSampleSurfaceMap_t> caloRegionSampleSurfaceMap;
52 std::map<caloRegion, caloSampleDDEElementsMap_t> caloRegionSampleDDEElementsMap;
53
54 fillMaps(caloRegionSampleSurfaceMap, caloRegionSampleDDEElementsMap);
55
56 ATH_MSG_DEBUG("Have filled first two maps");
57
58 generateCylinderSurfaces(caloRegionSampleSurfaceMap[caloRegion::CylinderSymmetricZZero], caloRegionSampleDDEElementsMap[caloRegion::CylinderSymmetricZZero],false);
59 generateCylinderSurfaces(caloRegionSampleSurfaceMap[caloRegion::CylinderNegativeZ], caloRegionSampleDDEElementsMap[caloRegion::CylinderNegativeZ],true);
60 generateCylinderSurfaces(caloRegionSampleSurfaceMap[caloRegion::CylinderPositiveZ], caloRegionSampleDDEElementsMap[caloRegion::CylinderPositiveZ],true);
61 generateDiscSurfaces(caloRegionSampleSurfaceMap[caloRegion::DiscNegativeZ], caloRegionSampleDDEElementsMap[caloRegion::DiscNegativeZ]);
62 generateDiscSurfaces(caloRegionSampleSurfaceMap[caloRegion::DiscPositiveZ], caloRegionSampleDDEElementsMap[caloRegion::DiscPositiveZ]);
63
64 ATH_MSG_DEBUG("Have generated calorimeter cylindrical surfaces");
65
66 // The calo node is a container node that will hold the itk and calo nodes as children.
67 // The calo cylinder is static in order to avoid merging issues with the itk portals
68 // that are supposed to carry material.
69 // Given this node expands to encompass the sub-nodes added, we set the dimensions to nominal
70 // values of 0,100,100.
71 std::shared_ptr<StaticBlueprintNode> itkCaloNode{};
72 {
73 auto envelope = std::make_unique<TrackingVolume>(Amg::Transform3D::Identity(),
74 std::make_shared<CylinderVolumeBounds>(0., 100.0, 100.0),"ITkCalo");
75 envelope->assignGeometryId(Acts::GeometryIdentifier{}.withVolume(s_caloEnvelopeID));
76 itkCaloNode = std::make_shared<StaticBlueprintNode>(std::move(envelope));
77 }
78 if (childNode) {
79 itkCaloNode->addChild(std::move(childNode));
80 }
81
82 ATH_MSG_DEBUG("Top level calorimeter node created");
83
84 auto caloNode = std::make_shared<CylinderContainerBlueprintNode>("CaloNode", AxisDirection::AxisZ);
85 CylinderContainerBlueprintNode& caloBarrelCylinderNode = caloNode->addCylinderContainer("CaloBarrelSymmetricZZeroCylinders", AxisDirection::AxisR);
86 caloBarrelCylinderNode.setAttachmentStrategy(VolumeAttachmentStrategy::Gap);
87 caloBarrelCylinderNode.setResizeStrategy(ResizeStrategy::Gap);
88
89 ATH_MSG_DEBUG("EM Barrel container node created");
90
91 //Barrel cylinders symmetric about z = 0
92 for (unsigned int sampleIndex = 0; sampleIndex < m_caloCylinderSymmetricSampleList.size(); ++sampleIndex) {
93 auto& sampleName = m_caloCylinderSymmetricSampleList.at(sampleIndex).first;
94 addCylindricalTrackingVolumeToCaloNode(caloBarrelCylinderNode, sampleName, caloRegionSampleSurfaceMap[caloRegion::CylinderSymmetricZZero].at({sampleName, getSampleEnum(sampleName)}), sampleIndex, false);
95 }
96
97 //now do asymmetric cylinders, first negative z
98
99 CylinderContainerBlueprintNode& caloBarrelCylinderNegativeZNode = caloNode->addCylinderContainer("CaloBarrelNegativeZAsymmetricCylinders", AxisDirection::AxisR);
100 caloBarrelCylinderNegativeZNode.setAttachmentStrategy(VolumeAttachmentStrategy::Gap);
101 caloBarrelCylinderNegativeZNode.setResizeStrategy(ResizeStrategy::Gap);
102
103 //then positive z
104 CylinderContainerBlueprintNode& caloBarrelCylinderPositiveZNode = caloNode->addCylinderContainer("CaloBarrelPositiveZAsymmetricCylinders", AxisDirection::AxisR);
105 caloBarrelCylinderPositiveZNode.setAttachmentStrategy(VolumeAttachmentStrategy::Gap);
106 caloBarrelCylinderPositiveZNode.setResizeStrategy(ResizeStrategy::Gap);
107
108 for (unsigned int sampleIndex = 0; sampleIndex < m_caloCylinderAsymmetricSampleList.size(); ++sampleIndex) {
109 auto& sampleName = m_caloCylinderAsymmetricSampleList.at(sampleIndex).first;
110 //We only add TileGap1 and 2 here, because the TileExt0,1,2
111 //will need a special treatment to avoid clashes in Z.
112 if (sampleIndex < 2){
113 addCylindricalTrackingVolumeToCaloNode(caloBarrelCylinderNegativeZNode, sampleName+"NegZ", caloRegionSampleSurfaceMap[caloRegion::CylinderNegativeZ].at({sampleName, getSampleEnum(sampleName)}), sampleIndex+m_caloCylinderSymmetricSampleList.size(), false);
114 addCylindricalTrackingVolumeToCaloNode(caloBarrelCylinderPositiveZNode, sampleName+"PosZ", caloRegionSampleSurfaceMap[caloRegion::CylinderPositiveZ].at({sampleName, getSampleEnum(sampleName)}), sampleIndex+m_caloCylinderSymmetricSampleList.size()+m_caloCylinderAsymmetricSampleList.size(), false);
115 }
116 else{
117 //Tile extended barrel surfaces must be added to top level node directly because they always overlap in R
118 //or Z with other calorimeter surfaces, volumes etc.
119 //Note there is a speed penalty to do it this way.
120 itkCaloNode->addLayer(sampleName+"NegZ" + "_Layer", [&](auto& layer) {
121 layer.setSurfaces(caloRegionSampleSurfaceMap[caloRegion::CylinderNegativeZ].at({sampleName, getSampleEnum(sampleName)}));
122 layer.setEnvelope(Acts::ExtentEnvelope{{
123 .z = {0.1_mm, 0.1_mm},
124 .r = {2_mm, 2_mm},
125 }});
126 });
127 itkCaloNode->addLayer(sampleName+"PosZ" + "_Layer", [&](auto& layer) {
128 layer.setSurfaces(caloRegionSampleSurfaceMap[caloRegion::CylinderPositiveZ].at({sampleName, getSampleEnum(sampleName)}));
129 layer.setEnvelope(Acts::ExtentEnvelope{{
130 .z = {0.1_mm, 0.1_mm},
131 .r = {2_mm, 2_mm},
132 }});
133 });
134 }
135 }
136
137
138 CylinderContainerBlueprintNode& caloEndCapDiscNegativeZNode = caloNode->addCylinderContainer("CaloEndCapDiscNegativeZ", AxisDirection::AxisZ);
139 caloEndCapDiscNegativeZNode.setAttachmentStrategy(VolumeAttachmentStrategy::Gap);
140 caloEndCapDiscNegativeZNode.setResizeStrategy(ResizeStrategy::Gap);
141
142 CylinderContainerBlueprintNode& caloEndCapDiscPositiveZNode = caloNode->addCylinderContainer("CaloEndCapDiscPositiveZ", AxisDirection::AxisZ);
143 caloEndCapDiscPositiveZNode.setAttachmentStrategy(VolumeAttachmentStrategy::Gap);
144 caloEndCapDiscPositiveZNode.setResizeStrategy(ResizeStrategy::Gap);
145
146 for (unsigned int sampleIndex = 0; sampleIndex < m_caloDiscSampleList.size(); ++sampleIndex) {
147 auto& sampleName = m_caloDiscSampleList.at(sampleIndex).first;
148 addCylindricalTrackingVolumeToCaloNode(caloEndCapDiscNegativeZNode, sampleName+"NegZ", caloRegionSampleSurfaceMap[caloRegion::DiscNegativeZ].at({sampleName, getSampleEnum(sampleName)}), sampleIndex+m_caloCylinderSymmetricSampleList.size()+(2*m_caloCylinderAsymmetricSampleList.size()), true);
149 addCylindricalTrackingVolumeToCaloNode(caloEndCapDiscPositiveZNode, sampleName+"PosZ", caloRegionSampleSurfaceMap[caloRegion::DiscPositiveZ].at({sampleName, getSampleEnum(sampleName)}), sampleIndex+m_caloCylinderSymmetricSampleList.size()+(2*m_caloCylinderAsymmetricSampleList.size())+m_caloDiscSampleList.size(), true);
150 }
151
152 ATH_MSG_DEBUG("Have added all Barrel layers to caloBarrelCylinderNode");
153
154 // Add calo barrel node to the top level calo node.
155 itkCaloNode->addChild(caloNode);
156
157 //return the top level calo node
158 return itkCaloNode;
159}
160
162 ATH_MSG_DEBUG("Finalizing CaloBlueprintNodeBuilder");
163 return StatusCode::SUCCESS;
164}
165
166void ActsTrk::CaloBlueprintNodeBuilder::fillMaps(std::map<caloRegion, caloSampleSurfaceMap_t>& caloRegionSampleSurfaceMap,
167 std::map<caloRegion, caloSampleDDEElementsMap_t>& caloRegionSampleDDEElementsMap) const {
168
169
170 //loop over all possible calo sampling layers
171 //and create empty vectors of surfaces in the map
172
173 //Create map between each calorimeter sampling and a vector of
174 //cylinder surfaces. We can have N cylinders in a given sampling,
175 //and the value of N is determined by how often the average radius
176 //calculated for a given phi ring, at fixed Z, changes by more than
177 //a tolerance value
178
179 //Use the same loop to create map bwteeen sampling and vectors of DDE
180 for (const auto & currentSample : m_caloCylinderSymmetricSampleList) {
181 caloRegionSampleSurfaceMap[caloRegion::CylinderSymmetricZZero][currentSample] = std::vector<std::shared_ptr<Surface> >();
182 caloRegionSampleDDEElementsMap[caloRegion::CylinderSymmetricZZero][currentSample] = std::vector<const CaloDetDescrElement*>();
183 }
184
185 for (const auto & currentSample : m_caloCylinderAsymmetricSampleList) {
186 caloRegionSampleSurfaceMap[caloRegion::CylinderNegativeZ][currentSample] = std::vector<std::shared_ptr<Surface> >();
187 caloRegionSampleDDEElementsMap[caloRegion::CylinderNegativeZ][currentSample] = std::vector<const CaloDetDescrElement*>();
188 caloRegionSampleSurfaceMap[caloRegion::CylinderPositiveZ][currentSample] = std::vector<std::shared_ptr<Surface> >();
189 caloRegionSampleDDEElementsMap[caloRegion::CylinderPositiveZ][currentSample] = std::vector<const CaloDetDescrElement*>();
190 }
191
192 for (const auto & currentSample : m_caloDiscSampleList) {
193 caloRegionSampleSurfaceMap[caloRegion::DiscNegativeZ][currentSample] = std::vector<std::shared_ptr<Surface> >();
194 caloRegionSampleDDEElementsMap[caloRegion::DiscNegativeZ][currentSample] = std::vector<const CaloDetDescrElement*>();
195 caloRegionSampleSurfaceMap[caloRegion::DiscPositiveZ][currentSample] = std::vector<std::shared_ptr<Surface> >();
196 caloRegionSampleDDEElementsMap[caloRegion::DiscPositiveZ][currentSample] = std::vector<const CaloDetDescrElement*>();
197 }
198
199 //for each calo sampling collect all the DDE in a vector
200 for (const CaloDetDescrElement* theDDE : m_caloDetSecrMgr->element_range()){
201 if (!theDDE){
202 ATH_MSG_ERROR("Null pointer to CaloDetDescrElement");
203 continue;
204 }
205
206 CaloCell_ID::CaloSample currentSample=theDDE->getSampling();
207 std::pair <std::string, CaloCell_ID::CaloSample> samplePair = std::make_pair(getSampleName(currentSample), currentSample);
208
209 //check if have cylinder symmetric about z = 0
211 caloRegionSampleDDEElementsMap[caloRegion::CylinderSymmetricZZero][{samplePair.first,samplePair.second}].push_back(theDDE);
212 }
213
214 //check if have cylinder asymmetric about z = 0, if so check if in negative or positive z
216 if (theDDE->z() < 0.0) {
217 caloRegionSampleDDEElementsMap[caloRegion::CylinderNegativeZ][{samplePair.first,samplePair.second}].push_back(theDDE);
218 }
219 else {
220 caloRegionSampleDDEElementsMap[caloRegion::CylinderPositiveZ][{samplePair.first,samplePair.second}].push_back(theDDE);
221 }
222 }
223
224 //check if sampling is in disc list
225 if (std::find(m_caloDiscSampleList.begin(), m_caloDiscSampleList.end(), std::make_pair(samplePair.first,samplePair.second)) != m_caloDiscSampleList.end()) {
226 //check if in negative or positive z
227 if (theDDE->z() < 0.0) {
228 caloRegionSampleDDEElementsMap[caloRegion::DiscNegativeZ][{getSampleName(currentSample), currentSample}].push_back(theDDE);
229 }
230 else {
231 caloRegionSampleDDEElementsMap[caloRegion::DiscPositiveZ][{getSampleName(currentSample), currentSample}].push_back(theDDE);
232 }
233 }
234
235 }
236
237 auto sortAllLayersInZ = [&caloRegionSampleDDEElementsMap](const std::vector<std::pair<std::string, CaloCell_ID::CaloSample>>& caloSampleList, const caloRegion& region) {
238 for (const auto & currentSample : caloSampleList) {
239 std::vector<const CaloDetDescrElement*> currentElements = caloRegionSampleDDEElementsMap[region][currentSample];
240 std::sort(currentElements.begin(), currentElements.end(), [](const CaloDetDescrElement* a, const CaloDetDescrElement* b) {return a->z() < b->z();});
241 caloRegionSampleDDEElementsMap[region][currentSample] = std::move(currentElements);
242 }
243 };
244
245 //Sort the DDE, by Z, in all possible layers
249
250 auto sortAllLayersInR = [&caloRegionSampleDDEElementsMap](const std::vector<std::pair<std::string, CaloCell_ID::CaloSample>>& caloSampleList, const caloRegion& region) {
251 for (const auto& currentSample : caloSampleList) {
252 std::vector<const CaloDetDescrElement*> currentElements = caloRegionSampleDDEElementsMap[region][currentSample];
253 std::sort(currentElements.begin(), currentElements.end(), [](const CaloDetDescrElement* a, const CaloDetDescrElement* b) {return a->r() < b->r();});
254 caloRegionSampleDDEElementsMap[region][currentSample] = std::move(currentElements);
255 }
256 };
257
258 //Sort the DDE, by R, in all possible layers
261
262}
263
264void ActsTrk::CaloBlueprintNodeBuilder::generateCylinderSurfaces(caloSampleSurfaceMap_t& caloSampleSurfaceMap, caloSampleDDEElementsMap_t& caloSampleDDEElementsMap, bool asymmetricZ) const{
265
266 std::vector<std::pair<std::string, CaloCell_ID::CaloSample>> sampleList;
267 if (asymmetricZ) sampleList = m_caloCylinderAsymmetricSampleList;
268 else sampleList = m_caloCylinderSymmetricSampleList;
269
270 for (const auto & currentSample : sampleList) {
271
272 std::vector<const CaloDetDescrElement*> currentElements = caloSampleDDEElementsMap[currentSample];
273
274 double maxLArBRadius = 0.0, minLArBRadius = std::numeric_limits<double>::max();
275 double lowZLarB = 0.0, highZLarB = 0.0;
276
277 //loop over cells runs from -z to +z in a given sampling layer
278 //There are many cells with the same z value, but different phi values
279 //We will find the average radius of the cells in a given phi ring
280 double totalRadiusFixedPhi = 0.0;
281 bool firstCellInPhiRing = true;
282 unsigned int phiCounter = 0;
283
284 //Then we will also track changes in radius as we move in Z from
285 //each ring of cells in phi to the next ring of cells in phi
286 bool firstPhiRing = true;
287 double initialRadius = 0.0;
288 double initialZ = -std::numeric_limits<double>::max();
289
290 //check if we ever move along in Z value
291 bool movedInZ = false;
292
293 for (const CaloDetDescrElement* theDDE : currentElements){
294
295 double z = theDDE->z();
296 double radius = theDDE->r();
297
298 ATH_MSG_DEBUG(" Calo Sampling is " << currentSample.first);
299
300 if (firstCellInPhiRing) {
301 ATH_MSG_DEBUG("First Cell in phi ring " << currentSample.first << " has z = " << z << " and r = " << radius);
302 initialZ = z;
303 firstCellInPhiRing = false;
304 }
305
306 if (firstPhiRing) {
307 ATH_MSG_DEBUG("First Cell in layer " << currentSample.first << " has z = " << z << " and r = " << radius);
308 initialRadius = theDDE->r();
309 firstPhiRing = false;
310 lowZLarB = z;
311 }
312
313 ATH_MSG_DEBUG("Z and initialZ are " << z << " and " << initialZ);
314
315 //if z has not changed then we add the radius to the summed radius for this phi ring
316 //and increment the counter of cells in this phi ring
317 if (std::abs(z - initialZ) < 0.0001) {
318 ATH_MSG_DEBUG("phiCounter is " << phiCounter << " and radius is " << radius << " and totalRadiusFixedPhi is " << totalRadiusFixedPhi << " and hash is " << theDDE->calo_hash());
319 totalRadiusFixedPhi += radius;
320 phiCounter++;
321 continue;
322 }
323 else {
324 movedInZ = true;
325 firstCellInPhiRing = true;
326 if (phiCounter > 0) {
327 double cellRingRadius = totalRadiusFixedPhi / phiCounter;
328 totalRadiusFixedPhi = 0.0;
329 phiCounter = 0;
330
331 if (cellRingRadius > maxLArBRadius) maxLArBRadius = radius;
332 if (cellRingRadius < minLArBRadius) minLArBRadius = radius;
333
334 //if radius changes by more than tolerance, then we will create a cylinder
335 //with the average cell radius and length from neg to pos z
336 highZLarB = z;
337 ATH_MSG_DEBUG("Values of cellRingRadius, initialRadius, highZLarB and lowZLarB are " << cellRingRadius << ", " << initialRadius << ", " << highZLarB << " and " << lowZLarB);
338 if (std::abs(cellRingRadius - initialRadius) > m_radiusTolerance && highZLarB - lowZLarB > 0.0) {
339 ATH_MSG_DEBUG("CYLINDER: Create cylinder for layer " << currentSample.first);
340 ATH_MSG_DEBUG("CYLINDER: Create Cylinder: Min and Max LAr B radius are " << minLArBRadius << " " << maxLArBRadius);
341 ATH_MSG_DEBUG("CYLINDER: Create Cylinder: Min and Max LAr B z are " << lowZLarB << " " << highZLarB);
342
343 caloSampleSurfaceMap[currentSample].push_back(generateCylinderSurface(maxLArBRadius, minLArBRadius, lowZLarB, highZLarB, asymmetricZ));
344
345 //reset the dimensions of the cylinder to the initial conditions, in
346 //preparation for the next cylinder
347 firstPhiRing = true;
348 minLArBRadius = std::numeric_limits<double>::max();
349 maxLArBRadius = 0.0;
350 lowZLarB = 0.0;
351 highZLarB = 0.0;
352 }//if radius changes by more than tolerance
353 }//if at least one cell in phi (should always be the case!)
354 else ATH_MSG_ERROR("phiCounter is zero!");
355 }//if z has changed
356 }//loop over calorimeter DDE
357
358 if (0 == caloSampleSurfaceMap[currentSample].size()){
359 //If we never found any shift in Z whilst looping over the DDE
360 //then thee min/max Z and radius were not set
361 //so we set them here.
362 if (!movedInZ) {
363 lowZLarB = initialZ;
364 highZLarB = initialZ+0.001;
365 if (phiCounter > 0) {
366 maxLArBRadius = totalRadiusFixedPhi / phiCounter;
367 minLArBRadius = 0.0;
368 }
369 }
370 ATH_MSG_DEBUG("CYLINDER: Zero size Vector: Create cylinder for layer " << currentSample.first);
371 ATH_MSG_DEBUG("CYLINDER: Create Cylinder: Min and Max LAr B radius are " << minLArBRadius << " " << maxLArBRadius);
372 ATH_MSG_DEBUG("CYLINDER: Create Cylinder: Min and Max LAr B z are " << lowZLarB << " " << highZLarB);
373 caloSampleSurfaceMap[currentSample].push_back(generateCylinderSurface(maxLArBRadius, minLArBRadius, lowZLarB, highZLarB, asymmetricZ));
374 }
375 }
376}
377
378std::shared_ptr<CylinderSurface> ActsTrk::CaloBlueprintNodeBuilder::generateCylinderSurface(const double& maxLArBRadius, const double& minLArBRadius, const double& lowZLarB, const double& highZLarB, bool asymmetricZ) const{
379
380 //Characterise the dimensions of the cylinder
381 double LArBRadius = (maxLArBRadius + minLArBRadius) / 2.0;
382 double LArBLength = std::abs(highZLarB - lowZLarB);
383
384 ATH_MSG_DEBUG("Cylinder radius and length are " << LArBRadius << " and " << LArBLength);
385
386 if (asymmetricZ) {
387 double zShift = (highZLarB + lowZLarB) / 2.0;
388 ATH_MSG_DEBUG("Cylinder is asymmetric in Z, with shift of " << zShift);
389 return Surface::makeShared<CylinderSurface>(Transform3(Translation3(0.0, 0.0, zShift)), LArBRadius, LArBLength/2);
390 }
391 else return Surface::makeShared<CylinderSurface>(Transform3::Identity(), LArBRadius, LArBLength/2);
392
393}
394
396
397 for (const auto & currentSample : m_caloDiscSampleList) {
398
399 const std::vector<const CaloDetDescrElement*> & currentElements = caloSampleDDEElementsMap[currentSample];
400
401 double totalZFixedPhi = 0.0;
402 bool firstCellInPhiRing = true;
403 unsigned int phiCounter = 0;
404
405 bool firstPhiRing = true;
406 double initialRadius = 0.0;
407 double initialZ = -std::numeric_limits<double>::max();
408
409 //loop over cells runs from -z to +z in a given sampling layer
410 //There are many cells with the same z value, but different phi values
411 //We will find a min amd max radius in this phi ring.
412 double minDiscRadius = std::numeric_limits<double>::max(), maxDiscRadius = 0.0;
413
414 unsigned int currentElementsSize = currentElements.size();
415 unsigned int DDECounter = 0;
416
417 for (const CaloDetDescrElement* theDDE : currentElements){
418
419 bool isLastDDE = (DDECounter == (currentElementsSize-1));
420
421 ATH_MSG_DEBUG("Disc DDE with sampling, r and z of " << currentSample << ", " << theDDE->r() << ", " << theDDE->z());
422 ATH_MSG_DEBUG("isLastDDE is " << isLastDDE);
423
424 double z = theDDE->z();
425 double radius = theDDE->r();
426
427 if (firstCellInPhiRing) {
428 initialRadius = radius;
429 firstCellInPhiRing = false;
430 }
431
432 if (firstPhiRing) {
433 initialZ = z;
434 firstPhiRing = false;
435 minDiscRadius = radius;
436 }
437
438 //if radius is unchanged then we add the z to the summed z for this phi ring
439 //and increment the counter of cells in this phi ring
440 if (std::abs(radius - initialRadius) < 0.0001 && !isLastDDE) {
441 totalZFixedPhi += z;
442 phiCounter++;
443 DDECounter++;
444 continue;
445 }
446 else {
447 firstCellInPhiRing = true;
448 if (phiCounter > 0) {
449 double cellRingZ = totalZFixedPhi / phiCounter;
450 totalZFixedPhi = 0.0;
451 phiCounter = 0;
452
453 //if z changes by more than tolerance, then we will create a disc
454 //with the min and max radius found
455 //if we reach the last DDE and no new surface has been created, then we also create a disc surface
456 maxDiscRadius = radius;
457 ATH_MSG_DEBUG("cellRingZ, initialZ and z tolerance are " << cellRingZ << ", " << initialZ << " and " << m_zTolerance);
458 if (std::abs(cellRingZ - initialZ) > m_zTolerance || isLastDDE) {
459 ATH_MSG_DEBUG("DISC: About to create disc surface for sampling " << currentSample);
460 caloSampleSurfaceMap[currentSample].push_back(generateDiscSurface(cellRingZ,maxDiscRadius, minDiscRadius));
461 //reset the dimensions of the disc to the initial conditions, in
462 //preparation for the next disc
463 minDiscRadius = std::numeric_limits<double>::max();
464 maxDiscRadius = 0.0;
465 firstPhiRing = true;
466 }//if z changes by more than tolerance
467 }//if at least one cell in phi (should always be the case!)
468 else ATH_MSG_ERROR("phiCounter is zero!");
469 }//if radius has changed
470 DDECounter++;
471 }//loop over calorimeter DDE
472 }//loop over calo samplings
473}
474
475std::shared_ptr<Acts::DiscSurface> ActsTrk::CaloBlueprintNodeBuilder::generateDiscSurface(const double& z, const double& maxLArBRadius, const double& minLArBRadius) const{
476
477 ATH_MSG_DEBUG("DISC: Disc min and max radius are " << minLArBRadius << " and " << maxLArBRadius << " with z of " << z);
478 auto surface = Surface::makeShared<DiscSurface>(Amg::getTranslateZ3D(z), minLArBRadius, maxLArBRadius);
479
480 return surface;
481
482}
483
484void ActsTrk::CaloBlueprintNodeBuilder::addCylindricalTrackingVolumeToCaloNode(CylinderContainerBlueprintNode& containerNode, const std::string& volumeName,const std::vector<std::shared_ptr<Acts::Surface>>& surfaces, int layerIndex, const bool& isDisc) const{
485
486 // Construct the container node with geometry identifier and layer, and add the surfaces to the layer.
487 Acts::Experimental::GeometryIdentifierBlueprintNode& geoIdNode = containerNode.withGeometryIdentifier();
488 geoIdNode.setAllVolumeIdsTo(s_caloBarrelId +
489 layerIndex);
490
491 AxisDirection axis = AxisDirection::AxisZ;
492 if (isDisc) axis = AxisDirection::AxisR;
493 CylinderContainerBlueprintNode& cylinder = geoIdNode.addCylinderContainer(volumeName,
494 axis);
495
496 cylinder.addLayer(volumeName + "_Layer", [&](auto& layer) {
497 layer.setSurfaces(surfaces);
498 layer.setEnvelope(Acts::ExtentEnvelope{{
499 .z = {0.1_mm, 0.1_mm},
500 .r = {2_mm, 2_mm},
501 }});
502 });
503
504}
#define ATH_MSG_ERROR(x)
#define ATH_MSG_DEBUG(x)
Acts::VolumeResizeStrategy ResizeStrategy
Acts::VolumeAttachmentStrategy AttachmentStrategy
std::map< std::pair< std::string, CaloCell_ID::CaloSample >, std::vector< std::shared_ptr< Acts::Surface > > > caloSampleSurfaceMap_t
std::map< std::pair< std::string, CaloCell_ID::CaloSample >, std::vector< const CaloDetDescrElement * > > caloSampleDDEElementsMap_t
std::unique_ptr< CaloDetDescrManager > buildCaloDetDescrNoAlign(ISvcLocator *svcLocator, IMessageSvc *msgSvc)
static Double_t a
size_t size() const
Number of registered mappings.
#define z
void fillMaps(std::map< caloRegion, caloSampleSurfaceMap_t > &caloRegionSampleSurfaceMap, std::map< caloRegion, caloSampleDDEElementsMap_t > &caloRegionSampleDDEElementsMap) const
fillMaps fills two maps.
std::vector< std::pair< std::string, CaloCell_ID::CaloSample > > m_caloDiscSampleList
std::string getSampleName(CaloCell_ID::CaloSample currentSample) const
void addCylindricalTrackingVolumeToCaloNode(Acts::Experimental::CylinderContainerBlueprintNode &containerNode, const std::string &volumeName, const std::vector< std::shared_ptr< Acts::Surface > > &surfaces, int layerIndex, const bool &isDisc) const
addCylindricalTrackingVolumeToCaloNode adds a cylindrical tracking volume to the calo node.
std::shared_ptr< Acts::CylinderSurface > generateCylinderSurface(const double &maxLArBRadius, const double &minLArBRadius, const double &lowZLarB, const double &highZLarB, bool asymmetricZ) const
generateCylinderSurface generates a cylindrical surface for a given set of parameters.
std::shared_ptr< Acts::DiscSurface > generateDiscSurface(const double &z, const double &maxLArBRadius, const double &minLArBRadius) const
std::vector< std::pair< std::string, CaloCell_ID::CaloSample > > m_caloCylinderAsymmetricSampleList
void generateCylinderSurfaces(caloSampleSurfaceMap_t &caloSampleSurfaceMap, caloSampleDDEElementsMap_t &caloSampleDDEElementsMap, bool asymmetricZ) const
generateCylinderSurfaces generates cylindrical surfaces for each calo sampling.
std::vector< std::pair< std::string, CaloCell_ID::CaloSample > > m_caloCylinderSymmetricSampleList
std::shared_ptr< Acts::Experimental::BlueprintNode > buildBlueprintNode(const Acts::GeometryContext &gctx, std::shared_ptr< Acts::Experimental::BlueprintNode > &&childNode) override
Build the Itk Blueprint Node.
std::unique_ptr< CaloDetDescrManager > m_caloDetSecrMgr
CaloCell_ID::CaloSample getSampleEnum(const std::string &sampleName) const
void generateDiscSurfaces(caloSampleSurfaceMap_t &caloSampleSurfaceMap, caloSampleDDEElementsMap_t &caloSampleDDEElementsMap) const
CaloSampling::CaloSample CaloSample
Definition CaloCell_ID.h:53
This class groups all DetDescr information related to a CaloCell.
Define the volume parts of the GeometryIdentifier for each ATLAS subsystem centrally.
constexpr std::size_t s_caloEnvelopeID
Volume Ids ofthe Calorimeter.
constexpr std::size_t s_caloBarrelId
Amg::Transform3D getTranslateZ3D(const double Z)
: Returns a shift transformation along the z-axis
IMessageSvc * getMessageSvc(bool quiet=false)
void sort(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end)
Specialization of sort for DataVector/List.