ATLAS Offline Software
Public Member Functions | Private Types | Private Member Functions | Static Private Member Functions | Private Attributes | List of all members
MuonGMR4::ChamberAssembleTool Class Reference

#include <ChamberAssembleTool.h>

Inheritance diagram for MuonGMR4::ChamberAssembleTool:
Collaboration diagram for MuonGMR4::ChamberAssembleTool:

Public Member Functions

virtual StatusCode buildReadOutElements (MuonDetectorManager &mgr) override final
 

Private Types

using TrapVolBound_t = Acts::TrapezoidVolumeBounds
 
using SurfBoundPtr_t = std::shared_ptr< const Acts::PlanarBounds >
 
using VolBoundPtr_t = std::shared_ptr< Acts::TrapezoidVolumeBounds >
 
using TrfWithBounds = std::tuple< Amg::Transform3D, VolBoundPtr_t, SurfBoundPtr_t >
 Abrivation of the volume transform together with a set of volume & surface bounds. More...
 

Private Member Functions

TrfWithBounds boundingBox (const ActsGeometryContext &gctx, const std::vector< const MuonReadoutElement * > &readoutEles, const Amg::Transform3D &globToLoc, Acts::VolumeBoundFactory &volBoundSet, Acts::SurfaceBoundFactory &surfBoundSet, const double margin=1.*Gaudi::Units::cm) const
 builds the bounding box trapezoidal volume bounds from the set of readout elements Returns a pair of the volume bounds & the transformation to center the volume More...
 

Static Private Member Functions

static VolBoundPtr_t boundingBox (const MuonReadoutElement *reEle, Acts::VolumeBoundFactory &boundSet)
 Builds the trapezoidal bounding box enclosing a single readout element. More...
 
static std::array< Amg::Vector3D, 4 > cornerPointsPlane (const Amg::Transform3D &localToGlob, const TrapVolBound_t &bounds)
 Returns the 4 corners of the trapezoid in the x-y plane. More...
 
static std::array< Amg::Vector3D, 8 > cornerPoints (const Amg::Transform3D &localToGlob, const TrapVolBound_t &bounds)
 Returns the 8 corners marking the trapezoid. More...
 
static Amg::Transform3D centerTrapezoid (const std::array< Amg::Vector3D, 8 > &cornerPoints)
 Returns the translation transform centering the 8 corner points of the trapezoid. More...
 
static double trapezoidEdgeDist (const Amg::Vector3D &linePos, const Amg::Vector3D &lineDir, const Amg::Vector3D &testMe, bool leftEdge)
 Returns the signed distances of an external point to the trapezoidal edge. More...
 

Private Attributes

ServiceHandle< Muon::IMuonIdHelperSvcm_idHelperSvc {this, "IdHelperSvc", "Muon::MuonIdHelperSvc/MuonIdHelperSvc"}
 
PublicToolHandle< IMuonGeoUtilityToolm_geoUtilTool {this,"GeoUtilTool", "" }
 

Detailed Description

Definition at line 31 of file ChamberAssembleTool.h.

Member Typedef Documentation

◆ SurfBoundPtr_t

using MuonGMR4::ChamberAssembleTool::SurfBoundPtr_t = std::shared_ptr<const Acts::PlanarBounds>
private

Definition at line 40 of file ChamberAssembleTool.h.

◆ TrapVolBound_t

using MuonGMR4::ChamberAssembleTool::TrapVolBound_t = Acts::TrapezoidVolumeBounds
private

Definition at line 39 of file ChamberAssembleTool.h.

◆ TrfWithBounds

Abrivation of the volume transform together with a set of volume & surface bounds.

Definition at line 44 of file ChamberAssembleTool.h.

◆ VolBoundPtr_t

using MuonGMR4::ChamberAssembleTool::VolBoundPtr_t = std::shared_ptr<Acts::TrapezoidVolumeBounds>
private

Definition at line 41 of file ChamberAssembleTool.h.

Member Function Documentation

◆ boundingBox() [1/2]

ChamberAssembleTool::TrfWithBounds MuonGMR4::ChamberAssembleTool::boundingBox ( const ActsGeometryContext gctx,
const std::vector< const MuonReadoutElement * > &  readoutEles,
const Amg::Transform3D globToLoc,
Acts::VolumeBoundFactory &  volBoundSet,
Acts::SurfaceBoundFactory &  surfBoundSet,
const double  margin = 1.*Gaudi::Units::cm 
) const
private

builds the bounding box trapezoidal volume bounds from the set of readout elements Returns a pair of the volume bounds & the transformation to center the volume

Parameters
gctxGeometry context holding the alignment & global transformations
readoutElesList of readout elements around which the bounding box shall be built
globToLocTransformation to go from the global -> local chamber's frame
boundSetCache of create bounds to share the same bounds across multiple volumes

Hack to cope with the RPCs which may be rotated by 180 degrees around the x or z-axis in cases, they're upside down.

Check whether the bounds are already embedded in the trapezoid

