ATLAS Offline Software
ChamberAssembleTool.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3 */
4 #ifndef SIMULATIONBASE
5 
7 
15 #include <sstream>
16 
17 
18 namespace {
19  int sign(int numb) {
20  return numb > 0 ? 1 : (numb == 0 ? 0 : -1);
21  }
22  bool isNsw(const MuonGMR4::MuonReadoutElement* re) {
23  return re->detectorType() == ActsTrk::DetectorType::Mm ||
24  re->detectorType() == ActsTrk::DetectorType::sTgc;
25  }
26 }
27 
28 
29 
30 namespace MuonGMR4{
31 
33 
34 ChamberAssembleTool::ChamberAssembleTool(const std::string &type, const std::string &name,
35  const IInterface *parent):
37 
38 
39 
41  ATH_CHECK(m_idHelperSvc.retrieve());
42  ATH_CHECK(m_geoUtilTool.retrieve());
43 
45  auto mdtStationIndex = [this] (const std::string& stName) {
46  return m_idHelperSvc->hasMDT() ? m_idHelperSvc->mdtIdHelper().stationNameIndex(stName) : -1;
47  };
48  auto tgcStationIndex = [this] (const std::string& stName) {
49  return m_idHelperSvc->hasTGC() ? m_idHelperSvc->tgcIdHelper().stationNameIndex(stName) : -1;
50  };
51 
52  const std::set<int> stIndicesEIL{mdtStationIndex("EIL"), mdtStationIndex("T4E")};
53  const std::set<int> stIndicesEM{mdtStationIndex("EML"), mdtStationIndex("EMS"),
54  tgcStationIndex("T1E"), tgcStationIndex("T1F"),
55  tgcStationIndex("T2E"), tgcStationIndex("T2F"),
56  tgcStationIndex("T3E"), tgcStationIndex("T3F")};
57 
58  const std::set<Identifier> BOE_ids{m_idHelperSvc->hasMDT() ? m_idHelperSvc->mdtIdHelper().elementID("BOL", 7,7): Identifier{},
59  m_idHelperSvc->hasMDT() ? m_idHelperSvc->mdtIdHelper().elementID("BOL", -7,7): Identifier{},
60  m_idHelperSvc->hasRPC() ? m_idHelperSvc->rpcIdHelper().elementID("BOL", -8, 7, 1) : Identifier{},
61  m_idHelperSvc->hasRPC() ? m_idHelperSvc->rpcIdHelper().elementID("BOL", 8, 7, 1) : Identifier{}};
62 
63  std::vector<MuonReadoutElement*> allReadOutEles = mgr.getAllReadoutElements();
64 
65  std::vector<defineArgs> muonChamberCandidates{};
66 
70  for (const MuonReadoutElement* readOutEle : allReadOutEles) {
72  std::find_if(muonChamberCandidates.begin(), muonChamberCandidates.end(),
73  [this, readOutEle, &stIndicesEIL, &stIndicesEM, &BOE_ids](const defineArgs& args){
74  const MuonReadoutElement* refEle = args.readoutEles[0];
75  const Identifier refId = refEle->identify();
76  const Identifier testId = readOutEle->identify();
78  if (sign(refEle->stationEta()) != sign(readOutEle->stationEta())) {
79  return false;
80  }
82  if (m_idHelperSvc->sector(testId) != m_idHelperSvc->sector(refId)) {
83  return false;
84  }
86  if (BOE_ids.count(m_idHelperSvc->chamberId(refId)) !=
87  BOE_ids.count(m_idHelperSvc->chamberId(testId))){
88  return false;
89  }
92  if (readOutEle->stationName() == refEle->stationName()) {
93  return true;
94  }
96  if (isNsw(readOutEle) && isNsw(refEle)) return true;
98  if (stIndicesEM.count(readOutEle->stationName()) &&
99  stIndicesEM.count(refEle->stationName())) {
100  return true;
101  }
103  if (stIndicesEIL.count(readOutEle->stationName()) &&
104  stIndicesEIL.count(refEle->stationName())) {
105  return true;
106  }
107  return false;
108  });
110  if (exist == muonChamberCandidates.end()) {
111  defineArgs newChamb{};
112  newChamb.readoutEles.push_back(readOutEle);
113  muonChamberCandidates.push_back(std::move(newChamb));
114  } else {
115  exist->readoutEles.push_back(readOutEle);
116  }
117  }
119  ActsGeometryContext gctx{};
120 
129 
130  const Amg::Transform3D axisRotation{Amg::getRotateZ3D(-90. * Gaudi::Units::deg) *
132 
133  constexpr double margin = 1.*Gaudi::Units::cm;
134 
135  for (defineArgs& candidate : muonChamberCandidates) {
136  std::vector<Amg::Vector3D> edgePoints{};
137  std::vector<Identifier> reIds{};
138  double minPhi{1.e6};
139  const Amg::Transform3D toCenter = axisRotation * candidate.readoutEles[0]->globalToLocalTrans(gctx);
140  for (const MuonReadoutElement* re : candidate.readoutEles) {
141  const GeoShape* readOutShape = re->getMaterialGeom()->getLogVol()->getShape();
142  std::vector<Amg::Vector3D> reEdges = m_geoUtilTool->shapeEdges(readOutShape,
143  toCenter * re->localToGlobalTrans(gctx));
144  if (msgLvl(MSG::VERBOSE)) {
145  std::stringstream edgeStream{};
146  for (const Amg::Vector3D& edge : reEdges) {
147  edgeStream<<" *** "<<Amg::toString(edge)<<std::endl;
148  }
149  ATH_MSG_VERBOSE(m_idHelperSvc->toStringDetEl(re->identify())<<" dumped shape "
150  <<m_geoUtilTool->dumpShape(readOutShape)<<std::endl<<std::endl<<edgeStream.str());
151  }
152  edgePoints.insert(edgePoints.end(), std::make_move_iterator(reEdges.begin()),
153  std::make_move_iterator(reEdges.end()));
154  reIds.push_back(re->identify());
155  }
156 
157  double minX{1.e6}, minY{1.e6}, minZ{1.e6}, maxX{-1.e6}, maxY{-1.e6}, maxZ{-1.e6}, maxXNegY{-1.e6};;
158 
160  for (const Amg::Vector3D& edge : edgePoints) {
161  minY = std::min(minY, edge.y());
162  maxY = std::max(maxY, edge.y());
163  minZ = std::min(minZ, edge.z());
164  maxZ = std::max(maxZ, edge.z());
165  minX = std::min(minX, edge.x());
166  maxX = std::max(maxX, edge.x());
167  }
168  const double midX = 0.5*(minX + maxX);
169  const double midY = 0.5*(minY + maxY);
170  const double midZ = 0.5*(minZ + maxZ);
171 
172  const double hLengthY = 0.5 * (maxY - minY);
173  const double hLengthZ = 0.5 * (maxZ - minZ);
174 
175  candidate.centerTrans = axisRotation.inverse() * Amg::Translation3D{midX, midY, midZ};
176 
177  for (const Amg::Vector3D &edge : edgePoints) {
178  // translate the edges to the local frame of the chamber
179  const Amg::Vector2D &localedge =
180  (Amg::getTranslate3D(-midX, -midY, -midZ) * edge)
181  .block<2, 1>(0, 0);
182 
183  if (std::abs(localedge.y() + hLengthY) < 15. * Gaudi::Units::cm) {
184  maxXNegY = std::max(maxXNegY, localedge.x());
185  }
186  }
187 
188  const Amg::Vector2D refEdge{maxXNegY, -hLengthY};
189 
190  // find the minimum angle between the edge points to define the
191  // trapezoidal bounds of the chamber
192 
193  for (const Amg::Vector3D &edge : edgePoints) {
194  const Amg::Vector2D &localedge =
195  (Amg::getTranslate3D(-midX, -midY, -midZ) * edge)
196  .block<2, 1>(0, 0);
197  if (std::abs(localedge.y() - refEdge.y()) < 1.e-10) continue;
198 
199  if (localedge.x() > refEdge.x() ||
200  std::abs(localedge.x() - refEdge.x()) < 1.e-10) {
201  double phi = std::atan2((localedge.y() - refEdge.y()),
202  (localedge.x() - refEdge.x()));
203  minPhi = std::min(minPhi, phi);
204  }
205  }
206 
207  // Define the trapezoidal bounds of the chamber
208  candidate.halfXShort = maxXNegY + margin;
209  candidate.halfY = hLengthY + margin;
210  candidate.halfZ = hLengthZ + margin;
211  candidate.halfXLong =
212  candidate.halfXShort + 2 * candidate.halfY / std::tan(minPhi) + margin;
213 
214  if(msgLvl(MSG::VERBOSE)) {
215  std::stringstream debugStream{};
216  debugStream<<"minY: "<<minY<<", maxY: "<<maxY<<", minZ: "<<minZ<<", maxZ: "<<maxZ<<" -- ";
217  debugStream<<candidate<<std::endl;
218  const Amg::Transform3D globChambTrf{candidate.readoutEles[0]->localToGlobalTrans(gctx) * candidate.centerTrans};
219  for (const MuonReadoutElement* ele: candidate.readoutEles){
220  if(m_idHelperSvc->stationNameString(ele->identify()) == "BIR") {
221  const MdtReadoutElement* mdtRe = static_cast<const MdtReadoutElement*>(ele);
222 
223  debugStream<<" *** "<<m_idHelperSvc->toString(ele->identify())<<" "
224  <<Amg::toString(globChambTrf.inverse()*mdtRe->highVoltPos(gctx, mdtRe->identify()))
225  <<" -- "<<Amg::toString(globChambTrf.inverse()*mdtRe->readOutPos(gctx, mdtRe->identify()))<<std::endl;
226  }else
227  debugStream<<" **** "<<m_idHelperSvc->toStringDetEl(ele->identify())<<", local RE center: "
228  <<Amg::toString(globChambTrf.inverse() * ele->center(gctx))<<", global: "
229  <<Amg::toString(ele->center(gctx))<<std::endl;
230  }
231  ATH_MSG_VERBOSE(debugStream.str());
232  }
233  GeoModel::TransientConstSharedPtr<MuonChamber> newChamber = std::make_unique<MuonChamber>(std::move(candidate));
234 
235  for (const Identifier& chId : reIds) {
236  mgr.getReadoutElement(chId)->setChamberLink(newChamber);
237  }
238  }
239  return StatusCode::SUCCESS;
240 }
241 
242 }
243 #endif
xAOD::iterator
JetConstituentVector::iterator iterator
Definition: JetConstituentVector.cxx:68
GeoModel::TransientConstSharedPtr
The TransientConstSharedPtr allows non-const access if the pointer itself is non-const but in the con...
Definition: TransientConstSharedPtr.h:13
max
#define max(a, b)
Definition: cfImp.cxx:41
phi
Scalar phi() const
phi method
Definition: AmgMatrixBasePlugin.h:64
MuonGMR4::MuonDetectorManager
Definition: MuonPhaseII/MuonDetDescr/MuonReadoutGeometryR4/MuonReadoutGeometryR4/MuonDetectorManager.h:61
Amg::Vector2D
Eigen::Matrix< double, 2, 1 > Vector2D
Definition: GeoPrimitives.h:48
MuonGMR4::ChamberAssembleTool::m_idHelperSvc
ServiceHandle< Muon::IMuonIdHelperSvc > m_idHelperSvc
Definition: ChamberAssembleTool.h:28
MuonGMR4::MuonReadoutElement
The MuonReadoutElement is an abstract class representing the geometry representing the muon detector.
Definition: MuonPhaseII/MuonDetDescr/MuonReadoutGeometryR4/MuonReadoutGeometryR4/MuonReadoutElement.h:38
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
sTgcReadoutElement.h
MuonGMR4::MuonChamber::defineArgs::readoutEles
ReadoutSet readoutEles
List of readout elements in the chamber.
Definition: MuonPhaseII/MuonDetDescr/MuonReadoutGeometryR4/MuonReadoutGeometryR4/MuonChamber.h:44
Amg::toString
std::string toString(const Translation3D &translation, int precision=4)
GeoPrimitvesToStringConverter.
Definition: GeoPrimitivesToStringConverter.h:40
MuonGMR4
A muon chamber is a collection of readout elements belonging to the same station.
Definition: ChamberAssembleTool.h:16
WriteCellNoiseToCool.exist
exist
Definition: WriteCellNoiseToCool.py:543
ActsTrk::DetectorType::Mm
@ Mm
Maybe not needed in the migration.
Identifier
Definition: DetectorDescription/Identifier/Identifier/Identifier.h:32
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
Amg::Transform3D
Eigen::Affine3d Transform3D
Definition: GeoPrimitives.h:46
MuonDetectorManager.h
test_pyathena.parent
parent
Definition: test_pyathena.py:15
sign
int sign(int a)
Definition: TRT_StrawNeighbourSvc.h:127
MuonChamber.h
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
drawFromPickle.tan
tan
Definition: drawFromPickle.py:36
ActsGeometryContext
Include the GeoPrimitives which need to be put first.
Definition: ActsGeometryContext.h:28
min
#define min(a, b)
Definition: cfImp.cxx:40
MuonGMR4::ChamberAssembleTool::buildReadOutElements
StatusCode buildReadOutElements(MuonDetectorManager &mgr) override final
Retrieves the GeoModel from the GeoModelSvc and append the ReadoutElements of the Given MuonDetectorT...
Definition: ChamberAssembleTool.cxx:40
ChamberAssembleTool.h
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:192
MuonGMR4::ChamberAssembleTool::ChamberAssembleTool
ChamberAssembleTool(const std::string &type, const std::string &name, const IInterface *parent)
Definition: ChamberAssembleTool.cxx:34
Amg::getRotateY3D
Amg::Transform3D getRotateY3D(double angle)
get a rotation transformation around Y-axis
Definition: GeoPrimitivesHelpers.h:261
MuonGMR4::MuonChamber::defineArgs
Definition: MuonPhaseII/MuonDetDescr/MuonReadoutGeometryR4/MuonReadoutGeometryR4/MuonChamber.h:42
Amg::Vector3D
Eigen::Matrix< double, 3, 1 > Vector3D
Definition: GeoPrimitives.h:47
RpcReadoutElement.h
MdtReadoutElement.h
python.CaloScaleNoiseConfig.type
type
Definition: CaloScaleNoiseConfig.py:78
re
const boost::regex re(r_e)
Amg::Translation3D
Eigen::Translation< double, 3 > Translation3D
Definition: GeoPrimitives.h:44
if
if(febId1==febId2)
Definition: LArRodBlockPhysicsV0.cxx:569
python.Constants.VERBOSE
int VERBOSE
Definition: Control/AthenaCommon/python/Constants.py:14
AthAlgTool
Definition: AthAlgTool.h:26
MuonGMR4::ChamberAssembleTool::m_geoUtilTool
PublicToolHandle< IMuonGeoUtilityTool > m_geoUtilTool
Definition: ChamberAssembleTool.h:30
TgcReadoutElement.h
python.CaloScaleNoiseConfig.args
args
Definition: CaloScaleNoiseConfig.py:80
MmReadoutElement.h
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
MuonChamber::defineArgs defineArgs
Definition: ChamberAssembleTool.cxx:32