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