Everything is contained in the volume

Fetch the edges of the best known trapezoid to extend the dimensions

Reserve space for the new envelope trapezoid

The first 4 indices in the trpezoidal array are the bottom corners

Check the angles of the bounding trapzeoids

On the left edge the trapezoid opening angle needs to be larger while on the right side it's smaller

Calculate the distance to the trapezoidal edge. If it's less than 0, it's not embedded by the trapezoid and the smaller the number the farer it's from the trapezoid

Choose as reference point the one which is farest away from the edge

Extend the trapezoid in the x-y plane

Edge points of the best-known trapezoid

Finally re-center the trapezoid

Definition at line 161 of file ChamberAssembleTool.cxx.

166  {
167 
168  VolBoundPtr_t envelopeBounds{};
169 
170  Amg::Transform3D newCentreTrf{Amg::Transform3D::Identity()};
171  for (const MuonReadoutElement* chambEle : readoutEles) {
172  Amg::Transform3D trf = newCentreTrf * toCenter *
173  chambEle->localToGlobalTrans(gctx) *
174  axisRotation(chambEle->detectorType()).inverse();
175  VolBoundPtr_t bounds = boundingBox(chambEle, volBoundSet);
176  if (!envelopeBounds) {
177  envelopeBounds = bounds;
178  newCentreTrf = centerTrapezoid(cornerPoints(trf, *bounds)) * newCentreTrf;
179  ATH_MSG_VERBOSE("Envelope "<<(*envelopeBounds)<<", transform: "<<Amg::toString(newCentreTrf));
180  continue;
181  }
184  GeoTrf::CoordEulerAngles rotAngles = GeoTrf::getCoordRotationAngles(trf);
185  if (std::abs(rotAngles.gamma - 180.*Gaudi::Units::deg)< std::numeric_limits<float>::epsilon()){
187  }
188  if (std::abs(rotAngles.alpha - 180.*Gaudi::Units::deg)< std::numeric_limits<float>::epsilon()){
190  }
192  const std::array<Amg::Vector3D, 8> corners = cornerPoints(trf, *bounds);
193 
194  Acts::Volume volume{Amg::Transform3D::Identity(), envelopeBounds};
196  if (std::ranges::find_if(corners, [&volume](const Amg::Vector3D& v) {
197  return !volume.inside(v);}) == corners.end()) {
198  ATH_MSG_VERBOSE("Readout element "<<m_idHelperSvc->toStringDetEl(chambEle->identify())<<" "
199  <<(*boundingBox(chambEle, volBoundSet))<<" fully contained. ");
200  continue;
201  }
202  if (msgLvl(MSG::VERBOSE)) {
203  std::stringstream debugStr{};
204  for (const Amg::Vector3D& corner : corners) {
205  debugStr<<" ***** "<<Amg::toString(corner)<<std::endl;
206  }
207  ATH_MSG_VERBOSE(m_idHelperSvc->toString(chambEle->identify())<<" corner points "
208  <<GeoTrf::toString(trf, true)<<std::endl<<debugStr.str());
209  }
211  const std::array<Amg::Vector3D, 8> refCorners{cornerPoints(Amg::Transform3D::Identity(), *envelopeBounds)};
213  std::array<Amg::Vector3D, 8> newTrapBounds{make_array<Amg::Vector3D, 8>(Amg::Vector3D::Zero())};
214 
216  for (unsigned lowZ : {0, 4}) {
217  for (bool isLeft : {false, true}) {
218 
219  const size_t iHigh = 1 + (!isLeft)*2 + lowZ;
220  const size_t iLow = 0 + (!isLeft)*2 + lowZ;
222  const Amg::Vector3D dirRef{projectIntoXY(refCorners[iHigh] - refCorners[iLow]).unit()};
223  const Amg::Vector3D dirCan{projectIntoXY(corners[iHigh] - corners[iLow]).unit()};
224 
225 
226  ATH_MSG_VERBOSE((isLeft ? "Left" : "Right")<<" edge "<<Amg::toString(dirRef)
227  <<" "<<dirRef.phi() / Gaudi::Units::deg <<" --- "
228  <<m_idHelperSvc->toStringDetEl(chambEle->identify())<<" "
229  <<Amg::toString(dirCan)<<", phi: "<<dirCan.phi() / Gaudi::Units::deg);
230 
232  const Amg::Vector3D& pickDir{(dirRef.phi() > dirCan.phi()) == isLeft ? dirRef : dirCan};
235  const double cornerLowD = trapezoidEdgeDist(refCorners[iLow], pickDir, corners[iLow], isLeft);
236  const double cornerHighD = trapezoidEdgeDist(refCorners[iLow], pickDir, corners[iHigh], isLeft);
237  ATH_MSG_VERBOSE("Distance "<<cornerLowD<<"/ "<<cornerHighD);
239  const Amg::Vector3D& pickPos{cornerLowD < 0 || cornerHighD < 0 ?
240  cornerLowD < cornerHighD ? corners[iLow] : corners[iHigh]: refCorners[iLow]};
241 
242  ATH_MSG_VERBOSE("Low points "<<Amg::toString(corners[iLow])<<" - "<<Amg::toString(refCorners[iLow]));
243  ATH_MSG_VERBOSE("High points "<<Amg::toString(corners[iHigh])<<" - "<<Amg::toString(refCorners[iHigh]));
244 
246  newTrapBounds[iHigh] = pickPos + Amg::intersect<3>(pickPos, pickDir, Amg::Vector3D::UnitY(),
247  std::max(corners[iHigh].y(), refCorners[iHigh].y())).value_or(0.) * pickDir;
248 
249  newTrapBounds[iHigh].z() = lowZ ? std::max(corners[iHigh].z(),refCorners[iHigh].z())
250  : std::min(corners[iHigh].z(), refCorners[iHigh].z());
251  newTrapBounds[iLow] = pickPos + Amg::intersect<3>(pickPos, pickDir, Amg::Vector3D::UnitY(),
252  std::min(corners[iLow].y(), refCorners[iLow].y())).value_or(0.) * pickDir;
253  newTrapBounds[iLow].z() = lowZ ? std::max(corners[iLow].z(), refCorners[iLow].z())
254  : std::min(corners[iLow].z(), refCorners[iLow].z());
255 
256  ATH_MSG_VERBOSE("New end points "<<Amg::toString(newTrapBounds[iLow])<<" - "<<Amg::toString(newTrapBounds[iHigh]));
257  }
258  }
259  if (msgLvl(MSG::VERBOSE)) {
260  std::stringstream debugStr{};
261  for (const Amg::Vector3D& edge : newTrapBounds) {
262  debugStr<<"***** "<<Amg::toString(edge)<<std::endl;
263  }
264  ATH_MSG_VERBOSE("#############################################################"<<std::endl<<
265  debugStr.str()<<"#############################################################");
266  }
268  const double halfY = 0.5*std::max(newTrapBounds[1].y() - newTrapBounds[0].y(),
269  newTrapBounds[3].y() - newTrapBounds[2].y());
270  const double lHalfX = 0.5*(newTrapBounds[3].x() - newTrapBounds[1].x());
271  const double sHalfX = 0.5*(newTrapBounds[2].x() - newTrapBounds[0].x());
272  const double halfZ = 0.5*(newTrapBounds[4].z() - newTrapBounds[0].z());
273  envelopeBounds = volBoundSet.makeBounds<Acts::TrapezoidVolumeBounds>(sHalfX, lHalfX, halfY, halfZ);
274  ATH_MSG_VERBOSE(m_idHelperSvc->toStringDetEl(chambEle->identify())<<" "<<(*envelopeBounds));
275 
277  const Amg::Transform3D centerShift = centerTrapezoid(newTrapBounds);
278  newCentreTrf = centerShift * newCentreTrf;
279  ATH_MSG_VERBOSE("New trapezoid centering "<<Amg::toString(centerShift)<<" combined: "
280  <<Amg::toString(newCentreTrf));
281  }
282 
283  VolBoundPtr_t volToReturn =
284  volBoundSet.makeBounds<Acts::TrapezoidVolumeBounds>(envelopeBounds->get(BoundEnum::eHalfLengthXnegY)+margin,
285  envelopeBounds->get(BoundEnum::eHalfLengthXposY)+margin,
286  envelopeBounds->get(BoundEnum::eHalfLengthY)+margin,
287  envelopeBounds->get(BoundEnum::eHalfLengthZ)+margin);
288  SurfBoundPtr_t surfToReturn{};
289  if (std::abs(envelopeBounds->get(BoundEnum::eHalfLengthXnegY) -
290  envelopeBounds->get(BoundEnum::eHalfLengthXposY)) > margin) {
291  surfToReturn = surfBoundSet.makeBounds<Acts::TrapezoidBounds>(envelopeBounds->get(BoundEnum::eHalfLengthXposY),
292  envelopeBounds->get(BoundEnum::eHalfLengthXnegY),
293  envelopeBounds->get(BoundEnum::eHalfLengthY));
294  } else {
295  const double maxX = std::max(envelopeBounds->get(BoundEnum::eHalfLengthXnegY),
296  envelopeBounds->get(BoundEnum::eHalfLengthXposY));
297  surfToReturn = surfBoundSet.makeBounds<Acts::RectangleBounds>(maxX, envelopeBounds->get(BoundEnum::eHalfLengthY));
298  }
299  return std::make_tuple(newCentreTrf.inverse(), volToReturn, surfToReturn);
300 }

