Skip to content
Open
3 changes: 2 additions & 1 deletion Configuration/Eras/python/Era_Phase2_cff.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
3 changes: 2 additions & 1 deletion Configuration/Eras/python/Era_Run3_2025_cff.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
3 changes: 3 additions & 0 deletions Configuration/Eras/python/Modifier_phase2_RPC_cff.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import FWCore.ParameterSet.Config as cms

phase2_RPC = cms.Modifier()
4 changes: 4 additions & 0 deletions Configuration/Eras/python/Modifier_run3_RPC_2025_cff.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import FWCore.ParameterSet.Config as cms

run3_RPC_2025 = cms.Modifier()

4 changes: 3 additions & 1 deletion RecoMuon/DetLayers/plugins/MuonDetLayerGeometryESProducer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ class MuonDetLayerGeometryESProducer : public edm::ESProducer {
using namespace edm;

MuonDetLayerGeometryESProducer::MuonDetLayerGeometryESProducer(const edm::ParameterSet& p) {
MuonRPCDetLayerGeometryBuilder::useUpdatedRPCIsFront = p.getParameter<bool>("useUpdatedRPCIsFront");

auto cc = setWhatProduced(this);
dtToken_ = cc.consumes();
cscToken_ = cc.consumes();
Expand Down Expand Up @@ -109,7 +111,7 @@ std::unique_ptr<MuonDetLayerGeometry> MuonDetLayerGeometryESProducer::produce(co

void MuonDetLayerGeometryESProducer::fillDescriptions(edm::ConfigurationDescriptions& descriptions) {
edm::ParameterSetDescription desc;
//no parameters are used
desc.add<bool>("useUpdatedRPCIsFront", false);
descriptions.addDefault(desc);
}

Expand Down
6 changes: 5 additions & 1 deletion RecoMuon/DetLayers/python/muonDetLayerGeometry_cfi.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,11 @@
#
# This cfi should be included to build the muon DetLayers.
#
MuonDetLayerGeometryESProducer = cms.ESProducer("MuonDetLayerGeometryESProducer")

MuonDetLayerGeometryESProducer = cms.ESProducer("MuonDetLayerGeometryESProducer", useUpdatedRPCIsFront=False)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My fault. sorry @eigen1907
Here the type specification is needed, because you are not modifying an existing configuration.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure...
MuonDetLayerGeometryESProducer = cms.ESProducer(“MuonDetLayerGeometryESProducer”, useUpdatedRPCIsFront=False)
to
MuonDetLayerGeometryESProducer = cms.ESProducer(“MuonDetLayerGeometryESProducer”, useUpdatedRPCIsFront=cms.bool(False))

and running it seems to work fine.
Is this that you meant in this comment?

Copy link
Contributor Author

@eigen1907 eigen1907 Sep 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@perrotta I've committed the changes you mentioned.
Could you please request test again?


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)
140 changes: 131 additions & 9 deletions RecoMuon/DetLayers/src/MuRingForwardDoubleLayer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
#include <RecoMuon/DetLayers/interface/MuRingForwardDoubleLayer.h>
#include <RecoMuon/DetLayers/interface/MuDetRing.h>
#include <Geometry/CommonDetUnit/interface/GeomDet.h>
#include <DataFormats/MuonDetId/interface/MuonSubdetId.h>
#include <DataFormats/MuonDetId/interface/RPCDetId.h>
#include <DataFormats/GeometrySurface/interface/SimpleDiskBounds.h>
#include <TrackingTools/GeomPropagators/interface/Propagator.h>
#include <TrackingTools/DetLayers/interface/MeasurementEstimator.h>
Expand Down Expand Up @@ -45,7 +47,7 @@ MuRingForwardDoubleLayer::MuRingForwardDoubleLayer(const vector<const ForwardDet
<< " Z: " << specificSurface().position().z() << " R1: " << specificSurface().innerRadius()
<< " R2: " << specificSurface().outerRadius();

// selfTest();
selfTest();
}

BoundDisk* MuRingForwardDoubleLayer::computeSurface() {
Expand Down Expand Up @@ -182,18 +184,138 @@ bool MuRingForwardDoubleLayer::isCrack(const GlobalPoint& gp) const {
}

void MuRingForwardDoubleLayer::selfTest() const {
const std::string metname = "Muon|RecoMuon|RecoMuonDetLayers|MuRingForwardDoubleLayer";

const std::vector<const GeomDet*>& frontDets = theFrontLayer.basicComponents();
const std::vector<const GeomDet*>& backDets = theBackLayer.basicComponents();

std::vector<const GeomDet*>::const_iterator frontItr = frontDets.begin(), lastFront = frontDets.end(),
backItr = backDets.begin(), lastBack = backDets.end();
// Collect front/back chambers by sub-detectors
std::vector<const GeomDet*> frontCSCs, backCSCs;
std::vector<const GeomDet*> frontRPCs, backRPCs;
std::vector<const GeomDet*> frontGEMs, backGEMs;
std::vector<const GeomDet*> frontIRPCs, backIRPCs;
std::vector<const GeomDet*> 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);
}
68 changes: 43 additions & 25 deletions RecoMuon/DetLayers/src/MuonRPCDetLayerGeometryBuilder.cc
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include <RecoMuon/DetLayers/src/MuonRPCDetLayerGeometryBuilder.h>

#include <DataFormats/MuonDetId/interface/RPCDetId.h>
#include <Geometry/RPCGeometry/interface/RPCGeomServ.h>
#include <Geometry/CommonDetUnit/interface/GeomDet.h>
#include <RecoMuon/DetLayers/interface/MuRingForwardDoubleLayer.h>
#include <RecoMuon/DetLayers/interface/MuRodBarrelLayer.h>
Expand Down Expand Up @@ -297,31 +298,48 @@ void MuonRPCDetLayerGeometryBuilder::makeBarrelRods(vector<const GeomDet*>& 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;
}
2 changes: 2 additions & 0 deletions RecoMuon/DetLayers/src/MuonRPCDetLayerGeometryBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ class MuonRPCDetLayerGeometryBuilder {
/// Builds the barrel layers. Result vector is sorted inside-out
static std::vector<DetLayer*> buildBarrelLayers(const RPCGeometry& geo);

inline static bool useUpdatedRPCIsFront = false;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As such, you don't read this parameter from the configuration.
What is the rationale for having the parameter configured in MuonDetLayerGeometryESProducer and used here, instead?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correction: MuonRPCDetLayerGeometryBuilder::useUpdatedRPCIsFront is configured inside the plugin MuonDetLayerGeometryESProducer: what happens if that plugin is not processed, then?
@jfernan2 is this a common practice? Are there examples somewhere in cmssw?


private:
static void makeBarrelLayers(std::vector<const GeomDet*>& geomDets, std::vector<MuRodBarrelLayer*>& result);
static void makeBarrelRods(std::vector<const GeomDet*>& geomDets, std::vector<const DetRod*>& result);
Expand Down