Back to home page

Project CMSSW displayed by LXR

 
 

    


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

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