◆ boundingBox() [2/2]

ChamberAssembleTool::VolBoundPtr_t MuonGMR4::ChamberAssembleTool::boundingBox ( const MuonReadoutElement reEle,
Acts::VolumeBoundFactory &  boundSet 
)
staticprivate

Builds the trapezoidal bounding box enclosing a single readout element.

Parameters
reElePointer to the readout element to fetch the bounds from
boundSetCache of create bounds to share the same bounds across multiple volumes

Definition at line 80 of file ChamberAssembleTool.cxx.

81  {
82 
83  switch(chambEle->detectorType()) {
85  const auto* techEle = static_cast<const MdtReadoutElement*>(chambEle);
86  const auto& pars = techEle->getParameters();
87  return volBoundSet.makeBounds<Acts::TrapezoidVolumeBounds>(pars.shortHalfX, pars.longHalfX,
88  pars.halfY, pars.halfHeight );
89  break;
91  const auto* techEle = static_cast<const RpcReadoutElement*>(chambEle);
92  const auto& pars = techEle->getParameters();
93  return volBoundSet.makeBounds<Acts::TrapezoidVolumeBounds>(pars.halfWidth, pars.halfWidth,
94  pars.halfLength, pars.halfThickness);
95  break;
97  const auto* techEle = static_cast<const TgcReadoutElement*>(chambEle);
98  const auto& pars = techEle->getParameters();
99  return volBoundSet.makeBounds<Acts::TrapezoidVolumeBounds>(pars.halfWidthShort, pars.halfWidthLong,
100  pars.halfHeight, pars.halfThickness );
101  break;
103  const auto* techEle = static_cast<const sTgcReadoutElement*>(chambEle);
104  const auto& pars = techEle->getParameters();
105  return volBoundSet.makeBounds<Acts::TrapezoidVolumeBounds>(pars.sHalfChamberLength, pars.lHalfChamberLength,
106  pars.halfChamberHeight, pars.halfChamberTck );
107  break;
108  } case ActsTrk::DetectorType::Mm: {
109  const auto* techEle = static_cast<const MmReadoutElement*>(chambEle);
110  const auto& pars = techEle->getParameters();
111  return volBoundSet.makeBounds<Acts::TrapezoidVolumeBounds>(pars.halfShortWidth, pars.halfLongWidth,
112  pars.halfHeight, pars.halfThickness );
113  break;
114  } default:
115  THROW_EXCEPTION("Unsupported detector type "<<to_string(chambEle->detectorType()));
116  }
117  return nullptr;
118 }

