Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:21:08

0001 #include "L1Trigger/L1TMuonOverlapPhase1/interface/Omtf/OMTFinputMaker.h"
0002 #include "L1Trigger/L1TMuonOverlapPhase1/interface/MuonStub.h"
0003 #include "L1Trigger/L1TMuonOverlapPhase1/interface/ProcConfigurationBase.h"
0004 
0005 #include "DataFormats/CSCDigi/interface/CSCCorrelatedLCTDigi.h"
0006 #include "DataFormats/DetId/interface/DetId.h"
0007 #include "DataFormats/L1DTTrackFinder/interface/L1MuDTChambPhDigi.h"
0008 #include "DataFormats/L1TMuon/interface/RegionalMuonCandFwd.h"
0009 #include "DataFormats/MuonDetId/interface/CSCDetId.h"
0010 #include "DataFormats/MuonDetId/interface/DTChamberId.h"
0011 #include "DataFormats/MuonDetId/interface/MuonSubdetId.h"
0012 #include "DataFormats/MuonDetId/interface/RPCDetId.h"
0013 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0014 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0015 
0016 #include <map>
0017 #include <sstream>
0018 #include <string>
0019 
0020 //dtThDigis is provided as argument, because in the OMTF implementation the phi and eta digis are merged (even thought it is artificial)
0021 void DtDigiToStubsConverterOmtf::addDTphiDigi(MuonStubPtrs2D& muonStubsInLayers,
0022                                               const L1MuDTChambPhDigi& digi,
0023                                               const L1MuDTChambThContainer* dtThDigis,
0024                                               unsigned int iProcessor,
0025                                               l1t::tftype procTyp) {
0026   DTChamberId detid(digi.whNum(), digi.stNum(), digi.scNum() + 1);
0027 
0028   //LogTrace("l1tOmtfEventPrint")<<__FUNCTION__<<":"<<__LINE__<<" OMTFinputMaker "<<" detid "<<detid<<endl;
0029   ///Check Trigger primitive quality
0030   ///Ts2Tag() == 0 - take only first track from DT Trigger Server
0031   ///BxCnt()  == 0 - ??
0032   ///code()>=3     - take only double layer hits, HH, HL and LL
0033   // FIXME (MK): at least Ts2Tag selection is not correct! Check it
0034   //    if (digiIt.bxNum()!= 0 || digiIt.BxCnt()!= 0 || digiIt.Ts2Tag()!= 0 || digiIt.code()<4) continue;
0035 
0036   //7 is empty digi, TODO update if the definition of the quality is changed
0037   if (digi.code() == 7 || digi.code() < config->getMinDtPhiQuality())
0038     return;
0039 
0040   unsigned int hwNumber = config->getLayerNumber(detid.rawId());
0041   if (config->getHwToLogicLayer().find(hwNumber) == config->getHwToLogicLayer().end())
0042     return;
0043 
0044   auto iter = config->getHwToLogicLayer().find(hwNumber);
0045   unsigned int iLayer = iter->second;
0046   unsigned int iInput = OMTFinputMaker::getInputNumber(config, detid.rawId(), iProcessor, procTyp);
0047   //MuonStub& stub = muonStubsInLayers[iLayer][iInput];
0048   MuonStub stub;
0049 
0050   stub.type = MuonStub::DT_PHI_ETA;
0051   stub.qualityHw = digi.code();
0052   stub.phiHw = angleConverter->getProcessorPhi(
0053       OMTFinputMaker::getProcessorPhiZero(config, iProcessor), procTyp, digi.scNum(), digi.phi());
0054   stub.etaHw = angleConverter->getGlobalEta(detid, dtThDigis, digi.bxNum());
0055 
0056   //the cut if (stub.qualityHw >= config->getMinDtPhiBQuality()) is done in the ProcessorBase<GoldenPatternType>::restrictInput
0057   //as is is done like that in the firmware
0058   stub.phiBHw = digi.phiB();
0059 
0060   stub.bx = digi.bxNum();  //TODO sholdn't  it be BxCnt()?
0061   //stub.timing = digi.getTiming(); //TODO what about sub-bx timing, is is available?
0062 
0063   //stub.etaType = ?? TODO
0064   stub.logicLayer = iLayer;
0065   stub.detId = detid;
0066 
0067   OMTFinputMaker::addStub(config, muonStubsInLayers, iLayer, iInput, stub);
0068 }
0069 
0070 void DtDigiToStubsConverterOmtf::addDTetaStubs(MuonStubPtrs2D& muonStubsInLayers,
0071                                                const L1MuDTChambThDigi& thetaDigi,
0072                                                unsigned int iProcessor,
0073                                                l1t::tftype procTyp) {
0074   //in the Phase1 omtf the theta stubs are merged with the phi in the addDTphiDigi
0075 }
0076 
0077 bool DtDigiToStubsConverterOmtf::acceptDigi(const DTChamberId& dTChamberId,
0078                                             unsigned int iProcessor,
0079                                             l1t::tftype procType) {
0080   return OMTFinputMaker::acceptDtDigi(config, dTChamberId, iProcessor, procType);
0081 }
0082 
0083 void CscDigiToStubsConverterOmtf::addCSCstubs(MuonStubPtrs2D& muonStubsInLayers,
0084                                               unsigned int rawid,
0085                                               const CSCCorrelatedLCTDigi& digi,
0086                                               unsigned int iProcessor,
0087                                               l1t::tftype procTyp) {
0088   unsigned int hwNumber = config->getLayerNumber(rawid);
0089   if (config->getHwToLogicLayer().find(hwNumber) == config->getHwToLogicLayer().end())
0090     return;
0091 
0092   unsigned int iLayer = config->getHwToLogicLayer().at(hwNumber);
0093   unsigned int iInput = OMTFinputMaker::getInputNumber(config, rawid, iProcessor, procTyp);
0094 
0095   float r = 0;
0096   MuonStub stub;
0097   stub.type = MuonStub::CSC_PHI_ETA;
0098   stub.phiHw = angleConverter->getProcessorPhi(
0099       OMTFinputMaker::getProcessorPhiZero(config, iProcessor), procTyp, CSCDetId(rawid), digi, iInput);
0100   stub.etaHw = angleConverter->getGlobalEta(rawid, digi, r);
0101   stub.r = round(r);
0102   stub.phiBHw = digi.getPattern();  //TODO change to phiB when implemented
0103   stub.qualityHw = digi.getQuality();
0104 
0105   stub.bx = digi.getBX() - config->cscLctCentralBx();  //TODO sholdn't  it be getBX0()?
0106   //stub.timing = digi.getTiming(); //TODO what about sub-bx timing, is is available?
0107 
0108   //stub.etaType = ?? TODO
0109   stub.logicLayer = iLayer;
0110   stub.detId = rawid;
0111 
0112   //TODO this cut is not yet implemented in the FW,
0113   //but it is worth to apply it at least for the pattern generation and NN training
0114   if (iLayer == 9) {
0115     if (stub.r >= config->minCSCStubRME12())
0116       OMTFinputMaker::addStub(config, muonStubsInLayers, iLayer, iInput, stub);
0117   } else if (stub.r >= config->minCscStubR()) {
0118     OMTFinputMaker::addStub(config, muonStubsInLayers, iLayer, iInput, stub);
0119   }
0120 
0121   ///Accept CSC digis only up to eta=1.26.
0122   ///The nominal OMTF range is up to 1.24, but cutting at 1.24
0123   ///kill efficiency at the edge. 1.26 is one eta bin above nominal.
0124   //if(abs(iEta)>1.26/2.61*240) continue;
0125   //if (abs(iEta) > 115) continue;
0126 
0127   //LogTrace("l1tOmtfEventPrint")<<" ADDING CSC hit, proc: "<<iProcessor<<" iPhi : " << iPhi <<" iEta: "<< iEta << std::endl;
0128 }
0129 
0130 bool CscDigiToStubsConverterOmtf::acceptDigi(const CSCDetId& csc, unsigned int iProcessor, l1t::tftype procType) {
0131   if (procType == l1t::tftype::omtf_pos && (csc.endcap() == 2 || csc.ring() == 1 || csc.station() == 4))
0132     return false;
0133   if (procType == l1t::tftype::omtf_neg && (csc.endcap() == 1 || csc.ring() == 1 || csc.station() == 4))
0134     return false;
0135 
0136   if (procType == l1t::tftype::emtf_pos && (csc.endcap() == 2 || (csc.station() == 1 && csc.ring() == 3)))
0137     return false;
0138   if (procType == l1t::tftype::emtf_neg && (csc.endcap() == 1 || (csc.station() == 1 && csc.ring() == 3)))
0139     return false;
0140 
0141   unsigned int aSector = csc.chamber();
0142   unsigned int aMin = config->getEndcap10DegMin()[iProcessor];
0143   unsigned int aMax = config->getEndcap10DegMax()[iProcessor];
0144 
0145   if ((procType == l1t::tftype::emtf_pos || procType == l1t::tftype::emtf_neg) && csc.station() > 1 &&
0146       csc.ring() == 1) {
0147     aMin = config->getEndcap20DegMin()[iProcessor];
0148     aMax = config->getEndcap20DegMax()[iProcessor];
0149   }
0150 
0151   if (aMax > aMin && aSector >= aMin && aSector <= aMax)
0152     return true;
0153   if (aMax < aMin && (aSector >= aMin || aSector <= aMax))
0154     return true;
0155 
0156   return false;
0157 }
0158 
0159 void RpcDigiToStubsConverterOmtf::addRPCstub(MuonStubPtrs2D& muonStubsInLayers,
0160                                              const RPCDetId& roll,
0161                                              const RpcCluster& cluster,
0162                                              unsigned int iProcessor,
0163                                              l1t::tftype procTyp) {
0164   unsigned int rawid = roll.rawId();
0165 
0166   unsigned int hwNumber = config->getLayerNumber(rawid);
0167   unsigned int iLayer = config->getHwToLogicLayer().at(hwNumber);
0168   unsigned int iInput = OMTFinputMaker::getInputNumber(config, rawid, iProcessor, procTyp);
0169 
0170   //LogTrace("l1tOmtfEventPrint")<<"ADDING HIT: iLayer = " << iLayer << " iInput: " << iInput << " iPhi: " << iPhi << std::endl;
0171 
0172   //if (iLayer==17 && (iInput==0 || iInput==1)) continue;  // FIXME (MK) there is no RPC link for that input, because it is taken by DAQ link
0173 
0174   MuonStub stub;
0175   stub.type = MuonStub::RPC;
0176   stub.phiHw = angleConverter->getProcessorPhi(
0177       OMTFinputMaker::getProcessorPhiZero(config, iProcessor), procTyp, roll, cluster.firstStrip, cluster.lastStrip);
0178 
0179   float r = 0;
0180   stub.etaHw = angleConverter->getGlobalEtaRpc(rawid, cluster.firstStrip, r);
0181   stub.r = round(r);
0182 
0183   stub.qualityHw = cluster.size();
0184 
0185   stub.bx = cluster.bx;
0186   stub.timing = cluster.timing;
0187 
0188   //stub.etaType = ?? TODO
0189   stub.logicLayer = iLayer;
0190   stub.detId = rawid;
0191 
0192   //This is very simple filtering of the clusters
0193   //Till Nov 2021: unfortunately performance of the firmware cannot be easily emulated from digi
0194   //(in principle would required raws, because in the firmware the clusterizaton is based on the 8-bit strip partitions)
0195   //The FW from from Nov 2021 solved this problem - option dropAllClustersIfMoreThanMax:
0196   //if any cluster is dropped in one barrel roll or endcap chamber - all are dropped for this roll/chamber.
0197   //Beside better data-to-emulator agreement it provides better eff for high pt muons
0198   if (config->getRpcDropAllClustersIfMoreThanMax()) {
0199     //two clusters were already added, so as we have the next one, we mark as dropped the one that was added before
0200     if (muonStubsInLayers[iLayer][iInput + 1]) {
0201       //if iInput+1 is not null, iInput is not null as well
0202       muonStubsInLayers[iLayer][iInput]->type = MuonStub::RPC_DROPPED;
0203       muonStubsInLayers[iLayer][iInput + 1]->type = MuonStub::RPC_DROPPED;
0204     } else if (cluster.size() > config->getRpcMaxClusterSize()) {
0205       //marking as dropped the one that was added before on the iInput
0206       if (muonStubsInLayers[iLayer][iInput]) {
0207         muonStubsInLayers[iLayer][iInput]->type = MuonStub::RPC_DROPPED;
0208 
0209         muonStubsInLayers[iLayer][iInput + 1] = std::make_shared<MuonStub>(stub);
0210         muonStubsInLayers[iLayer][iInput + 1]->type = MuonStub::RPC_DROPPED;
0211       } else {
0212         //no stub was added at this input already, so adding a stub and marking it as dropped
0213         muonStubsInLayers[iLayer].at(iInput) = std::make_shared<MuonStub>(stub);
0214         muonStubsInLayers[iLayer][iInput]->type = MuonStub::RPC_DROPPED;
0215 
0216         muonStubsInLayers[iLayer][iInput + 1] = std::make_shared<MuonStub>(stub);
0217         muonStubsInLayers[iLayer][iInput + 1]->type = MuonStub::RPC_DROPPED;
0218       }
0219     } else
0220       OMTFinputMaker::addStub(config, muonStubsInLayers, iLayer, iInput, stub);
0221   } else {
0222     if (cluster.size() <= config->getRpcMaxClusterSize())
0223       OMTFinputMaker::addStub(config, muonStubsInLayers, iLayer, iInput, stub);
0224   }
0225 
0226   std::ostringstream str;
0227   str << " RPC halfDigi "
0228       << " begin: " << cluster.firstStrip << " end: " << cluster.lastStrip << " iPhi: " << stub.phiHw
0229       << " iEta: " << stub.etaHw << " hwNumber: " << hwNumber << " iInput: " << iInput << " iLayer: " << iLayer
0230       << std::endl;
0231 
0232   LogTrace("l1tOmtfEventPrint") << str.str();
0233 }
0234 
0235 bool RpcDigiToStubsConverterOmtf::acceptDigi(const RPCDetId& rpcDetId, unsigned int iProcessor, l1t::tftype procType) {
0236   unsigned int aMin = config->getBarrelMin()[iProcessor];
0237   unsigned int aMax = config->getBarrelMax()[iProcessor];
0238 
0239   unsigned int aSector = rpcDetId.sector();
0240 
0241   ///Select RPC chambers connected to OMTF
0242   if (procType == l1t::tftype::omtf_pos &&
0243       (rpcDetId.region() < 0 || (rpcDetId.region() == 0 && rpcDetId.ring() != 2) ||
0244        (rpcDetId.region() == 0 && rpcDetId.station() == 4) ||
0245        (rpcDetId.region() == 0 && rpcDetId.station() == 2 && rpcDetId.layer() == 2 && rpcDetId.roll() == 1) ||
0246        (rpcDetId.region() == 0 && rpcDetId.station() == 3 && rpcDetId.roll() == 1) ||
0247        (rpcDetId.region() == 1 && rpcDetId.station() == 4) ||
0248        ///RPC RE1/2 temporarily not used (rpcDetId.region()==1 && rpcDetId.station()==1 && rpcDetId.ring()<2) ||
0249        (rpcDetId.region() == 1 && rpcDetId.station() > 0 && rpcDetId.ring() < 3)))
0250     return false;
0251 
0252   if (procType == l1t::tftype::omtf_neg &&
0253       (rpcDetId.region() > 0 || (rpcDetId.region() == 0 && rpcDetId.ring() != -2) ||
0254        (rpcDetId.region() == 0 && rpcDetId.station() == 4) ||
0255        (rpcDetId.region() == 0 && rpcDetId.station() == 2 && rpcDetId.layer() == 2 && rpcDetId.roll() == 1) ||
0256        (rpcDetId.region() == 0 && rpcDetId.station() == 3 && rpcDetId.roll() == 1) ||
0257        (rpcDetId.region() == -1 && rpcDetId.station() == 4) ||
0258        //RPC RE1/2 temporarily not used (rpcDetId.region()==1 && rpcDetId.station()==1 && rpcDetId.ring()<2) ||
0259        (rpcDetId.region() == -1 && rpcDetId.station() > 0 && rpcDetId.ring() < 3)))
0260     return false;
0261 
0262   if (procType == l1t::tftype::omtf_pos || procType == l1t::tftype::omtf_neg) {
0263     if (rpcDetId.region() != 0 && rpcDetId.station() == 3) {  //endcaps, layer 17
0264       unsigned int iInput = OMTFinputMaker::getInputNumber(config, rpcDetId.rawId(), iProcessor, procType);
0265       if (iInput == 0 || iInput == 1)
0266         return false;  // FIXME (MK) there is no RPC link for that input, because it is taken by DAQ link
0267     }
0268   }
0269 
0270   if (procType == l1t::tftype::bmtf && rpcDetId.region() != 0)
0271     return false;
0272 
0273   if (procType == l1t::tftype::emtf_pos &&
0274       (rpcDetId.region() <= 0 || (rpcDetId.station() == 1 && rpcDetId.ring() == 3)))
0275     return false;
0276   if (procType == l1t::tftype::emtf_neg &&
0277       (rpcDetId.region() >= 0 || (rpcDetId.station() == 1 && rpcDetId.ring() == 3)))
0278     return false;
0279   ////////////////
0280   if (rpcDetId.region() == 0)
0281     aSector = rpcDetId.sector();
0282   if (rpcDetId.region() != 0) {
0283     aSector = (rpcDetId.sector() - 1) * 6 + rpcDetId.subsector();
0284     aMin = config->getEndcap10DegMin()[iProcessor];
0285     aMax = config->getEndcap10DegMax()[iProcessor];
0286   }
0287 
0288   if (aMax > aMin && aSector >= aMin && aSector <= aMax)
0289     return true;
0290   if (aMax < aMin && (aSector >= aMin || aSector <= aMax))
0291     return true;
0292 
0293   return false;
0294 }
0295 ///////////////////////////////////////
0296 ///////////////////////////////////////
0297 bool OMTFinputMaker::acceptDtDigi(const OMTFConfiguration* config,
0298                                   const DTChamberId& dTChamberId,
0299                                   unsigned int iProcessor,
0300                                   l1t::tftype procType) {
0301   unsigned int aMin = config->getBarrelMin()[iProcessor];
0302   unsigned int aMax = config->getBarrelMax()[iProcessor];
0303 
0304   if (procType == l1t::tftype::omtf_pos && dTChamberId.wheel() != 2)
0305     return false;
0306   if (procType == l1t::tftype::omtf_neg && dTChamberId.wheel() != -2)
0307     return false;
0308   if (procType == l1t::tftype::emtf_pos || procType == l1t::tftype::emtf_neg)
0309     return false;
0310 
0311   unsigned int aSector = dTChamberId.sector();
0312 
0313   if (aMax > aMin && aSector >= aMin && aSector <= aMax)
0314     return true;
0315   if (aMax < aMin && (aSector >= aMin || aSector <= aMax))
0316     return true;
0317 
0318   return false;
0319 }
0320 
0321 ///////////////////////////////////////
0322 ///////////////////////////////////////
0323 OMTFinputMaker::OMTFinputMaker(const edm::ParameterSet& edmParameterSet,
0324                                MuStubsInputTokens& muStubsInputTokens,
0325                                const OMTFConfiguration* config,
0326                                std::unique_ptr<OmtfAngleConverter> angleConverter)
0327     : MuonStubMakerBase(config), config(config), angleConverter(std::move(angleConverter)) {
0328   if (!edmParameterSet.getParameter<bool>("dropDTPrimitives"))
0329     digiToStubsConverters.emplace_back(std::make_unique<DtDigiToStubsConverterOmtf>(
0330         config, this->angleConverter.get(), muStubsInputTokens.inputTokenDtPh, muStubsInputTokens.inputTokenDtTh));
0331 
0332   if (!edmParameterSet.getParameter<bool>("dropCSCPrimitives"))
0333     digiToStubsConverters.emplace_back(std::make_unique<CscDigiToStubsConverterOmtf>(
0334         config, this->angleConverter.get(), muStubsInputTokens.inputTokenCSC));
0335 
0336   if (!edmParameterSet.getParameter<bool>("dropRPCPrimitives"))
0337     digiToStubsConverters.emplace_back(std::make_unique<RpcDigiToStubsConverterOmtf>(
0338         config, this->angleConverter.get(), &rpcClusterization, muStubsInputTokens.inputTokenRPC));
0339 }
0340 
0341 void OMTFinputMaker::initialize(const edm::ParameterSet& edmCfg,
0342                                 const edm::EventSetup& es,
0343                                 const MuonGeometryTokens& muonGeometryTokens) {
0344   MuonStubMakerBase::initialize(edmCfg, es, muonGeometryTokens);
0345   angleConverter->checkAndUpdateGeometry(es, config, muonGeometryTokens);
0346 }
0347 
0348 ///////////////////////////////////////
0349 ///////////////////////////////////////
0350 OMTFinputMaker::~OMTFinputMaker() {}
0351 ///////////////////////////////////////
0352 ///////////////////////////////////////
0353 unsigned int OMTFinputMaker::getInputNumber(const OMTFConfiguration* config,
0354                                             unsigned int rawId,
0355                                             unsigned int iProcessor,
0356                                             l1t::tftype type) {
0357   unsigned int iInput = 99;
0358   unsigned int aSector = 99;
0359   int aMin = config->getBarrelMin()[iProcessor];
0360   int iRoll = 1;
0361   int nInputsPerSector = 2;
0362 
0363   DetId detId(rawId);
0364   if (detId.det() != DetId::Muon)
0365     edm::LogError("Critical OMTFinputMaker") << "PROBLEM: hit in unknown Det, detID: " << detId.det() << std::endl;
0366   switch (detId.subdetId()) {
0367     case MuonSubdetId::RPC: {
0368       RPCDetId rpc(rawId);
0369       if (rpc.region() == 0) {
0370         nInputsPerSector = 4;
0371         aSector = rpc.sector();
0372         ///on the 0-2pi border we need to add 1 30 deg sector
0373         ///to get the correct index
0374         if (iProcessor == (config->nProcessors() - 1) && aSector < 3)
0375           aSector += 12;  //aMin = -1;
0376         //Use division into rolls
0377         iRoll = rpc.roll();
0378         ///Set roll number by hand to keep common input
0379         ///number shift formula for all stations
0380         if (rpc.station() == 2 && rpc.layer() == 2 && rpc.roll() == 2)
0381           iRoll = 1;
0382         ///Only one roll from station 3 is connected.
0383         if (rpc.station() == 3) {
0384           iRoll = 1;
0385           nInputsPerSector = 2;
0386         }
0387         ///At the moment do not use RPC chambers splitting into rolls for bmtf part
0388         if (type == l1t::tftype::bmtf)
0389           iRoll = 1;
0390       }
0391       if (rpc.region() != 0) {
0392         aSector = (rpc.sector() - 1) * 6 + rpc.subsector();
0393         aMin = config->getEndcap10DegMin()[iProcessor];
0394         ///on the 0-2pi border we need to add 4 10 deg sectors
0395         ///to get the correct index
0396         if (iProcessor == (config->nProcessors() - 1) && aSector < 5)
0397           aSector += 36;  //aMin = -4;
0398       }
0399       break;
0400     }
0401     case MuonSubdetId::DT: {
0402       DTChamberId dt(rawId);
0403       aSector = dt.sector();
0404       ///on the 0-2pi border we need to add 1 30 deg sector
0405       ///to get the correct index
0406       if (iProcessor == (config->nProcessors() - 1) && aSector < 3)
0407         aSector += 12;  //aMin = -1;
0408       break;
0409     }
0410     case MuonSubdetId::CSC: {
0411       CSCDetId csc(rawId);
0412       aSector = csc.chamber();
0413       aMin = config->getEndcap10DegMin()[iProcessor];
0414       ///on the 0-2pi border we need to add 4 10deg sectors
0415       ///to get the correct index
0416       if (iProcessor == (config->nProcessors() - 1) && aSector < 5)
0417         aSector += 36;  //aMin = -4;
0418       ///Endcap region covers algo 10 deg sectors
0419       ///on the 0-2pi border we need to add 2 20deg sectors
0420       ///to get the correct index
0421       if ((type == l1t::tftype::emtf_pos || type == l1t::tftype::emtf_neg) && csc.station() > 1 && csc.ring() == 1) {
0422         aMin = config->getEndcap20DegMin()[iProcessor];
0423         if (iProcessor == (config->nProcessors() - 1) && aSector < 3)
0424           aSector += 18;  //aMin = -2;
0425       }
0426       break;
0427     }
0428   }
0429 
0430   ///Assume 2 hits per chamber
0431   iInput = (aSector - aMin) * nInputsPerSector;
0432   ///Chambers divided into two rolls have rolls number 1 and 3
0433   iInput += iRoll - 1;
0434 
0435   return iInput;
0436 }
0437 ////////////////////////////////////////////
0438 ////////////////////////////////////////////
0439 
0440 //iProcessor counted from 0
0441 int OMTFinputMaker::getProcessorPhiZero(const OMTFConfiguration* config, unsigned int iProcessor) {
0442   unsigned int nPhiBins = config->nPhiBins();
0443 
0444   int phiZero =
0445       nPhiBins / config->nProcessors() * (iProcessor) + nPhiBins / 24;  //this 24 gives 15deg (360deg/24 = 15deg)
0446   // "0" is 15degree moved cyclically to each processor, note [0,2pi]
0447 
0448   return config->foldPhi(phiZero);
0449 }
0450 
0451 ////////////////////////////////////////////
0452 ////////////////////////////////////////////
0453 void OMTFinputMaker::addStub(const OMTFConfiguration* config,
0454                              MuonStubPtrs2D& muonStubsInLayers,
0455                              unsigned int iLayer,
0456                              unsigned int iInput,
0457                              MuonStub& stub) {
0458   //LogTrace("l1tOmtfEventPrint") << __FUNCTION__ << ":" << __LINE__ << " iInput " << iInput << " " << stub << endl;
0459   //there is a small rate of duplicated digis in the real data in the DT and CSC, the reason for this duplicates is not understood
0460   //in case of RPC the duplicated digis appear in data only for the layer 17 (RE3), where the rolls 2 and 3 has the same eta = 115 assigned, and the muon can hit both rolls
0461   //the reason of the  duplicates cannot be the fact that the same data (links) goes to neighboring boards, because this is  removed in the OMTF unpacker
0462   //the duplicates cannot be dropped, because if they appear in data, are also duplicated on the input of the algorithm, and both can be used as the reference hits
0463   if (muonStubsInLayers[iLayer][iInput] && muonStubsInLayers[iLayer][iInput]->phiHw == stub.phiHw &&
0464       muonStubsInLayers[iLayer][iInput]->phiBHw == stub.phiBHw &&
0465       muonStubsInLayers[iLayer][iInput]->etaHw == stub.etaHw) {
0466     LogTrace("OMTFReconstruction") << "addStub: the stub with exactly the same phi, phiB and eta was already added:\n"
0467                                    << "incomnig stub " << stub << "\n"
0468                                    << "existing stub " << *(muonStubsInLayers[iLayer][iInput]) << std::endl;
0469     //return;
0470   }
0471 
0472   if (muonStubsInLayers[iLayer][iInput] && muonStubsInLayers[iLayer][iInput]->phiHw != (int)config->nPhiBins())
0473     ++iInput;
0474 
0475   if (muonStubsInLayers[iLayer][iInput] && muonStubsInLayers[iLayer][iInput]->phiHw != (int)config->nPhiBins())
0476     return;
0477   //in this implementation only two first stubs are added for a given iInput
0478 
0479   stub.input = iInput;
0480   muonStubsInLayers.at(iLayer).at(iInput) = std::make_shared<MuonStub>(stub);
0481 }