diff --git a/Configuration/Eras/python/Era_Phase2_cff.py b/Configuration/Eras/python/Era_Phase2_cff.py index 46432f200234e..87c8ca4cf7dbb 100644 --- a/Configuration/Eras/python/Era_Phase2_cff.py +++ b/Configuration/Eras/python/Era_Phase2_cff.py @@ -20,6 +20,7 @@ from Configuration.Eras.Modifier_ctpps_2022_cff import ctpps_2022 from Configuration.ProcessModifiers.dd4hep_cff import dd4hep from Configuration.Eras.ModifierChain_trackingMkFitProd_cff import trackingMkFitProdPhase2 +from Configuration.Eras.Modifier_phase2_RPC_cff import phase2_RPC Phase2 = cms.ModifierChain(Run3_noMkFit.copyAndExclude([phase1Pixel,trackingPhase1,seedingDeepCore,displacedRegionalTracking,ctpps_2022,dd4hep]), - phase2_common, phase2_tracker, trackingPhase2PU140, phase2_ecal, phase2_hcal, phase2_hgcal, phase2_muon, phase2_GEM, hcalHardcodeConditions, phase2_timing, phase2_timing_layer, phase2_trigger, trackingMkFitProdPhase2) + phase2_common, phase2_tracker, trackingPhase2PU140, phase2_ecal, phase2_hcal, phase2_hgcal, phase2_muon, phase2_GEM, hcalHardcodeConditions, phase2_timing, phase2_timing_layer, phase2_trigger, trackingMkFitProdPhase2, phase2_RPC) diff --git a/Configuration/Eras/python/Era_Run3_2025_cff.py b/Configuration/Eras/python/Era_Run3_2025_cff.py index 8a56316309e45..77bde18e68b46 100644 --- a/Configuration/Eras/python/Era_Run3_2025_cff.py +++ b/Configuration/Eras/python/Era_Run3_2025_cff.py @@ -8,5 +8,6 @@ from Configuration.Eras.Modifier_run3_nanoAOD_2025_cff import run3_nanoAOD_2025 from Configuration.ProcessModifiers.ecal_cctiming_cff import ecal_cctiming from Configuration.ProcessModifiers.siPixelGoodEdgeAlgo_cff import siPixelGoodEdgeAlgo +from Configuration.Eras.Modifier_run3_RPC_2025_cff import run3_RPC_2025 -Run3_2025 = cms.ModifierChain(Run3_2024, run3_GEM_2025, stage2L1Trigger_2025, run3_SiPixel_2025, run3_CSC_2025, run3_nanoAOD_2025, ecal_cctiming, siPixelGoodEdgeAlgo) +Run3_2025 = cms.ModifierChain(Run3_2024, run3_GEM_2025, stage2L1Trigger_2025, run3_SiPixel_2025, run3_CSC_2025, run3_nanoAOD_2025, ecal_cctiming, siPixelGoodEdgeAlgo, run3_RPC_2025) diff --git a/Configuration/Eras/python/Modifier_phase2_RPC_cff.py b/Configuration/Eras/python/Modifier_phase2_RPC_cff.py new file mode 100644 index 0000000000000..4c530d0816efd --- /dev/null +++ b/Configuration/Eras/python/Modifier_phase2_RPC_cff.py @@ -0,0 +1,3 @@ +import FWCore.ParameterSet.Config as cms + +phase2_RPC = cms.Modifier() diff --git a/Configuration/Eras/python/Modifier_run3_RPC_2025_cff.py b/Configuration/Eras/python/Modifier_run3_RPC_2025_cff.py new file mode 100644 index 0000000000000..099dc524a9905 --- /dev/null +++ b/Configuration/Eras/python/Modifier_run3_RPC_2025_cff.py @@ -0,0 +1,4 @@ +import FWCore.ParameterSet.Config as cms + +run3_RPC_2025 = cms.Modifier() + diff --git a/RecoMuon/DetLayers/plugins/MuonDetLayerGeometryESProducer.cc b/RecoMuon/DetLayers/plugins/MuonDetLayerGeometryESProducer.cc index 5b9114ff074a2..c4010dfc86857 100644 --- a/RecoMuon/DetLayers/plugins/MuonDetLayerGeometryESProducer.cc +++ b/RecoMuon/DetLayers/plugins/MuonDetLayerGeometryESProducer.cc @@ -53,6 +53,8 @@ class MuonDetLayerGeometryESProducer : public edm::ESProducer { using namespace edm; MuonDetLayerGeometryESProducer::MuonDetLayerGeometryESProducer(const edm::ParameterSet& p) { + MuonRPCDetLayerGeometryBuilder::useUpdatedRPCIsFront = p.getParameter("useUpdatedRPCIsFront"); + auto cc = setWhatProduced(this); dtToken_ = cc.consumes(); cscToken_ = cc.consumes(); @@ -109,7 +111,7 @@ std::unique_ptr MuonDetLayerGeometryESProducer::produce(co void MuonDetLayerGeometryESProducer::fillDescriptions(edm::ConfigurationDescriptions& descriptions) { edm::ParameterSetDescription desc; - //no parameters are used + desc.add("useUpdatedRPCIsFront", false); descriptions.addDefault(desc); } diff --git a/RecoMuon/DetLayers/python/muonDetLayerGeometry_cfi.py b/RecoMuon/DetLayers/python/muonDetLayerGeometry_cfi.py index a2d05612a7fa1..103cc83beb773 100644 --- a/RecoMuon/DetLayers/python/muonDetLayerGeometry_cfi.py +++ b/RecoMuon/DetLayers/python/muonDetLayerGeometry_cfi.py @@ -3,7 +3,11 @@ # # This cfi should be included to build the muon DetLayers. # -MuonDetLayerGeometryESProducer = cms.ESProducer("MuonDetLayerGeometryESProducer") +MuonDetLayerGeometryESProducer = cms.ESProducer("MuonDetLayerGeometryESProducer", useUpdatedRPCIsFront=cms.bool(False)) +from Configuration.Eras.Modifier_run3_RPC_2025_cff import run3_RPC_2025 +from Configuration.Eras.Modifier_phase2_RPC_cff import phase2_RPC +run3_RPC_2025.toModify(MuonDetLayerGeometryESProducer, useUpdatedRPCIsFront=True) +phase2_RPC.toModify(MuonDetLayerGeometryESProducer, useUpdatedRPCIsFront=True) diff --git a/RecoMuon/DetLayers/src/MuRingForwardDoubleLayer.cc b/RecoMuon/DetLayers/src/MuRingForwardDoubleLayer.cc index 26041968c4dce..4d056a7a7c773 100644 --- a/RecoMuon/DetLayers/src/MuRingForwardDoubleLayer.cc +++ b/RecoMuon/DetLayers/src/MuRingForwardDoubleLayer.cc @@ -6,6 +6,8 @@ #include #include #include +#include +#include #include #include #include @@ -45,7 +47,7 @@ MuRingForwardDoubleLayer::MuRingForwardDoubleLayer(const vector& frontDets = theFrontLayer.basicComponents(); const std::vector& backDets = theBackLayer.basicComponents(); - std::vector::const_iterator frontItr = frontDets.begin(), lastFront = frontDets.end(), - backItr = backDets.begin(), lastBack = backDets.end(); + // Collect front/back chambers by sub-detectors + std::vector frontCSCs, backCSCs; + std::vector frontRPCs, backRPCs; + std::vector frontGEMs, backGEMs; + std::vector frontIRPCs, backIRPCs; + std::vector frontME0s, backME0s; + + for (const GeomDet* frontDet : frontDets) { + const int subdetId = frontDet->geographicalId().subdetId(); + if (subdetId == MuonSubdetId::CSC) { + frontCSCs.push_back(frontDet); + } else if (subdetId == MuonSubdetId::GEM) { + frontGEMs.push_back(frontDet); + } else if (subdetId == MuonSubdetId::ME0) { + frontME0s.push_back(frontDet); + } else if (subdetId == MuonSubdetId::RPC) { + // RPC has to split existing RPC and iRPC + const RPCDetId rpcId(frontDet->geographicalId()); + const int ring = rpcId.ring(); + if (ring == 1) { + frontIRPCs.push_back(frontDet); + } else { + frontRPCs.push_back(frontDet); + } + } + } - // test that each front z is less than each back z - for (; frontItr != lastFront; ++frontItr) { - float frontz = fabs((**frontItr).surface().position().z()); - for (; backItr != lastBack; ++backItr) { - float backz = fabs((**backItr).surface().position().z()); - assert(frontz < backz); + for (const GeomDet* backDet : backDets) { + const int subdetId = backDet->geographicalId().subdetId(); + if (subdetId == MuonSubdetId::CSC) { + backCSCs.push_back(backDet); + } else if (subdetId == MuonSubdetId::GEM) { + backGEMs.push_back(backDet); + } else if (subdetId == MuonSubdetId::ME0) { + backME0s.push_back(backDet); + } else if (subdetId == MuonSubdetId::RPC) { + // RPC has to split existing RPC and iRPC + const RPCDetId rpcId(backDet->geographicalId()); + const int ring = rpcId.ring(); + if (ring == 1) { + backIRPCs.push_back(backDet); + } else { + backRPCs.push_back(backDet); + } } } + + // Perform test for each subsystems, that front-z is less than back-z + // In other word, maximum of front-z must be less than minimum of back-z + + // Check the CSC ordering + double maxZFrontCSC = 0, minZBackCSC = 1e9; + for (auto frontCSC : frontCSCs) { + const double z = std::abs(frontCSC->surface().position().z()); + if (maxZFrontCSC < z) + maxZFrontCSC = z; + } + for (auto backCSC : backCSCs) { + const double z = std::abs(backCSC->surface().position().z()); + if (minZBackCSC > z) + minZBackCSC = z; + } + if (frontCSCs.size() + backCSCs.size() != 0) + LogTrace(metname) << "CSC " << maxZFrontCSC << '<' << minZBackCSC << endl; + assert(maxZFrontCSC < minZBackCSC); + + // Check the RPC ordering + double maxZFrontRPC = 0, minZBackRPC = 1e9; + for (auto frontRPC : frontRPCs) { + const double z = std::abs(frontRPC->surface().position().z()); + if (maxZFrontRPC < z) + maxZFrontRPC = z; + } + for (auto backRPC : backRPCs) { + const double z = std::abs(backRPC->surface().position().z()); + if (minZBackRPC > z) + minZBackRPC = z; + } + if (frontRPCs.size() + backRPCs.size() != 0) + LogTrace(metname) << "RPC " << maxZFrontRPC << '<' << minZBackRPC << endl; + assert(maxZFrontRPC < minZBackRPC); + + // Check the GEM ordering + double maxZFrontGEM = 0, minZBackGEM = 1e9; + for (auto frontGEM : frontGEMs) { + const double z = std::abs(frontGEM->surface().position().z()); + if (maxZFrontGEM < z) + maxZFrontGEM = z; + } + for (auto backGEM : backGEMs) { + const double z = std::abs(backGEM->surface().position().z()); + if (minZBackGEM > z) + minZBackGEM = z; + } + if (frontGEMs.size() + backGEMs.size() != 0) + LogTrace(metname) << "GEM " << maxZFrontGEM << '<' << minZBackGEM << endl; + assert(maxZFrontGEM < minZBackGEM); + + // Check the IRPC ordering + double maxZFrontIRPC = 0, minZBackIRPC = 1e9; + for (auto frontIRPC : frontIRPCs) { + const double z = std::abs(frontIRPC->surface().position().z()); + if (maxZFrontIRPC < z) + maxZFrontIRPC = z; + } + for (auto backIRPC : backIRPCs) { + const double z = std::abs(backIRPC->surface().position().z()); + if (minZBackIRPC > z) + minZBackIRPC = z; + } + if (frontIRPCs.size() + backIRPCs.size() != 0) + LogTrace(metname) << "IRPC " << maxZFrontIRPC << '<' << minZBackIRPC << endl; + assert(maxZFrontIRPC < minZBackIRPC); + + // Check the ME0 ordering + double maxZFrontME0 = 0, minZBackME0 = 1e9; + for (auto frontME0 : frontME0s) { + const double z = std::abs(frontME0->surface().position().z()); + if (maxZFrontME0 < z) + maxZFrontME0 = z; + } + for (auto backME0 : backME0s) { + const double z = std::abs(backME0->surface().position().z()); + if (minZBackME0 > z) + minZBackME0 = z; + } + if (frontME0s.size() + backME0s.size() != 0) + LogTrace(metname) << "ME0 " << maxZFrontME0 << '<' << minZBackME0 << endl; + assert(maxZFrontME0 < minZBackME0); } diff --git a/RecoMuon/DetLayers/src/MuonRPCDetLayerGeometryBuilder.cc b/RecoMuon/DetLayers/src/MuonRPCDetLayerGeometryBuilder.cc index 314706732da5d..939709c0e1c4d 100644 --- a/RecoMuon/DetLayers/src/MuonRPCDetLayerGeometryBuilder.cc +++ b/RecoMuon/DetLayers/src/MuonRPCDetLayerGeometryBuilder.cc @@ -1,6 +1,7 @@ #include #include +#include #include #include #include @@ -297,31 +298,48 @@ void MuonRPCDetLayerGeometryBuilder::makeBarrelRods(vector& geom } bool MuonRPCDetLayerGeometryBuilder::isFront(const RPCDetId& rpcId) { - // ME1/2 is always in back - // if(rpcId.station() == 1 && rpcId.ring() == 2) return false; - - bool result = false; - int ring = rpcId.ring(); - int station = rpcId.station(); - // 20 degree rings are a little weird! not anymore from 17x - if (ring == 1 && station > 1) { - // RE2/1 RE3/1 Upscope Geometry - /* goes (sector) (subsector) 1/3 - 1 1 back // front - 1 2 front // back - 1 3 front // front - 2 1 front // back - 2 2 back // from - 2 3 back // back - - */ - result = (rpcId.subsector() != 2); - if (rpcId.sector() % 2 == 0) - result = !result; - return result; + if (useUpdatedRPCIsFront) { + const int station = rpcId.station(); + const int ring = rpcId.ring(); + const int sector = RPCGeomServ(rpcId).segment(); + + // The front/back or off-yoke/on-yoke rule is different for the iRPC, RE+-1, and the others. + if (ring == 1) { + return (sector % 2 != 0); + } else if (station == 1) { + // For RE+-1, even chambers are closer to the IP + return (sector % 2 == 0); + } else { + // For the others, odd chambers are closer to the IP + return (sector % 2 != 0); + } } else { - // 10 degree rings have odd subsectors in front - result = (rpcId.subsector() % 2 == 0); + // ME1/2 is always in back + // if(rpcId.station() == 1 && rpcId.ring() == 2) return false; + + bool result = false; + int ring = rpcId.ring(); + int station = rpcId.station(); + // 20 degree rings are a little weird! not anymore from 17x + if (ring == 1 && station > 1) { + // RE2/1 RE3/1 Upscope Geometry + /* goes (sector) (subsector) 1/3 + 1 1 back // front + 1 2 front // back + 1 3 front // front + 2 1 front // back + 2 2 back // from + 2 3 back // back + + */ + result = (rpcId.subsector() != 2); + if (rpcId.sector() % 2 == 0) + result = !result; + return result; + } else { + // 10 degree rings have odd subsectors in front + result = (rpcId.subsector() % 2 == 0); + } + return result; } - return result; } diff --git a/RecoMuon/DetLayers/src/MuonRPCDetLayerGeometryBuilder.h b/RecoMuon/DetLayers/src/MuonRPCDetLayerGeometryBuilder.h index 18dd64a45b30a..f615f07338fa5 100644 --- a/RecoMuon/DetLayers/src/MuonRPCDetLayerGeometryBuilder.h +++ b/RecoMuon/DetLayers/src/MuonRPCDetLayerGeometryBuilder.h @@ -31,6 +31,8 @@ class MuonRPCDetLayerGeometryBuilder { /// Builds the barrel layers. Result vector is sorted inside-out static std::vector buildBarrelLayers(const RPCGeometry& geo); + inline static bool useUpdatedRPCIsFront = false; + private: static void makeBarrelLayers(std::vector& geomDets, std::vector& result); static void makeBarrelRods(std::vector& geomDets, std::vector& result);