◆ buildReadOutElements()

StatusCode MuonGMR4::ChamberAssembleTool::buildReadOutElements ( MuonDetectorManager mgr)
finaloverridevirtual

TGC T4E chambers & Mdt EIL chambers are glued together

Group chambers by sectors && station layer.

Check that the two readout elements are on the same side. Exception BOG eta 0 -> attributes to positive sectors

The two readout elements shall be located in the same sector

Separate out the BOE chambers

Summarize all readout element in the same sector & layer into a single chamber

sTgcs && Micromegas should belong to the same chamber

EM readout element shall be grouped together too

Finally the EIL chambers should belong to the same chamber

If no chamber has been found, then create a new one

Find the chamber middle and create the geometry from that

Define the spectrometer sector

Define the chamber envelopes

Sort the readout elements by common parent volume

Create the enclosing chamber volume

now, build simplified 2D representations of the sorted chambers we collected.

Definition at line 302 of file ChamberAssembleTool.cxx.

302  {
303  ATH_CHECK(m_idHelperSvc.retrieve());
304  ATH_CHECK(m_geoUtilTool.retrieve());
305 
307  auto mdtStationIndex = [this] (const std::string& stName) {
308  return m_idHelperSvc->hasMDT() ? m_idHelperSvc->mdtIdHelper().stationNameIndex(stName) : -1;
309  };
310  auto tgcStationIndex = [this] (const std::string& stName) {
311  return m_idHelperSvc->hasTGC() ? m_idHelperSvc->tgcIdHelper().stationNameIndex(stName) : -1;
312  };
313 
314  const std::unordered_set<int> stIndicesEIL{mdtStationIndex("EIL"), mdtStationIndex("T4E")};
315  const std::unordered_set<int> stIndicesEM{mdtStationIndex("EML"), mdtStationIndex("EMS"),
316  tgcStationIndex("T1E"), tgcStationIndex("T1F"),
317  tgcStationIndex("T2E"), tgcStationIndex("T2F"),
318  tgcStationIndex("T3E"), tgcStationIndex("T3F")};
319 
320  const std::set<Identifier> BOE_ids{m_idHelperSvc->hasMDT() ? m_idHelperSvc->mdtIdHelper().elementID("BOL", 7,7): Identifier{},
321  m_idHelperSvc->hasMDT() ? m_idHelperSvc->mdtIdHelper().elementID("BOL", -7,7): Identifier{},
322  m_idHelperSvc->hasRPC() ? m_idHelperSvc->rpcIdHelper().elementID("BOL", -8, 7, 1) : Identifier{},
323  m_idHelperSvc->hasRPC() ? m_idHelperSvc->rpcIdHelper().elementID("BOL", 8, 7, 1) : Identifier{}};
324 
325  std::vector<MuonReadoutElement*> allReadOutEles = mgr.getAllReadoutElements();
326 
327  std::vector<chamberArgs> envelopeCandidates{};
328 
330  for (const MuonReadoutElement* readOutEle : allReadOutEles) {
331  std::vector<chamberArgs>::iterator exist = std::ranges::find_if(envelopeCandidates,
332  [this, readOutEle, &stIndicesEIL, &stIndicesEM, &BOE_ids](const chamberArgs& args){
333  const MuonReadoutElement* refEle = args.detEles.front();
334  const Identifier refId = refEle->identify();
335  const Identifier testId = readOutEle->identify();
338  if (sign(refEle->stationEta()) * sign(readOutEle->stationEta()) <0) {
339  return false;
340  }
342  if (m_idHelperSvc->sector(testId) != m_idHelperSvc->sector(refId)) {
343  return false;
344  }
346  if (BOE_ids.count(m_idHelperSvc->chamberId(refId)) !=
347  BOE_ids.count(m_idHelperSvc->chamberId(testId))){
348  return false;
349  }
352  if (readOutEle->chamberIndex() == refEle->chamberIndex()) {
353  return true;
354  }
356  if (isNsw(readOutEle) && isNsw(refEle)) return true;
358  if (stIndicesEM.count(readOutEle->stationName()) &&
359  stIndicesEM.count(refEle->stationName())) {
360  return true;
361  }
363  if (stIndicesEIL.count(readOutEle->stationName()) &&
364  stIndicesEIL.count(refEle->stationName())) {
365  return true;
366  }
367  return false;
368  });
370  if (exist == envelopeCandidates.end()) {
371  chamberArgs newChamb{};
372  newChamb.detEles.push_back(readOutEle);
373  envelopeCandidates.push_back(std::move(newChamb));
374  } else {
375  exist->detEles.push_back(readOutEle);
376  }
377  }
379  ActsGeometryContext gctx{};
380 
381 
382  Acts::VolumeBoundFactory volBoundSet{};
383  Acts::SurfaceBoundFactory surfBoundSet{};
384  for (chamberArgs& candidate : envelopeCandidates) {
385  std::unordered_set<Identifier> reIds{};
386  const MuonReadoutElement* refEle = candidate.detEles.front();
387  const Amg::Transform3D toCenter = axisRotation(refEle->detectorType()) * refEle->globalToLocalTrans(gctx);
388  ATH_MSG_VERBOSE("New envelope candidate ");
389  const auto [envelopeCentre, envelopeBox, envelopePlane] = boundingBox(gctx, candidate.detEles, toCenter,
390  volBoundSet, surfBoundSet);
391 
393  SpectrometerSector::defineArgs sectorArgs{};
394  sectorArgs.bounds = envelopeBox;
395  sectorArgs.surface = Acts::Surface::makeShared<Acts::PlaneSurface>(toCenter.inverse() * envelopeCentre, envelopePlane);
396 
397  if (!isNsw(candidate.detEles.front())) {
399  std::map<PVConstLink, std::vector<const MuonReadoutElement*>> stationMap{};
401  for (const MuonReadoutElement* re : candidate.detEles) {
402  stationMap[re->getMaterialGeom()->getParent()].push_back(re);
403  }
405  for (auto& [parent, detEles]: stationMap) {
406  const MuonReadoutElement* refEle = detEles.front();
407  const Amg::Transform3D toChambCentre = axisRotation(refEle->detectorType()) * refEle->globalToLocalTrans(gctx);
408  ATH_MSG_VERBOSE("New chambre candidate "<<m_idHelperSvc->toStringChamber(refEle->identify()));
409  const auto[chamberCentre, chamberBox, planeBounds] = boundingBox(gctx, detEles, toChambCentre, volBoundSet,
410  surfBoundSet, 0.1*Gaudi::Units::cm);
411  chamberArgs chambArgs{};
412  chambArgs.detEles =std::move(detEles);
413  chambArgs.bounds = chamberBox;
414  chambArgs.surface = Acts::Surface::makeShared<Acts::PlaneSurface>(toChambCentre.inverse() * chamberCentre, planeBounds);
415  const Chamber* newChamber {sectorArgs.chambers.emplace_back(std::make_unique<Chamber>(std::move(chambArgs))).get()};
416  for (const MuonReadoutElement* re : newChamber->readoutEles()) {
417  reIds.insert(re->identify());
418  mgr.getReadoutElement(re->identify())->setChamberLink(newChamber);
419  }
420  }
421  } else {
422  const MuonReadoutElement* refEle = candidate.detEles.front();
423  const Amg::Transform3D toChambCentre = axisRotation(refEle->detectorType()) * refEle->globalToLocalTrans(gctx);
424  ATH_MSG_VERBOSE("New chambre candidate "<<m_idHelperSvc->toStringChamber(refEle->identify()));
425  const auto[chamberCentre, chamberBox, planeBounds] = boundingBox(gctx, candidate.detEles, toChambCentre,
426  volBoundSet, surfBoundSet, 0.1*Gaudi::Units::cm);
427  chamberArgs chambArgs{};
428  chambArgs.detEles = candidate.detEles;
429  chambArgs.bounds = chamberBox;
430  chambArgs.surface = Acts::Surface::makeShared<Acts::PlaneSurface>(toChambCentre.inverse() * chamberCentre, planeBounds);
431  const Chamber* newChamber {sectorArgs.chambers.emplace_back(std::make_unique<Chamber>(std::move(chambArgs))).get()};
432  for (const MuonReadoutElement* re : newChamber->readoutEles()) {
433  reIds.insert(re->identify());
434  mgr.getReadoutElement(re->identify())->setChamberLink(newChamber);
435  }
436  }
437  std::ranges::sort(sectorArgs.chambers, [](const SpectrometerSector::ChamberPtr& a,
439  return (*a) < (*b);
440  });
441  const Amg::Transform3D globalToSector = sectorArgs.surface->transform(gctx.context()).inverse();
442 
444  for (auto & chamber : sectorArgs.chambers){
445  // split by readout elements - MDT multilayers and trigger chambers
446  for (auto & RE : chamber->readoutEles()){
447  // get the center of the element in the sector frame
448  const Amg::Transform3D& chamberToGlobal{RE->localToGlobalTrans(gctx)};
449  const Amg::Vector3D origin = (globalToSector * chamberToGlobal).translation();
450  // and then add the bounds of the element - this is technology dependent
451  sectorArgs.detectorLocs.emplace_back(origin, RE, boundingBox(RE, volBoundSet));
452  }
453  }
454  auto newSector = std::make_unique<SpectrometerSector>(std::move(sectorArgs));
455 
456  for (const Identifier& chId : reIds) {
457  mgr.getReadoutElement(chId)->setSectorLink(newSector.get());
458  }
459  ATH_MSG_VERBOSE("Add new sector "<<(*newSector));
460  mgr.addSpectrometerSector(std::move(newSector));
461  }
462  return StatusCode::SUCCESS;
463 }

