Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-04-21 02:53:24

0001 #include <cmath>
0002 #include <vector>
0003 #include <iostream>
0004 #include <algorithm>
0005 
0006 #include "DataFormats/MuonDetId/interface/CSCDetId.h"
0007 #include "DataFormats/MuonDetId/interface/RPCDetId.h"
0008 #include "DataFormats/MuonDetId/interface/DTChamberId.h"
0009 #include "DataFormats/MuonDetId/interface/MuonSubdetId.h"
0010 
0011 #include "L1Trigger/L1TMuonOverlap/interface/OMTFinputMaker.h"
0012 #include "L1Trigger/L1TMuonOverlap/interface/OMTFinput.h"
0013 #include "L1Trigger/L1TMuonOverlap/interface/OMTFConfiguration.h"
0014 #include "L1Trigger/L1TMuonOverlap/interface/AngleConverter.h"
0015 #include "DataFormats/CSCDigi/interface/CSCConstants.h"
0016 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0017 
0018 ///////////////////////////////////////
0019 ///////////////////////////////////////
0020 OMTFinputMaker::OMTFinputMaker(edm::ConsumesCollector &iC, bool getDuringEvent)
0021     : myAngleConverter(std::make_unique<AngleConverter>(iC, getDuringEvent)) {}
0022 ///////////////////////////////////////
0023 ///////////////////////////////////////
0024 void OMTFinputMaker::initialize(const edm::EventSetup &es, const OMTFConfiguration *omtfConfig) {
0025   myAngleConverter->checkAndUpdateGeometry(es, omtfConfig->nPhiBins());
0026 
0027   myOmtfConfig = omtfConfig;
0028 }
0029 ///////////////////////////////////////
0030 ///////////////////////////////////////
0031 OMTFinputMaker::~OMTFinputMaker() {}
0032 ///////////////////////////////////////
0033 ///////////////////////////////////////
0034 bool OMTFinputMaker::acceptDigi(uint32_t rawId, unsigned int iProcessor, l1t::tftype type) {
0035   unsigned int aMin = myOmtfConfig->getBarrelMin()[iProcessor];
0036   unsigned int aMax = myOmtfConfig->getBarrelMax()[iProcessor];
0037   unsigned int aSector = 99;
0038 
0039   ///Clean up digis. Remove unconnected detectors
0040   DetId detId(rawId);
0041   if (detId.det() != DetId::Muon)
0042     edm::LogError("Critical OMTFinputMaker") << "PROBLEM: hit in unknown Det, detID: " << detId.det() << std::endl;
0043   switch (detId.subdetId()) {
0044     case MuonSubdetId::RPC: {
0045       RPCDetId aId(rawId);
0046 
0047       ///Select RPC chambers connected to OMTF
0048       if (type == l1t::tftype::omtf_pos &&
0049           (aId.region() < 0 || (aId.region() == 0 && aId.ring() != 2) || (aId.region() == 0 && aId.station() == 4) ||
0050            (aId.region() == 0 && aId.station() == 2 && aId.layer() == 2 && aId.roll() == 1) ||
0051            (aId.region() == 0 && aId.station() == 3 && aId.roll() == 1) || (aId.region() == 1 && aId.station() == 4) ||
0052            ///RPC RE1/2 temporarily not used (aId.region()==1 && aId.station()==1 && aId.ring()<2) ||
0053            (aId.region() == 1 && aId.station() > 0 && aId.ring() < 3)))
0054         return false;
0055 
0056       if (type == l1t::tftype::omtf_neg &&
0057           (aId.region() > 0 || (aId.region() == 0 && aId.ring() != -2) || (aId.region() == 0 && aId.station() == 4) ||
0058            (aId.region() == 0 && aId.station() == 2 && aId.layer() == 2 && aId.roll() == 1) ||
0059            (aId.region() == 0 && aId.station() == 3 && aId.roll() == 1) || (aId.region() == -1 && aId.station() == 4) ||
0060            //RPC RE1/2 temporarily not used (aId.region()==1 && aId.station()==1 && aId.ring()<2) ||
0061            (aId.region() == -1 && aId.station() > 0 && aId.ring() < 3)))
0062         return false;
0063 
0064       if (type == l1t::tftype::bmtf && aId.region() != 0)
0065         return false;
0066 
0067       if (type == l1t::tftype::emtf_pos && (aId.region() <= 0 || (aId.station() == 1 && aId.ring() == 3)))
0068         return false;
0069       if (type == l1t::tftype::emtf_neg && (aId.region() >= 0 || (aId.station() == 1 && aId.ring() == 3)))
0070         return false;
0071       ////////////////
0072       if (aId.region() == 0)
0073         aSector = aId.sector();
0074       if (aId.region() != 0) {
0075         aSector = (aId.sector() - 1) * 6 + aId.subsector();
0076         aMin = myOmtfConfig->getEndcap10DegMin()[iProcessor];
0077         aMax = myOmtfConfig->getEndcap10DegMax()[iProcessor];
0078       }
0079 
0080       break;
0081     }
0082     case MuonSubdetId::DT: {
0083       DTChamberId dt(rawId);
0084 
0085       if (type == l1t::tftype::omtf_pos && dt.wheel() != 2)
0086         return false;
0087       if (type == l1t::tftype::omtf_neg && dt.wheel() != -2)
0088         return false;
0089       if (type == l1t::tftype::emtf_pos || type == l1t::tftype::emtf_neg)
0090         return false;
0091 
0092       aSector = dt.sector();
0093       break;
0094     }
0095     case MuonSubdetId::CSC: {
0096       CSCDetId csc(rawId);
0097       if (type == l1t::tftype::omtf_pos && (csc.endcap() == 2 || csc.ring() == 1 || csc.station() == 4))
0098         return false;
0099       if (type == l1t::tftype::omtf_neg && (csc.endcap() == 1 || csc.ring() == 1 || csc.station() == 4))
0100         return false;
0101 
0102       if (type == l1t::tftype::emtf_pos && (csc.endcap() == 2 || (csc.station() == 1 && csc.ring() == 3)))
0103         return false;
0104       if (type == l1t::tftype::emtf_neg && (csc.endcap() == 1 || (csc.station() == 1 && csc.ring() == 3)))
0105         return false;
0106 
0107       aSector = csc.chamber();
0108       aMin = myOmtfConfig->getEndcap10DegMin()[iProcessor];
0109       aMax = myOmtfConfig->getEndcap10DegMax()[iProcessor];
0110 
0111       if ((type == l1t::tftype::emtf_pos || type == l1t::tftype::emtf_neg) && csc.station() > 1 && csc.ring() == 1) {
0112         aMin = myOmtfConfig->getEndcap20DegMin()[iProcessor];
0113         aMax = myOmtfConfig->getEndcap20DegMax()[iProcessor];
0114       }
0115       break;
0116     }
0117   }
0118 
0119   if (aMax > aMin && aSector >= aMin && aSector <= aMax)
0120     return true;
0121   if (aMax < aMin && (aSector >= aMin || aSector <= aMax))
0122     return true;
0123 
0124   return false;
0125 }
0126 ///////////////////////////////////////
0127 ///////////////////////////////////////
0128 unsigned int OMTFinputMaker::getInputNumber(unsigned int rawId, unsigned int iProcessor, l1t::tftype type) {
0129   unsigned int iInput = 99;
0130   unsigned int aSector = 99;
0131   int aMin = myOmtfConfig->getBarrelMin()[iProcessor];
0132   int iRoll = 1;
0133   int nInputsPerSector = 2;
0134 
0135   DetId detId(rawId);
0136   if (detId.det() != DetId::Muon)
0137     edm::LogError("Critical OMTFinputMaker") << "PROBLEM: hit in unknown Det, detID: " << detId.det() << std::endl;
0138   switch (detId.subdetId()) {
0139     case MuonSubdetId::RPC: {
0140       RPCDetId rpc(rawId);
0141       if (rpc.region() == 0) {
0142         nInputsPerSector = 4;
0143         aSector = rpc.sector();
0144         ///on the 0-2pi border we need to add 1 30 deg sector
0145         ///to get the correct index
0146         if (iProcessor == 5 && aSector < 3)
0147           aMin = -1;
0148         //Use division into rolls
0149         iRoll = rpc.roll();
0150         ///Set roll number by hand to keep common input
0151         ///number shift formula for all stations
0152         if (rpc.station() == 2 && rpc.layer() == 2 && rpc.roll() == 2)
0153           iRoll = 1;
0154         ///Only one roll from station 3 is connected.
0155         if (rpc.station() == 3) {
0156           iRoll = 1;
0157           nInputsPerSector = 2;
0158         }
0159         ///At the moment do not use RPC chambers splitting into rolls for bmtf part
0160         if (type == l1t::tftype::bmtf)
0161           iRoll = 1;
0162       }
0163       if (rpc.region() != 0) {
0164         aSector = (rpc.sector() - 1) * 6 + rpc.subsector();
0165         aMin = myOmtfConfig->getEndcap10DegMin()[iProcessor];
0166         ///on the 0-2pi border we need to add 4 10 deg sectors
0167         ///to get the correct index
0168         if (iProcessor == 5 && aSector < 5)
0169           aMin = -4;
0170       }
0171       break;
0172     }
0173     case MuonSubdetId::DT: {
0174       DTChamberId dt(rawId);
0175       aSector = dt.sector();
0176       ///on the 0-2pi border we need to add 1 30 deg sector
0177       ///to get the correct index
0178       if (iProcessor == 5 && aSector < 3)
0179         aMin = -1;
0180       break;
0181     }
0182     case MuonSubdetId::CSC: {
0183       CSCDetId csc(rawId);
0184       aSector = csc.chamber();
0185       aMin = myOmtfConfig->getEndcap10DegMin()[iProcessor];
0186       ///on the 0-2pi border we need to add 4 10deg sectors
0187       ///to get the correct index
0188       if (iProcessor == 5 && aSector < 5)
0189         aMin = -4;
0190       ///Endcap region covers algo 10 deg sectors
0191       ///on the 0-2pi border we need to add 2 20deg sectors
0192       ///to get the correct index
0193       if ((type == l1t::tftype::emtf_pos || type == l1t::tftype::emtf_neg) && csc.station() > 1 && csc.ring() == 1) {
0194         aMin = myOmtfConfig->getEndcap20DegMin()[iProcessor];
0195         if (iProcessor == 5 && aSector < 3)
0196           aMin = -2;
0197       }
0198       break;
0199     }
0200   }
0201 
0202   ///Assume 2 hits per chamber
0203   iInput = (aSector - aMin) * nInputsPerSector;
0204   ///Chambers divided into two rolls have rolls number 1 and 3
0205   iInput += iRoll - 1;
0206 
0207   return iInput;
0208 }
0209 ////////////////////////////////////////////
0210 ////////////////////////////////////////////
0211 OMTFinput OMTFinputMaker::processDT(const L1MuDTChambPhContainer *dtPhDigis,
0212                                     const L1MuDTChambThContainer *dtThDigis,
0213                                     unsigned int iProcessor,
0214                                     l1t::tftype type,
0215                                     int bxTrg) {
0216   OMTFinput result(myOmtfConfig);
0217   if (!dtPhDigis)
0218     return result;
0219 
0220   for (const auto &digiIt : *dtPhDigis->getContainer()) {
0221     DTChamberId detid(digiIt.whNum(), digiIt.stNum(), digiIt.scNum() + 1);
0222 
0223     ///Check it the data fits into given processor input range
0224     if (!acceptDigi(detid.rawId(), iProcessor, type))
0225       continue;
0226 
0227     ///Check Trigger primitive quality
0228     ///Ts2Tag() == 0 - take only first track from DT Trigger Server
0229     ///BxCnt()  == 0 - ??
0230     ///code()>=3     - take only double layer hits, HH, HL and LL
0231     // FIXME (MK): at least Ts2Tag selection is not correct! Check it
0232     //    if (digiIt.bxNum()!= 0 || digiIt.BxCnt()!= 0 || digiIt.Ts2Tag()!= 0 || digiIt.code()<4) continue;
0233 
0234     if (digiIt.bxNum() != bxTrg)
0235       continue;
0236 
0237     if (myOmtfConfig->fwVersion() <= 4) {
0238       if (digiIt.code() != 4 && digiIt.code() != 5 && digiIt.code() != 6)
0239         continue;
0240     } else {
0241       if (digiIt.code() != 2 && digiIt.code() != 3 && digiIt.code() != 4 && digiIt.code() != 5 && digiIt.code() != 6)
0242         continue;
0243     }
0244 
0245     unsigned int hwNumber = myOmtfConfig->getLayerNumber(detid.rawId());
0246     if (myOmtfConfig->getHwToLogicLayer().find(hwNumber) == myOmtfConfig->getHwToLogicLayer().end())
0247       continue;
0248 
0249     auto iter = myOmtfConfig->getHwToLogicLayer().find(hwNumber);
0250     unsigned int iLayer = iter->second;
0251     int iPhi = myAngleConverter->getProcessorPhi(iProcessor, type, digiIt);
0252     int iEta = myAngleConverter->getGlobalEta(detid.rawId(), digiIt, dtThDigis);
0253     unsigned int iInput = getInputNumber(detid.rawId(), iProcessor, type);
0254     bool allowOverwrite = false;
0255     result.addLayerHit(iLayer, iInput, iPhi, iEta, allowOverwrite);
0256     result.addLayerHit(iLayer + 1, iInput, digiIt.phiB(), iEta, allowOverwrite);
0257   }
0258 
0259   return result;
0260 }
0261 ////////////////////////////////////////////
0262 ////////////////////////////////////////////
0263 OMTFinput OMTFinputMaker::processCSC(const CSCCorrelatedLCTDigiCollection *cscDigis,
0264                                      unsigned int iProcessor,
0265                                      l1t::tftype type,
0266                                      int bxTrg) {
0267   OMTFinput result(myOmtfConfig);
0268   if (!cscDigis)
0269     return result;
0270 
0271   auto chamber = cscDigis->begin();
0272   auto chend = cscDigis->end();
0273   for (; chamber != chend; ++chamber) {
0274     unsigned int rawid = (*chamber).first;
0275     ///Check it the data fits into given processor input range
0276     if (!acceptDigi(rawid, iProcessor, type))
0277       continue;
0278     auto digi = (*chamber).second.first;
0279     auto dend = (*chamber).second.second;
0280     for (; digi != dend; ++digi) {
0281       ///Check if LCT trigger primitive has the right BX.
0282       if (digi->getBX() - CSCConstants::LCT_CENTRAL_BX != bxTrg)
0283         continue;
0284 
0285       unsigned int hwNumber = myOmtfConfig->getLayerNumber(rawid);
0286       if (myOmtfConfig->getHwToLogicLayer().find(hwNumber) == myOmtfConfig->getHwToLogicLayer().end())
0287         continue;
0288 
0289       unsigned int iLayer = myOmtfConfig->getHwToLogicLayer().at(hwNumber);
0290       int iPhi = myAngleConverter->getProcessorPhi(iProcessor, type, CSCDetId(rawid), *digi);
0291       int iEta = myAngleConverter->getGlobalEta(rawid, *digi);
0292       ///Accept CSC digis only up to eta=1.26.
0293       ///The nominal OMTF range is up to 1.24, but cutting at 1.24
0294       ///kill efficnency at the edge. 1.26 is one eta bin above nominal.
0295       //if(abs(iEta)>1.26/2.61*240) continue;
0296       //if (abs(iEta) > 115) continue;
0297       unsigned int iInput = getInputNumber(rawid, iProcessor, type);
0298       //    std::cout <<" ADDING CSC hit, proc: "<<iProcessor<<" iPhi : " << iPhi <<" iEta: "<< iEta << std::endl;
0299       bool allowOverwrite = false;
0300       result.addLayerHit(iLayer, iInput, iPhi, iEta, allowOverwrite);
0301     }
0302   }
0303   return result;
0304 }
0305 ////////////////////////////////////////////
0306 ////////////////////////////////////////////
0307 bool rpcPrimitiveCmp(const RPCDigi &a, const RPCDigi &b) { return a.strip() < b.strip(); };
0308 ////////////////////////////////////////////
0309 ////////////////////////////////////////////
0310 OMTFinput OMTFinputMaker::processRPC(const RPCDigiCollection *rpcDigis,
0311                                      unsigned int iProcessor,
0312                                      l1t::tftype type,
0313                                      int bxTrg) {
0314   OMTFinput result(myOmtfConfig);
0315   if (!rpcDigis)
0316     return result;
0317   std::stringstream str;
0318 
0319   //  std::cout <<" RPC HITS, processor : " << iProcessor << std::endl;
0320 
0321   const RPCDigiCollection &rpcDigiCollection = *rpcDigis;
0322   for (auto rollDigis : rpcDigiCollection) {
0323     RPCDetId roll = rollDigis.first;
0324     unsigned int rawid = roll.rawId();
0325     int nClusters = 0;
0326     if (!acceptDigi(rawid, iProcessor, type))
0327       continue;
0328     ///Find clusters of consecutive fired strips.
0329     ///Have to copy the digis in chamber to sort them (not optimal).
0330     ///NOTE: when copying I select only digis with bx==       //FIXME: find a better place/way to filtering digi against quality/BX etc.
0331     //  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; }
0332     std::vector<RPCDigi> digisCopy;
0333     //  std::copy_if(rollDigis.second.first, rollDigis.second.second, std::back_inserter(digisCopy), [](const RPCDigi & aDigi){return (aDigi.bx()==0);} );
0334     for (auto pDigi = rollDigis.second.first; pDigi != rollDigis.second.second; pDigi++) {
0335       if (pDigi->bx() == bxTrg)
0336         digisCopy.push_back(*pDigi);
0337     }
0338     std::sort(digisCopy.begin(), digisCopy.end(), rpcPrimitiveCmp);
0339     typedef std::pair<unsigned int, unsigned int> Cluster;
0340     std::vector<Cluster> clusters;
0341     for (auto &digi : digisCopy) {
0342       if (clusters.empty())
0343         clusters.push_back(Cluster(digi.strip(), digi.strip()));
0344       else if (digi.strip() - clusters.back().second == 1)
0345         clusters.back().second = digi.strip();
0346       else if (digi.strip() - clusters.back().second > 1)
0347         clusters.push_back(Cluster(digi.strip(), digi.strip()));
0348     }
0349 
0350     for (auto &cluster : clusters) {
0351       //      int iPhiHalfStrip1 = myAngleConverter->getProcessorPhi(iProcessor, type, roll, cluster.first);
0352       //      int iPhiHalfStrip2 = myAngleConverter->getProcessorPhi(iProcessor, type, roll, cluster.second);
0353       int iPhi = myAngleConverter->getProcessorPhi(iProcessor, type, roll, cluster.first, cluster.second);
0354       int cSize = abs(int(cluster.first) - int(cluster.second)) + 1;
0355       //      std::cout << " HStrip_1: " << iPhiHalfStrip1 <<" HStrip_2: "<<iPhiHalfStrip2<<" iPhi: " << iPhi << " cluster: ["<< cluster.first << ", "<<  cluster.second <<"]"<< std::endl;
0356       if (cSize > 3)
0357         continue;
0358       int iEta = myAngleConverter->getGlobalEta(rawid, cluster.first);
0359       unsigned int hwNumber = myOmtfConfig->getLayerNumber(rawid);
0360       unsigned int iLayer = myOmtfConfig->getHwToLogicLayer().at(hwNumber);
0361       unsigned int iInput = getInputNumber(rawid, iProcessor, type);
0362       //      std::cout <<"ADDING HIT: iLayer = " << iLayer << " iInput: " << iInput << " iPhi: " << iPhi << std::endl;
0363       if (iLayer == 17 && (iInput == 0 || iInput == 1))
0364         continue;  // FIXME (MK) there is no RPC link for that input, because it is taken by DAQ link
0365       bool outres = result.addLayerHit(iLayer, iInput, iPhi, iEta);
0366       //      if (cSize>2) flag |= 2;
0367       //      if (!outres) flag |= 1;
0368       nClusters++;
0369 
0370       str << " RPC halfDigi "
0371           << " begin: " << cluster.first << " end: " << cluster.second << " iPhi: " << iPhi << " iEta: " << iEta
0372           << " hwNumber: " << hwNumber << " iInput: " << iInput << " iLayer: " << iLayer << " out: " << outres
0373           << std::endl;
0374     }
0375     //    if (nClusters > 2) flag=1;
0376   }
0377 
0378   edm::LogInfo("OMTFInputMaker") << str.str();
0379   return result;
0380 }
0381 ////////////////////////////////////////////
0382 ////////////////////////////////////////////
0383 OMTFinput OMTFinputMaker::buildInputForProcessor(const L1MuDTChambPhContainer *dtPhDigis,
0384                                                  const L1MuDTChambThContainer *dtThDigis,
0385                                                  const CSCCorrelatedLCTDigiCollection *cscDigis,
0386                                                  const RPCDigiCollection *rpcDigis,
0387                                                  unsigned int iProcessor,
0388                                                  l1t::tftype type,
0389                                                  int bx) {
0390   OMTFinput result(myOmtfConfig);
0391   result += processDT(dtPhDigis, dtThDigis, iProcessor, type, bx);
0392   result += processCSC(cscDigis, iProcessor, type, bx);
0393   result += processRPC(rpcDigis, iProcessor, type, bx);
0394   return result;
0395 }
0396 ////////////////////////////////////////////
0397 ////////////////////////////////////////////