Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:14:41

0001 /*
0002 //\class GEMGeometryBuilder
0003 
0004  Description: GEM Geometry builder from DD and DD4hep
0005               DD4hep part added to the original old file (DD version) made by M. Maggi (INFN Bari)
0006               Sergio Lo Meo (sergio.lo.meo@cern.ch) following what Ianna Osburne made for DTs (DD4hep migration)
0007               Updated by Sunanda Banerjee (Fermilab) to make it working for dd4hep
0008               Updated:  7 August 2020 
0009               Updated by Ian J. Watson (ian.james.watson@cern.ch) to allow GE2/1 demonstrator to be built
0010               Updated: 7 December 2021
0011               Updated by Yechan Kang (yechan.kang@cern.ch) to allow GE2/1 demonstrator to be built while 2 GE2/1 layers are in the other region during 2024
0012               Updated : 13 Feburary 2024
0013 */
0014 #include "Geometry/GEMGeometryBuilder/src/GEMGeometryBuilder.h"
0015 #include "Geometry/GEMGeometry/interface/GEMGeometry.h"
0016 #include "Geometry/GEMGeometry/interface/GEMEtaPartitionSpecs.h"
0017 
0018 #include "DetectorDescription/Core/interface/DDFilter.h"
0019 #include "DetectorDescription/Core/interface/DDFilteredView.h"
0020 #include "DetectorDescription/Core/interface/DDSolid.h"
0021 #include "DetectorDescription/DDCMS/interface/DDFilteredView.h"
0022 #include "DetectorDescription/DDCMS/interface/DDCompactView.h"
0023 
0024 #include "Geometry/MuonNumbering/interface/MuonGeometryNumbering.h"
0025 #include "Geometry/MuonNumbering/interface/MuonBaseNumber.h"
0026 #include "Geometry/MuonNumbering/interface/MuonGeometryConstants.h"
0027 #include "Geometry/MuonNumbering/interface/GEMNumberingScheme.h"
0028 
0029 #include "DataFormats/GeometrySurface/interface/TrapezoidalPlaneBounds.h"
0030 #include "DataFormats/GeometryVector/interface/Basic3DVector.h"
0031 
0032 #include "DetectorDescription/DDCMS/interface/DDSpecParRegistry.h"
0033 
0034 #include "DataFormats/Math/interface/GeantUnits.h"
0035 
0036 #include <algorithm>
0037 #include <iostream>
0038 #include <string>
0039 
0040 using namespace geant_units::operators;
0041 
0042 //#define EDM_ML_DEBUG
0043 
0044 GEMGeometryBuilder::GEMGeometryBuilder() {}
0045 
0046 GEMGeometryBuilder::~GEMGeometryBuilder() {}
0047 
0048 // DDD
0049 void GEMGeometryBuilder::build(GEMGeometry& theGeometry,
0050                                const DDCompactView* cview,
0051                                const MuonGeometryConstants& muonConstants) {
0052   std::string attribute = "MuStructure";
0053   std::string value = "MuonEndCapGEM";
0054 
0055   // Asking only for the MuonGEM's
0056   DDSpecificsMatchesValueFilter filterGE2{DDValue(attribute, value, 0.0)};
0057   DDFilteredView fvGE2(*cview, filterGE2);
0058 
0059   MuonGeometryNumbering mdddnum(muonConstants);
0060   GEMNumberingScheme gemNum(muonConstants);
0061 
0062   // Check for the demonstrator geometry (only 1 chamber of GE2/1)
0063   int nGE21 = 0;
0064   bool doSuper = fvGE2.firstChild();
0065   while (doSuper) {
0066     // getting chamber id from eta partitions
0067     fvGE2.firstChild();
0068     fvGE2.firstChild();
0069     int rawidCh = gemNum.baseNumberToUnitNumber(mdddnum.geoHistoryToBaseNumber(fvGE2.geoHistory()));
0070     GEMDetId detIdCh = GEMDetId(rawidCh);
0071     if (detIdCh.station() == 2)
0072       nGE21++;
0073 
0074     // back to chambers
0075     fvGE2.parent();
0076     fvGE2.parent();
0077     doSuper = fvGE2.nextSibling();
0078   }
0079   bool demonstratorGeometry = nGE21 % 2 == 1;
0080 
0081 #ifdef EDM_ML_DEBUG
0082   edm::LogVerbatim("Geometry") << "Found " << nGE21 << " GE2/1 chambers. Demonstrator geometry on? "
0083                                << demonstratorGeometry;
0084 #endif
0085 
0086   // Asking only for the MuonGEM's
0087   DDSpecificsMatchesValueFilter filter{DDValue(attribute, value, 0.0)};
0088   DDFilteredView fv(*cview, filter);
0089 
0090 #ifdef EDM_ML_DEBUG
0091   edm::LogVerbatim("Geometry") << "Building the geometry service";
0092   edm::LogVerbatim("Geometry") << "About to run through the GEM structure\n"
0093                                << " First logical part " << fv.logicalPart().name().name();
0094 #endif
0095   doSuper = fv.firstChild();
0096 
0097 #ifdef EDM_ML_DEBUG
0098   edm::LogVerbatim("Geometry") << "doSuperChamber = " << doSuper << " with " << fv.geoHistory() << " Levels "
0099                                << mdddnum.geoHistoryToBaseNumber(fv.geoHistory()).getLevels();
0100   ;
0101 #endif
0102   // loop over superchambers
0103   std::vector<GEMSuperChamber*> superChambers;
0104   while (doSuper) {
0105     // getting chamber id from eta partitions
0106     fv.firstChild();
0107     fv.firstChild();
0108 
0109 #ifdef EDM_ML_DEBUG
0110     edm::LogVerbatim("Geometry") << "MuonGeometry 1 " << fv.geoHistory() << " Levels "
0111                                  << mdddnum.geoHistoryToBaseNumber(fv.geoHistory()).getLevels();
0112 #endif
0113     int rawidCh = gemNum.baseNumberToUnitNumber(mdddnum.geoHistoryToBaseNumber(fv.geoHistory()));
0114     GEMDetId detIdCh = GEMDetId(rawidCh);
0115 
0116     // back to chambers
0117 
0118     fv.parent();
0119     fv.parent();
0120 #ifdef EDM_ML_DEBUG
0121     edm::LogVerbatim("Geometry") << "MuonGeometry 2 " << fv.geoHistory() << " Levels "
0122                                  << mdddnum.geoHistoryToBaseNumber(fv.geoHistory()).getLevels();
0123     gemNum.baseNumberToUnitNumber(mdddnum.geoHistoryToBaseNumber(fv.geoHistory()));
0124 #endif
0125     // currently there is no superchamber in the geometry
0126     // only 2 chambers are present separated by a gap.
0127     // making superchamber out of the first chamber layer including the gap between chambers
0128 
0129     // In Run 3 we also have a GE2/1 station at layer 2. We make sure
0130     // the superchamber gets built but also we build on the first
0131     // layer for the other stations so the superchamber is in the
0132     // right position there.
0133     if ((detIdCh.layer() == 1) || (detIdCh.layer() == 2 and detIdCh.station() == 2 and demonstratorGeometry)) {
0134       GEMSuperChamber* gemSuperChamber = buildSuperChamber(fv, detIdCh);
0135       superChambers.push_back(gemSuperChamber);
0136     }
0137     GEMChamber* gemChamber = ((detIdCh.station() == GEMDetId::minStationId0) ? nullptr : buildChamber(fv, detIdCh));
0138 
0139     // loop over chambers
0140     // only 1 chamber
0141     bool doChambers = fv.firstChild();
0142     bool loopExecuted = false;
0143 
0144     while (doChambers) {
0145       loopExecuted = true;
0146 
0147       if (detIdCh.station() == GEMDetId::minStationId0) {
0148         fv.firstChild();
0149         int rawId = gemNum.baseNumberToUnitNumber(mdddnum.geoHistoryToBaseNumber(fv.geoHistory()));
0150         GEMDetId detId = GEMDetId(rawId);
0151         fv.parent();
0152 #ifdef EDM_ML_DEBUG
0153         edm::LogVerbatim("Geometry") << "MuonGeometry 3 " << fv.geoHistory() << " Levels "
0154                                      << mdddnum.geoHistoryToBaseNumber(fv.geoHistory()).getLevels();
0155         gemNum.baseNumberToUnitNumber(mdddnum.geoHistoryToBaseNumber(fv.geoHistory()));
0156 #endif
0157         gemChamber = buildChamber(fv, detId);
0158       }
0159 
0160       // loop over GEMEtaPartitions
0161       bool doEtaPart = fv.firstChild();
0162 
0163       while (doEtaPart) {
0164 #ifdef EDM_ML_DEBUG
0165         edm::LogVerbatim("Geometry") << "MuonGeometry 4 " << fv.geoHistory() << " Levels "
0166                                      << mdddnum.geoHistoryToBaseNumber(fv.geoHistory()).getLevels();
0167 #endif
0168         int rawid = gemNum.baseNumberToUnitNumber(mdddnum.geoHistoryToBaseNumber(fv.geoHistory()));
0169         GEMDetId detId = GEMDetId(rawid);
0170         GEMEtaPartition* etaPart = buildEtaPartition(fv, detId);
0171         gemChamber->add(etaPart);
0172         theGeometry.add(etaPart);
0173         doEtaPart = fv.nextSibling();
0174       }
0175 
0176       fv.parent();
0177 
0178       theGeometry.add(gemChamber);
0179 
0180       doChambers = fv.nextSibling();
0181     }
0182     fv.parent();
0183 
0184     doSuper = fv.nextSibling();
0185 
0186     if (!loopExecuted) {
0187       delete gemChamber;
0188     }
0189   }
0190 
0191   buildRegions(theGeometry, superChambers, demonstratorGeometry);
0192 }
0193 
0194 GEMSuperChamber* GEMGeometryBuilder::buildSuperChamber(DDFilteredView& fv, GEMDetId detId) const {
0195 #ifdef EDM_ML_DEBUG
0196   edm::LogVerbatim("Geometry") << "buildSuperChamber " << fv.logicalPart().name().name() << " " << detId;
0197 #endif
0198   DDBooleanSolid solid = (DDBooleanSolid)(fv.logicalPart().solid());
0199   bool ge0Station = detId.station() == GEMDetId::minStationId0;
0200   std::vector<double> dpar = ge0Station ? solid.parameters() : solid.solidA().parameters();
0201 
0202   double dy = convertMmToCm(dpar[0]);   //length is along local Y
0203   double dz = convertMmToCm(dpar[3]);   // thickness is long local Z
0204   double dx1 = convertMmToCm(dpar[4]);  // bottom width is along local X
0205   double dx2 = convertMmToCm(dpar[8]);  // top width is along local X
0206 
0207   if (!ge0Station) {
0208     const int nch = 2;
0209     const double chgap = 2.105;
0210 
0211     dpar = solid.solidB().parameters();
0212 
0213     dz += convertMmToCm(dpar[3]);  // chamber thickness
0214     dz *= nch;                     // 2 chambers in superchamber
0215     dz += chgap;                   // gap between chambers
0216   }
0217 
0218   bool isOdd = detId.chamber() % 2;
0219   RCPBoundPlane surf(boundPlane(fv, new TrapezoidalPlaneBounds(dx1, dx2, dy, dz), isOdd));
0220 
0221 #ifdef EDM_ML_DEBUG
0222   edm::LogVerbatim("Geometry") << "size " << dx1 << " " << dx2 << " " << dy << " " << dz;
0223 #endif
0224   GEMSuperChamber* superChamber = new GEMSuperChamber(detId.superChamberId(), surf);
0225   return superChamber;
0226 }
0227 
0228 GEMChamber* GEMGeometryBuilder::buildChamber(DDFilteredView& fv, GEMDetId detId) const {
0229 #ifdef EDM_ML_DEBUG
0230   edm::LogVerbatim("Geometry") << "buildChamber " << fv.logicalPart().name().name() << " " << detId;
0231 #endif
0232   DDBooleanSolid solid = (DDBooleanSolid)(fv.logicalPart().solid());
0233   bool ge0Station = detId.station() == GEMDetId::minStationId0;
0234   std::vector<double> dpar = ge0Station ? solid.parameters() : solid.solidA().parameters();
0235 
0236   double dy = convertMmToCm(dpar[0]);   //length is along local Y
0237   double dz = convertMmToCm(dpar[3]);   // thickness is long local Z
0238   double dx1 = convertMmToCm(dpar[4]);  // bottom width is along local X
0239   double dx2 = convertMmToCm(dpar[8]);  // top width is along local X
0240 
0241   if (!ge0Station) {
0242     dpar = solid.solidB().parameters();
0243     dz += convertMmToCm(dpar[3]);  // chamber thickness
0244   }
0245 
0246   bool isOdd = ge0Station ? false : detId.chamber() % 2;
0247 
0248   RCPBoundPlane surf(boundPlane(fv, new TrapezoidalPlaneBounds(dx1, dx2, dy, dz), isOdd));
0249 
0250 #ifdef EDM_ML_DEBUG
0251   edm::LogVerbatim("Geometry") << "size " << dx1 << " " << dx2 << " " << dy << " " << dz;
0252 #endif
0253   GEMChamber* chamber = new GEMChamber(detId.chamberId(), surf);
0254   return chamber;
0255 }
0256 
0257 GEMEtaPartition* GEMGeometryBuilder::buildEtaPartition(DDFilteredView& fv, GEMDetId detId) const {
0258 #ifdef EDM_ML_DEBUG
0259   edm::LogVerbatim("Geometry") << "buildEtaPartition " << fv.logicalPart().name().name() << " " << detId;
0260 #endif
0261   // EtaPartition specific parameter (nstrips and npads)
0262   DDValue numbOfStrips("nStrips");
0263   DDValue numbOfPads("nPads");
0264   DDValue delPhi("dPhi");
0265   std::vector<const DDsvalues_type*> specs(fv.specifics());
0266   std::vector<const DDsvalues_type*>::iterator is = specs.begin();
0267   double nStrips = 0., nPads = 0., dPhi = 0.;
0268   for (; is != specs.end(); is++) {
0269     if (DDfetch(*is, numbOfStrips))
0270       nStrips = numbOfStrips.doubles()[0];
0271     if (DDfetch(*is, numbOfPads))
0272       nPads = numbOfPads.doubles()[0];
0273     if (DDfetch(*is, delPhi))
0274       dPhi = delPhi.doubles()[0];
0275   }
0276 #ifdef EDM_ML_DEBUG
0277   edm::LogVerbatim("Geometry") << ((nStrips == 0.) ? ("No nStrips found!!")
0278                                                    : ("Number of strips: " + std::to_string(nStrips)));
0279   edm::LogVerbatim("Geometry") << ((nPads == 0.) ? ("No nPads found!!") : ("Number of pads: " + std::to_string(nPads)));
0280 #endif
0281   // EtaPartition specific parameter (size)
0282   std::vector<double> dpar = fv.logicalPart().solid().parameters();
0283 
0284   double be = convertMmToCm(dpar[4]);  // half bottom edge
0285   double te = convertMmToCm(dpar[8]);  // half top edge
0286   double ap = convertMmToCm(dpar[0]);  // half apothem
0287   double ti = 0.4;                     // half thickness
0288 
0289   std::vector<float> pars;
0290   pars.emplace_back(be);
0291   pars.emplace_back(te);
0292   pars.emplace_back(ap);
0293   pars.emplace_back(nStrips);
0294   pars.emplace_back(nPads);
0295   pars.emplace_back(dPhi);
0296 
0297   bool isOdd = detId.chamber() % 2;
0298   RCPBoundPlane surf(boundPlane(fv, new TrapezoidalPlaneBounds(be, te, ap, ti), isOdd));
0299   std::string name = fv.logicalPart().name().name();
0300   GEMEtaPartitionSpecs* e_p_specs = new GEMEtaPartitionSpecs(GeomDetEnumerators::GEM, name, pars);
0301 
0302 #ifdef EDM_ML_DEBUG
0303   edm::LogVerbatim("Geometry") << "size " << be << " " << te << " " << ap << " " << ti;
0304 #endif
0305   GEMEtaPartition* etaPartition = new GEMEtaPartition(detId, surf, e_p_specs);
0306   return etaPartition;
0307 }
0308 
0309 GEMGeometryBuilder::RCPBoundPlane GEMGeometryBuilder::boundPlane(const DDFilteredView& fv,
0310                                                                  Bounds* bounds,
0311                                                                  bool isOddChamber) const {
0312   // extract the position
0313   const DDTranslation& trans(fv.translation());
0314   const Surface::PositionType posResult(convertMmToCm(trans.x()), convertMmToCm(trans.y()), convertMmToCm(trans.z()));
0315 
0316   // now the rotation
0317   const DDRotationMatrix& rotation = fv.rotation();
0318   DD3Vector x, y, z;
0319   rotation.GetComponents(x, y, z);
0320 
0321   Surface::RotationType rotResult(float(x.X()),
0322                                   float(x.Y()),
0323                                   float(x.Z()),
0324                                   float(y.X()),
0325                                   float(y.Y()),
0326                                   float(y.Z()),
0327                                   float(z.X()),
0328                                   float(z.Y()),
0329                                   float(z.Z()));
0330 
0331   //Change of axes for the forward
0332   Basic3DVector<float> newX(1., 0., 0.);
0333   Basic3DVector<float> newY(0., 0., -1.);
0334   Basic3DVector<float> newZ(0., 1., 0.);
0335 
0336   rotResult.rotateAxes(newX, newY, newZ);
0337 
0338   return RCPBoundPlane(new BoundPlane(posResult, rotResult, bounds));
0339 }
0340 
0341 // DD4hep
0342 
0343 void GEMGeometryBuilder::build(GEMGeometry& theGeometry,
0344                                const cms::DDCompactView* cview,
0345                                const MuonGeometryConstants& muonConstants) {
0346   std::string attribute = "MuStructure";
0347   std::string value = "MuonEndCapGEM";
0348   const cms::DDFilter filterGE2(attribute, value);
0349   cms::DDFilteredView fvGE2(*cview, filterGE2);
0350 
0351   MuonGeometryNumbering mdddnum(muonConstants);
0352   GEMNumberingScheme gemNum(muonConstants);
0353   static constexpr uint32_t levelChamb = 7;
0354   int chamb(0), region(0);
0355   int theLevelPart = muonConstants.getValue("level");
0356   int theRingLevel = muonConstants.getValue("mg_ring") / theLevelPart;
0357   int theSectorLevel = muonConstants.getValue("mg_sector") / theLevelPart;
0358 
0359   // Check for the demonstrator geometry (only 1 chamber of GE2/1)
0360   int nGE21 = 0;
0361   while (fvGE2.firstChild()) {
0362     const auto& history = fvGE2.history();
0363     MuonBaseNumber num(mdddnum.geoHistoryToBaseNumber(history));
0364     GEMDetId detId(gemNum.baseNumberToUnitNumber(num));
0365     if (detId.station() == GEMDetId::minStationId0) {
0366     } else {
0367       if (fvGE2.level() == levelChamb) {
0368         if (detId.station() == 2)
0369           nGE21++;
0370       }
0371     }
0372   }
0373 
0374   bool demonstratorGeometry = nGE21 % 2 == 1;
0375 #ifdef EDM_ML_DEBUG
0376   edm::LogVerbatim("Geometry") << "Found " << nGE21 << " GE2/1 chambers. Demonstrator geometry on? "
0377                                << demonstratorGeometry;
0378 #endif
0379 
0380   const cms::DDFilter filter(attribute, value);
0381   cms::DDFilteredView fv(*cview, filter);
0382   std::vector<GEMSuperChamber*> superChambers;
0383   std::vector<GEMChamber*> chambers;
0384 
0385   while (fv.firstChild()) {
0386     const auto& history = fv.history();
0387     MuonBaseNumber num(mdddnum.geoHistoryToBaseNumber(history));
0388     GEMDetId detId(gemNum.baseNumberToUnitNumber(num));
0389 #ifdef EDM_ML_DEBUG
0390     edm::LogVerbatim("Geometry") << fv.name() << " with " << history.tags.size() << " Levels and ID " << detId
0391                                  << " Mask " << std::hex << GEMDetId::chamberIdMask << std::dec << " and "
0392                                  << GEMDetId(((detId.rawId()) & GEMDetId::chamberIdMask)) << " Levels " << theRingLevel
0393                                  << ":" << theSectorLevel << ":" << history.tags.size() << ":" << fv.level();
0394     for (unsigned int k = 0; k < history.tags.size(); ++k)
0395       edm::LogVerbatim("Geometry") << "[" << k << "] Tag " << history.tags[k] << " Offset " << history.offsets[k]
0396                                    << " copy " << history.copyNos[k];
0397 #endif
0398 
0399     if (detId.station() == GEMDetId::minStationId0) {
0400       if (num.getLevels() == theRingLevel) {
0401         if (detId.region() != region) {
0402           region = detId.region();
0403           chamb = 0;
0404         }
0405         ++chamb;
0406         detId = GEMDetId(detId.region(), detId.ring(), detId.station(), detId.layer(), chamb, 0);
0407         GEMSuperChamber* gemSuperChamber = buildSuperChamber(fv, detId);
0408         superChambers.emplace_back(gemSuperChamber);
0409       } else if (num.getLevels() == theSectorLevel) {
0410         GEMChamber* gemChamber = buildChamber(fv, detId);
0411         chambers.emplace_back(gemChamber);
0412       } else {
0413         GEMEtaPartition* etaPart = buildEtaPartition(fv, detId);
0414         theGeometry.add(etaPart);
0415       }
0416     } else {
0417       if (fv.level() == levelChamb) {
0418         if ((detId.layer() == 1) || (detId.layer() == 2 and detId.station() == 2 and demonstratorGeometry)) {
0419           GEMSuperChamber* gemSuperChamber = buildSuperChamber(fv, detId);
0420           superChambers.emplace_back(gemSuperChamber);
0421         }
0422         GEMChamber* gemChamber = buildChamber(fv, detId);
0423         chambers.emplace_back(gemChamber);
0424       } else if (num.getLevels() > theSectorLevel) {
0425         GEMEtaPartition* etaPart = buildEtaPartition(fv, detId);
0426         theGeometry.add(etaPart);
0427       }
0428     }
0429   }
0430 
0431   auto& partitions = theGeometry.etaPartitions();
0432   for (auto& gemChamber : chambers) {
0433     uint32_t id0 = ((gemChamber->id().rawId()) & GEMDetId::chamberIdMask);
0434     for (auto& etaPart : partitions) {
0435       if (((etaPart->id().rawId()) & GEMDetId::chamberIdMask) == id0) {
0436         gemChamber->add(etaPart);
0437       }
0438     }
0439     theGeometry.add(gemChamber);
0440   }
0441 
0442   buildRegions(theGeometry, superChambers, demonstratorGeometry);
0443 }
0444 
0445 GEMSuperChamber* GEMGeometryBuilder::buildSuperChamber(cms::DDFilteredView& fv, GEMDetId detId) const {
0446   cms::DDSolid solid(fv.solid());
0447   auto solidA = solid.solidA();
0448   std::vector<double> dpar = solidA.dimensions();
0449 
0450   double dy = k_ScaleFromDD4hep * dpar[3];   //length is along local Y
0451   double dz = k_ScaleFromDD4hep * dpar[2];   // thickness is long local Z
0452   double dx1 = k_ScaleFromDD4hep * dpar[0];  // bottom width is along local X
0453   double dx2 = k_ScaleFromDD4hep * dpar[1];  // top width is along loc
0454 
0455   auto solidB = solid.solidB();
0456   dpar = solidB.dimensions();
0457   const int nch = 2;
0458   const double chgap = 2.105;
0459 
0460   dz += (k_ScaleFromDD4hep * dpar[2]);  // chamber thickness
0461   dz *= nch;                            // 2 chambers in superchamber
0462   dz += chgap;                          // gap between chambers
0463 
0464   bool isOdd = detId.chamber() % 2;
0465   RCPBoundPlane surf(boundPlane(fv, new TrapezoidalPlaneBounds(dx1, dx2, dy, dz), isOdd));
0466 
0467   GEMSuperChamber* superChamber = new GEMSuperChamber(detId.superChamberId(), surf);
0468   return superChamber;
0469 }
0470 
0471 GEMChamber* GEMGeometryBuilder::buildChamber(cms::DDFilteredView& fv, GEMDetId detId) const {
0472   cms::DDSolid solid(fv.solid());
0473   auto solidA = solid.solidA();
0474   std::vector<double> dpar = solidA.dimensions();
0475 
0476   double dy = k_ScaleFromDD4hep * dpar[3];   //length is along local Y
0477   double dz = k_ScaleFromDD4hep * dpar[2];   // thickness is long local Z
0478   double dx1 = k_ScaleFromDD4hep * dpar[0];  // bottom width is along local X
0479   double dx2 = k_ScaleFromDD4hep * dpar[1];  // top width is along local X
0480 
0481   auto solidB = solid.solidB();
0482   dpar = solidB.dimensions();
0483 
0484   dz += (k_ScaleFromDD4hep * dpar[2]);  // chamber thickness
0485 
0486   bool isOdd = detId.chamber() % 2;
0487   RCPBoundPlane surf(boundPlane(fv, new TrapezoidalPlaneBounds(dx1, dx2, dy, dz), isOdd));
0488 
0489   GEMChamber* chamber = new GEMChamber(detId.chamberId(), surf);
0490   return chamber;
0491 }
0492 
0493 GEMEtaPartition* GEMGeometryBuilder::buildEtaPartition(cms::DDFilteredView& fv, GEMDetId detId) const {
0494   // EtaPartition specific parameter (nstrips and npads)
0495 
0496   auto nStrips = fv.get<double>("nStrips");
0497   auto nPads = fv.get<double>("nPads");
0498   auto dPhi = fv.get<double>("dPhi");
0499   // EtaPartition specific parameter (size)
0500 
0501   std::vector<double> dpar = fv.parameters();
0502 
0503   double ti = 0.4;  // half thickness
0504 
0505   const std::vector<float> pars{float(k_ScaleFromDD4hep * dpar[0]),
0506                                 float(k_ScaleFromDD4hep * dpar[1]),
0507                                 float(k_ScaleFromDD4hep * dpar[3]),
0508                                 float(nStrips),
0509                                 float(nPads),
0510                                 float(dPhi)};
0511 
0512   bool isOdd = detId.chamber() % 2;
0513   RCPBoundPlane surf(
0514       boundPlane(fv,
0515                  new TrapezoidalPlaneBounds(
0516                      k_ScaleFromDD4hep * dpar[0], k_ScaleFromDD4hep * dpar[1], k_ScaleFromDD4hep * dpar[3], ti),
0517                  isOdd));
0518 
0519   std::string_view name = fv.name();
0520 
0521   GEMEtaPartitionSpecs* e_p_specs = new GEMEtaPartitionSpecs(GeomDetEnumerators::GEM, std::string(name), pars);
0522 
0523   GEMEtaPartition* etaPartition = new GEMEtaPartition(detId, surf, e_p_specs);
0524   return etaPartition;
0525 }
0526 
0527 GEMGeometryBuilder::RCPBoundPlane GEMGeometryBuilder::boundPlane(const cms::DDFilteredView& fv,
0528                                                                  Bounds* bounds,
0529                                                                  bool isOddChamber) const {
0530   // extract the position
0531   const Double_t* tran = fv.trans();
0532   Surface::PositionType posResult(
0533       k_ScaleFromDD4hep * tran[0], k_ScaleFromDD4hep * tran[1], k_ScaleFromDD4hep * tran[2]);
0534 
0535   // now the rotation
0536   DDRotationMatrix rota;
0537   fv.rot(rota);
0538   DD3Vector x, y, z;
0539   rota.GetComponents(x, y, z);
0540   Surface::RotationType rotResult(float(x.X()),
0541                                   float(x.Y()),
0542                                   float(x.Z()),
0543                                   float(y.X()),
0544                                   float(y.Y()),
0545                                   float(y.Z()),
0546                                   float(z.X()),
0547                                   float(z.Y()),
0548                                   float(z.Z()));
0549 
0550   //Change of axes for the forward
0551   Basic3DVector<float> newX(1., 0., 0.);
0552   Basic3DVector<float> newY(0., 0., -1.);
0553   Basic3DVector<float> newZ(0., 1., 0.);
0554 
0555   rotResult.rotateAxes(newX, newY, newZ);
0556 
0557   return RCPBoundPlane(new BoundPlane(posResult, rotResult, bounds));
0558 }
0559 
0560 void GEMGeometryBuilder::buildRegions(GEMGeometry& theGeometry,
0561                                       const std::vector<GEMSuperChamber*>& superChambers,
0562                                       bool demonstratorGeometry) {
0563   // construct the regions, stations and rings.
0564   for (int re = -1; re <= 1; re = re + 2) {
0565     GEMRegion* region = new GEMRegion(re);
0566     for (int st = GEMDetId::minStationId0; st <= GEMDetId::maxStationId; ++st) {
0567       bool ge0Station = st == GEMDetId::minStationId0;
0568       GEMStation* station = new GEMStation(re, st);
0569       std::string sign(re == -1 ? "-" : "");
0570       std::string suffix = ge0Station ? "" : "/1";
0571       std::string name = "GE" + sign + std::to_string(st) + suffix;
0572       station->setName(name);
0573       bool foundSuperChamber = false;
0574       for (int ri = 1; ri <= 1; ++ri) {
0575         GEMRing* ring = new GEMRing(re, st, ri);
0576         for (auto superChamber : superChambers) {
0577           const GEMDetId detId(superChamber->id());
0578           if (detId.region() != re || detId.station() != st || detId.ring() != ri)
0579             continue;
0580 
0581           foundSuperChamber = true;
0582           int nlayers = ge0Station ? GEMDetId::maxLayerId0 : GEMDetId::maxLayerId;
0583 
0584           // GEMDetId::minLayerId is to id the superchamber, so minLayerId+1 is the first layer
0585           for (int la = GEMDetId::minLayerId + 1; la <= nlayers; ++la) {
0586             GEMDetId chId(detId.region(), detId.ring(), detId.station(), la, detId.chamber(), 0);
0587             auto chamber = theGeometry.chamber(chId);
0588             if (!chamber) {
0589               // this particular layer 1 chamber *should* be missing in the demonstrator geometry (we only have layer 2)
0590               if (!demonstratorGeometry or not(chId.station() == 2)) {
0591                 edm::LogWarning("GEMGeometryBuilder") << "Missing chamber " << chId;
0592               }
0593             } else {
0594               superChamber->add(chamber);
0595             }
0596           }
0597           ring->add(superChamber);
0598           theGeometry.add(superChamber);
0599 #ifdef EDM_ML_DEBUG
0600           edm::LogVerbatim("Geometry") << "Adding super chamber " << detId << " to ring: "
0601                                        << "re " << re << " st " << st << " ri " << ri;
0602 #endif
0603         }
0604 #ifdef EDM_ML_DEBUG
0605         edm::LogVerbatim("Geometry") << "Adding ring " << ri << " to station "
0606                                      << "re " << re << " st " << st;
0607 #endif
0608         if (foundSuperChamber) {
0609           station->add(ring);
0610           theGeometry.add(ring);
0611         }
0612       }
0613       if (!foundSuperChamber) {
0614 #ifdef EDM_ML_DEBUG
0615         edm::LogVerbatim("Geometry") << "No superchamber found: re:" << re << " st:" << st;
0616 #endif
0617         delete station;
0618       } else {
0619 #ifdef EDM_ML_DEBUG
0620         edm::LogVerbatim("Geometry") << "Adding station " << st << " to region " << re;
0621 #endif
0622         region->add(station);
0623         theGeometry.add(station);
0624       }
0625     }
0626 #ifdef EDM_ML_DEBUG
0627     edm::LogVerbatim("Geometry") << "Adding region " << re << " to the geometry ";
0628 #endif
0629     theGeometry.add(region);
0630   }
0631 }