◆ centerTrapezoid()

Amg::Transform3D MuonGMR4::ChamberAssembleTool::centerTrapezoid ( const std::array< Amg::Vector3D, 8 > &  cornerPoints)
staticprivate

Returns the translation transform centering the 8 corner points of the trapezoid.

The centre is defined as the centre point of the surrounding box

Parameters
cornerPointsArray to all 8 corner points of the trapezoid

Definition at line 144 of file ChamberAssembleTool.cxx.

144  {
145 
146  static constexpr double maxSize = 200.*Gaudi::Units::km;
147  double minX{maxSize}, maxX{-maxSize}, minY{maxSize}, maxY{-maxSize}, minZ{maxSize}, maxZ{-maxSize};
148  for (const Amg::Vector3D& corner : corners) {
149  minX = std::min(corner.x(), minX);
150  maxX = std::max(corner.x(), maxX);
151  minY = std::min(corner.y(), minY);
152  maxY = std::max(corner.y(), maxY);
153  minZ = std::min(corner.z(), minZ);
154  maxZ = std::max(corner.z(), maxZ);
155  }
156  return Amg::getTranslate3D(-0.5*(minX + maxX), -0.5*(minY + maxY), -0.5*(minZ + maxZ));
157 }

◆ cornerPoints()

std::array< Amg::Vector3D, 8 > MuonGMR4::ChamberAssembleTool::cornerPoints ( const Amg::Transform3D localToGlob,
const TrapVolBound_t bounds 
)
staticprivate

