File indexing completed on 2024-04-06 12:20:48
0001 #include "L1Trigger/L1TMuon/interface/GeometryTranslator.h"
0002
0003 #include "FWCore/Framework/interface/EventSetup.h"
0004 #include "FWCore/Framework/interface/ConsumesCollector.h"
0005
0006 #include "Geometry/Records/interface/MuonGeometryRecord.h"
0007 #include "Geometry/DTGeometry/interface/DTGeometry.h"
0008 #include "Geometry/CSCGeometry/interface/CSCGeometry.h"
0009 #include "Geometry/RPCGeometry/interface/RPCGeometry.h"
0010 #include "Geometry/GEMGeometry/interface/GEMGeometry.h"
0011 #include "Geometry/GEMGeometry/interface/ME0Geometry.h"
0012 #include "MagneticField/Engine/interface/MagneticField.h"
0013 #include "MagneticField/Records/interface/IdealMagneticFieldRecord.h"
0014
0015 #include "L1Trigger/DTUtilities/interface/DTTrigGeom.h"
0016 #include "DataFormats/CSCDigi/interface/CSCConstants.h"
0017 #include "L1Trigger/CSCTriggerPrimitives/interface/CSCPatternBank.h"
0018
0019 #include "L1Trigger/L1TMuon/interface/MuonTriggerPrimitive.h"
0020
0021 #include <cmath> // for pi
0022
0023 using namespace L1TMuon;
0024
0025 GeometryTranslator::GeometryTranslator(edm::ConsumesCollector iC)
0026 : _geom_cache_id(0ULL),
0027 geodtToken_(iC.esConsumes()),
0028 geocscToken_(iC.esConsumes()),
0029 georpcToken_(iC.esConsumes()),
0030 geogemToken_(iC.esConsumes()),
0031 geome0Token_(iC.esConsumes()),
0032 _magfield_cache_id(0ULL),
0033 magfieldToken_(iC.esConsumes()) {}
0034
0035 GeometryTranslator::~GeometryTranslator() {}
0036
0037 double GeometryTranslator::calculateGlobalEta(const TriggerPrimitive& tp) const {
0038 switch (tp.subsystem()) {
0039 case L1TMuon::kDT:
0040 return calcDTSpecificEta(tp);
0041 break;
0042 case L1TMuon::kCSC:
0043 return calcCSCSpecificEta(tp);
0044 break;
0045 case L1TMuon::kRPC:
0046 return calcRPCSpecificEta(tp);
0047 break;
0048 case L1TMuon::kGEM:
0049 return calcGEMSpecificEta(tp);
0050 break;
0051 case L1TMuon::kME0:
0052 return calcME0SpecificEta(tp);
0053 break;
0054 default:
0055 return std::nan("Invalid TP type!");
0056 break;
0057 }
0058 }
0059
0060 double GeometryTranslator::calculateGlobalPhi(const TriggerPrimitive& tp) const {
0061 switch (tp.subsystem()) {
0062 case L1TMuon::kDT:
0063 return calcDTSpecificPhi(tp);
0064 break;
0065 case L1TMuon::kCSC:
0066 return calcCSCSpecificPhi(tp);
0067 break;
0068 case L1TMuon::kRPC:
0069 return calcRPCSpecificPhi(tp);
0070 break;
0071 case L1TMuon::kGEM:
0072 return calcGEMSpecificPhi(tp);
0073 break;
0074 case L1TMuon::kME0:
0075 return calcME0SpecificPhi(tp);
0076 break;
0077 default:
0078 return std::nan("Invalid TP type!");
0079 break;
0080 }
0081 }
0082
0083 double GeometryTranslator::calculateBendAngle(const TriggerPrimitive& tp) const {
0084 switch (tp.subsystem()) {
0085 case L1TMuon::kDT:
0086 return calcDTSpecificBend(tp);
0087 break;
0088 case L1TMuon::kCSC:
0089 return calcCSCSpecificBend(tp);
0090 break;
0091 case L1TMuon::kRPC:
0092 return calcRPCSpecificBend(tp);
0093 break;
0094 case L1TMuon::kGEM:
0095 return calcGEMSpecificBend(tp);
0096 break;
0097 case L1TMuon::kME0:
0098 return calcME0SpecificBend(tp);
0099 break;
0100 default:
0101 return std::nan("Invalid TP type!");
0102 break;
0103 }
0104 }
0105
0106 GlobalPoint GeometryTranslator::getGlobalPoint(const TriggerPrimitive& tp) const {
0107 switch (tp.subsystem()) {
0108 case L1TMuon::kDT:
0109 return calcDTSpecificPoint(tp);
0110 break;
0111 case L1TMuon::kCSC:
0112 return getCSCSpecificPoint(tp);
0113 break;
0114 case L1TMuon::kRPC:
0115 return getRPCSpecificPoint(tp);
0116 break;
0117 case L1TMuon::kGEM:
0118 return getGEMSpecificPoint(tp);
0119 break;
0120 case L1TMuon::kME0:
0121 return getME0SpecificPoint(tp);
0122 break;
0123 default:
0124 GlobalPoint ret(
0125 GlobalPoint::Polar(std::nan("Invalid TP type!"), std::nan("Invalid TP type!"), std::nan("Invalid TP type!")));
0126 return ret;
0127 break;
0128 }
0129 }
0130
0131 void GeometryTranslator::checkAndUpdateGeometry(const edm::EventSetup& es) {
0132 const MuonGeometryRecord& geom = es.get<MuonGeometryRecord>();
0133 unsigned long long geomid = geom.cacheIdentifier();
0134 if (_geom_cache_id != geomid) {
0135 _geodt = geom.getHandle(geodtToken_);
0136 _geocsc = geom.getHandle(geocscToken_);
0137 _georpc = geom.getHandle(georpcToken_);
0138 _geogem = geom.getHandle(geogemToken_);
0139 _geome0 = geom.getHandle(geome0Token_);
0140 _geom_cache_id = geomid;
0141 }
0142
0143 const IdealMagneticFieldRecord& magfield = es.get<IdealMagneticFieldRecord>();
0144 unsigned long long magfieldid = magfield.cacheIdentifier();
0145 if (_magfield_cache_id != magfieldid) {
0146 _magfield = magfield.getHandle(magfieldToken_);
0147 _magfield_cache_id = magfieldid;
0148 }
0149 }
0150
0151
0152
0153 GlobalPoint GeometryTranslator::getME0SpecificPoint(const TriggerPrimitive& tp) const {
0154 if (tp.detId<DetId>().subdetId() == MuonSubdetId::GEM) {
0155 const GEMDetId id(tp.detId<GEMDetId>());
0156 const GEMSuperChamber* chamber = _geogem->superChamber(id);
0157 const GEMChamber* keylayer = chamber->chamber(3);
0158 int partition = tp.getME0Data().partition;
0159 int iroll = (partition >> 1) + 1;
0160 const GEMEtaPartition* roll = keylayer->etaPartition(iroll);
0161
0162
0163 if (roll == nullptr) {
0164 throw cms::Exception("Invalid GE0 Roll") << "Failed to get GEM roll for GE0" << std::endl;
0165 }
0166
0167
0168 int phiposition = tp.getME0Data().phiposition;
0169 int istrip = (phiposition >> 1);
0170 int phiposition2 = (phiposition & 0x1);
0171 float centreOfStrip = istrip + 0.25 + phiposition2 * 0.5;
0172 const LocalPoint& lp = roll->centreOfStrip(centreOfStrip);
0173 const GlobalPoint& gp = roll->surface().toGlobal(lp);
0174 return gp;
0175 } else {
0176 const ME0DetId id(tp.detId<ME0DetId>());
0177 const ME0Chamber* chamber = _geome0->chamber(id);
0178 const ME0Layer* keylayer = chamber->layer(3);
0179 int partition = tp.getME0Data().partition;
0180 int iroll = (partition >> 1) + 1;
0181 const ME0EtaPartition* roll = keylayer->etaPartition(iroll);
0182
0183
0184 if (roll == nullptr) {
0185 throw cms::Exception("Invalid ME0 Roll") << "Failed to get ME0 roll" << std::endl;
0186 }
0187
0188
0189 int phiposition = tp.getME0Data().phiposition;
0190 int istrip = (phiposition >> 1);
0191 int phiposition2 = (phiposition & 0x1);
0192 float centreOfStrip = istrip + 0.25 + phiposition2 * 0.5;
0193 const LocalPoint& lp = roll->centreOfStrip(centreOfStrip);
0194 const GlobalPoint& gp = roll->surface().toGlobal(lp);
0195 return gp;
0196 }
0197 }
0198
0199 double GeometryTranslator::calcME0SpecificEta(const TriggerPrimitive& tp) const {
0200 return getME0SpecificPoint(tp).eta();
0201 }
0202
0203 double GeometryTranslator::calcME0SpecificPhi(const TriggerPrimitive& tp) const {
0204 return getME0SpecificPoint(tp).phi();
0205 }
0206
0207 double GeometryTranslator::calcME0SpecificBend(const TriggerPrimitive& tp) const {
0208 return tp.getME0Data().deltaphi * (tp.getME0Data().bend == 0 ? 1 : -1);
0209 }
0210
0211
0212
0213 GlobalPoint GeometryTranslator::getGEMSpecificPoint(const TriggerPrimitive& tp) const {
0214 const GEMDetId id(tp.detId<GEMDetId>());
0215 const GEMEtaPartition* roll = _geogem->etaPartition(id);
0216 assert(roll != nullptr);
0217
0218
0219 const float pad = (0.5 * static_cast<float>(tp.getGEMData().pad_low + tp.getGEMData().pad_hi)) + 0.5f;
0220 const LocalPoint& lp = roll->centreOfPad(pad);
0221 const GlobalPoint& gp = roll->surface().toGlobal(lp);
0222 return gp;
0223 }
0224
0225 double GeometryTranslator::calcGEMSpecificEta(const TriggerPrimitive& tp) const {
0226 return getGEMSpecificPoint(tp).eta();
0227 }
0228
0229 double GeometryTranslator::calcGEMSpecificPhi(const TriggerPrimitive& tp) const {
0230 return getGEMSpecificPoint(tp).phi();
0231 }
0232
0233 double GeometryTranslator::calcGEMSpecificBend(const TriggerPrimitive& tp) const { return 0.0; }
0234
0235
0236
0237 GlobalPoint GeometryTranslator::getRPCSpecificPoint(const TriggerPrimitive& tp) const {
0238 const RPCDetId id(tp.detId<RPCDetId>());
0239 const RPCRoll* roll = _georpc->roll(id);
0240 assert(roll != nullptr);
0241
0242
0243 const float strip = (0.5 * static_cast<float>(tp.getRPCData().strip_low + tp.getRPCData().strip_hi)) - 0.5f;
0244 const LocalPoint& lp = roll->centreOfStrip(strip);
0245 const GlobalPoint& gp = roll->surface().toGlobal(lp);
0246 return gp;
0247 }
0248
0249 double GeometryTranslator::calcRPCSpecificEta(const TriggerPrimitive& tp) const {
0250 return getRPCSpecificPoint(tp).eta();
0251 }
0252
0253 double GeometryTranslator::calcRPCSpecificPhi(const TriggerPrimitive& tp) const {
0254 return getRPCSpecificPoint(tp).phi();
0255 }
0256
0257
0258
0259 double GeometryTranslator::calcRPCSpecificBend(const TriggerPrimitive& tp) const { return 0.0; }
0260
0261
0262
0263
0264
0265
0266
0267
0268 GlobalPoint GeometryTranslator::getCSCSpecificPoint(const TriggerPrimitive& tp) const {
0269 const CSCDetId id(tp.detId<CSCDetId>());
0270
0271
0272 std::unique_ptr<const CSCChamber> chamb(_geocsc->chamber(id));
0273 assert(chamb != nullptr);
0274 std::unique_ptr<const CSCLayerGeometry> layer_geom(chamb->layer(CSCConstants::KEY_ALCT_LAYER)->geometry());
0275 std::unique_ptr<const CSCLayer> layer(chamb->layer(CSCConstants::KEY_ALCT_LAYER));
0276
0277 const uint16_t halfstrip = tp.getCSCData().strip;
0278 const uint16_t pattern = tp.getCSCData().pattern;
0279 const uint16_t keyWG = tp.getCSCData().keywire;
0280
0281
0282
0283
0284 double offset = 0.0;
0285 switch (1) {
0286 case 1:
0287 offset = CSCPatternBank::getLegacyPosition(pattern);
0288 }
0289 const unsigned halfstrip_offs = static_cast<unsigned>(0.5 + halfstrip + offset);
0290 const unsigned strip = halfstrip_offs / 2 + 1;
0291
0292
0293
0294 const LocalPoint& coarse_lp = layer_geom->stripWireGroupIntersection(strip, keyWG);
0295 const GlobalPoint& coarse_gp = layer->surface().toGlobal(coarse_lp);
0296
0297
0298
0299 const double hs_offset = layer_geom->stripPhiPitch() / 4.0;
0300
0301
0302 const bool ccw = isCSCCounterClockwise(layer);
0303
0304 const double phi_offset = ((halfstrip_offs % 2 ? 1 : -1) * (ccw ? -hs_offset : hs_offset));
0305
0306
0307
0308 const GlobalPoint final_gp(
0309 GlobalPoint::Polar(coarse_gp.theta(), (coarse_gp.phi().value() + phi_offset), coarse_gp.mag()));
0310
0311
0312
0313
0314
0315
0316 chamb.release();
0317 layer_geom.release();
0318 layer.release();
0319
0320 return final_gp;
0321 }
0322
0323 double GeometryTranslator::calcCSCSpecificEta(const TriggerPrimitive& tp) const {
0324 return getCSCSpecificPoint(tp).eta();
0325 }
0326
0327 double GeometryTranslator::calcCSCSpecificPhi(const TriggerPrimitive& tp) const {
0328 return getCSCSpecificPoint(tp).phi();
0329 }
0330
0331 double GeometryTranslator::calcCSCSpecificBend(const TriggerPrimitive& tp) const { return tp.getCSCData().bend; }
0332
0333 bool GeometryTranslator::isCSCCounterClockwise(const std::unique_ptr<const CSCLayer>& layer) const {
0334 const int nStrips = layer->geometry()->numberOfStrips();
0335 const double phi1 = layer->centerOfStrip(1).phi();
0336 const double phiN = layer->centerOfStrip(nStrips).phi();
0337 return ((std::abs(phi1 - phiN) < M_PI && phi1 >= phiN) || (std::abs(phi1 - phiN) >= M_PI && phi1 < phiN));
0338 }
0339
0340
0341
0342 GlobalPoint GeometryTranslator::calcDTSpecificPoint(const TriggerPrimitive& tp) const {
0343 const DTChamberId baseid(tp.detId<DTChamberId>());
0344
0345 std::unique_ptr<DTChamber> chamb(const_cast<DTChamber*>(_geodt->chamber(baseid)));
0346 std::unique_ptr<DTTrigGeom> trig_geom(new DTTrigGeom(chamb.get(), false));
0347 chamb.release();
0348
0349
0350
0351
0352
0353
0354 const int NBTI_theta = ((baseid.station() != 4) ? trig_geom->nCell(2) : trig_geom->nCell(3));
0355 const int bti_group = tp.getDTData().theta_bti_group;
0356 const unsigned bti_actual = bti_group * NBTI_theta / 7 + NBTI_theta / 14 + 1;
0357 DTBtiId thetaBTI;
0358 if (baseid.station() != 4 && bti_group != -1) {
0359 thetaBTI = DTBtiId(baseid, 2, bti_actual);
0360 } else {
0361
0362
0363 thetaBTI = DTBtiId(baseid, 3, 1);
0364 }
0365 const GlobalPoint& theta_gp = trig_geom->CMSPosition(thetaBTI);
0366
0367
0368 double phi = static_cast<double>(tp.getDTData().radialAngle) / 4096.0;
0369 phi += tp.getDTData().sector * M_PI / 6.0;
0370
0371 return GlobalPoint(GlobalPoint::Polar(theta_gp.theta(), phi, theta_gp.mag()));
0372 }
0373
0374 double GeometryTranslator::calcDTSpecificEta(const TriggerPrimitive& tp) const { return calcDTSpecificPoint(tp).eta(); }
0375
0376 double GeometryTranslator::calcDTSpecificPhi(const TriggerPrimitive& tp) const { return calcDTSpecificPoint(tp).phi(); }
0377
0378
0379 double GeometryTranslator::calcDTSpecificBend(const TriggerPrimitive& tp) const {
0380 int bend = tp.getDTData().bendingAngle;
0381 double bendf = bend / 512.0;
0382 return bendf;
0383 }