Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes in the RPC clusterization in the L1Trigger/L1TMuonOverlapPhase1 #36827

Merged
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion L1Trigger/L1TMuonOverlapPhase1/interface/MuonStub.h
Original file line number Diff line number Diff line change
@@ -22,6 +22,7 @@ struct MuonStub {
DT_PHI_ETA,
DT_HIT,
RPC,
RPC_DROPPED, //to mark that all clusters were dropped because there are more than 2 clusters or at least one too big cluster
CSC_PHI,
CSC_ETA,
CSC_PHI_ETA,
@@ -61,7 +62,7 @@ struct MuonStub {
typedef std::vector<MuonStub> MuonStubs1D;
typedef std::vector<MuonStubs1D> MuonStubs2D;

typedef std::shared_ptr<const MuonStub> MuonStubPtr;
typedef std::shared_ptr<MuonStub> MuonStubPtr;
typedef std::vector<MuonStubPtr> MuonStubPtrs1D;
typedef std::vector<MuonStubPtrs1D> MuonStubPtrs2D;

2 changes: 1 addition & 1 deletion L1Trigger/L1TMuonOverlapPhase1/src/AngleConverterBase.cc
Original file line number Diff line number Diff line change
@@ -235,7 +235,7 @@ EtaValue AngleConverterBase::getGlobalEtaDt(const DTChamberId& detId) const {

EtaValue etaValue = {
config->etaToHwEta(chamberMiddleGP.eta()),
config->etaToHwEta(abs(chamberMiddleGP.eta() - chambNeighMiddleGP.eta())) / 2,
config->etaToHwEta(fabs(chamberMiddleGP.eta() - chambNeighMiddleGP.eta())) / 2,
0, //quality
0, //bx
0 //timin
17 changes: 15 additions & 2 deletions L1Trigger/L1TMuonOverlapPhase1/src/MuonStubMakerBase.cc
Original file line number Diff line number Diff line change
@@ -104,7 +104,7 @@ void RpcDigiToStubsConverter::makeStubs(
///To find the clusters we have to copy the digis in chamber to sort them (not optimal).
// for (auto tdigi = rollDigis.second.first; tdigi != rollDigis.second.second; tdigi++) { std::cout << "RPC DIGIS: " << roll.rawId()<< " "<<roll<<" digi: " << tdigi->strip() <<" bx: " << tdigi->bx() << std::endl; }
std::vector<RPCDigi> digisCopy;
// std::copy_if(rollDigis.second.first, rollDigis.second.second, std::back_inserter(digisCopy), [](const RPCDigi & aDigi){return (aDigi.bx()==0);} );

for (auto pDigi = rollDigis.second.first; pDigi != rollDigis.second.second; pDigi++) {
if (pDigi->bx() >= bxFrom && pDigi->bx() <= bxTo) {
digisCopy.push_back(*pDigi);
@@ -114,10 +114,23 @@ void RpcDigiToStubsConverter::makeStubs(
std::vector<RpcCluster> clusters = rpcClusterization->getClusters(roll, digisCopy);

for (auto& cluster : clusters) {
//LogTrace("l1tOmtfEventPrint")<<__FUNCTION__<<":"<<155<<" roll "<<roll<<" cluster: firstStrip "<<cluster.firstStrip<<" lastStrip "<<cluster.lastStrip<<" halfStrip "<<cluster.halfStrip()<<std::endl;
addRPCstub(muonStubsInLayers, roll, cluster, iProcessor, procTyp);
}
}

//removing the RPC stubs that were mark as dropped in the RpcDigiToStubsConverterOmtf::addRPCstub
//10 is the first RPC layer
for (unsigned int iLayer = 10; iLayer < muonStubsInLayers.size(); iLayer++) {
for (unsigned int iInput = 0; iInput < muonStubsInLayers[iLayer].size(); iInput++) {
if (muonStubsInLayers[iLayer][iInput] && muonStubsInLayers[iLayer][iInput]->type == MuonStub::RPC_DROPPED) {
LogTrace("l1tOmtfEventPrint") << "RpcDigiToStubsConverter::makeStubs "
<< " iProcessor " << iProcessor << " procTyp " << procTyp
<< " dropping a stub iLayer " << iLayer << " iInput "
<< *(muonStubsInLayers[iLayer][iInput]) << std::endl;
muonStubsInLayers[iLayer][iInput].reset();
}
}
}
}

///////////////////////////////////////
1 change: 1 addition & 0 deletions L1Trigger/L1TMuonOverlapPhase1/src/Omtf/OMTFProcessor.cc
Original file line number Diff line number Diff line change
@@ -386,6 +386,7 @@ std::vector<l1t::RegionalMuonCand> OMTFProcessor<GoldenPatternType>::run(
//uncomment if you want to check execution time of each method
//boost::timer::auto_cpu_timer t("%ws wall, %us user in getProcessorCandidates\n");

//input is shared_ptr because the observers may need them after the run() method execution is finished
std::shared_ptr<OMTFinput> input = std::make_shared<OMTFinput>(this->myOmtfConfig);
inputMaker->buildInputForProcessor(input->getMuonStubs(), iProcessor, mtfType, bx, bx);

30 changes: 28 additions & 2 deletions L1Trigger/L1TMuonOverlapPhase1/src/Omtf/OMTFinputMaker.cc
Original file line number Diff line number Diff line change
@@ -177,7 +177,33 @@ void RpcDigiToStubsConverterOmtf::addRPCstub(MuonStubPtrs2D& muonStubsInLayers,
stub.logicLayer = iLayer;
stub.detId = rawid;

OMTFinputMaker::addStub(config, muonStubsInLayers, iLayer, iInput, stub);
//This is very simple filtering of the clusters
//Till Nov 2021: unfortunately performance of the firmware cannot be easily emulated from digi
//(in principle would required raws, because in the firmware the clusterizaton is based on the 8-bit strip partitions)
//The FW from from Nov 2021 solved this problem - option dropAllClustersIfMoreThanMax:
//if any cluster is dropped in one barrel roll or endcap chamber - all are dropped for this roll/chamber.
//Beside better data-to-emulator agreement it provides better eff for high pt muons
if (config->getRpcDropAllClustersIfMoreThanMax()) {
//two clusters were already added, so as we have the next one, we mark as dropped the one that was added before
if (muonStubsInLayers[iLayer][iInput + 1]) {
//if iInput+1 is not null, iInput is not null as well
muonStubsInLayers[iLayer][iInput]->type = MuonStub::RPC_DROPPED;
muonStubsInLayers[iLayer][iInput + 1]->type = MuonStub::RPC_DROPPED;
} else if (cluster.size() > config->getRpcMaxClusterSize()) {
//marking as dropped the one that was added before on the iInput
if (muonStubsInLayers[iLayer][iInput])
muonStubsInLayers[iLayer][iInput]->type = MuonStub::RPC_DROPPED;
else {
//no stub was added at this input already, so adding a stub and marking it as dropped
muonStubsInLayers.at(iLayer).at(iInput) = std::make_shared<MuonStub>(stub);
muonStubsInLayers[iLayer][iInput]->type = MuonStub::RPC_DROPPED;
}
} else
OMTFinputMaker::addStub(config, muonStubsInLayers, iLayer, iInput, stub);
} else {
if (cluster.size() <= config->getRpcMaxClusterSize())
OMTFinputMaker::addStub(config, muonStubsInLayers, iLayer, iInput, stub);
}

std::ostringstream str;
str << " RPC halfDigi "
@@ -431,5 +457,5 @@ void OMTFinputMaker::addStub(const OMTFConfiguration* config,
return;
//in this implementation only two first stubs are added for a given iInput

muonStubsInLayers.at(iLayer).at(iInput) = std::make_shared<const MuonStub>(stub);
muonStubsInLayers.at(iLayer).at(iInput) = std::make_shared<MuonStub>(stub);
}
92 changes: 55 additions & 37 deletions L1Trigger/L1TMuonOverlapPhase1/src/RpcClusterization.cc
Original file line number Diff line number Diff line change
@@ -16,53 +16,71 @@ RpcClusterization::~RpcClusterization() {}
std::vector<RpcCluster> RpcClusterization::getClusters(const RPCDetId& roll, std::vector<RPCDigi>& digis) const {
std::vector<RpcCluster> allClusters;

std::sort(digis.begin(), digis.end(), [](const RPCDigi& a, const RPCDigi& b) { return a.strip() < b.strip(); });
if (!dropAllClustersIfMoreThanMax) {
//with the 2018 firmware the agreement is better with this sort
std::sort(digis.begin(), digis.end(), [](const RPCDigi& a, const RPCDigi& b) { return a.strip() < b.strip(); });
} else {
//with the fixed RPC clusterization (Nov 2021 firmware) the data to emulator agreement is better if this reverse is used here,
//with the 2018 firmware the agreement is worse with this reverse,
std::reverse(digis.begin(), digis.end());
}

typedef std::pair<unsigned int, unsigned int> Cluster;

for (auto& digi : digis) {
if (allClusters.empty()) {
allClusters.emplace_back(digi.strip(), digi.strip());
allClusters.back().bx = digi.bx();
allClusters.back().timing = convertTiming(digi.time());
} else if (digi.strip() - allClusters.back().lastStrip == 1) {
allClusters.back().lastStrip = digi.strip();
//TODO update bx and timing in some smart way
} else if (digi.strip() - allClusters.back().lastStrip > 1) {
allClusters.emplace_back(digi.strip(), digi.strip());
allClusters.back().bx = digi.bx();
allClusters.back().timing = convertTiming(digi.time());
}
}
//This implementation of clusterization emulation gives the cluster in the same order as the order of digis,
//and the order of unpacked digis should be the same as the order of the LB channels on which the clustrization
//in the firmware is performed.
//This cluster order plays role in some rare cases for the OMTF algorithm
//when two hits has the same abs(minDistPhi), and then the phi of the resulting candidate
//depends on the order of these hits.
for (unsigned int iDigi = 0; iDigi < digis.size(); iDigi++) {
//edm::LogVerbatim("l1tOmtfEventPrint")<< __FUNCTION__ << ":" << __LINE__<<" "<<roll<<" iDigi "<<iDigi<<" digi "<<digis[iDigi];

std::vector<RpcCluster> filteredClusters;
//removing duplicated digis
//the digis might be duplicated, because the same data might be received by two OMTF boards (as the same link goes to two neighboring boards)
//and the unpacker is not cleaning them
bool duplicatedDigi = false;
for (unsigned int iDigi2 = 0; iDigi2 < iDigi; iDigi2++) {
if (digis[iDigi].strip() == digis[iDigi2].strip()) {
duplicatedDigi = true;
//edm::LogVerbatim("l1tOmtfEventPrint")<<"duplicatedDigi";
break;
}
}

if (dropAllClustersIfMoreThanMax)
if (allClusters.size() > maxClusterCnt)
return filteredClusters;
if (duplicatedDigi)
continue;

//debug printout only
if (allClusters.size() > maxClusterCnt) {
LogTrace("l1tOmtfEventPrint") << __FUNCTION__ << ":" << __LINE__ << " allClusters.size() >= maxClusterCnt "
<< std::endl;
for (auto& cluster : allClusters)
edm::LogVerbatim("l1tOmtfEventPrint")
<< __FUNCTION__ << ":" << __LINE__ << " roll " << roll << " cluster: firstStrip " << cluster.firstStrip
<< " lastStrip " << cluster.lastStrip << " halfStrip " << cluster.halfStrip() << std::endl;
}
bool addNewCluster = true;

//TODO this is very simple filtering of the cluster,
//unfortunately the in firmware it is more complicated and cannot be easily emulated from digi
//(in principle would required raws, because in the firmware the clusterizaton is based on the 8-bit strip partitions
for (auto& cluster : allClusters) {
if (cluster.size() <= maxClusterSize)
filteredClusters.emplace_back(cluster);
for (auto& cluster : allClusters) {
if (digis[iDigi].strip() - cluster.lastStrip == 1) {
cluster.lastStrip = digis[iDigi].strip();
addNewCluster = false;
} else if (digis[iDigi].strip() - cluster.firstStrip == -1) {
cluster.firstStrip = digis[iDigi].strip();
addNewCluster = false;
} else if (digis[iDigi].strip() >= cluster.firstStrip && digis[iDigi].strip() <= cluster.lastStrip) {
addNewCluster = false;
}
}

if (filteredClusters.size() >= maxClusterCnt)
break;
if (addNewCluster) {
allClusters.emplace_back(digis[iDigi].strip(), digis[iDigi].strip());
allClusters.back().bx = digis[iDigi].bx();
allClusters.back().timing = convertTiming(digis[iDigi].time());
}
}

return filteredClusters;
/* Debug only
if(allClusters.size())
edm::LogVerbatim("l1tOmtfEventPrint")<< __FUNCTION__ <<" "<<roll<<" allClusters.size() "<<allClusters.size();
for (auto& cluster : allClusters)
edm::LogVerbatim("l1tOmtfEventPrint")
<< __FUNCTION__ << " cluster: firstStrip " << cluster.firstStrip
<< " lastStrip " << cluster.lastStrip << " halfStrip " << cluster.halfStrip() << std::endl;*/

return allClusters;
}

int RpcClusterization::convertTiming(double timing) const {
Original file line number Diff line number Diff line change
@@ -15,11 +15,8 @@
process.CondDB,
timetype = cms.untracked.string('runnumber'),
toPut = cms.VPSet(cms.PSet(
record = cms.string('L1TMTFOverlapParamsRcd'),
tag = cms.string('params')),
cms.PSet(
record = cms.string('L1TMTFOverlapParamsRcd'),
tag = cms.string('patterns'))
record = cms.string('L1TMuonOverlapParamsRcd'),
tag = cms.string('params'))
)
)

63 changes: 49 additions & 14 deletions L1Trigger/L1TMuonOverlapPhase1/test/runMuonOverlap_run3_data.py
Original file line number Diff line number Diff line change
@@ -4,6 +4,10 @@
import os
import sys

loadConfigFrom_sqlite_file = True

loadConfigFrom_fakeOmtfParams = False

process.load("FWCore.MessageLogger.MessageLogger_cfi")

process.MessageLogger = cms.Service("MessageLogger",
@@ -56,11 +60,12 @@

#'/store/express/Commissioning2021/ExpressCosmics/FEVT/Express-v1/000/342/094/00000/038c179a-d2ce-45f0-a7d5-8b2d40017042.root', # only DT, fw 0x0008
'/store/express/Commissioning2021/ExpressCosmics/FEVT/Express-v1/000/344/266/00000/db2cfbdd-5edf-4ee4-aab0-5bdba105728d.root' #DT and RPC fw 0x0008
#'/store/express/Commissioning2021/ExpressCosmics/FEVT/Express-v1/000/344/566/00000/19ef107a-4cd9-4df0-ba93-dbfbab8df1cb.root'
#'/store/express/Commissioning2021/ExpressCosmics/FEVT/Express-v1/000/344/566/00000/19ef107a-4cd9-4df0-ba93-dbfbab8df1cb.root'
#'/store/express/Commissioning2021/ExpressCosmics/FEVT/Express-v1/000/347/053/00000/7b486245-96ea-4b7c-9fe7-76c957968785.root' #RPC noise only
),
)

process.maxEvents = cms.untracked.PSet( input = cms.untracked.int32(-1))
process.maxEvents = cms.untracked.PSet( input = cms.untracked.int32(1000))

# import of standard configurations
process.load('Configuration.StandardSequences.Services_cff')
@@ -81,17 +86,40 @@



####Event Setup Producer
process.load('L1Trigger.L1TMuonOverlapPhase1.fakeOmtfParams_cff')
#process.omtfParams.configXMLFile = cms.FileInPath("L1Trigger/L1TMuon/data/omtf_config/hwToLogicLayer_0x0008.xml")
if loadConfigFrom_fakeOmtfParams :
####Event Setup Producer
process.load('L1Trigger.L1TMuonOverlapPhase1.fakeOmtfParams_cff')
#process.omtfParams.configXMLFile = cms.FileInPath("L1Trigger/L1TMuon/data/omtf_config/hwToLogicLayer_0x0008.xml")

process.esProd = cms.EDAnalyzer("EventSetupRecordDataGetter",
toGet = cms.VPSet(
cms.PSet(record = cms.string('L1TMuonOverlapParamsRcd'),
data = cms.vstring('L1TMuonOverlapParams'))
),
verbose = cms.untracked.bool(False)
)

process.esProd = cms.EDAnalyzer("EventSetupRecordDataGetter",
toGet = cms.VPSet(
cms.PSet(record = cms.string('L1TMuonOverlapParamsRcd'),
data = cms.vstring('L1TMuonOverlapParams'))
),
verbose = cms.untracked.bool(False)
)

if loadConfigFrom_sqlite_file :
process.load("CondCore.CondDB.CondDB_cfi")

process.CondDB.connect = "sqlite_file:Patterns.db"
#process.CondDB.connect = "sqlite_file:l1config.db"

process.CondDB.DBParameters.messageLevel = 3

process.PoolDBESSourceSqlite = cms.ESSource("PoolDBESSource",
process.CondDB,
toGet = cms.VPSet(
cms.PSet(
record = cms.string('L1TMuonOverlapParamsRcd'),
tag = cms.string('params') #check the tag name int the DB: sqlite3 l1config.db ; select * from TAG;
)
),
verbose = cms.untracked.bool(False)
)

process.es_prefer_EcalTBWeights = cms.ESPrefer("PoolDBESSource", "PoolDBESSourceSqlite")

#process.TFileService = cms.Service("TFileService", fileName = cms.string('omtfAnalysis1.root'), closeFileFast = cms.untracked.bool(True) )

@@ -141,11 +169,18 @@
process.dumpED = cms.EDAnalyzer("EventContentAnalyzer")
process.dumpES = cms.EDAnalyzer("PrintEventSetupContent")

process.L1TMuonSeq = cms.Sequence( process.esProd +
if loadConfigFrom_fakeOmtfParams :
process.L1TMuonSeq = cms.Sequence( process.esProd +
process.omtfStage2Digis + process.simOmtfDigis
#+ process.dumpED
#+ process.dumpES
)
)
else :
process.L1TMuonSeq = cms.Sequence(
process.omtfStage2Digis + process.simOmtfDigis
#+ process.dumpED
#+ process.dumpES
)

process.L1TMuonPath = cms.Path(process.L1TMuonSeq)