Returns the 8 corners marking the trapezoid.

Parameters
localToGlobTransform from the trapezoid restframe -> chambers frame
boundsReference to the trapezoidal bounds defining the volume

Definition at line 131 of file ChamberAssembleTool.cxx.

132  {
133  std::array<Amg::Vector3D, 8> toRet{make_array<Amg::Vector3D,8>(Amg::Vector3D::Zero())};
134  std::array<Amg::Vector3D, 4> plane = cornerPointsPlane(localToGlob, bounds);
135  for (unsigned int z : {0, 1}){
136  const double sign {z ? 1. : -1.};
137  const Amg::Vector3D stretch = (sign * bounds.get(BoundEnum::eHalfLengthZ)) * Amg::Vector3D::UnitZ();
138  for (unsigned int b = 0; b < plane.size(); ++b){
139  toRet[b + z * plane.size()] = plane[b] + stretch;
140  }
141  }
142  return toRet;
143 }

◆ cornerPointsPlane()

std::array< Amg::Vector3D, 4 > MuonGMR4::ChamberAssembleTool::cornerPointsPlane ( const Amg::Transform3D localToGlob,
const TrapVolBound_t bounds 
)
staticprivate

Returns the 4 corners of the trapezoid in the x-y plane.

Parameters
localToGlobTransform from the trapezoid restframe -> chambers frame
boundsReference to the trapezoidal bounds defining the volume

Definition at line 121 of file ChamberAssembleTool.cxx.

