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

 ChamberAssembleTool (const std::string &type, const std::string &name, const IInterface *parent)
 Standard constructor of the tool. More...
 
virtual StatusCode buildReadOutElements (MuonDetectorManager &mgr) override final
 

Private Types

using BoundType = Acts::TrapezoidVolumeBounds
 
using BoundTrfPair = std::pair< std::shared_ptr< BoundType >, Amg::Transform3D >
 

Private Member Functions

BoundTrfPair boundingBox (const ActsGeometryContext &gctx, const std::vector< const MuonReadoutElement * > &readoutEles, const Amg::Transform3D &globToLoc, ActsTrk::SurfaceBoundSet< BoundType > &boundSet, 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 std::shared_ptr< BoundTypeboundingBox (const MuonReadoutElement *reEle, ActsTrk::SurfaceBoundSet< BoundType > &boundSet)
 Builds the trapezoidal bounding box enclosing a single readout element. More...
 
static std::array< Amg::Vector3D, 4 > cornerPointsPlane (const Amg::Transform3D &localToGlob, const BoundType &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 BoundType &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 26 of file ChamberAssembleTool.h.

Member Typedef Documentation

◆ BoundTrfPair

using MuonGMR4::ChamberAssembleTool::BoundTrfPair = std::pair<std::shared_ptr<BoundType>, Amg::Transform3D>
private

Definition at line 38 of file ChamberAssembleTool.h.

◆ BoundType

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

Definition at line 36 of file ChamberAssembleTool.h.

Constructor & Destructor Documentation

◆ ChamberAssembleTool()

MuonGMR4::ChamberAssembleTool::ChamberAssembleTool ( const std::string &  type,
const std::string &  name,
const IInterface *  parent 
)

Standard constructor of the tool.

Definition at line 64 of file ChamberAssembleTool.cxx.

65  :
66  base_class{type,name,parent}{}

Member Function Documentation

◆ boundingBox() [1/2]

ChamberAssembleTool::BoundTrfPair MuonGMR4::ChamberAssembleTool::boundingBox ( const ActsGeometryContext gctx,
const std::vector< const MuonReadoutElement * > &  readoutEles,
const Amg::Transform3D globToLoc,
ActsTrk::SurfaceBoundSet< BoundType > &  boundSet,
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 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 162 of file ChamberAssembleTool.cxx.

166  {
167 
168  std::shared_ptr<BoundType> 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  std::shared_ptr<BoundType> bounds = boundingBox(chambEle, boundSet);
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  }
189  const std::array<Amg::Vector3D, 8> corners = cornerPoints(trf, *bounds);
190 
191  Acts::Volume volume{Amg::Transform3D::Identity(), envelopeBounds};
193  if (std::ranges::find_if(corners, [&volume](const Amg::Vector3D& v) {
194  return !volume.inside(v);}) == corners.end()) {
195  ATH_MSG_VERBOSE("Readout element "<<m_idHelperSvc->toStringDetEl(chambEle->identify())<<" "
196  <<(*boundingBox(chambEle, boundSet))<<" fully contained. ");
197  continue;
198  }
199  if (msgLvl(MSG::VERBOSE)) {
200  std::stringstream debugStr{};
201  for (const Amg::Vector3D& corner : corners) {
202  debugStr<<" ***** "<<Amg::toString(corner)<<std::endl;
203  }
204  ATH_MSG_VERBOSE(m_idHelperSvc->toString(chambEle->identify())<<" corner points "
205  <<GeoTrf::toString(trf, true)<<std::endl<<debugStr.str());
206  }
208  const std::array<Amg::Vector3D, 8> refCorners{cornerPoints(Amg::Transform3D::Identity(), *envelopeBounds)};
210  std::array<Amg::Vector3D, 8> newTrapBounds{make_array<Amg::Vector3D, 8>(Amg::Vector3D::Zero())};
211 
213  for (unsigned lowZ : {0, 4}) {
214  for (bool isLeft : {false, true}) {
215 
216  const size_t iHigh = 1 + (!isLeft)*2 + lowZ;
217  const size_t iLow = 0 + (!isLeft)*2 + lowZ;
219  const Amg::Vector3D dirRef{projectIntoXY(refCorners[iHigh] - refCorners[iLow]).unit()};
220  const Amg::Vector3D dirCan{projectIntoXY(corners[iHigh] - corners[iLow]).unit()};
221 
222 
223  ATH_MSG_VERBOSE((isLeft ? "Left" : "Right")<<" edge "<<Amg::toString(dirRef)
224  <<" "<<dirRef.phi() / Gaudi::Units::deg <<" --- "
225  <<m_idHelperSvc->toStringDetEl(chambEle->identify())<<" "
226  <<Amg::toString(dirCan)<<", phi: "<<dirCan.phi() / Gaudi::Units::deg);
227 
229  const Amg::Vector3D& pickDir{(dirRef.phi() > dirCan.phi()) == isLeft ? dirRef : dirCan};
232  const double cornerLowD = trapezoidEdgeDist(refCorners[iLow], pickDir, corners[iLow], isLeft);
233  const double cornerHighD = trapezoidEdgeDist(refCorners[iLow], pickDir, corners[iHigh], isLeft);
234  ATH_MSG_VERBOSE("Distance "<<cornerLowD<<"/ "<<cornerHighD);
236  const Amg::Vector3D& pickPos{cornerLowD < 0 || cornerHighD < 0 ?
237  cornerLowD < cornerHighD ? corners[iLow] : corners[iHigh]: refCorners[iLow]};
238 
239  ATH_MSG_VERBOSE("Low points "<<Amg::toString(corners[iLow])<<" - "<<Amg::toString(refCorners[iLow]));
240  ATH_MSG_VERBOSE("High points "<<Amg::toString(corners[iHigh])<<" - "<<Amg::toString(refCorners[iHigh]));
241 
243  newTrapBounds[iHigh] = pickPos + Amg::intersect<3>(pickPos, pickDir, Amg::Vector3D::UnitY(),
244  std::max(corners[iHigh].y(), refCorners[iHigh].y())).value_or(0.) * pickDir;
245 
246  newTrapBounds[iHigh].z() = lowZ ? std::max(corners[iHigh].z(),refCorners[iHigh].z())
247  : std::min(corners[iHigh].z(), refCorners[iHigh].z());
248  newTrapBounds[iLow] = pickPos + Amg::intersect<3>(pickPos, pickDir, Amg::Vector3D::UnitY(),
249  std::min(corners[iLow].y(), refCorners[iLow].y())).value_or(0.) * pickDir;
250  newTrapBounds[iLow].z() = lowZ ? std::max(corners[iLow].z(), refCorners[iLow].z())
251  : std::min(corners[iLow].z(), refCorners[iLow].z());
252 
253  ATH_MSG_VERBOSE("New end points "<<Amg::toString(newTrapBounds[iLow])<<" - "<<Amg::toString(newTrapBounds[iHigh]));
254  }
255  }
256  if (msgLvl(MSG::VERBOSE)) {
257  std::stringstream debugStr{};
258  for (const Amg::Vector3D& edge : newTrapBounds) {
259  debugStr<<"***** "<<Amg::toString(edge)<<std::endl;
260  }
261  ATH_MSG_VERBOSE("#############################################################"<<std::endl<<
262  debugStr.str()<<"#############################################################");
263  }
265  const double halfY = 0.5*std::max(newTrapBounds[1].y() - newTrapBounds[0].y(),
266  newTrapBounds[3].y() - newTrapBounds[2].y());
267  const double lHalfX = 0.5*(newTrapBounds[3].x() - newTrapBounds[1].x());
268  const double sHalfX = 0.5*(newTrapBounds[2].x() - newTrapBounds[0].x());
269  const double halfZ = 0.5*(newTrapBounds[4].z() - newTrapBounds[0].z());
270  envelopeBounds = boundSet.make_bounds(sHalfX, lHalfX, halfY, halfZ);
271  ATH_MSG_VERBOSE(m_idHelperSvc->toStringDetEl(chambEle->identify())<<" "<<(*envelopeBounds));
272 
274  const Amg::Transform3D centerShift = centerTrapezoid(newTrapBounds);
275  newCentreTrf = centerShift * newCentreTrf;
276  ATH_MSG_VERBOSE("New trapezoid centering "<<Amg::toString(centerShift)<<" combined: "
277  <<Amg::toString(newCentreTrf));
278  }
279 
280  envelopeBounds = boundSet.make_bounds(envelopeBounds->get(BoundEnum::eHalfLengthXnegY)+margin,
281  envelopeBounds->get(BoundEnum::eHalfLengthXposY)+margin,
282  envelopeBounds->get(BoundEnum::eHalfLengthY)+margin,
283  envelopeBounds->get(BoundEnum::eHalfLengthZ)+margin);
284  return std::make_pair(envelopeBounds, newCentreTrf.inverse());
285 }

◆ boundingBox() [2/2]

std::shared_ptr< ChamberAssembleTool::BoundType > MuonGMR4::ChamberAssembleTool::boundingBox ( const MuonReadoutElement reEle,
ActsTrk::SurfaceBoundSet< BoundType > &  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 81 of file ChamberAssembleTool.cxx.

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

◆ 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

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 287 of file ChamberAssembleTool.cxx.

287  {
288  ATH_CHECK(m_idHelperSvc.retrieve());
289  ATH_CHECK(m_geoUtilTool.retrieve());
290 
292  auto mdtStationIndex = [this] (const std::string& stName) {
293  return m_idHelperSvc->hasMDT() ? m_idHelperSvc->mdtIdHelper().stationNameIndex(stName) : -1;
294  };
295  auto tgcStationIndex = [this] (const std::string& stName) {
296  return m_idHelperSvc->hasTGC() ? m_idHelperSvc->tgcIdHelper().stationNameIndex(stName) : -1;
297  };
298 
299  const std::unordered_set<int> stIndicesEIL{mdtStationIndex("EIL"), mdtStationIndex("T4E")};
300  const std::unordered_set<int> stIndicesEM{mdtStationIndex("EML"), mdtStationIndex("EMS"),
301  tgcStationIndex("T1E"), tgcStationIndex("T1F"),
302  tgcStationIndex("T2E"), tgcStationIndex("T2F"),
303  tgcStationIndex("T3E"), tgcStationIndex("T3F")};
304 
305  const std::set<Identifier> BOE_ids{m_idHelperSvc->hasMDT() ? m_idHelperSvc->mdtIdHelper().elementID("BOL", 7,7): Identifier{},
306  m_idHelperSvc->hasMDT() ? m_idHelperSvc->mdtIdHelper().elementID("BOL", -7,7): Identifier{},
307  m_idHelperSvc->hasRPC() ? m_idHelperSvc->rpcIdHelper().elementID("BOL", -8, 7, 1) : Identifier{},
308  m_idHelperSvc->hasRPC() ? m_idHelperSvc->rpcIdHelper().elementID("BOL", 8, 7, 1) : Identifier{}};
309 
310  std::vector<MuonReadoutElement*> allReadOutEles = mgr.getAllReadoutElements();
311 
312  std::vector<chamberArgs> envelopeCandidates{};
313 
315  for (const MuonReadoutElement* readOutEle : allReadOutEles) {
316  std::vector<chamberArgs>::iterator exist = std::ranges::find_if(envelopeCandidates,
317  [this, readOutEle, &stIndicesEIL, &stIndicesEM, &BOE_ids](const chamberArgs& args){
318  const MuonReadoutElement* refEle = args.detEles.front();
319  const Identifier refId = refEle->identify();
320  const Identifier testId = readOutEle->identify();
322  if (sign(refEle->stationEta()) != sign(readOutEle->stationEta())) {
323  return false;
324  }
326  if (m_idHelperSvc->sector(testId) != m_idHelperSvc->sector(refId)) {
327  return false;
328  }
330  if (BOE_ids.count(m_idHelperSvc->chamberId(refId)) !=
331  BOE_ids.count(m_idHelperSvc->chamberId(testId))){
332  return false;
333  }
336  if (readOutEle->stationName() == refEle->stationName()) {
337  return true;
338  }
340  if (isNsw(readOutEle) && isNsw(refEle)) return true;
342  if (stIndicesEM.count(readOutEle->stationName()) &&
343  stIndicesEM.count(refEle->stationName())) {
344  return true;
345  }
347  if (stIndicesEIL.count(readOutEle->stationName()) &&
348  stIndicesEIL.count(refEle->stationName())) {
349  return true;
350  }
351  return false;// readOutEle->chamberIndex() == refEle->chamberIndex();
352  });
354  if (exist == envelopeCandidates.end()) {
355  chamberArgs newChamb{};
356  newChamb.detEles.push_back(readOutEle);
357  envelopeCandidates.push_back(std::move(newChamb));
358  } else {
359  exist->detEles.push_back(readOutEle);
360  }
361  }
363  ActsGeometryContext gctx{};
364 
365 
367  for (chamberArgs& candidate : envelopeCandidates) {
368  std::unordered_set<Identifier> reIds{};
369  const MuonReadoutElement* refEle = candidate.detEles.front();
370  const Amg::Transform3D toCenter = axisRotation(refEle->detectorType()) * refEle->globalToLocalTrans(gctx);
371  ATH_MSG_VERBOSE("New envelope candidate ");
372  const auto [envelopeBox, envelopeCentre] = boundingBox(gctx, candidate.detEles, toCenter, boundSet);
373 
375  SpectrometerSector::defineArgs sectorArgs{};
376  sectorArgs.bounds = envelopeBox;
377  sectorArgs.locToGlobTrf = toCenter.inverse() * envelopeCentre;
378 
379  if (!isNsw(candidate.detEles.front())) {
381  std::map<PVConstLink, std::vector<const MuonReadoutElement*>> stationMap{};
383  for (const MuonReadoutElement* re : candidate.detEles) {
384  stationMap[re->getMaterialGeom()->getParent()].push_back(re);
385  }
387  for (auto& [parent, detEles]: stationMap) {
388  const MuonReadoutElement* refEle = detEles.front();
389  const Amg::Transform3D toChambCentre = axisRotation(refEle->detectorType()) * refEle->globalToLocalTrans(gctx);
390  ATH_MSG_VERBOSE("New chambre candidate "<<m_idHelperSvc->toStringChamber(refEle->identify()));
391  const auto[chamberBox, chamberCentre] = boundingBox(gctx, detEles, toChambCentre, boundSet, 0.1*Gaudi::Units::cm);
392  chamberArgs chambArgs{};
393  chambArgs.detEles =std::move(detEles);
394  chambArgs.bounds = chamberBox;
395  chambArgs.locToGlobTrf = toChambCentre.inverse() * chamberCentre;
396  const Chamber* newChamber {sectorArgs.chambers.emplace_back(std::make_unique<Chamber>(std::move(chambArgs))).get()};
397  for (const MuonReadoutElement* re : newChamber->readoutEles()) {
398  reIds.insert(re->identify());
399  mgr.getReadoutElement(re->identify())->setChamberLink(newChamber);
400  }
401  }
402  } else {
403  const MuonReadoutElement* refEle = candidate.detEles.front();
404  const Amg::Transform3D toChambCentre = axisRotation(refEle->detectorType()) * refEle->globalToLocalTrans(gctx);
405  ATH_MSG_VERBOSE("New chambre candidate "<<m_idHelperSvc->toStringChamber(refEle->identify()));
406  const auto[chamberBox, chamberCentre] = boundingBox(gctx, candidate.detEles, toChambCentre, boundSet, 0.1*Gaudi::Units::cm);
407  chamberArgs chambArgs{};
408  chambArgs.detEles = candidate.detEles;
409  chambArgs.bounds = chamberBox;
410  chambArgs.locToGlobTrf = toChambCentre.inverse() * chamberCentre;
411  const Chamber* newChamber {sectorArgs.chambers.emplace_back(std::make_unique<Chamber>(std::move(chambArgs))).get()};
412  for (const MuonReadoutElement* re : newChamber->readoutEles()) {
413  reIds.insert(re->identify());
414  mgr.getReadoutElement(re->identify())->setChamberLink(newChamber);
415  }
416  }
417  std::ranges::sort(sectorArgs.chambers, [](const SpectrometerSector::ChamberPtr& a,
419  return (*a) < (*b);
420  });
421  auto globalToSector = sectorArgs.locToGlobTrf.inverse();
422 
424  for (auto & chamber : sectorArgs.chambers){
425  // split by readout elements - MDT multilayers and trigger chambers
426  for (auto & RE : chamber->readoutEles()){
427  // get the center of the element in the sector frame
428  auto chamberToGlobal = RE->localToGlobalTrans(gctx);
429  Amg::Vector3D origin {0, 0, 0};
430  origin = globalToSector * chamberToGlobal * origin;
431  // and then add the bounds of the element - this is technology dependent
432  if (RE->detectorType()==ActsTrk::DetectorType::Mdt){
433  const MuonGMR4::MdtReadoutElement* MDT = dynamic_cast<const MuonGMR4::MdtReadoutElement*>(RE);
434  sectorArgs.chamberLocs.emplace_back(origin.y() - MDT->getParameters().halfY,
435  origin.y() + MDT->getParameters().halfY,
436  origin.z() - MDT->getParameters().halfHeight,
437  origin.z() + MDT->getParameters().halfHeight,
438  RE->detectorType());
439  }
440  else if (RE->detectorType()==ActsTrk::DetectorType::Rpc){
441  const MuonGMR4::RpcReadoutElement* RPC = dynamic_cast<const MuonGMR4::RpcReadoutElement*>(RE);
442  sectorArgs.chamberLocs.emplace_back(origin.y() - RPC->getParameters().halfLength,
443  origin.y() + RPC->getParameters().halfLength,
444  origin.z() - RPC->getParameters().halfThickness,
445  origin.z() + RPC->getParameters().halfThickness,
446  RE->detectorType());
447  }
448  else if (RE->detectorType()==ActsTrk::DetectorType::Tgc){
449  const MuonGMR4::TgcReadoutElement* TGC = dynamic_cast<const MuonGMR4::TgcReadoutElement*>(RE);
450  sectorArgs.chamberLocs.emplace_back(origin.y() - TGC->getParameters().halfHeight,
451  origin.y() + TGC->getParameters().halfHeight,
452  origin.z() - TGC->getParameters().halfThickness,
453  origin.z() + TGC->getParameters().halfThickness,
454  RE->detectorType());
455  }
456  else if (RE->detectorType() == ActsTrk::DetectorType::Mm){
457  const MuonGMR4::MmReadoutElement* MM = dynamic_cast<const MuonGMR4::MmReadoutElement*>(RE);
458  sectorArgs.chamberLocs.emplace_back(origin.y() - MM->getParameters().halfHeight,
459  origin.y() + MM->getParameters().halfHeight,
460  origin.z() - MM->getParameters().halfThickness,
461  origin.z() + MM->getParameters().halfThickness,
462  RE->detectorType());
463  }
464  }
465  }
466  auto newSector = std::make_unique<SpectrometerSector>(std::move(sectorArgs));
467 
468  for (const Identifier& chId : reIds) {
469  mgr.getReadoutElement(chId)->setSectorLink(newSector.get());
470  }
471  ATH_MSG_VERBOSE("Add new sector "<<(*newSector));
472  mgr.addSpectrometerSector(std::move(newSector));
473  }
474  return StatusCode::SUCCESS;
475 }

◆ 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 145 of file ChamberAssembleTool.cxx.

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

◆ cornerPoints()

std::array< Amg::Vector3D, 8 > MuonGMR4::ChamberAssembleTool::cornerPoints ( const Amg::Transform3D localToGlob,
const BoundType 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 132 of file ChamberAssembleTool.cxx.

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

◆ cornerPointsPlane()

std::array< Amg::Vector3D, 4 > MuonGMR4::ChamberAssembleTool::cornerPointsPlane ( const Amg::Transform3D localToGlob,
const BoundType 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 122 of file ChamberAssembleTool.cxx.

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

◆ 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 70 of file ChamberAssembleTool.cxx.

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

Member Data Documentation

◆ m_geoUtilTool

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

Definition at line 86 of file ChamberAssembleTool.h.

◆ m_idHelperSvc

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

Definition at line 85 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::MmReadoutElement
Definition: MmReadoutElement.h:19
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:145
MuonGMR4::Chamber::defineArgs::detEles
ReadoutSet detEles
List of associated readout elements.
Definition: Chamber.h:30
xAOD::L2MuonParameters::Chamber
Chamber
Define chamber types and locations.
Definition: TrigMuonDefs.h:15
calibdata.chamber
chamber
Definition: calibdata.py:32
max
constexpr double max()
Definition: ap_fixedTest.cxx:33
MuonGMR4::chamberArgs
Chamber::defineArgs chamberArgs
Definition: ChamberAssembleTool.cxx:62
min
constexpr double min()
Definition: ap_fixedTest.cxx:26
MuonGMR4::ChamberAssembleTool::m_idHelperSvc
ServiceHandle< Muon::IMuonIdHelperSvc > m_idHelperSvc
Definition: ChamberAssembleTool.h:85
ActsTrk::DetectorType::Tgc
@ Tgc
Resitive Plate Chambers.
MuonGMR4::ChamberAssembleTool::cornerPointsPlane
static std::array< Amg::Vector3D, 4 > cornerPointsPlane(const Amg::Transform3D &localToGlob, const BoundType &bounds)
Returns the 4 corners of the trapezoid in the x-y plane.
Definition: ChamberAssembleTool.cxx:122
deg
#define deg
Definition: SbPolyhedron.cxx:17
MM
@ MM
Definition: RegSelEnums.h:38
ATH_MSG_VERBOSE
#define ATH_MSG_VERBOSE(x)
Definition: AthMsgStreamMacros.h:28
ActsTrk::DetectorType::sTgc
@ sTgc
Micromegas (NSW)
THROW_EXCEPTION
#define THROW_EXCEPTION(MSG)
Definition: MMReadoutElement.cxx:48
MuonGMR4::RpcReadoutElement
Definition: MuonPhaseII/MuonDetDescr/MuonReadoutGeometryR4/MuonReadoutGeometryR4/RpcReadoutElement.h:17
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
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
TGC
Definition: TgcBase.h:6
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:107
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
MuonGMR4::ChamberAssembleTool::cornerPoints
static std::array< Amg::Vector3D, 8 > cornerPoints(const Amg::Transform3D &localToGlob, const BoundType &bounds)
Returns the 8 corners marking the trapezoid.
Definition: ChamberAssembleTool.cxx:132
ActsGeometryContext
Include the GeoPrimitives which need to be put first.
Definition: ActsGeometryContext.h:27
ActsTrk::SurfaceBoundSet
Definition: Tracking/Acts/ActsGeoUtils/ActsGeoUtils/Defs.h:17
MuonGMR4::ChamberAssembleTool::boundingBox
BoundTrfPair boundingBox(const ActsGeometryContext &gctx, const std::vector< const MuonReadoutElement * > &readoutEles, const Amg::Transform3D &globToLoc, ActsTrk::SurfaceBoundSet< BoundType > &boundSet, 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:162
ActsTrk::SurfaceBoundSet::make_bounds
std::shared_ptr< BoundType > make_bounds(argList... args)
Factory method to create new SurfaceBounds.
Definition: SurfaceBoundSet.h:20
ActsTrk::DetectorType::Mdt
@ Mdt
MuonSpectrometer.
RPC
@ RPC
Definition: RegSelEnums.h:32
MuonGMR4::MdtReadoutElement
Definition: MuonPhaseII/MuonDetDescr/MuonReadoutGeometryR4/MuonReadoutGeometryR4/MdtReadoutElement.h:22
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:228
ActsTrk::to_string
std::string to_string(const DetectorType &type)
Definition: GeometryDefs.h:34
plotBeamSpotMon.b
b
Definition: plotBeamSpotMon.py:77
Amg::Vector3D
Eigen::Matrix< double, 3, 1 > Vector3D
Definition: GeoPrimitives.h:47
python.PyAthena.v
v
Definition: PyAthena.py:154
a
TList * a
Definition: liststreamerinfos.cxx:10
y
#define y
python.CaloScaleNoiseConfig.type
type
Definition: CaloScaleNoiseConfig.py:78
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:70
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:14
CaloLCW_tf.trf
trf
Definition: CaloLCW_tf.py:20
MuonGMR4::ChamberAssembleTool::m_geoUtilTool
PublicToolHandle< IMuonGeoUtilityTool > m_geoUtilTool
Definition: ChamberAssembleTool.h:86
python.SystemOfUnits.km
int km
Definition: SystemOfUnits.py:95
MuonGMR4::TgcReadoutElement
Definition: MuonPhaseII/MuonDetDescr/MuonReadoutGeometryR4/MuonReadoutGeometryR4/TgcReadoutElement.h:19
python.CaloScaleNoiseConfig.args
args
Definition: CaloScaleNoiseConfig.py:80
MDT
@ MDT
Definition: RegSelEnums.h:31
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:37
Identifier
Definition: IdentifierFieldParser.cxx:14