Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2025-01-22 07:34:08

0001 /* Implementation of the  GEMGeometryParsFromDD Class
0002  *  Build the GEMGeometry from the DDD and DD4hep description
0003  *  
0004  *  DD4hep part added to the original old file (DD version) made by M. Maggi (INFN Bari)
0005  *  Author:  Sergio Lo Meo (sergio.lo.meo@cern.ch) 
0006  *  Created:  Mon, 15 Feb 2021 
0007  *
0008  */
0009 #include "Geometry/GEMGeometryBuilder/interface/GEMGeometryParsFromDD.h"
0010 #include "DataFormats/MuonDetId/interface/GEMDetId.h"
0011 
0012 #include "CondFormats/GeometryObjects/interface/RecoIdealGeometry.h"
0013 #include "DetectorDescription/Core/interface/DDFilter.h"
0014 #include "DetectorDescription/Core/interface/DDFilteredView.h"
0015 #include "DetectorDescription/Core/interface/DDSolid.h"
0016 
0017 #include "Geometry/MuonNumbering/interface/MuonGeometryNumbering.h"
0018 #include "Geometry/MuonNumbering/interface/MuonBaseNumber.h"
0019 #include "Geometry/MuonNumbering/interface/GEMNumberingScheme.h"
0020 #include "Geometry/MuonNumbering/interface/MuonGeometryConstants.h"
0021 
0022 #include "DataFormats/GeometryVector/interface/Basic3DVector.h"
0023 
0024 #include "DetectorDescription/DDCMS/interface/DDFilteredView.h"
0025 #include "DetectorDescription/DDCMS/interface/DDCompactView.h"
0026 #include "DetectorDescription/DDCMS/interface/DDSpecParRegistry.h"
0027 
0028 #include <iostream>
0029 #include <algorithm>
0030 
0031 GEMGeometryParsFromDD::GEMGeometryParsFromDD() {}
0032 
0033 GEMGeometryParsFromDD::~GEMGeometryParsFromDD() {}
0034 
0035 // DDD
0036 
0037 void GEMGeometryParsFromDD::build(const DDCompactView* cview,
0038                                   const MuonGeometryConstants& muonConstants,
0039                                   RecoIdealGeometry& rgeo) {
0040   std::string attribute = "MuStructure";
0041   std::string value = "MuonEndCapGEM";
0042 
0043   // Asking only for the MuonGEM's
0044   DDSpecificsMatchesValueFilter filter{DDValue(attribute, value, 0.0)};
0045   DDFilteredView fv(*cview, filter);
0046   DDFilteredView fv2(*cview, filter);
0047 
0048   this->buildGeometry(fv, fv2, muonConstants, rgeo);
0049 }
0050 
0051 void GEMGeometryParsFromDD::buildGeometry(DDFilteredView& fv,
0052                                           DDFilteredView& fvGE2,
0053                                           const MuonGeometryConstants& muonConstants,
0054                                           RecoIdealGeometry& rgeo) {
0055   LogDebug("GEMGeometryParsFromDD") << "Building the geometry service";
0056   LogDebug("GEMGeometryParsFromDD") << "About to run through the GEM structure\n"
0057                                     << " First logical part " << fv.logicalPart().name().name();
0058 
0059   edm::LogVerbatim("GEMGeometryParsFromDD") << "(0) GEMGeometryParsFromDD - DDD ";
0060   MuonGeometryNumbering muonDDDNumbering(muonConstants);
0061   GEMNumberingScheme gemNumbering(muonConstants);
0062 
0063   // Check for the demonstrator geometry (only 1 chamber of GE2/1)
0064   int nGE21 = 0;
0065   bool doSuper = fvGE2.firstChild();
0066   while (doSuper) {
0067     // getting chamber id from eta partitions
0068     fvGE2.firstChild();
0069     doSuper = fvGE2.firstChild();
0070     if (doSuper) {
0071       int rawidCh = gemNumbering.baseNumberToUnitNumber(muonDDDNumbering.geoHistoryToBaseNumber(fvGE2.geoHistory()));
0072       GEMDetId detIdCh = GEMDetId(rawidCh);
0073       if (detIdCh.station() == 2)
0074         nGE21++;
0075 
0076       // back to chambers
0077       fvGE2.parent();
0078       fvGE2.parent();
0079       // in 2021 we have 1 demonstrator chamber in 2024 we have 3 chambers.
0080       // in 2025 we have 7 chambers.
0081       // Need to account for both
0082       doSuper = (nGE21 < 8 && fvGE2.nextSibling());
0083     } else {
0084       edm::LogError("GEMGeometryParsFromDD") << "Failed to find next child volume. Cannot determine presence of GE 2/1";
0085     }
0086   }
0087   bool demonstratorGeometry = (nGE21 < 8);
0088 
0089 #ifdef EDM_ML_DEBUG
0090   edm::LogVerbatim("Geometry") << "Found " << nGE21 << " GE2/1 chambers. Demonstrator geometry on? "
0091                                << demonstratorGeometry;
0092 #endif
0093 
0094   doSuper = fv.firstChild();
0095 
0096   LogDebug("GEMGeometryParsFromDD") << "doSuperChamber = " << doSuper;
0097   // loop over superchambers
0098   while (doSuper) {
0099     // getting chamber id from eta partitions
0100     fv.firstChild();
0101     doSuper = fv.firstChild();
0102     if (doSuper) {
0103       GEMDetId detIdCh =
0104           GEMDetId(gemNumbering.baseNumberToUnitNumber(muonDDDNumbering.geoHistoryToBaseNumber(fv.geoHistory())));
0105       // back to chambers
0106       fv.parent();
0107       fv.parent();
0108 
0109       // currently there is no superchamber in the geometry
0110       // only 2 chambers are present separated by a gap.
0111       // making superchamber out of the first chamber layer including the gap between chambers
0112 
0113       // In Run 3 we also have a single GE2/1 chamber at layer 2. We
0114       // make sure the superchamber gets built but also we build on the
0115       // first layer for the other stations so the superchamber is in
0116       // the right position there.
0117       if ((detIdCh.layer() == 1) || (detIdCh.layer() == 2 and detIdCh.station() == 2 and demonstratorGeometry)) {
0118         buildSuperChamber(fv, detIdCh, rgeo);
0119       }
0120       buildChamber(fv, detIdCh, rgeo);
0121 
0122       // loop over chambers
0123       // only 1 chamber
0124       bool doChambers = fv.firstChild();
0125       while (doChambers) {
0126         // loop over GEMEtaPartitions
0127         bool doEtaPart = fv.firstChild();
0128         while (doEtaPart) {
0129           GEMDetId detId =
0130               GEMDetId(gemNumbering.baseNumberToUnitNumber(muonDDDNumbering.geoHistoryToBaseNumber(fv.geoHistory())));
0131           buildEtaPartition(fv, detId, rgeo);
0132 
0133           doEtaPart = fv.nextSibling();
0134         }
0135         fv.parent();
0136         doChambers = fv.nextSibling();
0137       }
0138       fv.parent();
0139       doSuper = fv.nextSibling();
0140     } else {
0141       edm::LogError("GEMGeometryParsFromDD") << "Failed to find next child volume. Cannot build GEM chambers.";
0142     }
0143   }
0144 }
0145 
0146 void GEMGeometryParsFromDD::buildSuperChamber(DDFilteredView& fv, GEMDetId detId, RecoIdealGeometry& rgeo) {
0147   LogDebug("GEMGeometryParsFromDD") << "buildSuperChamber " << fv.logicalPart().name().name() << " " << detId
0148                                     << std::endl;
0149 
0150   DDBooleanSolid solid = (DDBooleanSolid)(fv.logicalPart().solid());
0151   std::vector<double> dpar = solid.solidA().parameters();
0152 
0153   GEMDetId gemid = detId.superChamberId();
0154 
0155   double dy = dpar[0];   //length is along local Y
0156   double dz = dpar[3];   // thickness is long local Z
0157   double dx1 = dpar[4];  // bottom width is along local X
0158   double dx2 = dpar[8];  // top width is along local X
0159   dpar = solid.solidB().parameters();
0160 
0161   dz += dpar[3];  // chamber thickness
0162   dz *= 2;        // 2 chambers in superchamber
0163   dz += 2.105;    // gap between chambers
0164 
0165   std::vector<double> pars{dx1, dx2, dy, dz};
0166   std::vector<double> vtra = getTranslation(fv);
0167   std::vector<double> vrot = getRotation(fv);
0168 
0169   LogDebug("GEMGeometryParsFromDD") << "dimension dx1 " << dx1 << ", dx2 " << dx2 << ", dy " << dy << ", dz " << dz;
0170   edm::LogVerbatim("GEMGeometryParsFromDD")
0171       << "(3) DDD, SuperChamber DetID " << gemid.rawId() << " Name " << fv.logicalPart().name().name() << " dx1 " << dx1
0172       << " dx2 " << dx2 << " dy " << dy << " dz " << dz;
0173   rgeo.insert(gemid.rawId(), vtra, vrot, pars, {fv.logicalPart().name().name()});
0174 }
0175 
0176 void GEMGeometryParsFromDD::buildChamber(DDFilteredView& fv, GEMDetId detId, RecoIdealGeometry& rgeo) {
0177   LogDebug("GEMGeometryParsFromDD") << "buildChamber " << fv.logicalPart().name().name() << " " << detId << std::endl;
0178 
0179   DDBooleanSolid solid = (DDBooleanSolid)(fv.logicalPart().solid());
0180   std::vector<double> dpar = solid.solidA().parameters();
0181 
0182   double dy = dpar[0];   //length is along local Y
0183   double dz = dpar[3];   // thickness is long local Z
0184   double dx1 = dpar[4];  // bottom width is along local X
0185   double dx2 = dpar[8];  // top width is along local X
0186   dpar = solid.solidB().parameters();
0187   dz += dpar[3];  // chamber thickness
0188 
0189   GEMDetId gemid = detId.chamberId();
0190 
0191   std::vector<double> pars{dx1, dx2, dy, dz};
0192   std::vector<double> vtra = getTranslation(fv);
0193   std::vector<double> vrot = getRotation(fv);
0194 
0195   LogDebug("GEMGeometryParsFromDD") << "dimension dx1 " << dx1 << ", dx2 " << dx2 << ", dy " << dy << ", dz " << dz;
0196   edm::LogVerbatim("GEMGeometryParsFromDD")
0197       << "(4) DDD, Chamber DetID " << gemid.rawId() << " Name " << fv.logicalPart().name().name() << " dx1 " << dx1
0198       << " dx2 " << dx2 << " dy " << dy << " dz " << dz;
0199   rgeo.insert(gemid.rawId(), vtra, vrot, pars, {fv.logicalPart().name().name()});
0200 }
0201 
0202 void GEMGeometryParsFromDD::buildEtaPartition(DDFilteredView& fv, GEMDetId detId, RecoIdealGeometry& rgeo) {
0203   LogDebug("GEMGeometryParsFromDD") << "buildEtaPartition " << fv.logicalPart().name().name() << " " << detId
0204                                     << std::endl;
0205 
0206   // EtaPartition specific parameter (nstrips and npads)
0207   DDValue numbOfStrips("nStrips");
0208   DDValue numbOfPads("nPads");
0209   DDValue delPhi("dPhi");
0210   const std::vector<const DDsvalues_type*>& specs = fv.specifics();
0211   double nStrips = 0., nPads = 0., dPhi = 0.;
0212   for (auto const& is : specs) {
0213     if (DDfetch(is, numbOfStrips))
0214       nStrips = numbOfStrips.doubles()[0];
0215     if (DDfetch(is, numbOfPads))
0216       nPads = numbOfPads.doubles()[0];
0217     if (DDfetch(is, delPhi))
0218       dPhi = delPhi.doubles()[0];
0219   }
0220   LogDebug("GEMGeometryParsFromDD") << ((nStrips == 0.) ? ("No nStrips found!!")
0221                                                         : ("Number of strips: " + std::to_string(nStrips)));
0222   LogDebug("GEMGeometryParsFromDD") << ((nPads == 0.) ? ("No nPads found!!")
0223                                                       : ("Number of pads: " + std::to_string(nPads)));
0224 
0225   // EtaPartition specific parameter (size)
0226   std::vector<double> dpar = fv.logicalPart().solid().parameters();
0227 
0228   double dy = dpar[0];   //length is along local Y
0229   double dz = dpar[3];   //0.4;// thickness is long local Z
0230   double dx1 = dpar[4];  // bottom width is along local X
0231   double dx2 = dpar[8];  // top width is along local X
0232 
0233   std::vector<double> pars{dx1, dx2, dy, dz, nStrips, nPads, dPhi};
0234   std::vector<double> vtra = getTranslation(fv);
0235   std::vector<double> vrot = getRotation(fv);
0236 
0237   LogDebug("GEMGeometryParsFromDD") << " dx1 " << dx1 << " dx2 " << dx2 << " dy " << dy << " dz " << dz << " nStrips "
0238                                     << nStrips << " nPads " << nPads << " dPhi " << dPhi;
0239 
0240   edm::LogVerbatim("GEMGeometryParsFromDD")
0241       << "(5) DDD, Eta Partion DetID " << detId.rawId() << " Name " << fv.logicalPart().name().name() << " dx1 " << dx1
0242       << " dx2 " << dx2 << " dy " << dy << " dz " << dz << " nStrips " << nStrips << " nPads " << nPads << " dPhi "
0243       << dPhi;
0244   rgeo.insert(detId.rawId(), vtra, vrot, pars, {fv.logicalPart().name().name()});
0245 }
0246 
0247 std::vector<double> GEMGeometryParsFromDD::getTranslation(DDFilteredView& fv) {
0248   const DDTranslation& tran = fv.translation();
0249   edm::LogVerbatim("GEMGeometryParsFromDD")
0250       << "(1) DDD, tran vector " << tran.x() << "  " << tran.y() << "  " << tran.z();
0251   return {tran.x(), tran.y(), tran.z()};
0252 }
0253 
0254 std::vector<double> GEMGeometryParsFromDD::getRotation(DDFilteredView& fv) {
0255   const DDRotationMatrix& rota = fv.rotation();  //.Inverse();
0256   DD3Vector x, y, z;
0257   rota.GetComponents(x, y, z);
0258   edm::LogVerbatim("GEMGeometryParsFromDD")
0259       << "(2) DDD, rot matrix " << x.X() << "  " << x.Y() << "  " << x.Z() << " " << y.X() << "  " << y.Y() << "  "
0260       << y.Z() << " " << z.X() << "  " << z.Y() << "  " << z.Z();
0261   return {x.X(), x.Y(), x.Z(), y.X(), y.Y(), y.Z(), z.X(), z.Y(), z.Z()};
0262 }
0263 
0264 // DD4hep
0265 
0266 void GEMGeometryParsFromDD::build(const cms::DDCompactView* cview,
0267                                   const MuonGeometryConstants& muonConstants,
0268                                   RecoIdealGeometry& rgeo) {
0269   std::string attribute = "MuStructure";
0270   std::string value = "MuonEndCapGEM";
0271 
0272   const cms::DDFilter filter(attribute, value);
0273   cms::DDFilteredView fv(*cview, filter);
0274 
0275   this->buildGeometry(fv, muonConstants, rgeo);
0276 }
0277 
0278 void GEMGeometryParsFromDD::buildGeometry(cms::DDFilteredView& fv,
0279                                           const MuonGeometryConstants& muonConstants,
0280                                           RecoIdealGeometry& rgeo) {
0281   edm::LogVerbatim("GEMGeometryParsFromDD") << "(0) GEMGeometryParsFromDD - DD4hep ";
0282 
0283   MuonGeometryNumbering mdddnum(muonConstants);
0284   GEMNumberingScheme gemNum(muonConstants);
0285   static constexpr uint32_t levelChamb = 7;
0286   int chamb(0), region(0);
0287   int theLevelPart = muonConstants.getValue("level");
0288   int theRingLevel = muonConstants.getValue("mg_ring") / theLevelPart;
0289   int theSectorLevel = muonConstants.getValue("mg_sector") / theLevelPart;
0290 
0291   // Check for the demonstrator geometry (only 1 chamber of GE2/1)
0292   auto start = fv.copyNos();
0293   int nGE21 = 0;
0294   while (nGE21 < 2 && fv.firstChild()) {
0295     const auto& history = fv.history();
0296     MuonBaseNumber num(mdddnum.geoHistoryToBaseNumber(history));
0297     GEMDetId detId(gemNum.baseNumberToUnitNumber(num));
0298     if (fv.level() == levelChamb && detId.station() == 2) {
0299       nGE21++;
0300     }
0301   }
0302   bool demonstratorGeometry = nGE21 % 2 == 1;
0303 #ifdef EDM_ML_DEBUG
0304   edm::LogVerbatim("Geometry") << "Found " << nGE21 << " GE2/1 chambers. Demonstrator geometry on? "
0305                                << demonstratorGeometry;
0306 #endif
0307 
0308   fv.goTo(start);
0309   while (fv.firstChild()) {
0310     const auto& history = fv.history();
0311     MuonBaseNumber num(mdddnum.geoHistoryToBaseNumber(history));
0312     GEMDetId detId(gemNum.baseNumberToUnitNumber(num));
0313 
0314     if (detId.station() == GEMDetId::minStationId0) {
0315       if (num.getLevels() == theRingLevel) {
0316         if (detId.region() != region) {
0317           region = detId.region();
0318           chamb = 0;
0319         }
0320         ++chamb;
0321         detId = GEMDetId(detId.region(), detId.ring(), detId.station(), detId.layer(), chamb, 0);
0322         buildSuperChamber(fv, detId, rgeo);
0323       } else if (num.getLevels() == theSectorLevel) {
0324         buildChamber(fv, detId, rgeo);
0325       } else {
0326         buildEtaPartition(fv, detId, rgeo);
0327       }
0328     } else {
0329       if (fv.level() == levelChamb) {
0330         if ((detId.layer() == 1) || (detId.layer() == 2 and detId.station() == 2 and demonstratorGeometry)) {
0331           buildSuperChamber(fv, detId, rgeo);
0332         }
0333         buildChamber(fv, detId, rgeo);
0334       } else if (num.getLevels() > theSectorLevel) {
0335         buildEtaPartition(fv, detId, rgeo);
0336       }
0337     }
0338   }
0339 }
0340 
0341 void GEMGeometryParsFromDD::buildSuperChamber(cms::DDFilteredView& fv, GEMDetId detId, RecoIdealGeometry& rgeo) {
0342   cms::DDSolid solid(fv.solid());
0343   auto solidA = solid.solidA();
0344   std::vector<double> dpar = solidA.dimensions();
0345 
0346   double dy = dpar[3] / dd4hep::mm;   //length is along local Y
0347   double dz = dpar[2] / dd4hep::mm;   // thickness is long local Z
0348   double dx1 = dpar[0] / dd4hep::mm;  // bottom width is along local X
0349   double dx2 = dpar[1] / dd4hep::mm;  // top width is along loc
0350 
0351   auto solidB = solid.solidB();
0352   dpar = solidB.dimensions();
0353   const int nch = 2;
0354   const double chgap = 2.105;
0355 
0356   GEMDetId gemid = detId.superChamberId();
0357   std::string_view name = fv.name();
0358 
0359   dz += (dpar[2] / dd4hep::mm);  // chamber thickness
0360   dz *= nch;                     // 2 chambers in superchamber
0361   dz += chgap;                   // gap between chambers
0362 
0363   std::vector<double> pars{dx1, dx2, dy, dz};
0364   std::vector<double> vtra = getTranslation(fv);
0365   std::vector<double> vrot = getRotation(fv);
0366 
0367   edm::LogVerbatim("GEMGeometryParsFromDD")
0368       << "(3) DD4hep, SuperChamber DetID " << gemid.rawId() << " Name " << std::string(name) << " dx1 " << dx1
0369       << " dx2 " << dx2 << " dy " << dy << " dz " << dz;
0370   rgeo.insert(gemid.rawId(), vtra, vrot, pars, {std::string(name)});
0371 }
0372 
0373 void GEMGeometryParsFromDD::buildChamber(cms::DDFilteredView& fv, GEMDetId detId, RecoIdealGeometry& rgeo) {
0374   cms::DDSolid solid(fv.solid());
0375   auto solidA = solid.solidA();
0376   std::vector<double> dpar = solidA.dimensions();
0377 
0378   double dy = dpar[3] / dd4hep::mm;   //length is along local Y
0379   double dz = dpar[2] / dd4hep::mm;   // thickness is long local Z
0380   double dx1 = dpar[0] / dd4hep::mm;  // bottom width is along local X
0381   double dx2 = dpar[1] / dd4hep::mm;  // top width is along local X
0382 
0383   auto solidB = solid.solidB();
0384   dpar = solidB.dimensions();
0385 
0386   dz += (dpar[2] / dd4hep::mm);  // chamber thickness
0387 
0388   GEMDetId gemid = detId.chamberId();
0389   std::string_view name = fv.name();
0390 
0391   std::vector<double> pars{dx1, dx2, dy, dz};
0392   std::vector<double> vtra = getTranslation(fv);
0393   std::vector<double> vrot = getRotation(fv);
0394 
0395   edm::LogVerbatim("GEMGeometryParsFromDD")
0396       << "(4) DD4hep, Chamber DetID " << gemid.rawId() << " Name " << std::string(name) << " dx1 " << dx1 << " dx2 "
0397       << dx2 << " dy " << dy << " dz " << dz;
0398   rgeo.insert(gemid.rawId(), vtra, vrot, pars, {std::string(name)});
0399 }
0400 
0401 void GEMGeometryParsFromDD::buildEtaPartition(cms::DDFilteredView& fv, GEMDetId detId, RecoIdealGeometry& rgeo) {
0402   auto nStrips = fv.get<double>("nStrips");
0403   auto nPads = fv.get<double>("nPads");
0404   auto dPhi = fv.get<double>("dPhi");
0405 
0406   std::vector<double> dpar = fv.parameters();
0407   std::string_view name = fv.name();
0408 
0409   double dx1 = dpar[0] / dd4hep::mm;
0410   double dx2 = dpar[1] / dd4hep::mm;
0411   double dy = dpar[3] / dd4hep::mm;
0412   double dz = dpar[2] / dd4hep::mm;
0413 
0414   std::vector<double> pars{dx1, dx2, dy, dz, nStrips, nPads, dPhi};
0415   std::vector<double> vtra = getTranslation(fv);
0416   std::vector<double> vrot = getRotation(fv);
0417 
0418   edm::LogVerbatim("GEMGeometryParsFromDD")
0419       << "(5) DD4hep, Eta Partion DetID " << detId.rawId() << " Name " << std::string(name) << " dx1 " << dx1 << " dx2 "
0420       << dx2 << " dy " << dy << " dz " << dz << " nStrips " << nStrips << " nPads " << nPads << " dPhi " << dPhi;
0421   rgeo.insert(detId.rawId(), vtra, vrot, pars, {std::string(name)});
0422 }
0423 
0424 std::vector<double> GEMGeometryParsFromDD::getTranslation(cms::DDFilteredView& fv) {
0425   std::vector<double> tran(3);
0426   tran[0] = static_cast<double>(fv.translation().X()) / dd4hep::mm;
0427   tran[1] = static_cast<double>(fv.translation().Y()) / dd4hep::mm;
0428   tran[2] = static_cast<double>(fv.translation().Z()) / dd4hep::mm;
0429 
0430   edm::LogVerbatim("GEMGeometryParsFromDD")
0431       << "(1) DD4hep, tran vector " << tran[0] << "  " << tran[1] << "  " << tran[2];
0432   return {tran[0], tran[1], tran[2]};
0433 }
0434 
0435 std::vector<double> GEMGeometryParsFromDD::getRotation(cms::DDFilteredView& fv) {
0436   DDRotationMatrix rota;
0437   fv.rot(rota);
0438   DD3Vector x, y, z;
0439   rota.GetComponents(x, y, z);
0440   const std::vector<double> rot = {x.X(), x.Y(), x.Z(), y.X(), y.Y(), y.Z(), z.X(), z.Y(), z.Z()};
0441   edm::LogVerbatim("GEMGeometryParsFromDD")
0442       << "(2) DD4hep, rot matrix " << rot[0] << "  " << rot[1] << "  " << rot[2] << " " << rot[3] << "  " << rot[4]
0443       << "  " << rot[5] << " " << rot[6] << "  " << rot[7] << "  " << rot[8];
0444   return {rot[0], rot[1], rot[2], rot[3], rot[4], rot[5], rot[6], rot[7], rot[8]};
0445 }