Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:15:31

0001 /****************************************************************************
0002 *
0003 * This is a part of the TOTEM offline software.
0004 * Authors:
0005 *   Jan Kašpar (jan.kaspar@gmail.com)
0006 *   CMSSW developers (based on GeometricDet class)
0007 *
0008 ****************************************************************************/
0009 
0010 #include <utility>
0011 
0012 #include "Geometry/VeryForwardGeometryBuilder/interface/DetGeomDesc.h"
0013 #include "Geometry/VeryForwardGeometryBuilder/interface/CTPPSDDDNames.h"
0014 #include "CondFormats/PPSObjects/interface/CTPPSRPAlignmentCorrectionData.h"
0015 
0016 #include "DetectorDescription/Core/interface/DDSolid.h"
0017 #include "DetectorDescription/DDCMS/interface/DDSolidShapes.h"
0018 
0019 #include "DataFormats/CTPPSDetId/interface/TotemRPDetId.h"
0020 #include "DataFormats/CTPPSDetId/interface/TotemTimingDetId.h"
0021 #include "DataFormats/CTPPSDetId/interface/CTPPSPixelDetId.h"
0022 #include "DataFormats/CTPPSDetId/interface/CTPPSDiamondDetId.h"
0023 #include <DD4hep/DD4hepUnits.h>
0024 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0025 
0026 /*
0027  *  Constructor from old DD DDFilteredView, also using the SpecPars to access 2x2 wafers info.
0028  */
0029 DetGeomDesc::DetGeomDesc(const DDFilteredView& fv, const bool isRun2)
0030     : m_name(computeNameWithNoNamespace(fv.name())),
0031       m_copy(fv.copyno()),
0032       m_isDD4hep(false),
0033       m_trans(fv.translation()),  // mm (legacy)
0034       m_rot(fv.rotation()),
0035       m_params(fv.parameters()),  // default unit from old DD (mm)
0036       m_isABox(fv.shape() == DDSolidShape::ddbox),
0037       m_diamondBoxParams(computeDiamondDimensions(m_isABox, m_isDD4hep, m_params)),  // mm (legacy)
0038       m_sensorType(computeSensorType(fv.logicalPart().name().fullname())),
0039       m_geographicalID(computeDetID(m_name, fv.copyNumbers(), fv.copyno(), isRun2)),
0040       m_z(fv.translation().z())  // mm (legacy)
0041 {}
0042 
0043 /*
0044  *  Constructor from DD4hep DDFilteredView, also using the SpecPars to access 2x2 wafers info.
0045  */
0046 DetGeomDesc::DetGeomDesc(const cms::DDFilteredView& fv, const bool isRun2)
0047     : m_name(computeNameWithNoNamespace(fv.name())),
0048       m_copy(fv.copyNum()),
0049       m_isDD4hep(true),
0050       m_trans(fv.translation() / dd4hep::mm),  // converted from DD4hep unit to mm
0051       m_rot(fv.rotation()),
0052       m_params(computeParameters(fv)),  // default unit from DD4hep
0053       m_isABox(dd4hep::isA<dd4hep::Box>(fv.solid())),
0054       m_diamondBoxParams(computeDiamondDimensions(m_isABox, m_isDD4hep, m_params)),  // converted from DD4hep unit to mm
0055       m_sensorType(computeSensorType(fv.name())),
0056       m_geographicalID(computeDetIDFromDD4hep(m_name, fv.copyNos(), fv.copyNum(), isRun2)),
0057       m_z(fv.translation().z() / dd4hep::mm)  // converted from DD4hep unit to mm
0058 {}
0059 
0060 DetGeomDesc::DetGeomDesc(const DetGeomDesc& ref, CopyMode cm) {
0061   m_name = ref.m_name;
0062   m_copy = ref.m_copy;
0063   m_isDD4hep = ref.m_isDD4hep;
0064   m_trans = ref.m_trans;
0065   m_rot = ref.m_rot;
0066   m_params = ref.m_params;
0067   m_isABox = ref.m_isABox;
0068   m_diamondBoxParams = ref.m_diamondBoxParams;
0069   m_sensorType = ref.m_sensorType;
0070   m_geographicalID = ref.m_geographicalID;
0071 
0072   if (cm == cmWithChildren)
0073     m_container = ref.m_container;
0074 
0075   m_z = ref.m_z;
0076 }
0077 
0078 // Constructor from DB object PDetGeomDesc::Item
0079 DetGeomDesc::DetGeomDesc(const PDetGeomDesc::Item& item)
0080     : m_name(item.name_),
0081       m_copy(item.copy_),
0082       m_isDD4hep(true),
0083       m_params(item.params_),  // default unit from DD4hep
0084       m_sensorType(item.sensorType_),
0085       m_geographicalID(item.geographicalID_),
0086       m_z(item.z_)  // converted from DD4hep to mm
0087 {
0088   Translation trans(item.dx_, item.dy_, item.dz_);
0089   m_trans = trans;
0090   RotationMatrix rot(item.axx_, item.axy_, item.axz_, item.ayx_, item.ayy_, item.ayz_, item.azx_, item.azy_, item.azz_);
0091   m_rot = rot;
0092   // Set the m_isABox flag for the box shaped sensors, so that m_params are properly set
0093   if ((m_name == DDD_CTPPS_PIXELS_SENSOR_NAME || m_name == DDD_CTPPS_PIXELS_SENSOR_NAME_2x2 ||
0094        m_name == DDD_CTPPS_DIAMONDS_SEGMENT_NAME || m_name == DDD_CTPPS_UFSD_SEGMENT_NAME ||
0095        m_name.substr(0, 7) == DDD_TOTEM_TIMING_SENSOR_TMPL.substr(0, 7)) &&
0096       m_params.size() > 2)
0097     m_isABox = true;
0098   else
0099     m_isABox = false;
0100   m_diamondBoxParams = computeDiamondDimensions(m_isABox, m_isDD4hep, m_params);
0101 }
0102 
0103 DetGeomDesc::DetGeomDesc(const PDetGeomDesc& pd) : m_copy(0), m_isDD4hep(false), m_isABox(false), m_z(0) {
0104   for (const auto& i : pd.container_) {
0105     DetGeomDesc* gd = new DetGeomDesc(i);
0106     this->addComponent(gd);
0107   }
0108 }
0109 
0110 DetGeomDesc::~DetGeomDesc() { deepDeleteComponents(); }
0111 
0112 void DetGeomDesc::addComponent(DetGeomDesc* det) { m_container.emplace_back(det); }
0113 
0114 void DetGeomDesc::applyAlignment(const CTPPSRPAlignmentCorrectionData& t) {
0115   m_rot = t.getRotationMatrix() * m_rot;
0116   m_trans = t.getTranslation() + m_trans;
0117 }
0118 
0119 void DetGeomDesc::print() const {
0120   edm::LogVerbatim("DetGeomDesc::print") << "............................." << std::endl;
0121   edm::LogVerbatim("DetGeomDesc::print") << "name = " << m_name << std::endl;
0122   edm::LogVerbatim("DetGeomDesc::print") << "copy = " << m_copy << std::endl;
0123   edm::LogVerbatim("DetGeomDesc::print") << "translation = " << std::fixed << std::setprecision(7) << m_trans
0124                                          << std::endl;
0125   edm::LogVerbatim("DetGeomDesc::print") << "rotation = " << std::fixed << std::setprecision(7) << m_rot << std::endl;
0126 
0127   if (m_isABox) {
0128     edm::LogVerbatim("DetGeomDesc::print")
0129         << "getDiamondDimensions() = " << std::fixed << std::setprecision(7) << getDiamondDimensions().xHalfWidth << " "
0130         << getDiamondDimensions().yHalfWidth << " " << getDiamondDimensions().zHalfWidth << std::endl;
0131   }
0132 
0133   edm::LogVerbatim("DetGeomDesc::print") << "sensorType = " << m_sensorType << std::endl;
0134 
0135   if (m_geographicalID() != 0) {
0136     edm::LogVerbatim("DetGeomDesc::print") << "geographicalID() = " << m_geographicalID << std::endl;
0137   }
0138 
0139   edm::LogVerbatim("DetGeomDesc::print") << "parentZPosition() = " << std::fixed << std::setprecision(7) << m_z
0140                                          << std::endl;
0141 }
0142 
0143 /*
0144  * PRIVATE FUNCTIONS
0145  */
0146 
0147 void DetGeomDesc::deleteComponents() { m_container.erase(m_container.begin(), m_container.end()); }
0148 
0149 void DetGeomDesc::deepDeleteComponents() {
0150   for (auto& it : m_container) {
0151     delete it;  // the destructor calls deepDeleteComponents
0152   }
0153   clearComponents();
0154 }
0155 
0156 std::string DetGeomDesc::computeNameWithNoNamespace(std::string_view nameFromView) const {
0157   const auto& semiColonPos = nameFromView.find(':');
0158   const std::string name{(semiColonPos != std::string::npos ? nameFromView.substr(semiColonPos + 1) : nameFromView)};
0159   return name;
0160 }
0161 
0162 /*
0163  * Compute DD4hep shape parameters.
0164  */
0165 std::vector<double> DetGeomDesc::computeParameters(const cms::DDFilteredView& fv) const {
0166   auto myShape = fv.solid();
0167   const std::vector<double>& parameters = myShape.dimensions();  // default unit from DD4hep (cm)
0168   return parameters;
0169 }
0170 
0171 /*
0172  * Compute diamond dimensions.
0173  * The diamond sensors are represented by the Box shape parameters.
0174  * oldDD: params are already in mm.
0175  * DD4hep: convert params from DD4hep unit to mm (mm is legacy expected by PPS reco software).
0176  */
0177 DiamondDimensions DetGeomDesc::computeDiamondDimensions(const bool isABox,
0178                                                         const bool isDD4hep,
0179                                                         const std::vector<double>& params) const {
0180   DiamondDimensions boxShapeParameters{};
0181   if (isABox) {
0182     if (!isDD4hep) {
0183       // mm (old DD)
0184       boxShapeParameters = {params.at(0), params.at(1), params.at(2)};
0185     } else {
0186       // convert from DD4hep unit to mm (mm is legacy expected by PPS reco software)
0187       boxShapeParameters = {params.at(0) / dd4hep::mm, params.at(1) / dd4hep::mm, params.at(2) / dd4hep::mm};
0188     }
0189   }
0190   return boxShapeParameters;
0191 }
0192 
0193 /*
0194  * old DD DetId computation.
0195  * Relies on name and volumes copy numbers.
0196  */
0197 DetId DetGeomDesc::computeDetID(const std::string& name,
0198                                 const std::vector<int>& copyNos,
0199                                 const unsigned int copyNum,
0200                                 const bool isRun2) const {
0201   DetId geoID;
0202 
0203   // strip sensors
0204   if (name == DDD_TOTEM_RP_SENSOR_NAME) {
0205     // check size of copy numbers vector
0206     if (copyNos.size() < 3)
0207       throw cms::Exception("DDDTotemRPConstruction")
0208           << "size of copyNumbers for strip sensor is " << copyNos.size() << ". It must be >= 3.";
0209 
0210     // extract information
0211     const unsigned int decRPId = copyNos[copyNos.size() - 3];
0212     const unsigned int arm = decRPId / 100;
0213     const unsigned int station = (decRPId % 100) / 10;
0214     const unsigned int rp = decRPId % 10;
0215     const unsigned int detector = copyNos[copyNos.size() - 1];
0216     geoID = TotemRPDetId(arm, station, rp, detector);
0217   }
0218 
0219   // strip and pixels RPs
0220   else if (name == DDD_TOTEM_RP_RP_NAME || name == DDD_CTPPS_PIXELS_RP_NAME) {
0221     unsigned int decRPId = copyNum;
0222 
0223     // check if it is a pixel RP
0224     if (decRPId >= 10000) {
0225       decRPId = decRPId % 10000;
0226       const unsigned int armIdx = (decRPId / 100) % 10;
0227       const unsigned int stIdx = (decRPId / 10) % 10;
0228       const unsigned int rpIdx = decRPId % 10;
0229       geoID = CTPPSPixelDetId(armIdx, stIdx, rpIdx);
0230     } else {
0231       const unsigned int armIdx = (decRPId / 100) % 10;
0232       const unsigned int stIdx = (decRPId / 10) % 10;
0233       const unsigned int rpIdx = decRPId % 10;
0234       geoID = TotemRPDetId(armIdx, stIdx, rpIdx);
0235     }
0236   }
0237 
0238   else if (std::regex_match(name, std::regex(DDD_TOTEM_TIMING_SENSOR_TMPL))) {
0239     // check size of copy numbers vector
0240     if (copyNos.size() < 4)
0241       throw cms::Exception("DDDTotemRPConstruction")
0242           << "size of copyNumbers for TOTEM timing sensor is " << copyNos.size() << ". It must be >= 4.";
0243 
0244     const unsigned int decRPId = copyNos[copyNos.size() - 4];
0245     const unsigned int arm = decRPId / 100, station = (decRPId % 100) / 10, rp = decRPId % 10;
0246     const unsigned int plane = copyNos[copyNos.size() - 2], channel = copyNos[copyNos.size() - 1];
0247     geoID = TotemTimingDetId(arm, station, rp, plane, channel);
0248   }
0249 
0250   else if (name == DDD_TOTEM_TIMING_RP_NAME) {
0251     const unsigned int arm = copyNum / 100, station = (copyNum % 100) / 10, rp = copyNum % 10;
0252     geoID = TotemTimingDetId(arm, station, rp);
0253   }
0254 
0255   // pixel sensors
0256   else if (name == DDD_CTPPS_PIXELS_SENSOR_NAME || name == DDD_CTPPS_PIXELS_SENSOR_NAME_2x2) {
0257     // check size of copy numbers vector
0258     if (copyNos.size() < 4)
0259       throw cms::Exception("DDDTotemRPConstruction")
0260           << "size of copyNumbers for pixel sensor is " << copyNos.size() << ". It must be >= 4.";
0261 
0262     // extract information
0263     const unsigned int decRPId = copyNos[copyNos.size() - 4] % 10000;
0264     const unsigned int arm = decRPId / 100;
0265     const unsigned int station = (decRPId % 100) / 10;
0266     const unsigned int rp = decRPId % 10;
0267     const unsigned int detector = copyNos[copyNos.size() - 2] - 1;
0268     geoID = CTPPSPixelDetId(arm, station, rp, detector);
0269   }
0270 
0271   // diamond/UFSD sensors
0272   else if (name == DDD_CTPPS_DIAMONDS_SEGMENT_NAME || name == DDD_CTPPS_UFSD_SEGMENT_NAME) {
0273     // check size of copy numbers vector
0274     if (copyNos.size() < 2)
0275       throw cms::Exception("DDDTotemRPConstruction")
0276           << "size of copyNumbers for diamond segments is " << copyNos.size() << ". It must be >= 2.";
0277     const unsigned int decRPId = copyNos[1];
0278     unsigned int arm, station, rp;
0279     if (isRun2) {
0280       arm = decRPId - 1;
0281       station = 1;
0282       rp = 6;
0283     } else {
0284       arm = (decRPId % 1000) / 100;
0285       station = (decRPId % 100) / 10;
0286       rp = decRPId % 10;
0287     }
0288     const unsigned int id = copyNos[copyNos.size() - 1];
0289     const unsigned int plane = id / 100;
0290     const unsigned int channel = id % 100;
0291     geoID = CTPPSDiamondDetId(arm, station, rp, plane, channel);
0292   }
0293 
0294   // diamond/UFSD RPs
0295   else if (name == DDD_CTPPS_DIAMONDS_RP_NAME) {
0296     // check size of copy numbers vector
0297     if (copyNos.size() < 2)
0298       throw cms::Exception("DDDTotemRPConstruction")
0299           << "size of copyNumbers for diamond RP is " << copyNos.size() << ". It must be >= 2.";
0300 
0301     const unsigned int decRPId = copyNos[1];
0302     unsigned int arm, station, rp;
0303     if (isRun2) {
0304       arm = decRPId - 1;
0305       station = 1;
0306       rp = 6;
0307     } else {
0308       arm = (decRPId % 1000) / 100;
0309       station = (decRPId % 100) / 10;
0310       rp = decRPId % 10;
0311     }
0312     geoID = CTPPSDiamondDetId(arm, station, rp);
0313   }
0314 
0315   return geoID;
0316 }
0317 
0318 /*
0319  * DD4hep DetId computation.
0320  */
0321 DetId DetGeomDesc::computeDetIDFromDD4hep(const std::string& name,
0322                                           const std::vector<int>& copyNos,
0323                                           const unsigned int copyNum,
0324                                           const bool isRun2) const {
0325   std::vector<int> copyNosOldDD = {copyNos.rbegin() + 1, copyNos.rend()};
0326 
0327   return computeDetID(name, copyNosOldDD, copyNum, isRun2);
0328 }
0329 
0330 /*
0331  * Sensor type computation.
0332  * Find out from the namespace (from DB) or the volume name (from XMLs), whether a sensor type is 2x2.
0333  */
0334 std::string DetGeomDesc::computeSensorType(std::string_view name) {
0335   std::string sensorType;
0336 
0337   // Case A: Construction from DB.
0338   // Namespace is present, and allow identification of 2x2 sensor type: just look for "2x2:RPixWafer" in name.
0339   const auto& foundFromDB = name.find(DDD_CTPPS_PIXELS_SENSOR_TYPE_2x2 + ":" + DDD_CTPPS_PIXELS_SENSOR_NAME);
0340   if (foundFromDB != std::string::npos) {
0341     sensorType = DDD_CTPPS_PIXELS_SENSOR_TYPE_2x2;
0342   }
0343 
0344   // Case B: Construction from XMLs.
0345   // Volume name allows identification of 2x2 sensor type: just look whether name is "RPixWafer2x2".
0346   const auto& foundFromXML = name.find(DDD_CTPPS_PIXELS_SENSOR_NAME_2x2);
0347   if (foundFromXML != std::string::npos) {
0348     sensorType = DDD_CTPPS_PIXELS_SENSOR_TYPE_2x2;
0349   }
0350 
0351   return sensorType;
0352 }