122  {
123  std::array<Amg::Vector3D,4> planePoints{
124  localToGlob * Amg::Vector3D(-bounds.get(BoundEnum::eHalfLengthXnegY), -bounds.get(BoundEnum::eHalfLengthY), 0. ),
125  localToGlob * Amg::Vector3D(-bounds.get(BoundEnum::eHalfLengthXposY), bounds.get(BoundEnum::eHalfLengthY), 0. ),
126  localToGlob * Amg::Vector3D(bounds.get(BoundEnum::eHalfLengthXnegY), -bounds.get(BoundEnum::eHalfLengthY), 0. ),
127  localToGlob * Amg::Vector3D(bounds.get(BoundEnum::eHalfLengthXposY), bounds.get(BoundEnum::eHalfLengthY), 0. ),
128  };
129  return planePoints;
130 }

◆ trapezoidEdgeDist()

double MuonGMR4::ChamberAssembleTool::trapezoidEdgeDist ( const Amg::Vector3D linePos,
const Amg::Vector3D lineDir,
const Amg::Vector3D testMe,
bool  leftEdge 
)
staticprivate

Returns the signed distances of an external point to the trapezoidal edge.

Distances > 0 indicate that the point is inside the boundaries and outside otherwise

Parameters
linePosArbitrary point on the trapezoidal edge
lineDirDirection of the trapezoidal edge
testMeExternal point to measure the distance
leftEdgeSwitch indicating whether the edge is on the left & right side

Construct the normal pointing inwards

Definition at line 69 of file ChamberAssembleTool.cxx.

72  {
74  const Amg::Vector3D normal = lineDir.cross((leftEdge ? 1. : -1.) *Amg::Vector3D::UnitZ());
75  const Amg::Vector3D closest = linePos + lineDir.dot(testMe - linePos) * lineDir;
76  return normal.dot(testMe - closest);
77 }

Member Data Documentation

◆ m_geoUtilTool

PublicToolHandle<IMuonGeoUtilityTool> MuonGMR4::ChamberAssembleTool::m_geoUtilTool {this,"GeoUtilTool", "" }
private

Definition at line 92 of file ChamberAssembleTool.h.

◆ m_idHelperSvc

ServiceHandle<Muon::IMuonIdHelperSvc> MuonGMR4::ChamberAssembleTool::m_idHelperSvc {this, "IdHelperSvc", "Muon::MuonIdHelperSvc/MuonIdHelperSvc"}
private

Definition at line 91 of file ChamberAssembleTool.h.


