CMS 3D CMS Logo

RPCGeometryBuilder.cc
Go to the documentation of this file.
1 /*
2 //\class RPCGeometryBuilder
3 
4  Description: RPC Geometry builder from DD & DD4hep
5  DD4hep part added to the original old file (DD version) made by M. Maggi (INFN Bari)
6 //
7 // Author: Sergio Lo Meo (sergio.lo.meo@cern.ch) following what Ianna Osborne made for DTs (DD4hep migration)
8 // Created: Fri, 20 Sep 2019
9 // Modified: Fri, 29 May 2020, following what Sunanda Banerjee made in PR #29842 PR #29943 and Ianna Osborne in PR #29954
10 */
26 #include <iostream>
27 #include <algorithm>
32 
33 using namespace cms_units::operators;
34 
36 
37 // for DDD
38 
39 std::unique_ptr<RPCGeometry> RPCGeometryBuilder::build(const DDCompactView* cview,
40  const MuonGeometryConstants& muonConstants) {
41  const std::string attribute = "ReadOutName";
42  const std::string value = "MuonRPCHits";
44  DDFilteredView fview(*cview, filter);
45  return this->buildGeometry(fview, muonConstants);
46 }
47 // for DD4hep
48 
49 std::unique_ptr<RPCGeometry> RPCGeometryBuilder::build(const cms::DDCompactView* cview,
50  const MuonGeometryConstants& muonConstants) {
51  const std::string attribute = "ReadOutName";
52  const std::string value = "MuonRPCHits";
53  const cms::DDFilter filter(attribute, value);
54  cms::DDFilteredView fview(*cview, filter);
55  return this->buildGeometry(fview, muonConstants);
56 }
57 // for DDD
58 
59 std::unique_ptr<RPCGeometry> RPCGeometryBuilder::buildGeometry(DDFilteredView& fview,
60  const MuonGeometryConstants& muonConstants) {
61  edm::LogVerbatim("RPCGeometryBuilder") << "Building the geometry service";
62  std::unique_ptr<RPCGeometry> geometry = std::make_unique<RPCGeometry>();
63  edm::LogVerbatim("RPCGeometryBuilder") << "About to run through the RPC structure\n"
64  << " First logical part " << fview.logicalPart().name().name();
65  bool doSubDets = fview.firstChild();
66  edm::LogVerbatim("RPCGeometryBuilder") << "doSubDets = " << doSubDets;
67  while (doSubDets) {
68  edm::LogVerbatim("RPCGeometryBuilder") << "start the loop";
69  MuonGeometryNumbering mdddnum(muonConstants);
70  edm::LogVerbatim("RPCGeometryBuilder") << "Getting the Muon base Number";
71  MuonBaseNumber mbn = mdddnum.geoHistoryToBaseNumber(fview.geoHistory());
72  // edm::LogVerbatim("RPCGeometryBuilder") << "Start the Rpc Numbering Schema";
73  RPCNumberingScheme rpcnum(muonConstants);
74  edm::LogVerbatim("RPCGeometryBuilder") << "Getting the Unit Number";
75  const int detid = rpcnum.baseNumberToUnitNumber(mbn);
76  edm::LogVerbatim("RPCGeometryBuilder") << "Getting the RPC det Id " << detid;
77  RPCDetId rpcid(detid);
78  RPCDetId chid(rpcid.region(), rpcid.ring(), rpcid.station(), rpcid.sector(), rpcid.layer(), rpcid.subsector(), 0);
79  edm::LogVerbatim("RPCGeometryBuilder") << "The RPCDetid is " << rpcid;
80 
81  DDValue numbOfStrips("nStrips");
82 
83  std::vector<const DDsvalues_type*> specs(fview.specifics());
84  int nStrips = 0;
85  for (auto& spec : specs) {
86  if (DDfetch(spec, numbOfStrips)) {
87  nStrips = int(numbOfStrips.doubles()[0]);
88  }
89  }
90 
91  if (nStrips == 0)
92  edm::LogVerbatim("RPCGeometryBuilder") << "No strip found!!";
93 
94  std::vector<double> dpar = fview.logicalPart().solid().parameters();
95  std::string name = fview.logicalPart().name().name();
96 
97  edm::LogVerbatim("RPCGeometryBuilder")
98  << "(1) "
99  << "detid: " << detid << " name: " << name << " number of Strips: " << nStrips;
100 
101  DDTranslation tran = fview.translation();
102  DDRotationMatrix rota = fview.rotation();
106  edm::LogVerbatim("RPCGeometryBuilder") << "(2) tran.x(): " << geant_units::operators::convertMmToCm(tran.x())
107  << " tran.y(): " << geant_units::operators::convertMmToCm(tran.y())
108  << " tran.z(): " << geant_units::operators::convertMmToCm(tran.z());
109 
110  DD3Vector x, y, z;
111  rota.GetComponents(x, y, z);
112  Surface::RotationType rot(float(x.X()),
113  float(x.Y()),
114  float(x.Z()),
115  float(y.X()),
116  float(y.Y()),
117  float(y.Z()),
118  float(z.X()),
119  float(z.Y()),
120  float(z.Z()));
121 
122  RPCRollSpecs* rollspecs = nullptr;
123  Bounds* bounds = nullptr;
124 
125  if (dpar.size() == 3) {
126  const float width = geant_units::operators::convertMmToCm(dpar[0]);
127  const float length = geant_units::operators::convertMmToCm(dpar[1]);
128  const float thickness = geant_units::operators::convertMmToCm(dpar[2]);
129 
130  // Barrel
131  edm::LogVerbatim("RPCGeometryBuilder")
132  << "(3) Box, width: " << width << " length: " << length << " thickness: " << thickness;
133 
135  const std::vector<float> pars = {width, length, float(numbOfStrips.doubles()[0])};
136 
137  rollspecs = new RPCRollSpecs(GeomDetEnumerators::RPCBarrel, name, pars);
138 
139  } else {
140  const float be = geant_units::operators::convertMmToCm(dpar[4]);
141  const float te = geant_units::operators::convertMmToCm(dpar[8]);
142  const float ap = geant_units::operators::convertMmToCm(dpar[0]);
143  const float ti = 0.4;
144 
145  bounds = new TrapezoidalPlaneBounds(be, te, ap, ti);
146 
147  const std::vector<float> pars = {be, te, ap, float(numbOfStrips.doubles()[0])};
148  //Forward
149  edm::LogVerbatim("RPCGeometryBuilder") << "(4) be: " << be << " te: " << te << " ap: " << ap << " ti: " << ti
150  << " strips " << numbOfStrips.doubles()[0];
151 
152  rollspecs = new RPCRollSpecs(GeomDetEnumerators::RPCEndcap, name, pars);
153 
154  Basic3DVector<float> newX(1., 0., 0.);
155  Basic3DVector<float> newY(0., 0., 1.);
156  newY *= -1;
157  Basic3DVector<float> newZ(0., 1., 0.);
158  rot.rotateAxes(newX, newY, newZ);
159  }
160  edm::LogVerbatim("RPCGeometryBuilder") << " Number of strips " << nStrips;
161 
162  BoundPlane* bp = new BoundPlane(pos, rot, bounds);
164  RPCRoll* r = new RPCRoll(rpcid, surf, rollspecs);
165  geometry->add(r);
166 
167  auto rls = chids.find(chid);
168  if (rls == chids.end())
169  rls = chids.insert(std::make_pair(chid, std::list<RPCRoll*>())).first;
170  rls->second.emplace_back(r);
171 
172  doSubDets = fview.nextSibling();
173  }
174  for (auto& ich : chids) {
175  const RPCDetId& chid = ich.first;
176  const auto& rls = ich.second;
177 
178  BoundPlane* bp = nullptr;
179  if (!rls.empty()) {
180  const auto& refSurf = (*rls.begin())->surface();
181  if (chid.region() == 0) {
182  float corners[6] = {0, 0, 0, 0, 0, 0};
183  for (auto rl : rls) {
184  const double h2 = rl->surface().bounds().length() / 2;
185  const double w2 = rl->surface().bounds().width() / 2;
186  const auto x1y1AtRef = refSurf.toLocal(rl->toGlobal(LocalPoint(-w2, -h2, 0)));
187  const auto x2y2AtRef = refSurf.toLocal(rl->toGlobal(LocalPoint(+w2, +h2, 0)));
188  corners[0] = std::min(corners[0], x1y1AtRef.x());
189  corners[1] = std::min(corners[1], x1y1AtRef.y());
190  corners[2] = std::max(corners[2], x2y2AtRef.x());
191  corners[3] = std::max(corners[3], x2y2AtRef.y());
192  corners[4] = std::min(corners[4], x1y1AtRef.z());
193  corners[5] = std::max(corners[5], x1y1AtRef.z());
194  }
195  const LocalPoint lpOfCentre((corners[0] + corners[2]) / 2, (corners[1] + corners[3]) / 2, 0);
196  const auto gpOfCentre = refSurf.toGlobal(lpOfCentre);
197  auto bounds = new RectangularPlaneBounds(
198  (corners[2] - corners[0]) / 2, (corners[3] - corners[1]) / 2, (corners[5] - corners[4]) + 0.5);
199  bp = new BoundPlane(gpOfCentre, refSurf.rotation(), bounds);
200  } else {
201  float cornersLo[3] = {0, 0, 0}, cornersHi[3] = {0, 0, 0};
202  float cornersZ[2] = {0, 0};
203  for (auto rl : rls) {
204  const double h2 = rl->surface().bounds().length() / 2;
205  const double w2 = rl->surface().bounds().width() / 2;
206  const auto& topo = dynamic_cast<const TrapezoidalStripTopology&>(rl->specificTopology());
207  const double r = topo.radius();
208  const double wAtLo = w2 / r * (r - h2);
209  const double wAtHi = w2 / r * (r + h2);
210 
211  const auto x1y1AtRef = refSurf.toLocal(rl->toGlobal(LocalPoint(-wAtLo, -h2, 0)));
212  const auto x2y1AtRef = refSurf.toLocal(rl->toGlobal(LocalPoint(+wAtLo, -h2, 0)));
213  const auto x1y2AtRef = refSurf.toLocal(rl->toGlobal(LocalPoint(-wAtHi, +h2, 0)));
214  const auto x2y2AtRef = refSurf.toLocal(rl->toGlobal(LocalPoint(+wAtHi, +h2, 0)));
215 
216  cornersLo[0] = std::min(cornersLo[0], x1y1AtRef.x());
217  cornersLo[1] = std::max(cornersLo[1], x2y1AtRef.x());
218  cornersLo[2] = std::min(cornersLo[2], x1y1AtRef.y());
219 
220  cornersHi[0] = std::min(cornersHi[0], x1y2AtRef.x());
221  cornersHi[1] = std::max(cornersHi[1], x2y2AtRef.x());
222  cornersHi[2] = std::max(cornersHi[2], x1y2AtRef.y());
223 
224  cornersZ[0] = std::min(cornersZ[0], x1y1AtRef.z());
225  cornersZ[1] = std::max(cornersZ[1], x1y1AtRef.z());
226  }
227  const LocalPoint lpOfCentre((cornersHi[0] + cornersHi[1]) / 2, (cornersLo[2] + cornersHi[2]) / 2, 0);
228  const auto gpOfCentre = refSurf.toGlobal(lpOfCentre);
229  auto bounds = new TrapezoidalPlaneBounds((cornersLo[1] - cornersLo[0]) / 2,
230  (cornersHi[1] - cornersHi[0]) / 2,
231  (cornersHi[2] - cornersLo[2]) / 2,
232  (cornersZ[1] - cornersZ[0]) + 0.5);
233  bp = new BoundPlane(gpOfCentre, refSurf.rotation(), bounds);
234  }
235  }
236 
238  RPCChamber* ch = new RPCChamber(chid, surf);
239  for (auto rl : rls)
240  ch->add(rl);
241  geometry->add(ch);
242  }
243 
244  return geometry;
245 }
246 
247 // for DD4hep
248 
249 std::unique_ptr<RPCGeometry> RPCGeometryBuilder::buildGeometry(cms::DDFilteredView& fview,
250  const MuonGeometryConstants& muonConstants) {
251  edm::LogVerbatim("RPCGeometryBuilder") << "Building the geometry service";
252  std::unique_ptr<RPCGeometry> geometry = std::make_unique<RPCGeometry>();
253 
254  while (fview.firstChild()) {
255  edm::LogVerbatim("RPCGeometryBuilder") << "start the loop";
256  MuonGeometryNumbering mdddnum(muonConstants);
257  edm::LogVerbatim("RPCGeometryBuilder") << "Getting the Muon base Number";
258  RPCNumberingScheme rpcnum(muonConstants);
259  edm::LogVerbatim("RPCGeometryBuilder") << "Getting the Unit Number";
260  int rawidCh = rpcnum.baseNumberToUnitNumber(mdddnum.geoHistoryToBaseNumber(fview.history()));
261  edm::LogVerbatim("RPCGeometryBuilder") << "Getting the RPC det Id " << rawidCh;
262  RPCDetId rpcid = RPCDetId(rawidCh);
263  edm::LogVerbatim("RPCGeometryBuilder") << "The RPCDetid is " << rpcid;
264 
265  RPCDetId chid(rpcid.region(), rpcid.ring(), rpcid.station(), rpcid.sector(), rpcid.layer(), rpcid.subsector(), 0);
266 
267  auto nStrips = fview.get<double>("nStrips");
268 
269  std::vector<double> dpar = fview.parameters();
270 
271  std::string_view name = fview.name();
272 
273  edm::LogVerbatim("RPCGeometryBuilder")
274  << "(1) detid: " << rawidCh << " name: " << std::string(name) << " number of Strips: " << nStrips;
275 
276  const Double_t* tran = fview.trans();
277 
278  DDRotationMatrix rota;
279  fview.rot(rota);
280 
281  Surface::PositionType pos(tran[0] / dd4hep::cm, tran[1] / dd4hep::cm, tran[2] / dd4hep::cm);
282  edm::LogVerbatim("RPCGeometryBuilder")
283  << "(2) tran.x(): " << tran[0] / dd4hep::cm << " tran.y(): " << tran[1] / dd4hep::cm
284  << " tran.z(): " << tran[2] / dd4hep::cm;
285  DD3Vector x, y, z;
286  rota.GetComponents(x, y, z);
287  Surface::RotationType rot(float(x.X()),
288  float(x.Y()),
289  float(x.Z()),
290  float(y.X()),
291  float(y.Y()),
292  float(y.Z()),
293  float(z.X()),
294  float(z.Y()),
295  float(z.Z()));
296 
297  RPCRollSpecs* rollspecs = nullptr;
298  Bounds* bounds = nullptr;
299 
300  if (dd4hep::isA<dd4hep::Box>(fview.solid())) {
301  const float width = dpar[0] / dd4hep::cm;
302  const float length = dpar[1] / dd4hep::cm;
303  const float thickness = dpar[2] / dd4hep::cm;
304  edm::LogVerbatim("RPCGeometryBuilder")
305  << "(3) Box, width: " << dpar[0] / dd4hep::cm << " length: " << dpar[1] / dd4hep::cm
306  << " thickness: " << dpar[2] / dd4hep::cm;
308 
309  const std::vector<float> pars = {width, length, float(nStrips)};
310 
312 
313  } else {
314  const float be = dpar[0] / dd4hep::cm;
315  const float te = dpar[1] / dd4hep::cm;
316  const float ap = dpar[3] / dd4hep::cm;
317  const float ti = 0.4;
318 
319  bounds = new TrapezoidalPlaneBounds(be, te, ap, ti);
320  const std::vector<float> pars = {be, te, ap, float(nStrips)};
321  edm::LogVerbatim("RPCGeometryBuilder")
322  << "(4) be: " << be << " te: " << te << " ap: " << ap << " ti: " << ti << " strips " << nStrips;
324 
325  Basic3DVector<float> newX(1., 0., 0.);
326  Basic3DVector<float> newY(0., 0., 1.);
327  newY *= -1;
328  Basic3DVector<float> newZ(0., 1., 0.);
329  rot.rotateAxes(newX, newY, newZ);
330  }
331  edm::LogVerbatim("RPCGeometryBuilder") << " Number of strips " << nStrips;
332 
333  BoundPlane* bp = new BoundPlane(pos, rot, bounds);
335  RPCRoll* r = new RPCRoll(rpcid, surf, rollspecs);
336  geometry->add(r);
337 
338  auto rls = chids.find(chid);
339  if (rls == chids.end())
340  rls = chids.insert(std::make_pair(chid, std::list<RPCRoll*>())).first;
341  rls->second.emplace_back(r);
342  }
343 
344  for (auto& ich : chids) {
345  const RPCDetId& chid = ich.first;
346  const auto& rls = ich.second;
347 
348  BoundPlane* bp = nullptr;
349  if (!rls.empty()) {
350  const auto& refSurf = (*rls.begin())->surface();
351  if (chid.region() == 0) {
352  float corners[6] = {0, 0, 0, 0, 0, 0};
353  for (auto rl : rls) {
354  const double h2 = rl->surface().bounds().length() / 2;
355  const double w2 = rl->surface().bounds().width() / 2;
356  const auto x1y1AtRef = refSurf.toLocal(rl->toGlobal(LocalPoint(-w2, -h2, 0)));
357  const auto x2y2AtRef = refSurf.toLocal(rl->toGlobal(LocalPoint(+w2, +h2, 0)));
358  corners[0] = std::min(corners[0], x1y1AtRef.x());
359  corners[1] = std::min(corners[1], x1y1AtRef.y());
360  corners[2] = std::max(corners[2], x2y2AtRef.x());
361  corners[3] = std::max(corners[3], x2y2AtRef.y());
362 
363  corners[4] = std::min(corners[4], x1y1AtRef.z());
364  corners[5] = std::max(corners[5], x1y1AtRef.z());
365  }
366  const LocalPoint lpOfCentre((corners[0] + corners[2]) / 2, (corners[1] + corners[3]) / 2, 0);
367  const auto gpOfCentre = refSurf.toGlobal(lpOfCentre);
368  auto bounds = new RectangularPlaneBounds(
369  (corners[2] - corners[0]) / 2, (corners[3] - corners[1]) / 2, (corners[5] - corners[4]) + 0.5);
370  bp = new BoundPlane(gpOfCentre, refSurf.rotation(), bounds);
371 
372  } else {
373  float cornersLo[3] = {0, 0, 0}, cornersHi[3] = {0, 0, 0};
374  float cornersZ[2] = {0, 0};
375  for (auto rl : rls) {
376  const double h2 = rl->surface().bounds().length() / 2;
377  const double w2 = rl->surface().bounds().width() / 2;
378  const auto& topo = dynamic_cast<const TrapezoidalStripTopology&>(rl->specificTopology());
379  const double r = topo.radius();
380  const double wAtLo = w2 / r * (r - h2);
381  const double wAtHi = w2 / r * (r + h2);
382  const auto x1y1AtRef = refSurf.toLocal(rl->toGlobal(LocalPoint(-wAtLo, -h2, 0)));
383  const auto x2y1AtRef = refSurf.toLocal(rl->toGlobal(LocalPoint(+wAtLo, -h2, 0)));
384  const auto x1y2AtRef = refSurf.toLocal(rl->toGlobal(LocalPoint(-wAtHi, +h2, 0)));
385  const auto x2y2AtRef = refSurf.toLocal(rl->toGlobal(LocalPoint(+wAtHi, +h2, 0)));
386 
387  cornersLo[0] = std::min(cornersLo[0], x1y1AtRef.x());
388  cornersLo[1] = std::max(cornersLo[1], x2y1AtRef.x());
389  cornersLo[2] = std::min(cornersLo[2], x1y1AtRef.y());
390 
391  cornersHi[0] = std::min(cornersHi[0], x1y2AtRef.x());
392  cornersHi[1] = std::max(cornersHi[1], x2y2AtRef.x());
393  cornersHi[2] = std::max(cornersHi[2], x1y2AtRef.y());
394 
395  cornersZ[0] = std::min(cornersZ[0], x1y1AtRef.z());
396  cornersZ[1] = std::max(cornersZ[1], x1y1AtRef.z());
397  }
398  const LocalPoint lpOfCentre((cornersHi[0] + cornersHi[1]) / 2, (cornersLo[2] + cornersHi[2]) / 2, 0);
399  const auto gpOfCentre = refSurf.toGlobal(lpOfCentre);
400  auto bounds = new TrapezoidalPlaneBounds((cornersLo[1] - cornersLo[0]) / 2,
401  (cornersHi[1] - cornersHi[0]) / 2,
402  (cornersHi[2] - cornersLo[2]) / 2,
403  (cornersZ[1] - cornersZ[0]) + 0.5);
404  bp = new BoundPlane(gpOfCentre, refSurf.rotation(), bounds);
405  }
406  }
407 
409 
410  RPCChamber* ch = new RPCChamber(chid, surf);
411 
412  for (auto rl : rls)
413  ch->add(rl);
414 
415  geometry->add(ch);
416  }
417  return geometry;
418 }
int sector() const
Sector id: the group of chambers at same phi (and increasing r)
Definition: RPCDetId.h:81
Log< level::Info, true > LogVerbatim
void add(RPCRoll *rl)
Add Roll to the chamber which takes ownership.
Definition: RPCChamber.cc:32
virtual float length() const =0
common ppss p3p6s2 common epss epspn46 common const1 w2
Definition: inclppp.h:1
const std::vector< double > & doubles() const
a reference to the double-valued values stored in the given instance of DDValue
Definition: DDValue.cc:111
bool nextSibling()
set the current node to the next sibling ...
int baseNumberToUnitNumber(const MuonBaseNumber &) const override
Plane BoundPlane
Definition: Plane.h:94
const Double_t * rot() const
The absolute rotation of the current node.
int ring() const
Definition: RPCDetId.h:59
const std::vector< double > & parameters(void) const
Give the parameters of the solid.
Definition: DDSolid.cc:125
Compact representation of the geometrical detector hierarchy.
Definition: DDCompactView.h:81
bool DDfetch(const DDsvalues_type *, DDValue &)
helper for retrieving DDValues from DDsvalues_type *.
Definition: DDsvalues.cc:79
nStrips
1.2 is to make the matching window safely the two nearest strips 0.35 is the size of an ME0 chamber i...
ROOT::Math::DisplacementVector3D< ROOT::Math::Cartesian3D< double > > DD3Vector
std::string_view name() const
const Double_t * trans() const
The absolute translation of the current node.
const std::string & name() const
Returns the name.
Definition: DDName.cc:41
std::unique_ptr< RPCGeometry > buildGeometry(DDFilteredView &fview, const MuonGeometryConstants &muonConstants)
ROOT::Math::Rotation3D DDRotationMatrix
A DDRotationMatrix is currently implemented with a ROOT Rotation3D.
const ExpandedNodes & history()
The numbering history of the current node.
Definition: value.py:1
bool firstChild()
set the current node to the first child
int subsector() const
SubSector id : some sectors are divided along the phi direction in subsectors (from 1 to 4 in Barrel...
Definition: RPCDetId.h:88
const N & name() const
Definition: DDBase.h:59
const DDLogicalPart & logicalPart() const
The logical-part of the current node in the filtered-view.
T get(const std::string &)
extract attribute value
std::vector< const DDsvalues_type * > specifics() const
constexpr NumType convertMmToCm(NumType millimeters)
Definition: angle_units.h:44
std::unique_ptr< RPCGeometry > build(const DDCompactView *cview, const MuonGeometryConstants &muonConstants)
const DDGeoHistory & geoHistory() const
The list of ancestors up to the root-node of the current node.
int station() const
Definition: RPCDetId.h:78
const DDSolid & solid(void) const
Returns a reference object of the solid being the shape of this LogicalPart.
dd4hep::Solid solid() const
int region() const
Region id: 0 for Barrel, +/-1 For +/- Endcap.
Definition: RPCDetId.h:53
const DDRotationMatrix & rotation() const
The absolute rotation of the current node.
bool firstChild()
set the current node to the first child ...
float x
Definition: Bounds.h:18
int layer() const
Definition: RPCDetId.h:85
const DDTranslation & translation() const
The absolute translation of the current node.
const std::vector< double > parameters() const
extract shape parameters
ROOT::Math::DisplacementVector3D< ROOT::Math::Cartesian3D< double > > DDTranslation
Definition: DDTranslation.h:7
MuonBaseNumber geoHistoryToBaseNumber(const DDGeoHistory &history) const
const Bounds & bounds() const
Definition: Surface.h:87