ATLAS Offline Software
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 
29 namespace {
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 
49 namespace 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 
62 std::unique_ptr<TrackingVolumeArray> TrackingVolumeArrayCreator::cylinderVolumesArrayInR(const std::vector<TrackingVolume*>& vols,
63  bool navtype) const {
64  return cylinderVolumesArrayInR(translateToShared(vols, navtype), navtype);
65 }
66 
67 std::unique_ptr<TrackingVolumeArray> TrackingVolumeArrayCreator::cylinderVolumesArrayInZ(const std::vector<TrackingVolume*>& vols,
68  bool navtype) const {
69  return cylinderVolumesArrayInZ(translateToShared(vols, navtype), navtype);
70 }
71 
72 std::unique_ptr<TrackingVolumeArray> TrackingVolumeArrayCreator::cylinderVolumesArrayInPhiR(const std::vector<TrackingVolume*>& vols,
73  bool navtype) const {
74  return cylinderVolumesArrayInPhiR(translateToShared(vols, navtype), navtype);
75 }
76 std::unique_ptr<TrackingVolumeArray> TrackingVolumeArrayCreator::cylinderVolumesArrayInPhiZ(const std::vector<TrackingVolume*>& vols,
77  bool navtype) const {
78  return cylinderVolumesArrayInPhiZ(translateToShared(vols, navtype), navtype);
79 }
80 
81 std::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 
156 std::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 
231 std::unique_ptr<TrackingVolumeArray>
232  TrackingVolumeArrayCreator::cylinderVolumesArrayInPhi(const std::vector<VolumePtr>& vols,
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 
266 std::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()) {
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()) {
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 
648 std::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()) {
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 
825 std::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 
849 std::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 
873 std::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 }
xAOD::iterator
JetConstituentVector::iterator iterator
Definition: JetConstituentVector.cxx:68
createLinkingScheme.iter
iter
Definition: createLinkingScheme.py:62
Trk::TrackingVolumeArrayCreator::trapezoidVolumesArrayNav
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...
Definition: TrackingVolumeArrayCreator.cxx:850
Trk::TrackingVolumeArrayCreator::cuboidVolumesArrayNav
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...
Definition: TrackingVolumeArrayCreator.cxx:826
Trk::BevelledCylinderVolumeBounds
Definition: BevelledCylinderVolumeBounds.h:100
Trk::CuboidVolumeBounds
Definition: CuboidVolumeBounds.h:52
Trk::binZ
@ binZ
Definition: BinningType.h:49
Trk::TrackingVolumeArrayCreator::doubleTrapezoidVolumesArrayNav
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...
Definition: TrackingVolumeArrayCreator.cxx:874
PixelAthClusterMonAlgCfg.zmin
zmin
Definition: PixelAthClusterMonAlgCfg.py:169
SharedDoNoDelete.h
BinnedArray2D.h
Trk::TrackingVolumeArrayCreator::TrackingVolumeArrayCreator
TrackingVolumeArrayCreator(const std::string &, const std::string &, const IInterface *)
Constructor.
Definition: TrackingVolumeArrayCreator.cxx:51
BinUtility.h
python.SystemOfUnits.second
float second
Definition: SystemOfUnits.py:135
M_PI
#define M_PI
Definition: ActiveFraction.h:11
TrackingVolumeArrayCreator.h
Trk::closed
@ closed
Definition: BinningType.h:41
BinnedArray1D1D.h
NavBinnedArray1D.h
read_hist_ntuple.t
t
Definition: read_hist_ntuple.py:5
drawFromPickle.cos
cos
Definition: drawFromPickle.py:36
ATH_MSG_VERBOSE
#define ATH_MSG_VERBOSE(x)
Definition: AthMsgStreamMacros.h:28
dbg::ptr
void * ptr(T *p)
Definition: SGImplSvc.cxx:74
python.CaloAddPedShiftConfig.type
type
Definition: CaloAddPedShiftConfig.py:42
TrapezoidVolumeBounds.h
Trk::TrackingVolumeArrayCreator::~TrackingVolumeArrayCreator
virtual ~TrackingVolumeArrayCreator()
Destructor.
mergePhysValFiles.end
end
Definition: DataQuality/DataQualityUtils/scripts/mergePhysValFiles.py:92
BinnedArray1D.h
GeometryStatics.h
CylinderVolumeBounds.h
python.utils.AtlRunQueryDQUtils.p
p
Definition: AtlRunQueryDQUtils.py:209
Trk::ITrackingVolumeArrayCreator::VolumePtr
std::shared_ptr< TrackingVolume > VolumePtr
Definition: ITrackingVolumeArrayCreator.h:47
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
lumiFormat.i
int i
Definition: lumiFormat.py:85
beamspotman.n
n
Definition: beamspotman.py:727
BevelledCylinderVolumeBounds.h
Amg::Transform3D
Eigen::Affine3d Transform3D
Definition: GeoPrimitives.h:46
Trk::CylinderVolumeBounds::halflengthZ
double halflengthZ() const
This method returns the halflengthZ.
Definition: CylinderVolumeBounds.h:207
PixelAthClusterMonAlgCfg.zmax
zmax
Definition: PixelAthClusterMonAlgCfg.py:169
find_tgc_unfilled_channelids.ip
ip
Definition: find_tgc_unfilled_channelids.py:3
Trk::BinUtility
Definition: BinUtility.h:39
Trk::CylinderVolumeBounds
Definition: CylinderVolumeBounds.h:70
Trk
Ensure that the ATLAS eigen extensions are properly loaded.
Definition: FakeTrackBuilder.h:9
DoubleTrapezoidVolumeBounds.h
Trk::TrackingVolumeArrayCreator::cylinderVolumesArrayInPhi
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.
Definition: TrackingVolumeArrayCreator.cxx:232
Trk::CylinderVolumeBounds::outerRadius
double outerRadius() const
This method returns the outer radius.
Definition: CylinderVolumeBounds.h:191
Trk::TrapezoidVolumeBounds
Definition: TrapezoidVolumeBounds.h:57
Trk::TrackingVolumeArrayCreator::cylinderVolumesArrayInR
std::unique_ptr< TrackingVolumeArray > cylinderVolumesArrayInR(const std::vector< TrackingVolume * > &vols, bool navigationtype=false) const override
Extra interface methods for compatibility.
Definition: TrackingVolumeArrayCreator.cxx:62
Amg::Vector3D
Eigen::Matrix< double, 3, 1 > Vector3D
Definition: GeoPrimitives.h:47
Trk::open
@ open
Definition: BinningType.h:40
Trk::binR
@ binR
Definition: BinningType.h:50
Trk::TrackingVolumeArrayCreator::cylinderVolumesArrayInPhiZ
std::unique_ptr< TrackingVolumeArray > cylinderVolumesArrayInPhiZ(const std::vector< TrackingVolume * > &vols, bool navigationtype=false) const override
Definition: TrackingVolumeArrayCreator.cxx:76
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
Trk::CylinderVolumeBounds::innerRadius
double innerRadius() const
This method returns the inner radius.
Definition: CylinderVolumeBounds.h:187
Trk::TrackingVolumeArrayCreator::cylinderVolumesArrayInZ
std::unique_ptr< TrackingVolumeArray > cylinderVolumesArrayInZ(const std::vector< TrackingVolume * > &vols, bool navigationtype=false) const override
Definition: TrackingVolumeArrayCreator.cxx:67
GeoPrimitivesHelpers.h
known
Definition: TrigBStoxAODTool.cxx:107
Trk::DoubleTrapezoidVolumeBounds
Definition: DoubleTrapezoidVolumeBounds.h:66
Trk::phi
@ phi
Definition: ParamDefs.h:75
drawFromPickle.sin
sin
Definition: drawFromPickle.py:36
AthAlgTool
Definition: AthAlgTool.h:26
Trk::TrackingVolume
Definition: TrackingVolume.h:119
LArCellBinning.phiSteps
dictionary phiSteps
Definition: LArCellBinning.py:37
CuboidVolumeBounds.h
PUfitVar::nPhiBins
constexpr std::size_t nPhiBins
Definition: GepMETPufitAlg.cxx:20
Trk::CylinderVolumeBounds::mediumRadius
double mediumRadius() const
This method returns the medium radius.
Definition: CylinderVolumeBounds.h:195
Trk::TrackingVolumeArrayCreator::cylinderVolumesArrayInPhiR
std::unique_ptr< TrackingVolumeArray > cylinderVolumesArrayInPhiR(const std::vector< TrackingVolume * > &vols, bool navigationtype=false) const override
Definition: TrackingVolumeArrayCreator.cxx:72
Trk::binPhi
@ binPhi
Definition: BinningType.h:51