Loading [MathJax]/extensions/tex2jax.js
ATLAS Offline Software
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
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 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 36 of file ChamberAssembleTool.h.

◆ BoundType

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

Definition at line 34 of file ChamberAssembleTool.h.

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

161  {
162 
163  std::shared_ptr<BoundType> envelopeBounds{};
164 
165  Amg::Transform3D newCentreTrf{Amg::Transform3D::Identity()};
166  for (const MuonReadoutElement* chambEle : readoutEles) {
167  Amg::Transform3D trf = newCentreTrf * toCenter *
168  chambEle->localToGlobalTrans(gctx) *
169  axisRotation(chambEle->detectorType()).inverse();
170  std::shared_ptr<BoundType> bounds = boundingBox(chambEle, boundSet);
171  if (!envelopeBounds) {
172  envelopeBounds = bounds;
173  newCentreTrf = centerTrapezoid(cornerPoints(trf, *bounds)) * newCentreTrf;
174  ATH_MSG_VERBOSE("Envelope "<<(*envelopeBounds)<<", transform: "<<Amg::toString(newCentreTrf));
175  continue;
176  }
179  GeoTrf::CoordEulerAngles rotAngles = GeoTrf::getCoordRotationAngles(trf);
180  if (std::abs(rotAngles.gamma - 180.*Gaudi::Units::deg)< std::numeric_limits<float>::epsilon()){
182  }
183  if (std::abs(rotAngles.alpha - 180.*Gaudi::Units::deg)< std::numeric_limits<float>::epsilon()){
185  }
187  const std::array<Amg::Vector3D, 8> corners = cornerPoints(trf, *bounds);
188 
189  Acts::Volume volume{Amg::Transform3D::Identity(), envelopeBounds};
191  if (std::ranges::find_if(corners, [&volume](const Amg::Vector3D& v) {
192  return !volume.inside(v);}) == corners.end()) {
193  ATH_MSG_VERBOSE("Readout element "<<m_idHelperSvc->toStringDetEl(chambEle->identify())<<" "
194  <<(*boundingBox(chambEle, boundSet))<<" fully contained. ");
195  continue;
196  }
197  if (msgLvl(MSG::VERBOSE)) {
198  std::stringstream debugStr{};
199  for (const Amg::Vector3D& corner : corners) {
200  debugStr<<" ***** "<<Amg::toString(corner)<<std::endl;
201  }
202  ATH_MSG_VERBOSE(m_idHelperSvc->toString(chambEle->identify())<<" corner points "
203  <<GeoTrf::toString(trf, true)<<std::endl<<debugStr.str());
204  }
206  const std::array<Amg::Vector3D, 8> refCorners{cornerPoints(Amg::Transform3D::Identity(), *envelopeBounds)};
208  std::array<Amg::Vector3D, 8> newTrapBounds{make_array<Amg::Vector3D, 8>(Amg::Vector3D::Zero())};
209 
211  for (unsigned lowZ : {0, 4}) {
212  for (bool isLeft : {false, true}) {
213 
214  const size_t iHigh = 1 + (!isLeft)*2 + lowZ;
215  const size_t iLow = 0 + (!isLeft)*2 + lowZ;
217  const Amg::Vector3D dirRef{projectIntoXY(refCorners[iHigh] - refCorners[iLow]).unit()};
218  const Amg::Vector3D dirCan{projectIntoXY(corners[iHigh] - corners[iLow]).unit()};
219 
220 
221  ATH_MSG_VERBOSE((isLeft ? "Left" : "Right")<<" edge "<<Amg::toString(dirRef)
222  <<" "<<dirRef.phi() / Gaudi::Units::deg <<" --- "
223  <<m_idHelperSvc->toStringDetEl(chambEle->identify())<<" "
224  <<Amg::toString(dirCan)<<", phi: "<<dirCan.phi() / Gaudi::Units::deg);
225 
227  const Amg::Vector3D& pickDir{(dirRef.phi() > dirCan.phi()) == isLeft ? dirRef : dirCan};
230  const double cornerLowD = trapezoidEdgeDist(refCorners[iLow], pickDir, corners[iLow], isLeft);
231  const double cornerHighD = trapezoidEdgeDist(refCorners[iLow], pickDir, corners[iHigh], isLeft);
232  ATH_MSG_VERBOSE("Distance "<<cornerLowD<<"/ "<<cornerHighD);
234  const Amg::Vector3D& pickPos{cornerLowD < 0 || cornerHighD < 0 ?
235  cornerLowD < cornerHighD ? corners[iLow] : corners[iHigh]: refCorners[iLow]};
236 
237  ATH_MSG_VERBOSE("Low points "<<Amg::toString(corners[iLow])<<" - "<<Amg::toString(refCorners[iLow]));
238  ATH_MSG_VERBOSE("High points "<<Amg::toString(corners[iHigh])<<" - "<<Amg::toString(refCorners[iHigh]));
239 
241  newTrapBounds[iHigh] = pickPos + Amg::intersect<3>(pickPos, pickDir, Amg::Vector3D::UnitY(),
242  std::max(corners[iHigh].y(), refCorners[iHigh].y())).value_or(0.) * pickDir;
243 
244  newTrapBounds[iHigh].z() = lowZ ? std::max(corners[iHigh].z(),refCorners[iHigh].z())
245  : std::min(corners[iHigh].z(), refCorners[iHigh].z());
246  newTrapBounds[iLow] = pickPos + Amg::intersect<3>(pickPos, pickDir, Amg::Vector3D::UnitY(),
247  std::min(corners[iLow].y(), refCorners[iLow].y())).value_or(0.) * pickDir;
248  newTrapBounds[iLow].z() = lowZ ? std::max(corners[iLow].z(), refCorners[iLow].z())
249  : std::min(corners[iLow].z(), refCorners[iLow].z());
250 
251  ATH_MSG_VERBOSE("New end points "<<Amg::toString(newTrapBounds[iLow])<<" - "<<Amg::toString(newTrapBounds[iHigh]));
252  }
253  }
254  if (msgLvl(MSG::VERBOSE)) {
255  std::stringstream debugStr{};
256  for (const Amg::Vector3D& edge : newTrapBounds) {
257  debugStr<<"***** "<<Amg::toString(edge)<<std::endl;
258  }
259  ATH_MSG_VERBOSE("#############################################################"<<std::endl<<
260  debugStr.str()<<"#############################################################");
261  }
263  const double halfY = 0.5*std::max(newTrapBounds[1].y() - newTrapBounds[0].y(),
264  newTrapBounds[3].y() - newTrapBounds[2].y());
265  const double lHalfX = 0.5*(newTrapBounds[3].x() - newTrapBounds[1].x());
266  const double sHalfX = 0.5*(newTrapBounds[2].x() - newTrapBounds[0].x());
267  const double halfZ = 0.5*(newTrapBounds[4].z() - newTrapBounds[0].z());
268  envelopeBounds = boundSet.make_bounds(sHalfX, lHalfX, halfY, halfZ);
269  ATH_MSG_VERBOSE(m_idHelperSvc->toStringDetEl(chambEle->identify())<<" "<<(*envelopeBounds));
270 
272  const Amg::Transform3D centerShift = centerTrapezoid(newTrapBounds);
273  newCentreTrf = centerShift * newCentreTrf;
274  ATH_MSG_VERBOSE("New trapezoid centering "<<Amg::toString(centerShift)<<" combined: "
275  <<Amg::toString(newCentreTrf));
276  }
277 
278  envelopeBounds = boundSet.make_bounds(envelopeBounds->get(BoundEnum::eHalfLengthXnegY)+margin,
279  envelopeBounds->get(BoundEnum::eHalfLengthXposY)+margin,
280  envelopeBounds->get(BoundEnum::eHalfLengthY)+margin,
281  envelopeBounds->get(BoundEnum::eHalfLengthZ)+margin);
282  return std::make_pair(envelopeBounds, newCentreTrf.inverse());
283 }

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

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

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

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

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

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

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

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

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

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

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

68  {
70  const Amg::Vector3D normal = lineDir.cross((leftEdge ? 1. : -1.) *Amg::Vector3D::UnitZ());
71  const Amg::Vector3D closest = linePos + lineDir.dot(testMe - linePos) * lineDir;
72  return normal.dot(testMe - closest);
73 }

Member Data Documentation

◆ m_geoUtilTool

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

Definition at line 84 of file ChamberAssembleTool.h.

◆ m_idHelperSvc

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

Definition at line 83 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:140
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
python.CaloAddPedShiftConfig.args
args
Definition: CaloAddPedShiftConfig.py:45
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:83
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:117
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)
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::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
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:127
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:157
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
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
THROW_EXCEPTION
#define THROW_EXCEPTION(MESSAGE)
Definition: throwExcept.h:10
python.PyAthena.v
v
Definition: PyAthena.py:154
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:65
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:84
python.SystemOfUnits.km
int km
Definition: SystemOfUnits.py:95
MuonGMR4::TgcReadoutElement
Definition: MuonPhaseII/MuonDetDescr/MuonReadoutGeometryR4/MuonReadoutGeometryR4/TgcReadoutElement.h:19
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:33
Identifier
Definition: IdentifierFieldParser.cxx:14