ATLAS Offline Software
Loading...
Searching...
No Matches
TrackingVolumeArrayCreator.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// TrackingVolumeArrayCreator.cxx, (c) ATLAS Detector software
8
9// Trk include
10#include <cmath>
11#include <algorithm>
12
26// Amg
28
29namespace {
31 inline std::vector<VolumePtr> translateToShared(const std::vector<Trk::TrackingVolume*>& inVols,
32 bool navtype) {
33 std::vector<VolumePtr> outVec{};
34 outVec.reserve(inVols.size());
35 for (Trk::TrackingVolume* vol : inVols) {
36 if(!navtype) {
37 outVec.emplace_back(vol);
38 } else {
39 //The volumes are just for navigation purposes
40 // so we want to have ust a view
41 outVec.emplace_back(vol, Trk::do_not_delete<Trk::TrackingVolume>);
42 }
43 }
44 return outVec;
45 }
46}
47
48
49namespace Trk{
50// constructor
52 const std::string& n,
53 const IInterface* p)
54 : AthAlgTool(t, n, p)
55{
56 declareInterface<ITrackingVolumeArrayCreator>(this);
57}
58
59std::unique_ptr<TrackingVolumeArray> TrackingVolumeArrayCreator::cylinderVolumesArrayInR(const std::vector<TrackingVolume*>& vols,
60 bool navtype) const {
61 return cylinderVolumesArrayInR(translateToShared(vols, navtype), navtype);
62}
63
64std::unique_ptr<TrackingVolumeArray> TrackingVolumeArrayCreator::cylinderVolumesArrayInZ(const std::vector<TrackingVolume*>& vols,
65 bool navtype) const {
66 return cylinderVolumesArrayInZ(translateToShared(vols, navtype), navtype);
67}
68
69std::unique_ptr<TrackingVolumeArray> TrackingVolumeArrayCreator::cylinderVolumesArrayInPhiR(const std::vector<TrackingVolume*>& vols,
70 bool navtype) const {
71 return cylinderVolumesArrayInPhiR(translateToShared(vols, navtype), navtype);
72}
73std::unique_ptr<TrackingVolumeArray> TrackingVolumeArrayCreator::cylinderVolumesArrayInPhiZ(const std::vector<TrackingVolume*>& vols,
74 bool navtype) const {
75 return cylinderVolumesArrayInPhiZ(translateToShared(vols, navtype), navtype);
76}
77
78std::unique_ptr<TrackingVolumeArray> TrackingVolumeArrayCreator::cylinderVolumesArrayInR(const std::vector<VolumePtr>& vols,
79 bool navtype) const {
80
81
82 ATH_MSG_VERBOSE("Create VolumeArray of "<< vols.size() << " Volumes (with CylinderVolumeBounds) with R-binning. ");
83
84 // check for compatibility - needs r-sorting first
85 double lastZmin{0.};
86 double lastZmax{0.};
87 double lastOuterRadius{0.};
88
89 // the vector of doubles for identification
90 std::vector<float> boundaries;
91 boundaries.reserve(vols.size() + 1);
92
93 // the vector needed for the BinnedArray
94 std::vector<TrackingVolumeOrderPosition> volOrder;
95 // loop over volumes and fill primaries
96 auto volIter = vols.begin();
97 for (unsigned int ivol = 0; volIter != vols.end(); ++volIter, ++ivol) {
98 const CylinderVolumeBounds* currentCylBounds = nullptr;
99 if (*volIter) currentCylBounds = dynamic_cast<const CylinderVolumeBounds*>(&((*volIter)->volumeBounds()));
100 if (!currentCylBounds) {
101 ATH_MSG_ERROR("Given TrackingVolume doesn't exist or is not of shape "
102 "'CylinderVolumeBounds': return 0");
103 return nullptr;
104 }
105 // current rmin/rmax
106 double currentRmin = currentCylBounds->innerRadius();
107 double currentRmax = currentCylBounds->outerRadius();
108 if (!ivol)
109 boundaries.push_back(currentRmin);
110 boundaries.push_back(currentRmax);
111
112 // compatibility checks
113 double currentZmin = (*volIter)->center().z() - currentCylBounds->halflengthZ();
114 double currentZmax = (*volIter)->center().z() + currentCylBounds->halflengthZ();
115
116 // check for compatibility of the new volume - not for navigation type
117 if (ivol && !navtype) {
118 // longitudinal clinch
119 if (std::abs(currentZmin - lastZmin) > 0.1 || std::abs(currentZmax - lastZmax) > 0.1) {
120 ATH_MSG_ERROR("Given TrackingVolume(s) do not extend in z to the same point (required) : return 0");
121 ATH_MSG_VERBOSE("Information : lastZmin / lastZmin = "<< lastZmin << " / " << currentZmin);
122 ATH_MSG_VERBOSE(" lastZmax / currentZmax = "<< lastZmax << " / " << currentZmax);
123 return nullptr;
124 }
125 // radial clinch
126 if (std::abs(currentRmin - lastOuterRadius) > 0.1) {
127 ATH_MSG_ERROR("Given TrackingVolume(s) are not wrapping, neither inside-out, nor v.v. : return 0");
128 ATH_MSG_VERBOSE("Information : currentRmin / lastOuterRadius = "<< currentRmin << " / " << lastOuterRadius);
129 return nullptr;
130 }
131 }
132 // register for next round
133 lastZmin = currentZmin;
134 lastZmax = currentZmax;
135 lastOuterRadius = currentRmax;
136 // output
137 ATH_MSG_VERBOSE("Adding Volume '" << (*volIter)->volumeName() << "' to Array");
138
139 volOrder.emplace_back((*volIter), currentCylBounds->mediumRadius() * Amg::Vector3D::UnitX());
140 // push back the volume order position
141
142 }
143 if (!volOrder.empty()) {
144 auto volBinUtilR = BinUtility(boundaries, open, binR);
145 ATH_MSG_VERBOSE("Return created Array. ");
146 return std::make_unique<BinnedArray1D<TrackingVolume>>(volOrder, volBinUtilR);
147 }
148 ATH_MSG_ERROR("No TrackingVolumes provided to the TrackingVolumeArrayCreator: return 0");
149 return nullptr;
150}
151
152
153std::unique_ptr<TrackingVolumeArray>
154 TrackingVolumeArrayCreator::cylinderVolumesArrayInZ(const std::vector<VolumePtr>& vols,
155 bool navtype) const {
156 ATH_MSG_VERBOSE("Create VolumeArray of "
157 << vols.size()
158 << " Volumes (with CylinderVolumeBounds) with Z-binning. ");
159
160 // for compatibility checks
161 double lastRmin{0.};
162 double lastRmax{0.};
163 double lastZmax{0.};
164
165 // the vector of doubles for identification
166 std::vector<float> boundaries;
167 boundaries.reserve(vols.size() + 1);
168
169 // the vector needed for the BinnedArray
170 std::vector<TrackingVolumeOrderPosition> volOrder;
171 // loop over volumes and fill primaries
172 auto volIter = vols.begin();
173 for (unsigned int ivol = 0; volIter != vols.end(); ++volIter, ++ivol) {
174 const CylinderVolumeBounds* currentCylBounds = nullptr;
175 if (*volIter)currentCylBounds = dynamic_cast<const CylinderVolumeBounds*>( &((*volIter)->volumeBounds()));
176 if (!currentCylBounds) {
177 ATH_MSG_ERROR("Given TrackingVolume doesn't exist or is not of shape 'CylinderVolumeBounds': return 0");
178 return nullptr;
179 }
180 //
181 const Amg::Vector3D& volCenter = (*volIter)->center();
182 double halflengthZ = currentCylBounds->halflengthZ();
183 // get the numbers
184 double currentZmin = volCenter.z() - halflengthZ;
185 double currentZmax = volCenter.z() + halflengthZ;
186 if (!ivol) boundaries.push_back(currentZmin);
187 boundaries.push_back(currentZmax);
188
189 // consistency checks
190 double currentRmin = currentCylBounds->innerRadius();
191 double currentRmax = currentCylBounds->outerRadius();
192
193 // compatibility check - not for navtype
194 if (ivol && !navtype) {
195 // first the radial check
196 if (std::abs(lastRmin - currentRmin) > 0.1 || std::abs(lastRmax - currentRmax) > 0.1) {
197 ATH_MSG_ERROR("Given TrackingVolume(s) do not have same radial extends (required): return 0");
198 ATH_MSG_VERBOSE("Information : lastRmin / currentRmin = " << lastRmin << " / " << currentRmin);
199 ATH_MSG_VERBOSE(" lastRmax / currentRmax = " << lastRmax << " / " << currentRmax);
200 return nullptr;
201 }
202 // then let's see whether they leave gaps in z
203 if (std::abs(lastZmax - currentZmin) > 0.1) {
204 ATH_MSG_ERROR("Given TrackingVolume(s) are not attaching in z (required) : return 0");
205 return nullptr;
206 }
207 }
208 // for the next round
209 lastRmin = currentRmin;
210 lastRmax = currentRmax;
211 lastZmax = currentZmax;
212 // output
213 ATH_MSG_VERBOSE("Adding Volume '" << (*volIter)->volumeName()
214 << "' to Array");
215 // push back the volume order position
216 volOrder.emplace_back((*volIter), (*volIter)->center());
217
218 }
219 if (!volOrder.empty()) {
220 auto volBinUtil = BinUtility(boundaries, open, binZ);
221 ATH_MSG_VERBOSE("Return created Array. ");
222 return std::make_unique<BinnedArray1D<TrackingVolume>>(volOrder, volBinUtil);
223 }
224 ATH_MSG_ERROR("No TrackingVolumes provided to the TrackingVolumeArrayCreator: return 0");
225 return nullptr;
226}
227
228std::unique_ptr<TrackingVolumeArray>
230 bool /*navtype*/) const {
231
232 ATH_MSG_VERBOSE("Create VolumeArray of " << vols.size()
233 << " Volumes (with CylinderVolumeBounds) with Phi-binning. ");
234
235 // phi binning; assume equidistant
236 int nPhiBins = !vols.empty() ? vols.size() : 1;
237 double phi = M_PI;
238 // the vector needed for the BinnedArray
239 std::vector<TrackingVolumeOrderPosition> volOrder;
240 // loop over volumes and fill primaries
241 auto volIter = vols.begin();
242 for (; volIter != vols.end(); ++volIter) {
243 const CylinderVolumeBounds* cyl = nullptr;
244 if (*volIter) cyl = dynamic_cast<const CylinderVolumeBounds*>(&((*volIter)->volumeBounds()));
245 if (!cyl) {
246 ATH_MSG_ERROR("Given TrackingVolume doesn't exist or is not of shape 'CylinderVolumeBounds': return 0");
247 return nullptr;
248 }
249 // output
250 ATH_MSG_VERBOSE("Adding Volume '" << (*volIter)->volumeName()<< "' to Array");
251 // push back the volume order position
252 volOrder.emplace_back((*volIter), (*volIter)->transform() * (cyl->mediumRadius() * Amg::Vector3D::UnitX()));
253
254 }
255 if (!volOrder.empty()) {
256 auto volBinUtil = BinUtility(nPhiBins, -phi, +phi, closed, binPhi);
257 return std::make_unique<BinnedArray1D<TrackingVolume>>(volOrder, volBinUtil);
258 }
259 ATH_MSG_ERROR("No TrackingVolumes provided to the TrackingVolumeArrayCreator: return 0");
260 return nullptr;
261}
262
263std::unique_ptr<TrackingVolumeArray>
265 bool navtype) const {
266 if (vols.empty())
267 return nullptr;
268
269 const bool bevelled = std::find_if(vols.begin(),vols.end(),
270 [](const VolumePtr& ptr) -> bool {
271 return dynamic_cast<const BevelledCylinderVolumeBounds*>(&(ptr->volumeBounds()));
272 }) != vols.end();
273
274 double tol = 0.001;
275
276 // the vector needed for the BinnedArray
277 std::vector<TrackingVolumeOrderPosition> volOrder;
278
279 if (bevelled) {
280 ATH_MSG_VERBOSE("Create 2dim VolumeArray of "<< vols.size()
281 << " Volumes (with CylinderVolumeBounds) with PhiH-binning. ");
282 std::vector<float> phiSteps;
283 std::vector<std::pair<std::pair<double, int>, std::pair<double, double>>>
284 volPos;
285 std::vector<VolumePtr> fullPhiVols;
286
287 for (const VolumePtr& vol : vols) {
288 const auto *cyl = dynamic_cast<const CylinderVolumeBounds*>(&(vol->volumeBounds()));
289 const auto *bcyl =dynamic_cast<const BevelledCylinderVolumeBounds*>(&(vol->volumeBounds()));
290 double rmin{0.};
291 double rmax{0.};
292 double dphi{0.};
293 double mRad{0.};
294 int type = 0;
295
296 if (cyl) {
297 rmin = cyl->innerRadius();
298 rmax = cyl->outerRadius();
299 dphi = cyl->halfPhiSector();
300 mRad = cyl->mediumRadius();
301 } else if (bcyl) {
302 rmin = bcyl->innerRadius();
303 rmax = bcyl->outerRadius();
304 dphi = bcyl->halfPhiSector();
305 mRad = bcyl->mediumRadius();
306 type = bcyl->type();
307 } else {
308 ATH_MSG_ERROR("volume not cylinder nor bevelled cylinder ");
309 return nullptr;
310 }
311
312 if (dphi < M_PI) {
313 // push back the volume order position
314 Amg::Vector3D ngp((vol->transform()) * (mRad * Amg::Vector3D::UnitX()));
315 volOrder.emplace_back(vol, ngp);
316
317 // push back volume position to avoid another loop
318 volPos.emplace_back(std::pair<double, int>(ngp.phi(), type),
319 std::pair<double, double>(rmin, rmax));
320 // phi binning
321 double phi1 = ngp.phi() - dphi;
322 double phi2 = ngp.phi() + dphi;
323 if (phi1 < -2 * M_PI) {
324 phi1 += 2 * M_PI;
325 } if (phi2 < -2 * M_PI) {
326 phi2 += 2 * M_PI;
327 } if (phi1 > 2 * M_PI) {
328 phi1 -= 2 * M_PI;
329 } if (phi2 > 2 * M_PI) {
330 phi2 -= 2 * M_PI;
331 }
332
333 if (!phiSteps.empty()) {
334 std::vector<float>::iterator iter = phiSteps.begin();
335 bool known = false;
336 while (iter != phiSteps.end()) {
337 if (std::abs(phi1 - (*iter)) < tol) {
338 known = true;
339 break;
340 }
341 if (phi1 < (*iter)) {
342 phiSteps.insert(iter, phi1);
343 known = true;
344 break;
345 }
346 ++iter;
347 }
348 if (!known)
349 phiSteps.push_back(phi1);
350 iter = phiSteps.begin();
351 known = false;
352 while (iter != phiSteps.end()) {
353 if (std::abs(phi2 - (*iter)) < tol) {
354 known = true;
355 break;
356 }
357 if (phi2 < (*iter)) {
358 phiSteps.insert(iter, phi2);
359 known = true;
360 break;
361 }
362 ++iter;
363 }
364 if (!known)
365 phiSteps.push_back(phi2);
366 } else {
367 phiSteps.push_back(fmin(phi1, phi2));
368 phiSteps.push_back(fmax(phi1, phi2));
369 }
370 } else {
371 fullPhiVols.push_back(vol);
372 }
373 } // end of first loop over volumes
374 // collect volumes with full phi range
375 if (phiSteps.empty()) {
376 phiSteps.push_back(-M_PI);
377 phiSteps.push_back(+M_PI);
378 }
379 for (auto & fullPhiVol : fullPhiVols) {
380 const auto *cyl =dynamic_cast<const CylinderVolumeBounds*>(&(fullPhiVol->volumeBounds()));
381 if (!cyl) {
382 ATH_MSG_WARNING("dynamic_cast<const CylinderVolumeBounds*> failed ... trying to continue loop");
383 continue;
384 }
385 double rmin = cyl->innerRadius();
386 double rmax = cyl->outerRadius();
387
388 for (unsigned int iphi = 0; iphi < phiSteps.size(); ++iphi) {
389 // reference position
390 double phiRef = 0.5 * phiSteps[iphi];
391 if (iphi < phiSteps.size() - 1)
392 phiRef += 0.5 * phiSteps[iphi + 1];
393 else
394 phiRef += 0.5 * phiSteps[0] + M_PI;
395 // setting the position in the phi sector
396 const Amg::Vector3D ngp{cyl->mediumRadius() * std::cos(phiRef),cyl->mediumRadius() * std::sin(phiRef),0.};
397
398 volOrder.emplace_back(fullPhiVol, ngp);
399
400 // push back volume position to avoid another loop
401 volPos.emplace_back(std::pair<double, int>(ngp.phi(), 0),
402 std::pair<double, double>(rmin, rmax));
403 }
404 }
405 // all volumes in arrays : build bin utilities
406
407 // adjust phiSteps : upper bound equal the lower
408 if (phiSteps.size() > 1) {
409 if (phiSteps.back() > M_PI)
410 phiSteps.erase(phiSteps.end() - 1);
411 else
412 phiSteps.erase(phiSteps.begin());
413 }
414
415 // phi binning
416 std::vector<std::vector<std::pair<int, float>>> hSteps(phiSteps.size());
417 std::vector<float> phiRef(phiSteps.size());
418 for (unsigned int ip = 0; ip < phiSteps.size() - 1; ++ip)
419 phiRef[ip] = 0.5 * (phiSteps[ip] + phiSteps[ip + 1]);
420 phiRef.back() = 0.5 * (phiSteps.back() + phiSteps.front());
421 phiRef.back() += (phiRef.back() > 0) ? -M_PI : M_PI;
422
423 auto phiBinUtil = BinUtility(phiSteps, closed, binPhi);
424
425 // H binning
426
427 for (unsigned int i = 0; i < volPos.size(); ++i) {
428
429 // double phi = volPos[i].first.first;
430 int type = volPos[i].first.second;
431 double rmin = volPos[i].second.first;
432 double rmax = volPos[i].second.second;
433 int tmin = (type != 1 && type != 3) ? 0 : 1;
434 int tmax = (type < 2) ? 0 : 1;
435
436 int phibin = phiBinUtil.bin(volOrder[i].second);
437
438 if (!hSteps[phibin].empty()) {
439 std::vector<std::pair<int, float>>::iterator iter =
440 hSteps[phibin].begin();
441 bool known = false;
442 while (iter != hSteps[phibin].end()) {
443 if (std::abs(rmin - (*iter).second) < tol) {
444 known = true;
445 break;
446 }
447 if (rmin < (*iter).second) {
448 hSteps[phibin].insert(iter, std::pair<int, float>(tmin, rmin));
449 known = true;
450 break;
451 }
452 ++iter;
453 }
454 if (!known)
455 hSteps[phibin].emplace_back(tmin, rmin);
456 iter = hSteps[phibin].begin();
457 known = false;
458 while (iter != hSteps[phibin].end()) {
459 if (std::abs(rmax - (*iter).second) < tol) {
460 known = true;
461 break;
462 }
463 if (rmax < (*iter).second) {
464 hSteps[phibin].insert(iter, std::pair<int, float>(tmax, rmax));
465 known = true;
466 break;
467 }
468 ++iter;
469 }
470 if (!known)
471 hSteps[phibin].emplace_back(tmax, rmax);
472 } else {
473 hSteps[phibin].emplace_back(tmin, rmin);
474 hSteps[phibin].emplace_back(tmax, rmax);
475 }
476 }
477 // verify size of the array
478 // 2dim array
479 // steering bin utility in phi
480 auto hUtil = std::vector<BinUtility>(phiSteps.size());
481
482 for (unsigned int ih = 0; ih < phiSteps.size(); ++ih) {
483 (hUtil)[ih] = BinUtility(phiRef[ih], hSteps[ih]);
484 }
485
486 return std::make_unique<BinnedArray1D1D<TrackingVolume>>(volOrder, phiBinUtil, hUtil);
487 }
488
489 ATH_MSG_VERBOSE("Create 2dim VolumeArray of of "<< vols.size()
490 << " Volumes (with CylinderVolumeBounds) with PhiR-binning. ");
491
492 std::vector<float> rSteps;
493 double phiSector = M_PI;
494 std::vector<std::pair<double, std::pair<double, double>>> volPos;
495
496 for (const auto& vol : vols) {
497 const auto *cyl =dynamic_cast<const CylinderVolumeBounds*>(&(vol->volumeBounds()));
498 if (!cyl) {
499 ATH_MSG_WARNING("dynamic_cast<const CylinderVolumeBounds*> failed ... trying to continue loop");
500 continue;
501 }
502 double rmin = cyl->innerRadius();
503 double rmax = cyl->outerRadius();
504 double dphi = cyl->halfPhiSector();
505 if (phiSector > 0. && std::abs(dphi - phiSector) > 0.001)
506 phiSector = phiSector < M_PI ? -1. : dphi;
507
508
509 const Amg::Vector3D ngp{vol->transform() * (cyl->mediumRadius()* Amg::Vector3D::UnitX())};
510 volOrder.emplace_back(vol, ngp);
511
512 // push back volume position to avoid another loop
513 volPos.emplace_back(cyl->mediumRadius(), std::make_pair(ngp.phi(), dphi));
514 // r binning
515 if (!rSteps.empty()) {
516 std::vector<float>::iterator iter = rSteps.begin();
517 bool known = false;
518 while (iter != rSteps.end()) {
519 if (std::abs(rmin - (*iter)) < tol) {
520 known = true;
521 break;
522 }
523 if (rmin < (*iter)) {
524 rSteps.insert(iter, rmin);
525 known = true;
526 break;
527 }
528 ++iter;
529 }
530 if (!known)
531 rSteps.push_back(rmin);
532 iter = rSteps.begin();
533 known = false;
534 while (iter != rSteps.end()) {
535 if (std::abs(rmax - (*iter)) < tol) {
536 known = true;
537 break;
538 }
539 if (rmax < (*iter)) {
540 rSteps.insert(iter, rmax);
541 known = true;
542 break;
543 }
544 ++iter;
545 }
546 if (!known)
547 rSteps.push_back(rmax);
548 } else {
549 rSteps.push_back(rmin);
550 rSteps.push_back(rmax);
551 }
552 }
553
554 if (phiSector > 0.) { // overall equidistant binning
555
556 const int rStepsSizem1 = rSteps.size() - 1;
557 std::vector<double> phi(rStepsSizem1, M_PI);
558 std::vector<int> phiSect(rStepsSizem1,int(M_PI / phiSector));
559
560 // simplify if possible
561 if (rSteps.size() == 1) {
562 return cylinderVolumesArrayInPhi(vols, navtype);
563 }
564 if (phiSector == M_PI) {
565 return cylinderVolumesArrayInR(vols, navtype);
566 }
567 // 2dim array
568 auto rBinUtil = BinUtility(rSteps, open, binR);
569 auto phiUtil = std::vector<BinUtility>(rSteps.size() - 1);
570 for (unsigned int ip = 0; ip < phiUtil.size(); ++ip) {
571 (phiUtil)[ip] =BinUtility(phiSect[ip], closed, binPhi);
572 }
573 return std::make_unique<BinnedArray1D1D<TrackingVolume>>(volOrder, rBinUtil, phiUtil);
574 }
575
576 // R binning : steering binUtility
577 auto binGenR = BinUtility(rSteps, open, binR);
578
579 // phi binning
580 std::vector<std::vector<float>> phiSteps(rSteps.size() - 1);
581
582 for (unsigned int i = 0; i < volPos.size(); ++i) {
583
584 double phi = volPos[i].second.first;
585 double dphi = volPos[i].second.second;
586
587 int binr = binGenR.bin(volOrder[i].second);
588
589 float phi1 = phi - dphi;
590 float phi2 = phi + dphi;
591 if (phi1 < 0)
592 phi1 += 2 * M_PI;
593 if (phi2 < 0)
594 phi2 += 2 * M_PI;
595
596 if (!phiSteps[binr].empty()) {
597 std::vector<float>::iterator iter = phiSteps[binr].begin();
598 bool known = false;
599 while (iter != phiSteps[binr].end()) {
600 if (std::abs(phi1 - (*iter)) < tol) {
601 known = true;
602 break;
603 }
604 if (phi1 < (*iter)) {
605 phiSteps[binr].insert(iter, phi1);
606 known = true;
607 break;
608 }
609 ++iter;
610 }
611 if (!known)
612 phiSteps[binr].push_back(phi1);
613 iter = phiSteps[binr].begin();
614 known = false;
615 while (iter != phiSteps[binr].end()) {
616 if (std::abs(phi2 - (*iter)) < tol) {
617 known = true;
618 break;
619 }
620 if (phi2 < (*iter)) {
621 phiSteps[binr].insert(iter, phi2);
622 known = true;
623 break;
624 }
625 ++iter;
626 }
627 if (!known)
628 phiSteps[binr].push_back(phi2);
629 } else {
630 phiSteps[binr].push_back(std::fmin(phi1, phi2));
631 phiSteps[binr].push_back(std::fmax(phi1, phi2));
632 }
633 }
634
635 // 2dim array
636 auto phiUtil = std::vector<BinUtility>(phiSteps.size());
637
638 for (unsigned int ip = 0; ip < phiSteps.size(); ++ip) {
639 (phiUtil)[ip] = BinUtility(phiSteps[ip], closed, binPhi);
640 }
641
642 return std::make_unique<BinnedArray1D1D<TrackingVolume>>(volOrder, binGenR, phiUtil);
643}
644
645std::unique_ptr<TrackingVolumeArray>
647 bool navtype) const {
648
649 ATH_MSG_VERBOSE("Create 2dim VolumeArray of of "<< vols.size()
650 << " Volumes (with CylinderVolumeBounds) with PhiZ-binning. ");
651
652 double tol = 0.001;
653 // the vector needed for the BinnedArray
654 std::vector<TrackingVolumeOrderPosition> volOrder;
655
656 std::vector<float> zSteps;
657
658 double phiSector = M_PI;
659 std::vector<std::pair<float, std::pair<float, float>>> volPos;
660
661 for (const VolumePtr& vol : vols) {
662 const auto *cyl = dynamic_cast<const CylinderVolumeBounds*>(&(vol->volumeBounds()));
663 const auto *bcyl = dynamic_cast<const BevelledCylinderVolumeBounds*>(&(vol->volumeBounds()));
664 double zmin{0.};
665 double zmax{0.};
666 double dphi{0.};
667 double mRad{0.};
668 if (cyl) {
669 zmin = vol->center().z() - cyl->halflengthZ();
670 zmax = vol->center().z() + cyl->halflengthZ();
671 dphi = cyl->halfPhiSector();
672 mRad = cyl->mediumRadius();
673 } else if (bcyl) {
674 zmin = vol->center().z() - bcyl->halflengthZ();
675 zmax = vol->center().z() + bcyl->halflengthZ();
676 dphi = bcyl->halfPhiSector();
677 mRad = bcyl->mediumRadius();
678 } else {
679 ATH_MSG_ERROR("volume not cylinder nor bevelled cylinder ");
680 return nullptr;
681 }
682
683 if (phiSector > 0. && std::abs(dphi - phiSector) > 0.001)
684 phiSector = phiSector < M_PI ? -1. : dphi;
685
686 // push back the volume order position
687 const Amg::Vector3D ngp{vol->transform() * (mRad * Amg::Vector3D::UnitX())};
688
689 volOrder.emplace_back(vol, ngp);
690 // push back volume position to avoid another loop
691 volPos.emplace_back(vol->center().z(), std::make_pair(ngp.phi(), dphi));
692 // z binning
693 if (!zSteps.empty()) {
694 std::vector<float>::iterator iter = zSteps.begin();
695 bool known = false;
696 while (iter != zSteps.end()) {
697 if (std::abs(zmin - (*iter)) < tol) {
698 known = true;
699 break;
700 }
701 if (zmin < (*iter)) {
702 zSteps.insert(iter, zmin);
703 known = true;
704 break;
705 }
706 ++iter;
707 }
708 if (!known)
709 zSteps.push_back(zmin);
710 iter = zSteps.begin();
711 known = false;
712 while (iter != zSteps.end()) {
713 if (std::abs(zmax - (*iter)) < tol) {
714 known = true;
715 break;
716 }
717 if (zmax < (*iter)) {
718 zSteps.insert(iter, zmax);
719 known = true;
720 break;
721 }
722 ++iter;
723 }
724 if (!known)
725 zSteps.push_back(zmax);
726 } else {
727 zSteps.push_back(zmin);
728 zSteps.push_back(zmax);
729 }
730 }
731
732 if (phiSector > 0.) { // overall equidistant binning
733
734 const int zStepsSizem1 = zSteps.size() - 1;
735 std::vector<double> phi(zStepsSizem1, M_PI);
736 std::vector<int> phiSect(zStepsSizem1,int(M_PI / phiSector));
737
738 // simplify if possible
739 if (phiSector == M_PI) {
740 return cylinderVolumesArrayInZ(vols, navtype);
741 }
742 if (zSteps.size() == 2) {
743 return cylinderVolumesArrayInPhi(vols, navtype);
744 }
745 // 2dim array
746 auto binGenZPhi = BinUtility(zSteps, open, binZ);
747 binGenZPhi += BinUtility(phiSector, -M_PI, M_PI, closed, binPhi);
748 return std::make_unique<BinnedArray2D<TrackingVolume>>(volOrder, binGenZPhi);
749 }
750
751 // steering binUtility in binZ
752 auto binGenZ = BinUtility(zSteps, open, binZ);
753
754 // phi binning - steering binUtility in binZ
755 std::vector<std::vector<float>> phiSteps(zSteps.size() - 1);
756
757 for (unsigned int i = 0; i < volPos.size(); ++i) {
758
759 float phi = volPos[i].second.first;
760 float dphi = volPos[i].second.second;
761
762 int binZ = binGenZ.bin(volOrder[i].second);
763
764 float phi1 = phi - dphi;
765 float phi2 = phi + dphi;
766 if (phi1 < 0)
767 phi1 += 2 * M_PI;
768 if (phi2 < 0)
769 phi2 += 2 * M_PI;
770
771 if (!phiSteps[binZ].empty()) {
772 std::vector<float>::iterator iter = phiSteps[binZ].begin();
773 bool known = false;
774 while (iter != phiSteps[binZ].end()) {
775 if (std::abs(phi1 - (*iter)) < tol) {
776 known = true;
777 break;
778 }
779 if (phi1 < (*iter)) {
780 phiSteps[binZ].insert(iter, phi1);
781 known = true;
782 break;
783 }
784 ++iter;
785 }
786 if (!known)
787 phiSteps[binZ].push_back(phi1);
788 iter = phiSteps[binZ].begin();
789 known = false;
790 while (iter != phiSteps[binZ].end()) {
791 if (std::abs(phi2 - (*iter)) < tol) {
792 known = true;
793 break;
794 }
795 if (phi2 < (*iter)) {
796 phiSteps[binZ].insert(iter, phi2);
797 known = true;
798 break;
799 }
800 ++iter;
801 }
802 if (!known)
803 phiSteps[binZ].push_back(phi2);
804 } else {
805 phiSteps[binZ].push_back(std::fmin(phi1, phi2));
806 phiSteps[binZ].push_back(std::fmax(phi1, phi2));
807 // phiSectors[binZ] = dphi ;
808 }
809 }
810
811 // 2dim array: construct from two 1D boundaries
812 auto phiUtil = std::vector<BinUtility>(phiSteps.size());
813
814 for (unsigned int ip = 0; ip < phiSteps.size(); ++ip) {
815 phiUtil[ip] = BinUtility(phiSteps[ip], closed, binPhi);
816 }
817
818 return std::make_unique<BinnedArray1D1D<TrackingVolume>>(volOrder, binGenZ, phiUtil);
819}
820
821
822std::unique_ptr<TrackingVolumeArray>
823 TrackingVolumeArrayCreator::cuboidVolumesArrayNav(const std::vector<VolumePtr>& vols,
824 const BinUtility& binUtil) const {
825 // the vector needed for the BinnedArray
826 std::vector<VolumePtr> volOrder;
827 // loop over volumes and fill primaries
828 auto volIter = vols.begin();
829 for (; volIter != vols.end(); ++volIter) {
830 const auto *currentCubBounds = dynamic_cast<const CuboidVolumeBounds*>(&((*volIter)->volumeBounds()));
831 if (!currentCubBounds) {
832 ATH_MSG_ERROR("Given TrackingVolume to TrackingVolumeArrayCreator didn't "
833 "match specified shape: return 0");
834 return nullptr;
835 }
836 volOrder.push_back(*volIter);
837 }
838 if (!volOrder.empty()) {
839 Amg::Transform3D navTransform = Amg::Transform3D::Identity();
840 return std::make_unique<NavBinnedArray1D<TrackingVolume>>(volOrder, binUtil, navTransform);
841 }
842 ATH_MSG_ERROR("No TrackingVolumes provided to the TrackingVolumeArrayCreator: return 0");
843 return nullptr;
844}
845
846std::unique_ptr<TrackingVolumeArray>
847 TrackingVolumeArrayCreator::trapezoidVolumesArrayNav(const std::vector<VolumePtr>& vols, const BinUtility& binUtil) const {
848 // the vector needed for the BinnedArray
849 std::vector<VolumePtr> volOrder;
850 // loop over volumes and fill primaries
851 auto volIter = vols.begin();
852 for (; volIter != vols.end(); ++volIter) {
853 const auto *currentTrdBounds = dynamic_cast<const TrapezoidVolumeBounds*>(&((*volIter)->volumeBounds()));
854 if (!currentTrdBounds) {
855 ATH_MSG_ERROR("Given TrackingVolume to TrackingVolumeArrayCreator didn't "
856 "match specified shape: return 0");
857 return nullptr;
858 }
859 // push back the volume order position
860 volOrder.push_back(*volIter);
861 }
862 if (!volOrder.empty()) {
863 Amg::Transform3D navTransform = Amg::Transform3D::Identity();
864 return std::make_unique<NavBinnedArray1D<TrackingVolume>>(volOrder, binUtil, navTransform);
865 }
866 ATH_MSG_ERROR("No TrackingVolumes provided to the TrackingVolumeArrayCreator: return 0");
867 return nullptr;
868}
869
870std::unique_ptr<TrackingVolumeArray>
871 TrackingVolumeArrayCreator::doubleTrapezoidVolumesArrayNav(const std::vector<VolumePtr>& vols, const BinUtility& binUtil) const {
872 // the vector needed for the BinnedArray
873 std::vector<VolumePtr> volOrder;
874 // loop over volumes and fill primaries
875 auto volIter = vols.begin();
876 for (; volIter != vols.end(); ++volIter) {
877 const auto *currentDTrdBounds =dynamic_cast<const DoubleTrapezoidVolumeBounds*>(&((*volIter)->volumeBounds()));
878 if (!currentDTrdBounds) {
879 ATH_MSG_ERROR("Given TrackingVolume to TrackingVolumeArrayCreator didn't "
880 "match specified shape: return 0");
881 return nullptr;
882 }
883 // push back the volume order position
884 volOrder.push_back(*volIter);
885 }
886 if (!volOrder.empty()) {
887 Amg::Transform3D navTransform = Amg::Transform3D::Identity();
888 return std::make_unique<NavBinnedArray1D<TrackingVolume>>(volOrder, binUtil, navTransform);
889 }
891 "No TrackingVolumes provided to the TrackingVolumeArrayCreator: return 0");
892 return nullptr;
893}
894
895}
#define M_PI
#define ATH_MSG_ERROR(x)
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
static const Attributes_t empty
AthAlgTool(const std::string &type, const std::string &name, const IInterface *parent)
Constructor with parameters:
Bounds for a cylindrical Volume, the decomposeToSurfaces method creates a vector of up to 6 surfaces:
A generic symmetric BinUtility, for fully symmetric binning in terms of binning grid and binning type...
Definition BinUtility.h:39
Bounds for a cubical Volume, the decomposeToSurfaces method creates a vector of 6 surfaces:
Bounds for a cylindrical Volume, the decomposeToSurfaces method creates a vector of up to 6 surfaces:
double mediumRadius() const
This method returns the medium radius.
double innerRadius() const
This method returns the inner radius.
double halflengthZ() const
This method returns the halflengthZ.
double outerRadius() const
This method returns the outer radius.
Bounds for a double trapezoidal shaped Volume, the decomposeToSurfaces method creates a vector of 8 s...
std::shared_ptr< TrackingVolume > VolumePtr
std::unique_ptr< TrackingVolumeArray > cuboidVolumesArrayNav(const std::vector< VolumePtr > &vols, const Trk::BinUtility &binUtil) const override
TrackingVolumeArrayCreator interface method - create a cuboid volume array - linked to detached track...
std::unique_ptr< TrackingVolumeArray > trapezoidVolumesArrayNav(const std::vector< VolumePtr > &vols, const Trk::BinUtility &binUtil) const override
TrackingVolumeArrayCreator interface method - create a trapezoid volume array - linked to detached tr...
std::unique_ptr< TrackingVolumeArray > cylinderVolumesArrayInPhi(const std::vector< VolumePtr > &vols, bool navigationtype=false) const override
TrackingVolumeArrayCreator interface method - create a R-binned cylindrical volume array.
std::unique_ptr< TrackingVolumeArray > cylinderVolumesArrayInR(const std::vector< TrackingVolume * > &vols, bool navigationtype=false) const override
Extra interface methods for compatibility.
TrackingVolumeArrayCreator(const std::string &, const std::string &, const IInterface *)
Constructor.
std::unique_ptr< TrackingVolumeArray > cylinderVolumesArrayInZ(const std::vector< TrackingVolume * > &vols, bool navigationtype=false) const override
std::unique_ptr< TrackingVolumeArray > doubleTrapezoidVolumesArrayNav(const std::vector< VolumePtr > &vols, const Trk::BinUtility &binUtil) const override
TrackingVolumeArrayCreator interface method - create a doubleTrapezoid volume array - linked to detac...
std::unique_ptr< TrackingVolumeArray > cylinderVolumesArrayInPhiZ(const std::vector< TrackingVolume * > &vols, bool navigationtype=false) const override
std::unique_ptr< TrackingVolumeArray > cylinderVolumesArrayInPhiR(const std::vector< TrackingVolume * > &vols, bool navigationtype=false) const override
Full Volume description used in Tracking, it inherits from Volume to get the geometrical structure,...
Bounds for a trapezoidal shaped Volume, the decomposeToSurfaces method creates a vector of 6 surfaces...
Eigen::Affine3d Transform3D
Eigen::Matrix< double, 3, 1 > Vector3D
Ensure that the ATLAS eigen extensions are properly loaded.
const auto do_not_delete
@ open
Definition BinningType.h:40
@ closed
Definition BinningType.h:41
@ phi
Definition ParamDefs.h:75
@ binR
Definition BinningType.h:50
@ binPhi
Definition BinningType.h:51
@ binZ
Definition BinningType.h:49
ElementLink_p1< typename GenerateELinkIndexType_p1< typename LINK::index_type >::type > type