The documentation for this class was generated from the following files:
xAOD::iterator
JetConstituentVector::iterator iterator
Definition: JetConstituentVector.cxx:68
make_hlt_rep.pars
pars
Definition: make_hlt_rep.py:90
MuonGMR4::SpectrometerSector::ChamberPtr
GeoModel::TransientConstSharedPtr< Chamber > ChamberPtr
Definition: SpectrometerSector.h:42
MuonGMR4::ChamberAssembleTool::centerTrapezoid
static Amg::Transform3D centerTrapezoid(const std::array< Amg::Vector3D, 8 > &cornerPoints)
Returns the translation transform centering the 8 corner points of the trapezoid.
Definition: ChamberAssembleTool.cxx:144
MuonGMR4::Chamber::defineArgs::detEles
ReadoutSet detEles
List of associated readout elements.
Definition: Chamber.h:31
xAOD::L2MuonParameters::Chamber
Chamber
Define chamber types and locations.
Definition: TrigMuonDefs.h:15
python.CaloAddPedShiftConfig.args
args
Definition: CaloAddPedShiftConfig.py:47
MuonGMR4::ChamberAssembleTool::cornerPointsPlane
static std::array< Amg::Vector3D, 4 > cornerPointsPlane(const Amg::Transform3D &localToGlob, const TrapVolBound_t &bounds)
Returns the 4 corners of the trapezoid in the x-y plane.
Definition: ChamberAssembleTool.cxx:121
calibdata.chamber
chamber
Definition: calibdata.py:31
max
constexpr double max()
Definition: ap_fixedTest.cxx:33
MuonGMR4::chamberArgs
Chamber::defineArgs chamberArgs
Definition: ChamberAssembleTool.cxx:66
min
constexpr double min()
Definition: ap_fixedTest.cxx:26
MuonGMR4::ChamberAssembleTool::m_idHelperSvc
ServiceHandle< Muon::IMuonIdHelperSvc > m_idHelperSvc
Definition: ChamberAssembleTool.h:91
Muon::MuonStationIndex::stName
const std::string & stName(StIndex index)
convert StIndex into a string
Definition: MuonStationIndex.cxx:104
ActsTrk::DetectorType::Tgc
@ Tgc
Resitive Plate Chambers.
deg
#define deg
Definition: SbPolyhedron.cxx:17
ATH_MSG_VERBOSE
#define ATH_MSG_VERBOSE(x)
Definition: AthMsgStreamMacros.h:28
ActsTrk::DetectorType::sTgc
@ sTgc
Micromegas (NSW)
Amg::getRotateZ3D
Amg::Transform3D getRotateZ3D(double angle)
get a rotation transformation around Z-axis
Definition: GeoPrimitivesHelpers.h:270
BchCleanup.mgr
mgr
Definition: BchCleanup.py:294
cm
const double cm
Definition: Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimParametrization/tools/FCAL_ChannelMap.cxx:25
MuonGMR4::ChamberAssembleTool::boundingBox
TrfWithBounds boundingBox(const ActsGeometryContext &gctx, const std::vector< const MuonReadoutElement * > &readoutEles, const Amg::Transform3D &globToLoc, Acts::VolumeBoundFactory &volBoundSet, Acts::SurfaceBoundFactory &surfBoundSet, const double margin=1.*Gaudi::Units::cm) const
builds the bounding box trapezoidal volume bounds from the set of readout elements Returns a pair of ...
Definition: ChamberAssembleTool.cxx:161
MuonGMR4::ChamberAssembleTool::VolBoundPtr_t
std::shared_ptr< Acts::TrapezoidVolumeBounds > VolBoundPtr_t
Definition: ChamberAssembleTool.h:41
Amg::getRotateX3D
Amg::Transform3D getRotateX3D(double angle)
get a rotation transformation around X-axis
Definition: GeoPrimitivesHelpers.h:252
Amg::toString
std::string toString(const Translation3D &translation, int precision=4)
GeoPrimitvesToStringConverter.
Definition: GeoPrimitivesToStringConverter.h:40
WriteCellNoiseToCool.exist
exist
Definition: WriteCellNoiseToCool.py:543
ActsTrk::DetectorType::Mm
@ Mm
Maybe not needed in the migration.
z
#define z
Amg::Transform3D
Eigen::Affine3d Transform3D
Definition: GeoPrimitives.h:46
test_pyathena.parent
parent
Definition: test_pyathena.py:15
sign
int sign(int a)
Definition: TRT_StrawNeighbourSvc.h:108
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
python.SystemOfUnits.km
float km
Definition: SystemOfUnits.py:110
ActsGeometryContext
Include the GeoPrimitives which need to be put first.
Definition: ActsGeometryContext.h:27
ActsTrk::DetectorType::Mdt
@ Mdt
MuonSpectrometer.
ActsTrk::to_string
std::string to_string(const DetectorType &type)
Definition: GeometryDefs.h:34
plotBeamSpotMon.b
b
Definition: plotBeamSpotMon.py:76
Amg::Vector3D
Eigen::Matrix< double, 3, 1 > Vector3D
Definition: GeoPrimitives.h:47
THROW_EXCEPTION
#define THROW_EXCEPTION(MESSAGE)
Definition: throwExcept.h:10
MuonGMR4::ChamberAssembleTool::cornerPoints
static std::array< Amg::Vector3D, 8 > cornerPoints(const Amg::Transform3D &localToGlob, const TrapVolBound_t &bounds)
Returns the 8 corners marking the trapezoid.
Definition: ChamberAssembleTool.cxx:131
python.PyAthena.v
v
Definition: PyAthena.py:154
MuonGMR4::ChamberAssembleTool::SurfBoundPtr_t
std::shared_ptr< const Acts::PlanarBounds > SurfBoundPtr_t
Definition: ChamberAssembleTool.h:40
a
TList * a
Definition: liststreamerinfos.cxx:10
y
#define y
re
const boost::regex re(r_e)
MuonGMR4::ChamberAssembleTool::trapezoidEdgeDist
static double trapezoidEdgeDist(const Amg::Vector3D &linePos, const Amg::Vector3D &lineDir, const Amg::Vector3D &testMe, bool leftEdge)
Returns the signed distances of an external point to the trapezoidal edge.
Definition: ChamberAssembleTool.cxx:69
if
if(febId1==febId2)
Definition: LArRodBlockPhysicsV0.cxx:567
ActsTrk::DetectorType::Rpc
@ Rpc
Monitored Drift Tubes.
python.Constants.VERBOSE
int VERBOSE
Definition: Control/AthenaCommon/python/Constants.py:13
CaloLCW_tf.trf
trf
Definition: CaloLCW_tf.py:20
MuonGMR4::ChamberAssembleTool::m_geoUtilTool
PublicToolHandle< IMuonGeoUtilityTool > m_geoUtilTool
Definition: ChamberAssembleTool.h:92
generate::Zero
void Zero(TH1D *hin)
Definition: generate.cxx:32
Amg::getTranslate3D
Amg::Transform3D getTranslate3D(const double X, const double Y, const double Z)
: Returns a shift transformation along an arbitrary axis
Definition: GeoPrimitivesHelpers.h:289
MuonGMR4::defineArgs
RpcReadoutElement::defineArgs defineArgs
Definition: RpcReadoutGeomTool.cxx:32
Identifier
Definition: IdentifierFieldParser.cxx:14