ATLAS Offline Software
TrackingVolumeArrayCreator.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2024 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 
25 // Amg
27 
28 namespace {
30  inline std::vector<VolumePtr> translateToShared(const std::vector<Trk::TrackingVolume*>& inVols,
31  bool no_deletePtr) {
32  std::vector<VolumePtr> outVec{};
33  outVec.reserve(inVols.size());
34  for (Trk::TrackingVolume* vol : inVols) {
35  if(!no_deletePtr) {
36  outVec.emplace_back(vol);
37  } else {
38  outVec.emplace_back(vol, Trk::do_not_delete<Trk::TrackingVolume>);
39  }
40  }
41  return outVec;
42  }
43 }
44 
45 
46 namespace Trk{
47 // constructor
49  const std::string& n,
50  const IInterface* p)
51  : AthAlgTool(t, n, p)
52 {
53  declareInterface<ITrackingVolumeArrayCreator>(this);
54 }
55 
56 // destructor
58 
60  bool navtype) const {
61  return cylinderVolumesArrayInR(translateToShared(vols, navtype), navtype).release();
62 }
63 std::unique_ptr<TrackingVolumeArray> TrackingVolumeArrayCreator::cylinderVolumesArrayInR(const std::vector<VolumePtr>& vols,
64  bool navtype) const {
65 
66 
67  ATH_MSG_VERBOSE("Create VolumeArray of "<< vols.size() << " Volumes (with CylinderVolumeBounds) with R-binning. ");
68 
69  // check for compatibility - needs r-sorting first
70  double lastZmin{0.}, lastZmax{0.}, lastOuterRadius{0.};
71 
72  // the vector of doubles for identification
73  std::vector<float> boundaries;
74  boundaries.reserve(vols.size() + 1);
75 
76  // the vector needed for the BinnedArray
77  std::vector<TrackingVolumeOrderPosition> volOrder;
78  // loop over volumes and fill primaries
79  auto volIter = vols.begin();
80  for (unsigned int ivol = 0; volIter != vols.end(); ++volIter, ++ivol) {
81  const CylinderVolumeBounds* currentCylBounds = nullptr;
82  if (*volIter) currentCylBounds = dynamic_cast<const CylinderVolumeBounds*>(&((*volIter)->volumeBounds()));
83  if (!currentCylBounds) {
84  ATH_MSG_ERROR("Given TrackingVolume doesn't exist or is not of shape "
85  "'CylinderVolumeBounds': return 0");
86  return nullptr;
87  }
88  // current rmin/rmax
89  double currentRmin = currentCylBounds->innerRadius();
90  double currentRmax = currentCylBounds->outerRadius();
91  if (!ivol)
92  boundaries.push_back(currentRmin);
93  boundaries.push_back(currentRmax);
94 
95  // compatibility checks
96  double currentZmin = (*volIter)->center().z() - currentCylBounds->halflengthZ();
97  double currentZmax = (*volIter)->center().z() + currentCylBounds->halflengthZ();
98 
99  // check for compatibility of the new volume - not for navigation type
100  if (ivol && !navtype) {
101  // longitudinal clinch
102  if (std::abs(currentZmin - lastZmin) > 0.1 || std::abs(currentZmax - lastZmax) > 0.1) {
103  ATH_MSG_ERROR("Given TrackingVolume(s) do not extend in z to the same point (required) : return 0");
104  ATH_MSG_VERBOSE("Information : lastZmin / lastZmin = "<< lastZmin << " / " << currentZmin);
105  ATH_MSG_VERBOSE(" lastZmax / currentZmax = "<< lastZmax << " / " << currentZmax);
106  return nullptr;
107  }
108  // radial clinch
109  if (std::abs(currentRmin - lastOuterRadius) > 0.1) {
110  ATH_MSG_ERROR("Given TrackingVolume(s) are not wrapping, neither inside-out, nor v.v. : return 0");
111  ATH_MSG_VERBOSE("Information : currentRmin / lastOuterRadius = "<< currentRmin << " / " << lastOuterRadius);
112  return nullptr;
113  }
114  }
115  // register for next round
116  lastZmin = currentZmin;
117  lastZmax = currentZmax;
118  lastOuterRadius = currentRmax;
119  // output
120  ATH_MSG_VERBOSE("Adding Volume '" << (*volIter)->volumeName() << "' to Array");
121 
122  volOrder.emplace_back((*volIter), currentCylBounds->mediumRadius() * Amg::Vector3D::UnitX());
123  // push back the volume order position
124 
125  }
126  if (!volOrder.empty()) {
127  auto volBinUtilR = std::make_unique<BinUtility>(boundaries, open, binR);
128  ATH_MSG_VERBOSE("Return created Array. ");
129  return std::make_unique<BinnedArray1D<TrackingVolume>>(volOrder, volBinUtilR.release());
130  }
131  ATH_MSG_ERROR("No TrackingVolumes provided to the TrackingVolumeArrayCreator: return 0");
132  return nullptr;
133 }
134 
135 
137  bool navtype) const {
138  return cylinderVolumesArrayInZ(translateToShared(vols, navtype), navtype).release();
139  }
140 
141 std::unique_ptr<TrackingVolumeArray>
142  TrackingVolumeArrayCreator::cylinderVolumesArrayInZ(const std::vector<VolumePtr>& vols,
143  bool navtype) const {
144  ATH_MSG_VERBOSE("Create VolumeArray of "
145  << vols.size()
146  << " Volumes (with CylinderVolumeBounds) with Z-binning. ");
147 
148  // for compatibility checks
149  double lastRmin{0.}, lastRmax{0.}, lastZmax{0.};
150 
151  // the vector of doubles for identification
152  std::vector<float> boundaries;
153  boundaries.reserve(vols.size() + 1);
154 
155  // the vector needed for the BinnedArray
156  std::vector<TrackingVolumeOrderPosition> volOrder;
157  // loop over volumes and fill primaries
158  auto volIter = vols.begin();
159  for (unsigned int ivol = 0; volIter != vols.end(); ++volIter, ++ivol) {
160  const CylinderVolumeBounds* currentCylBounds = nullptr;
161  if (*volIter)currentCylBounds = dynamic_cast<const CylinderVolumeBounds*>( &((*volIter)->volumeBounds()));
162  if (!currentCylBounds) {
163  ATH_MSG_ERROR("Given TrackingVolume doesn't exist or is not of shape 'CylinderVolumeBounds': return 0");
164  return nullptr;
165  }
166  //
167  const Amg::Vector3D& volCenter = (*volIter)->center();
168  double halflengthZ = currentCylBounds->halflengthZ();
169  // get the numbers
170  double currentZmin = volCenter.z() - halflengthZ;
171  double currentZmax = volCenter.z() + halflengthZ;
172  if (!ivol) boundaries.push_back(currentZmin);
173  boundaries.push_back(currentZmax);
174 
175  // consistency checks
176  double currentRmin = currentCylBounds->innerRadius();
177  double currentRmax = currentCylBounds->outerRadius();
178 
179  // compatibility check - not for navtype
180  if (ivol && !navtype) {
181  // first the radial check
182  if (std::abs(lastRmin - currentRmin) > 0.1 || std::abs(lastRmax - currentRmax) > 0.1) {
183  ATH_MSG_ERROR("Given TrackingVolume(s) do not have same radial extends (required): return 0");
184  ATH_MSG_VERBOSE("Information : lastRmin / currentRmin = " << lastRmin << " / " << currentRmin);
185  ATH_MSG_VERBOSE(" lastRmax / currentRmax = " << lastRmax << " / " << currentRmax);
186  return nullptr;
187  }
188  // then let's see whether they leave gaps in z
189  if (std::abs(lastZmax - currentZmin) > 0.1) {
190  ATH_MSG_ERROR("Given TrackingVolume(s) are not attaching in z (required) : return 0");
191  return nullptr;
192  }
193  }
194  // for the next round
195  lastRmin = currentRmin;
196  lastRmax = currentRmax;
197  lastZmax = currentZmax;
198  // output
199  ATH_MSG_VERBOSE("Adding Volume '" << (*volIter)->volumeName()
200  << "' to Array");
201  // push back the volume order position
202  volOrder.emplace_back((*volIter), (*volIter)->center());
203 
204  }
205  if (!volOrder.empty()) {
206  auto volBinUtil = std::make_unique<BinUtility>(boundaries, open, binZ);
207  ATH_MSG_VERBOSE("Return created Array. ");
208  return std::make_unique<BinnedArray1D<TrackingVolume>>(volOrder, volBinUtil.release());
209  }
210  ATH_MSG_ERROR("No TrackingVolumes provided to the TrackingVolumeArrayCreator: return 0");
211  return nullptr;
212 }
213 
215  bool navtype) const {
216  return cylinderVolumesArrayInPhi(translateToShared(vols,navtype), navtype).release();
217 }
218 
219 std::unique_ptr<TrackingVolumeArray>
220  TrackingVolumeArrayCreator::cylinderVolumesArrayInPhi(const std::vector<VolumePtr>& vols,
221  bool /*navtype*/) const {
222 
223  ATH_MSG_VERBOSE("Create VolumeArray of " << vols.size()
224  << " Volumes (with CylinderVolumeBounds) with Phi-binning. ");
225 
226  // phi binning; assume equidistant
227  int nPhiBins = !vols.empty() ? vols.size() : 1;
228  double phi = M_PI;
229  // the vector needed for the BinnedArray
230  std::vector<TrackingVolumeOrderPosition> volOrder;
231  // loop over volumes and fill primaries
232  auto volIter = vols.begin();
233  for (; volIter != vols.end(); ++volIter) {
234  const CylinderVolumeBounds* cyl = nullptr;
235  if (*volIter) cyl = dynamic_cast<const CylinderVolumeBounds*>(&((*volIter)->volumeBounds()));
236  if (!cyl) {
237  ATH_MSG_ERROR("Given TrackingVolume doesn't exist or is not of shape 'CylinderVolumeBounds': return 0");
238  return nullptr;
239  }
240  // output
241  ATH_MSG_VERBOSE("Adding Volume '" << (*volIter)->volumeName()<< "' to Array");
242  // push back the volume order position
243  volOrder.emplace_back((*volIter), (*volIter)->transform() * (cyl->mediumRadius() * Amg::Vector3D::UnitX()));
244 
245  }
246  if (!volOrder.empty()) {
247  auto volBinUtil = std::make_unique<BinUtility>(nPhiBins, -phi, +phi, closed, binPhi);
248  return std::make_unique<BinnedArray1D<TrackingVolume>>(volOrder, volBinUtil.release());
249  }
250  ATH_MSG_ERROR("No TrackingVolumes provided to the TrackingVolumeArrayCreator: return 0");
251  return nullptr;
252 }
253 
255  TrackingVolumeArrayCreator::cylinderVolumesArrayInPhiR(const std::vector<TrackingVolume*>& vols,
256  bool navtype) const {
257  return cylinderVolumesArrayInPhiR(translateToShared(vols, navtype), navtype).release();
258 }
259 std::unique_ptr<TrackingVolumeArray>
261  bool navtype) const {
262  if (vols.empty())
263  return nullptr;
264 
265  const bool bevelled = std::find_if(vols.begin(),vols.end(),
266  [](const VolumePtr& ptr) -> bool {
267  return dynamic_cast<const BevelledCylinderVolumeBounds*>(&(ptr->volumeBounds()));
268  }) != vols.end();
269 
270  double tol = 0.001;
271 
272  // the vector needed for the BinnedArray
273  std::vector<TrackingVolumeOrderPosition> volOrder;
274 
275  if (bevelled) {
276  ATH_MSG_VERBOSE("Create 2dim VolumeArray of "<< vols.size()
277  << " Volumes (with CylinderVolumeBounds) with PhiH-binning. ");
278  std::vector<float> phiSteps;
279  std::vector<std::pair<std::pair<double, int>, std::pair<double, double>>>
280  volPos;
281  std::vector<VolumePtr> fullPhiVols;
282 
283  for (const VolumePtr& vol : vols) {
284  const auto *cyl = dynamic_cast<const CylinderVolumeBounds*>(&(vol->volumeBounds()));
285  const auto *bcyl =dynamic_cast<const BevelledCylinderVolumeBounds*>(&(vol->volumeBounds()));
286  double rmin{0.}, rmax{0.}, dphi{0.}, mRad{0.};
287  int type = 0;
288 
289  if (cyl) {
290  rmin = cyl->innerRadius();
291  rmax = cyl->outerRadius();
292  dphi = cyl->halfPhiSector();
293  mRad = cyl->mediumRadius();
294  } else if (bcyl) {
295  rmin = bcyl->innerRadius();
296  rmax = bcyl->outerRadius();
297  dphi = bcyl->halfPhiSector();
298  mRad = bcyl->mediumRadius();
299  type = bcyl->type();
300  } else {
301  ATH_MSG_ERROR("volume not cylinder nor bevelled cylinder ");
302  return nullptr;
303  }
304 
305  if (dphi < M_PI) {
306  // push back the volume order position
307  Amg::Vector3D ngp((vol->transform()) * (mRad * Amg::Vector3D::UnitX()));
308  volOrder.emplace_back(vol, ngp);
309 
310  // push back volume position to avoid another loop
311  volPos.emplace_back(std::pair<double, int>(ngp.phi(), type),
312  std::pair<double, double>(rmin, rmax));
313  // phi binning
314  double phi1 = ngp.phi() - dphi;
315  double phi2 = ngp.phi() + dphi;
316  if (phi1 < -2 * M_PI) {
317  phi1 += 2 * M_PI;
318  } if (phi2 < -2 * M_PI) {
319  phi2 += 2 * M_PI;
320  } if (phi1 > 2 * M_PI) {
321  phi1 -= 2 * M_PI;
322  } if (phi2 > 2 * M_PI) {
323  phi2 -= 2 * M_PI;
324  }
325 
326  if (!phiSteps.empty()) {
327  std::vector<float>::iterator iter = phiSteps.begin();
328  bool known = false;
329  while (iter != phiSteps.end()) {
330  if (std::abs(phi1 - (*iter)) < tol) {
331  known = true;
332  break;
333  }
334  if (phi1 < (*iter)) {
335  phiSteps.insert(iter, phi1);
336  known = true;
337  break;
338  }
339  ++iter;
340  }
341  if (!known)
342  phiSteps.push_back(phi1);
343  iter = phiSteps.begin();
344  known = false;
345  while (iter != phiSteps.end()) {
346  if (std::abs(phi2 - (*iter)) < tol) {
347  known = true;
348  break;
349  }
350  if (phi2 < (*iter)) {
351  phiSteps.insert(iter, phi2);
352  known = true;
353  break;
354  }
355  ++iter;
356  }
357  if (!known)
358  phiSteps.push_back(phi2);
359  } else {
360  phiSteps.push_back(fmin(phi1, phi2));
361  phiSteps.push_back(fmax(phi1, phi2));
362  }
363  } else {
364  fullPhiVols.push_back(vol);
365  }
366  } // end of first loop over volumes
367  // collect volumes with full phi range
368  if (phiSteps.empty()) {
369  phiSteps.push_back(-M_PI);
370  phiSteps.push_back(+M_PI);
371  }
372  for (auto & fullPhiVol : fullPhiVols) {
373  const auto *cyl =dynamic_cast<const CylinderVolumeBounds*>(&(fullPhiVol->volumeBounds()));
374  if (!cyl) {
375  ATH_MSG_WARNING("dynamic_cast<const CylinderVolumeBounds*> failed ... trying to continue loop");
376  continue;
377  }
378  double rmin = cyl->innerRadius();
379  double rmax = cyl->outerRadius();
380 
381  for (unsigned int iphi = 0; iphi < phiSteps.size(); ++iphi) {
382  // reference position
383  double phiRef = 0.5 * phiSteps[iphi];
384  if (iphi < phiSteps.size() - 1)
385  phiRef += 0.5 * phiSteps[iphi + 1];
386  else
387  phiRef += 0.5 * phiSteps[0] + M_PI;
388  // setting the position in the phi sector
389  const Amg::Vector3D ngp{cyl->mediumRadius() * std::cos(phiRef),cyl->mediumRadius() * std::sin(phiRef),0.};
390 
391  volOrder.emplace_back(fullPhiVol, ngp);
392 
393  // push back volume position to avoid another loop
394  volPos.emplace_back(std::pair<double, int>(ngp.phi(), 0),
395  std::pair<double, double>(rmin, rmax));
396  }
397  }
398  // all volumes in arrays : build bin utilities
399 
400  // adjust phiSteps : upper bound equal the lower
401  if (phiSteps.size() > 1) {
402  if (phiSteps.back() > M_PI)
403  phiSteps.erase(phiSteps.end() - 1);
404  else
405  phiSteps.erase(phiSteps.begin());
406  }
407 
408  // phi binning
409  std::vector<std::vector<std::pair<int, float>>> hSteps(phiSteps.size());
410  std::vector<float> phiRef(phiSteps.size());
411  for (unsigned int ip = 0; ip < phiSteps.size() - 1; ++ip)
412  phiRef[ip] = 0.5 * (phiSteps[ip] + phiSteps[ip + 1]);
413  phiRef.back() = 0.5 * (phiSteps.back() + phiSteps.front());
414  phiRef.back() += (phiRef.back() > 0) ? -M_PI : M_PI;
415 
416  auto phiBinUtil = std::make_unique<BinUtility>(phiSteps, closed, binPhi);
417 
418  // H binning
419 
420  for (unsigned int i = 0; i < volPos.size(); ++i) {
421 
422  // double phi = volPos[i].first.first;
423  int type = volPos[i].first.second;
424  double rmin = volPos[i].second.first;
425  double rmax = volPos[i].second.second;
426  int tmin = (type != 1 && type != 3) ? 0 : 1;
427  int tmax = (type < 2) ? 0 : 1;
428 
429  int phibin = phiBinUtil->bin(volOrder[i].second);
430 
431  if (!hSteps[phibin].empty()) {
432  std::vector<std::pair<int, float>>::iterator iter =
433  hSteps[phibin].begin();
434  bool known = false;
435  while (iter != hSteps[phibin].end()) {
436  if (std::abs(rmin - (*iter).second) < tol) {
437  known = true;
438  break;
439  }
440  if (rmin < (*iter).second) {
441  hSteps[phibin].insert(iter, std::pair<int, float>(tmin, rmin));
442  known = true;
443  break;
444  }
445  ++iter;
446  }
447  if (!known)
448  hSteps[phibin].emplace_back(tmin, rmin);
449  iter = hSteps[phibin].begin();
450  known = false;
451  while (iter != hSteps[phibin].end()) {
452  if (std::abs(rmax - (*iter).second) < tol) {
453  known = true;
454  break;
455  }
456  if (rmax < (*iter).second) {
457  hSteps[phibin].insert(iter, std::pair<int, float>(tmax, rmax));
458  known = true;
459  break;
460  }
461  ++iter;
462  }
463  if (!known)
464  hSteps[phibin].emplace_back(tmax, rmax);
465  } else {
466  hSteps[phibin].emplace_back(tmin, rmin);
467  hSteps[phibin].emplace_back(tmax, rmax);
468  }
469  }
470  // verify size of the array
471  // 2dim array
472  // steering bin utility in phi
473  std::vector<BinUtility*>* hUtil =
474  new std::vector<BinUtility*>(phiSteps.size());
475 
476  for (unsigned int ih = 0; ih < phiSteps.size(); ++ih) {
477  (*hUtil)[ih] = new BinUtility(phiRef[ih], hSteps[ih]);
478  }
479 
480  return std::make_unique<BinnedArray1D1D<TrackingVolume>>(volOrder, phiBinUtil.release(), hUtil);
481  }
482 
483  ATH_MSG_VERBOSE("Create 2dim VolumeArray of of "<< vols.size()
484  << " Volumes (with CylinderVolumeBounds) with PhiR-binning. ");
485 
486  std::vector<float> rSteps;
487  double phiSector = M_PI;
488  std::vector<std::pair<double, std::pair<double, double>>> volPos;
489 
490  for (const auto& vol : vols) {
491  const auto *cyl =dynamic_cast<const CylinderVolumeBounds*>(&(vol->volumeBounds()));
492  if (!cyl) {
493  ATH_MSG_WARNING("dynamic_cast<const CylinderVolumeBounds*> failed ... trying to continue loop");
494  continue;
495  }
496  double rmin = cyl->innerRadius();
497  double rmax = cyl->outerRadius();
498  double dphi = cyl->halfPhiSector();
499  if (phiSector > 0. && std::abs(dphi - phiSector) > 0.001)
500  phiSector = phiSector < M_PI ? -1. : dphi;
501 
502 
503  const Amg::Vector3D ngp{vol->transform() * (cyl->mediumRadius()* Amg::Vector3D::UnitX())};
504  volOrder.emplace_back(vol, ngp);
505 
506  // push back volume position to avoid another loop
507  volPos.emplace_back(cyl->mediumRadius(), std::make_pair(ngp.phi(), dphi));
508  // r binning
509  if (!rSteps.empty()) {
510  std::vector<float>::iterator iter = rSteps.begin();
511  bool known = false;
512  while (iter != rSteps.end()) {
513  if (std::abs(rmin - (*iter)) < tol) {
514  known = true;
515  break;
516  }
517  if (rmin < (*iter)) {
518  rSteps.insert(iter, rmin);
519  known = true;
520  break;
521  }
522  ++iter;
523  }
524  if (!known)
525  rSteps.push_back(rmin);
526  iter = rSteps.begin();
527  known = false;
528  while (iter != rSteps.end()) {
529  if (std::abs(rmax - (*iter)) < tol) {
530  known = true;
531  break;
532  }
533  if (rmax < (*iter)) {
534  rSteps.insert(iter, rmax);
535  known = true;
536  break;
537  }
538  ++iter;
539  }
540  if (!known)
541  rSteps.push_back(rmax);
542  } else {
543  rSteps.push_back(rmin);
544  rSteps.push_back(rmax);
545  }
546  }
547 
548  if (phiSector > 0.) { // overall equidistant binning
549 
550  std::vector<double> phi;
551  std::vector<int> phiSect;
552  for (unsigned int i = 0; i < rSteps.size() - 1; ++i)
553  phi.push_back(M_PI);
554  for (unsigned int i = 0; i < rSteps.size() - 1; ++i)
555  phiSect.push_back(int(M_PI / phiSector));
556 
557  // simplify if possible
558  if (rSteps.size() == 1) {
559  return cylinderVolumesArrayInPhi(vols, navtype);
560  }
561  if (phiSector == M_PI) {
562  return cylinderVolumesArrayInR(vols, navtype);
563  }
564  // 2dim array
565  auto rBinUtil = std::make_unique<BinUtility>(rSteps, open, binR);
566  std::vector<BinUtility*>* phiUtil = new std::vector<BinUtility*>(rSteps.size() - 1);
567  for (unsigned int ip = 0; ip < phiUtil->size(); ++ip) {
568  (*phiUtil)[ip] = new BinUtility(phiSect[ip], closed, binPhi);
569  }
570  return std::make_unique<BinnedArray1D1D<TrackingVolume>>(volOrder, rBinUtil.release(), phiUtil);
571  }
572 
573  // R binning : steering binUtility
574  auto binGenR = std::make_unique<BinUtility>(rSteps, open, binR);
575 
576  // phi binning
577  std::vector<std::vector<float>> phiSteps(rSteps.size() - 1);
578 
579  for (unsigned int i = 0; i < volPos.size(); ++i) {
580 
581  double phi = volPos[i].second.first;
582  double dphi = volPos[i].second.second;
583 
584  int binr = binGenR->bin(volOrder[i].second);
585 
586  float phi1 = phi - dphi;
587  float phi2 = phi + dphi;
588  if (phi1 < 0)
589  phi1 += 2 * M_PI;
590  if (phi2 < 0)
591  phi2 += 2 * M_PI;
592 
593  if (!phiSteps[binr].empty()) {
594  std::vector<float>::iterator iter = phiSteps[binr].begin();
595  bool known = false;
596  while (iter != phiSteps[binr].end()) {
597  if (std::abs(phi1 - (*iter)) < tol) {
598  known = true;
599  break;
600  }
601  if (phi1 < (*iter)) {
602  phiSteps[binr].insert(iter, phi1);
603  known = true;
604  break;
605  }
606  ++iter;
607  }
608  if (!known)
609  phiSteps[binr].push_back(phi1);
610  iter = phiSteps[binr].begin();
611  known = false;
612  while (iter != phiSteps[binr].end()) {
613  if (std::abs(phi2 - (*iter)) < tol) {
614  known = true;
615  break;
616  }
617  if (phi2 < (*iter)) {
618  phiSteps[binr].insert(iter, phi2);
619  known = true;
620  break;
621  }
622  ++iter;
623  }
624  if (!known)
625  phiSteps[binr].push_back(phi2);
626  } else {
627  phiSteps[binr].push_back(std::fmin(phi1, phi2));
628  phiSteps[binr].push_back(std::fmax(phi1, phi2));
629  }
630  }
631 
632  // 2dim array
633  std::vector<BinUtility*>* phiUtil = new std::vector<BinUtility*>(phiSteps.size());
634 
635  for (unsigned int ip = 0; ip < phiSteps.size(); ++ip) {
636  (*phiUtil)[ip] =
638  }
639 
640  return std::make_unique<BinnedArray1D1D<TrackingVolume>>(volOrder, binGenR.release(), phiUtil);
641 }
642 
644 TrackingVolumeArrayCreator::cylinderVolumesArrayInPhiZ(const std::vector<TrackingVolume*>& vols,
645  bool navtype) const {
646  return cylinderVolumesArrayInPhiZ(translateToShared(vols, navtype), navtype).release();
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.}, zmax{0.}, dphi{0.}, 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  std::vector<float> phi;
735  std::vector<int> phiSect;
736  for (unsigned int i = 0; i < zSteps.size() - 1; ++i)
737  phi.push_back(M_PI);
738  for (unsigned int i = 0; i < zSteps.size() - 1; ++i)
739  phiSect.push_back(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 =std::make_unique<BinUtility>(zSteps, open, binZ);
750  (*binGenZPhi) += BinUtility(phiSector, -M_PI, M_PI, closed, binPhi);
751  return std::make_unique<BinnedArray2D<TrackingVolume>>(volOrder, binGenZPhi.release());
752  }
753 
754  // steering binUtility in binZ
755  auto binGenZ = std::make_unique<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  std::vector<BinUtility*>* phiUtil = new std::vector<BinUtility*>(phiSteps.size());
816 
817  for (unsigned int ip = 0; ip < phiSteps.size(); ++ip) {
818  (*phiUtil)[ip] = new BinUtility(phiSteps[ip], closed, binPhi);
819  }
820 
821  return std::make_unique<BinnedArray1D1D<TrackingVolume>>(volOrder, binGenZ.release(), phiUtil);
822 }
823 
824 
826 TrackingVolumeArrayCreator::cuboidVolumesArrayNav(const std::vector<TrackingVolume*>& vols,
827  BinUtility* binUtil,
828  bool navtype) const {
829  return cuboidVolumesArrayNav(translateToShared(vols, navtype), binUtil).release();
830 }
831 std::unique_ptr<TrackingVolumeArray>
832  TrackingVolumeArrayCreator::cuboidVolumesArrayNav(const std::vector<VolumePtr>& vols,
833  BinUtility* binUtil) const {
834  // the vector needed for the BinnedArray
835  std::vector<VolumePtr> volOrder;
836  // loop over volumes and fill primaries
837  auto volIter = vols.begin();
838  for (; volIter != vols.end(); ++volIter) {
839  const auto *currentCubBounds = dynamic_cast<const CuboidVolumeBounds*>(&((*volIter)->volumeBounds()));
840  if (!currentCubBounds) {
841  ATH_MSG_ERROR("Given TrackingVolume to TrackingVolumeArrayCreator didn't "
842  "match specified shape: return 0");
843  return nullptr;
844  }
845  volOrder.push_back(*volIter);
846  }
847  if (!volOrder.empty()) {
848  auto navTransform = std::make_unique<Amg::Transform3D>(Amg::Transform3D::Identity());
849  return std::make_unique<NavBinnedArray1D<TrackingVolume>>(volOrder, binUtil, navTransform.release());
850  }
851  ATH_MSG_ERROR("No TrackingVolumes provided to the TrackingVolumeArrayCreator: return 0");
852  return nullptr;
853 }
854 
855 
857 TrackingVolumeArrayCreator::trapezoidVolumesArrayNav(const std::vector<TrackingVolume*>& vols,
858  BinUtility* binUtil, bool navtype) const {
859  return trapezoidVolumesArrayNav(translateToShared(vols, navtype), binUtil).release();
860 }
861 
862 std::unique_ptr<TrackingVolumeArray>
863  TrackingVolumeArrayCreator::trapezoidVolumesArrayNav(const std::vector<VolumePtr>& vols, BinUtility* binUtil) const {
864  // the vector needed for the BinnedArray
865  std::vector<VolumePtr> volOrder;
866  // loop over volumes and fill primaries
867  auto volIter = vols.begin();
868  for (; volIter != vols.end(); ++volIter) {
869  const auto *currentTrdBounds = dynamic_cast<const TrapezoidVolumeBounds*>(&((*volIter)->volumeBounds()));
870  if (!currentTrdBounds) {
871  ATH_MSG_ERROR("Given TrackingVolume to TrackingVolumeArrayCreator didn't "
872  "match specified shape: return 0");
873  return nullptr;
874  }
875  // push back the volume order position
876  volOrder.push_back(*volIter);
877  }
878  if (!volOrder.empty()) {
879  Amg::Transform3D* navTransform = new Amg::Transform3D(Amg::Transform3D::Identity());
880  return std::make_unique<NavBinnedArray1D<TrackingVolume>>(volOrder, binUtil, navTransform);
881  }
882  ATH_MSG_ERROR("No TrackingVolumes provided to the TrackingVolumeArrayCreator: return 0");
883  return nullptr;
884 }
885 
887  BinUtility* binUtil,
888  bool navtype) const {
889  return doubleTrapezoidVolumesArrayNav(translateToShared(vols, navtype), binUtil).release();
890 }
891 
892 std::unique_ptr<TrackingVolumeArray>
893  TrackingVolumeArrayCreator::doubleTrapezoidVolumesArrayNav(const std::vector<VolumePtr>& vols, BinUtility* binUtil) const {
894  // the vector needed for the BinnedArray
895  std::vector<VolumePtr> volOrder;
896  // loop over volumes and fill primaries
897  auto volIter = vols.begin();
898  for (; volIter != vols.end(); ++volIter) {
899  const auto *currentDTrdBounds =dynamic_cast<const DoubleTrapezoidVolumeBounds*>(&((*volIter)->volumeBounds()));
900  if (!currentDTrdBounds) {
901  ATH_MSG_ERROR("Given TrackingVolume to TrackingVolumeArrayCreator didn't "
902  "match specified shape: return 0");
903  return nullptr;
904  }
905  // push back the volume order position
906  volOrder.push_back(*volIter);
907  }
908  if (!volOrder.empty()) {
909  Amg::Transform3D* navTransform = new Amg::Transform3D(Amg::Transform3D::Identity());
910  return std::make_unique<NavBinnedArray1D<TrackingVolume>>(volOrder, binUtil, navTransform);
911  }
913  "No TrackingVolumes provided to the TrackingVolumeArrayCreator: return 0");
914  return nullptr;
915 }
916 
917 }
xAOD::iterator
JetConstituentVector::iterator iterator
Definition: JetConstituentVector.cxx:68
Trk::TrackingVolumeArrayCreator::cylinderVolumesArrayInZ
TrackingVolumeArray * cylinderVolumesArrayInZ(const std::vector< TrackingVolume * > &vols, bool navigationtype=false) const override
TrackingVolumeArrayCreator interface method - create a R-binned cylindrical volume array.
Definition: TrackingVolumeArrayCreator.cxx:136
python.SystemOfUnits.second
int second
Definition: SystemOfUnits.py:120
Trk::BevelledCylinderVolumeBounds
Definition: BevelledCylinderVolumeBounds.h:100
Trk::CuboidVolumeBounds
Definition: CuboidVolumeBounds.h:52
Trk::binZ
@ binZ
Definition: BinningType.h:49
PixelAthClusterMonAlgCfg.zmin
zmin
Definition: PixelAthClusterMonAlgCfg.py:169
BinnedArray2D.h
Trk::TrackingVolumeArrayCreator::TrackingVolumeArrayCreator
TrackingVolumeArrayCreator(const std::string &, const std::string &, const IInterface *)
Constructor.
Definition: TrackingVolumeArrayCreator.cxx:48
BinUtility.h
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
empty
bool empty(TH1 *h)
Definition: computils.cxx:295
TrapezoidVolumeBounds.h
Trk::TrackingVolumeArrayCreator::~TrackingVolumeArrayCreator
virtual ~TrackingVolumeArrayCreator()
Destructor.
mergePhysValFiles.end
end
Definition: DataQuality/DataQualityUtils/scripts/mergePhysValFiles.py:93
Trk::TrackingVolumeArrayCreator::cylinderVolumesArrayInPhi
TrackingVolumeArray * cylinderVolumesArrayInPhi(const std::vector< TrackingVolume * > &vols, bool navigationtype=false) const override
TrackingVolumeArrayCreator interface method - create a R-binned cylindrical volume array.
Definition: TrackingVolumeArrayCreator.cxx:214
BinnedArray1D.h
GeometryStatics.h
CylinderVolumeBounds.h
python.utils.AtlRunQueryDQUtils.p
p
Definition: AtlRunQueryDQUtils.py:210
Trk::ITrackingVolumeArrayCreator::VolumePtr
std::shared_ptr< TrackingVolume > VolumePtr
Definition: ITrackingVolumeArrayCreator.h:49
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:731
BevelledCylinderVolumeBounds.h
Amg::Transform3D
Eigen::Affine3d Transform3D
Definition: GeoPrimitives.h:46
Trk::TrackingVolumeArrayCreator::doubleTrapezoidVolumesArrayNav
TrackingVolumeArray * doubleTrapezoidVolumesArrayNav(const std::vector< TrackingVolume * > &vols, Trk::BinUtility *binUtil, bool navigationtype=false) const override
TrackingVolumeArrayCreator interface method - create a doubleTrapezoid volume array - linked to detac...
Definition: TrackingVolumeArrayCreator.cxx:886
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::TrackingVolumeArrayCreator::cylinderVolumesArrayInPhiZ
TrackingVolumeArray * cylinderVolumesArrayInPhiZ(const std::vector< TrackingVolume * > &vols, bool navigationtype=false) const override
TrackingVolumeArrayCreator interface method - create a 2dim cylindrical volume array.
Definition: TrackingVolumeArrayCreator.cxx:644
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::CylinderVolumeBounds::outerRadius
double outerRadius() const
This method returns the outer radius.
Definition: CylinderVolumeBounds.h:191
Trk::TrapezoidVolumeBounds
Definition: TrapezoidVolumeBounds.h:57
Amg::Vector3D
Eigen::Matrix< double, 3, 1 > Vector3D
Definition: GeoPrimitives.h:47
Trk::TrackingVolumeArrayCreator::cylinderVolumesArrayInPhiR
TrackingVolumeArray * cylinderVolumesArrayInPhiR(const std::vector< TrackingVolume * > &vols, bool navigationtype=false) const override
TrackingVolumeArrayCreator interface method - create a 2dim cylindrical volume array.
Definition: TrackingVolumeArrayCreator.cxx:255
Trk::open
@ open
Definition: BinningType.h:40
Trk::binR
@ binR
Definition: BinningType.h:50
Trk::TrackingVolumeArrayCreator::trapezoidVolumesArrayNav
TrackingVolumeArray * trapezoidVolumesArrayNav(const std::vector< TrackingVolume * > &vols, Trk::BinUtility *binUtil, bool navigationtype=false) const override
TrackingVolumeArrayCreator interface method - create a trapezoid volume array - linked to detached tr...
Definition: TrackingVolumeArrayCreator.cxx:857
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
GeoPrimitivesHelpers.h
known
Definition: TrigBStoxAODTool.cxx:107
python.CaloScaleNoiseConfig.type
type
Definition: CaloScaleNoiseConfig.py:78
Trk::DoubleTrapezoidVolumeBounds
Definition: DoubleTrapezoidVolumeBounds.h:66
Trk::TrackingVolumeArrayCreator::cuboidVolumesArrayNav
TrackingVolumeArray * cuboidVolumesArrayNav(const std::vector< TrackingVolume * > &vols, Trk::BinUtility *binUtil, bool navigationtype=false) const override
TrackingVolumeArrayCreator interface method - create a cuboid volume array - linked to detached track...
Definition: TrackingVolumeArrayCreator.cxx:826
Trk::phi
@ phi
Definition: ParamDefs.h:75
Trk::TrackingVolumeArrayCreator::cylinderVolumesArrayInR
TrackingVolumeArray * cylinderVolumesArrayInR(const std::vector< TrackingVolume * > &vols, bool navigationtype=false) const override
TrackingVolumeArrayCreator interface method - create a R-binned cylindrical volume array.
Definition: TrackingVolumeArrayCreator.cxx:59
Trk::BinnedArray
Definition: BinnedArray.h:38
drawFromPickle.sin
sin
Definition: drawFromPickle.py:36
AthAlgTool
Definition: AthAlgTool.h:26
Trk::TrackingVolume
Definition: TrackingVolume.h:121
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::binPhi
@ binPhi
Definition: BinningType.h:51