diff --git a/DataFormats/L1DTTrackFinder/BuildFile.xml b/DataFormats/L1DTTrackFinder/BuildFile.xml index a4b5fbf1485f5..2a83a0228a182 100644 --- a/DataFormats/L1DTTrackFinder/BuildFile.xml +++ b/DataFormats/L1DTTrackFinder/BuildFile.xml @@ -2,4 +2,5 @@ + diff --git a/DataFormats/L1DTTrackFinder/interface/L1Phase2MuDTExtPhDigi.h b/DataFormats/L1DTTrackFinder/interface/L1Phase2MuDTExtPhDigi.h index 0364990377b19..0f9f2a720b148 100644 --- a/DataFormats/L1DTTrackFinder/interface/L1Phase2MuDTExtPhDigi.h +++ b/DataFormats/L1DTTrackFinder/interface/L1Phase2MuDTExtPhDigi.h @@ -56,7 +56,9 @@ class L1Phase2MuDTExtPhDigi : public L1Phase2MuDTPhDigi { int tdc[8] = nullptr, int lat[8] = nullptr); - L1Phase2MuDTExtPhDigi(const L1Phase2MuDTExtPhDigi &digi); + L1Phase2MuDTExtPhDigi(const L1Phase2MuDTExtPhDigi& digi); + L1Phase2MuDTExtPhDigi& operator=(const L1Phase2MuDTExtPhDigi&) = default; + L1Phase2MuDTExtPhDigi& operator=(L1Phase2MuDTExtPhDigi&&) = default; ~L1Phase2MuDTExtPhDigi() override {} diff --git a/DataFormats/L1DTTrackFinder/interface/L1Phase2MuDTExtPhiThetaPair.h b/DataFormats/L1DTTrackFinder/interface/L1Phase2MuDTExtPhiThetaPair.h new file mode 100644 index 0000000000000..105a9cd820860 --- /dev/null +++ b/DataFormats/L1DTTrackFinder/interface/L1Phase2MuDTExtPhiThetaPair.h @@ -0,0 +1,43 @@ +#ifndef DataFormats_L1DTTrackFinder_L1Phase2MuDTExtPhiThetaPair_h +#define DataFormats_L1DTTrackFinder_L1Phase2MuDTExtPhiThetaPair_h + +/** \class L1Phase2MuDTExtPhiThetaPair + * + * Data container for a matched pair of Phase-2 DT Phi and Theta digis. + * Provides utilities to retrieve the closest-N time-position pairs per chamber ordered by Phi quality. + * + * \author J. Fernandez + * \date 2025-11-19 + */ + +#include "DataFormats/L1DTTrackFinder/interface/L1Phase2MuDTExtPhDigi.h" +#include "DataFormats/L1DTTrackFinder/interface/L1Phase2MuDTExtThDigi.h" +#include +#include + +class L1Phase2MuDTExtPhiThetaPair { +public: + /// Default constructor + L1Phase2MuDTExtPhiThetaPair() = default; + + /// Constructor with digis and quality + L1Phase2MuDTExtPhiThetaPair(const L1Phase2MuDTExtPhDigi& phi, const L1Phase2MuDTExtThDigi& theta, int quality); + + // Explicitly allow copy/move + L1Phase2MuDTExtPhiThetaPair(const L1Phase2MuDTExtPhiThetaPair&) = default; + L1Phase2MuDTExtPhiThetaPair& operator=(const L1Phase2MuDTExtPhiThetaPair&) = default; + L1Phase2MuDTExtPhiThetaPair(L1Phase2MuDTExtPhiThetaPair&&) = default; + L1Phase2MuDTExtPhiThetaPair& operator=(L1Phase2MuDTExtPhiThetaPair&&) = default; + + /// Accessors + const L1Phase2MuDTExtPhDigi& phiDigi() const { return phi_; } + const L1Phase2MuDTExtThDigi& thetaDigi() const { return theta_; } + int quality() const { return quality_; } + +private: + L1Phase2MuDTExtPhDigi phi_; + L1Phase2MuDTExtThDigi theta_; + int quality_; +}; + +#endif diff --git a/DataFormats/L1DTTrackFinder/interface/L1Phase2MuDTExtPhiThetaPairContainer.h b/DataFormats/L1DTTrackFinder/interface/L1Phase2MuDTExtPhiThetaPairContainer.h new file mode 100644 index 0000000000000..74d9cf5bf076f --- /dev/null +++ b/DataFormats/L1DTTrackFinder/interface/L1Phase2MuDTExtPhiThetaPairContainer.h @@ -0,0 +1,50 @@ +//------------------------------------------------- +// +// Class L1Phase2MuDTExtPhiThetaPairContainer +// +// Description: trigger primtive data for the +// muon barrel Phase2 trigger +// +// +// Author List: J. Fernandez - Oviedo ICTEA +// +// +//-------------------------------------------------- +#ifndef L1Phase2MuDTExtPhiThetaPairContainer_H +#define L1Phase2MuDTExtPhiThetaPairContainer_H + +//------------------------------------ +// Collaborating Class Declarations -- +//------------------------------------ +#include "DataFormats/L1DTTrackFinder/interface/L1Phase2MuDTExtPhiThetaPair.h" + +//---------------------- +// Base Class Headers -- +//---------------------- +#include + +//--------------- +// C++ Headers -- +//--------------- + +//--------------------- +//-- Class Interface -- +//--------------------- + +class L1Phase2MuDTExtPhiThetaPairContainer { +public: + typedef std::vector Segment_Container; + typedef Segment_Container::const_iterator Segment_iterator; + + // Constructor + L1Phase2MuDTExtPhiThetaPairContainer(); + + void setContainer(const Segment_Container& inputSegments); + + Segment_Container const& getContainer() const; + +private: + Segment_Container m_segments; +}; + +#endif diff --git a/DataFormats/L1DTTrackFinder/interface/L1Phase2MuDTExtThDigi.h b/DataFormats/L1DTTrackFinder/interface/L1Phase2MuDTExtThDigi.h index 75fcc10478063..f6e392cdd33e9 100644 --- a/DataFormats/L1DTTrackFinder/interface/L1Phase2MuDTExtThDigi.h +++ b/DataFormats/L1DTTrackFinder/interface/L1Phase2MuDTExtThDigi.h @@ -54,7 +54,9 @@ class L1Phase2MuDTExtThDigi : public L1Phase2MuDTThDigi { int tdc[4] = nullptr, int lat[4] = nullptr); - L1Phase2MuDTExtThDigi(const L1Phase2MuDTExtThDigi &digi); + L1Phase2MuDTExtThDigi(const L1Phase2MuDTExtThDigi& digi); + L1Phase2MuDTExtThDigi& operator=(const L1Phase2MuDTExtThDigi&) = default; + L1Phase2MuDTExtThDigi& operator=(L1Phase2MuDTExtThDigi&&) = default; ~L1Phase2MuDTExtThDigi() override {} diff --git a/DataFormats/L1DTTrackFinder/src/L1Phase2MuDTExtPhiThetaPair.cc b/DataFormats/L1DTTrackFinder/src/L1Phase2MuDTExtPhiThetaPair.cc new file mode 100644 index 0000000000000..aafaee24912f7 --- /dev/null +++ b/DataFormats/L1DTTrackFinder/src/L1Phase2MuDTExtPhiThetaPair.cc @@ -0,0 +1,6 @@ +#include "DataFormats/L1DTTrackFinder/interface/L1Phase2MuDTExtPhiThetaPair.h" + +L1Phase2MuDTExtPhiThetaPair::L1Phase2MuDTExtPhiThetaPair(const L1Phase2MuDTExtPhDigi& phi, + const L1Phase2MuDTExtThDigi& theta, + int quality) + : phi_(phi), theta_(theta), quality_(quality) {} diff --git a/DataFormats/L1DTTrackFinder/src/L1Phase2MuDTExtPhiThetaPairContainer.cc b/DataFormats/L1DTTrackFinder/src/L1Phase2MuDTExtPhiThetaPairContainer.cc new file mode 100644 index 0000000000000..e6dd96c594f61 --- /dev/null +++ b/DataFormats/L1DTTrackFinder/src/L1Phase2MuDTExtPhiThetaPairContainer.cc @@ -0,0 +1,46 @@ +//------------------------------------------------- +// +// Class L1Phase2MuDTExtPhiThetaPairContainer +// +// Description: trigger primtive data for the +// muon barrel Phase2 trigger +// +// +// Author List: J. Fernandez - Oviedo ICTEA +// +// +//-------------------------------------------------- + +//----------------------- +// This Class's Header -- +//----------------------- +#include "DataFormats/L1DTTrackFinder/interface/L1Phase2MuDTExtPhiThetaPairContainer.h" + +//------------------------------- +// Collaborating Class Headers -- +//------------------------------- + +//--------------- +// C++ Headers -- +//--------------- + +//------------------- +// Initializations -- +//------------------- + +//---------------- +// Constructors -- +//---------------- +L1Phase2MuDTExtPhiThetaPairContainer::L1Phase2MuDTExtPhiThetaPairContainer() {} + +//-------------- +// Operations -- +//-------------- +void L1Phase2MuDTExtPhiThetaPairContainer::setContainer(const Segment_Container& inputSegments) { + m_segments = inputSegments; +} + +L1Phase2MuDTExtPhiThetaPairContainer::Segment_Container const& L1Phase2MuDTExtPhiThetaPairContainer::getContainer() + const { + return m_segments; +} diff --git a/DataFormats/L1DTTrackFinder/src/classes.h b/DataFormats/L1DTTrackFinder/src/classes.h index efcd0d5612165..b78a137cdbce1 100644 --- a/DataFormats/L1DTTrackFinder/src/classes.h +++ b/DataFormats/L1DTTrackFinder/src/classes.h @@ -14,4 +14,6 @@ #include #include #include +#include +#include #include diff --git a/DataFormats/L1DTTrackFinder/src/classes_def.xml b/DataFormats/L1DTTrackFinder/src/classes_def.xml index 7e68549b00265..b2fedfc4e5985 100644 --- a/DataFormats/L1DTTrackFinder/src/classes_def.xml +++ b/DataFormats/L1DTTrackFinder/src/classes_def.xml @@ -24,6 +24,7 @@ + @@ -34,6 +35,7 @@ + @@ -56,7 +58,7 @@ - + @@ -67,10 +69,12 @@ + + diff --git a/L1Trigger/Configuration/python/L1Trigger_EventContent_cff.py b/L1Trigger/Configuration/python/L1Trigger_EventContent_cff.py index a5ee86d334285..d5e9562eaf37f 100644 --- a/L1Trigger/Configuration/python/L1Trigger_EventContent_cff.py +++ b/L1Trigger/Configuration/python/L1Trigger_EventContent_cff.py @@ -258,6 +258,9 @@ def _appendPhase2Digis(obj): 'keep *_l1tPhase2L1CaloEGammaEmulator_*_*', 'keep *_l1tGTProducer_*_*', 'keep *_l1tGTAlgoBlockProducer_*_*', + 'keep *_dtTriggerPhase2PrimitiveDigis_*_*', + 'keep *_dtTriggerPhase2Showers_*_*', + 'keep *_dtTriggerPhase2PrimitivePairDigis_*_*' ] obj.outputCommands += l1Phase2Digis diff --git a/L1Trigger/Configuration/python/SimL1Emulator_cff.py b/L1Trigger/Configuration/python/SimL1Emulator_cff.py index 7c7b348875993..1ca6967ff2a25 100644 --- a/L1Trigger/Configuration/python/SimL1Emulator_cff.py +++ b/L1Trigger/Configuration/python/SimL1Emulator_cff.py @@ -79,6 +79,8 @@ _phase2_siml1emulator.add(dtTriggerPhase2PrimitiveDigis) from L1Trigger.DTTriggerPhase2.dtTriggerPhase2Showers_cfi import * _phase2_siml1emulator.add(dtTriggerPhase2Shower) +from L1Trigger.DTTriggerPhase2.dtTriggerPhase2PrimitivePairDigis_cfi import * +_phase2_siml1emulator.add(dtTriggerPhase2PrimitivePairDigis) # HGCAL TP # ######################################################################## diff --git a/L1Trigger/DTTriggerPhase2/plugins/DTTrigPhase2PairsProd.cc b/L1Trigger/DTTriggerPhase2/plugins/DTTrigPhase2PairsProd.cc new file mode 100644 index 0000000000000..47d9ac05f8e18 --- /dev/null +++ b/L1Trigger/DTTriggerPhase2/plugins/DTTrigPhase2PairsProd.cc @@ -0,0 +1,371 @@ +#include "FWCore/Framework/interface/MakerMacros.h" +#include "FWCore/Framework/interface/stream/EDProducer.h" +#include "FWCore/Utilities/interface/ESGetToken.h" +#include "FWCore/Framework/interface/ModuleFactory.h" +#include "FWCore/Framework/interface/ESProducer.h" +#include "FWCore/Framework/interface/ESHandle.h" +#include "FWCore/Framework/interface/ESProducts.h" +#include "FWCore/Framework/interface/ConsumesCollector.h" + +#include "FWCore/Framework/interface/Event.h" +#include "FWCore/Framework/interface/Frameworkfwd.h" +#include "FWCore/Framework/interface/EventSetup.h" +#include "FWCore/Framework/interface/Run.h" +#include "FWCore/ParameterSet/interface/ParameterSet.h" +#include "FWCore/MessageLogger/interface/MessageLogger.h" + +#include "Geometry/Records/interface/MuonGeometryRecord.h" +#include "Geometry/DTGeometry/interface/DTGeometry.h" +#include "Geometry/DTGeometry/interface/DTLayer.h" + +#include "L1Trigger/DTTriggerPhase2/interface/constants.h" + +//inputs +#include "DataFormats/L1DTTrackFinder/interface/L1Phase2MuDTExtPhContainer.h" +#include "DataFormats/L1DTTrackFinder/interface/L1Phase2MuDTExtPhDigi.h" +#include "DataFormats/L1DTTrackFinder/interface/L1Phase2MuDTExtThContainer.h" +#include "DataFormats/L1DTTrackFinder/interface/L1Phase2MuDTExtThDigi.h" + +//outputs +#include "DataFormats/L1DTTrackFinder/interface/L1Phase2MuDTExtPhiThetaPair.h" +#include "DataFormats/L1DTTrackFinder/interface/L1Phase2MuDTExtPhiThetaPairContainer.h" + +#include +#include +#include +#include + +// Plugin which takes Phi and Theta DT Phase2 digi Extended collections(*) and +// creates a new class container of the 4 best closest Phi-Theta digi pairs per DT chamber +// based on the time-position phase-space distance and ordered by Phi quality. + +// For those cases where there is no Phi/Theta partner, 4 best quality single Phi/Theta digis are saved +// and counterpart in pair is set to default values of the constructor digi class +// +// (*) Requires df_extended>0 in L1Trigger/DTTriggerPhase2/plugins/DTTrigPhase2Prod.cc + +using namespace std; +using namespace cmsdt; + +namespace { + struct { + bool operator()(const L1Phase2MuDTExtPhDigi& mp1, const L1Phase2MuDTExtPhDigi& mp2) const { + int sector1 = mp1.scNum(); + int wheel1 = mp1.whNum(); + int station1 = mp1.stNum(); + + int sector2 = mp2.scNum(); + int wheel2 = mp2.whNum(); + int station2 = mp2.stNum(); + + // First, compare by chamber + if (sector1 != sector2) + return sector1 < sector2; + if (wheel1 != wheel2) + return wheel1 < wheel2; + if (station1 != station2) + return station1 < station2; + + // If they are in the same chamber, sort by quality + return mp1.quality() > mp2.quality(); + } + } const comparePhiDigis; + + struct { + bool operator()(const L1Phase2MuDTThDigi& mp1, const L1Phase2MuDTThDigi& mp2) const { + int sector1 = mp1.scNum(); + int wheel1 = mp1.whNum(); + int station1 = mp1.stNum(); + + int sector2 = mp2.scNum(); + int wheel2 = mp2.whNum(); + int station2 = mp2.stNum(); + + // First, compare by chamber + if (sector1 != sector2) + return sector1 < sector2; + if (wheel1 != wheel2) + return wheel1 < wheel2; + if (station1 != station2) + return station1 < station2; + + // If they are in the same chamber, sort by quality + return mp1.quality() > mp2.quality(); + } + } const compareThetaDigis; + + struct { + bool operator()(const L1Phase2MuDTExtPhiThetaPair& mp1, const L1Phase2MuDTExtPhiThetaPair& mp2) const { + return mp1.quality() > mp2.quality(); + } + } const comparePairs; + +} //namespace + +class DTTrigPhase2PairsProd : public edm::stream::EDProducer<> { +public: + //! Constructor + DTTrigPhase2PairsProd(const edm::ParameterSet& pset); + + //! Destructor + ~DTTrigPhase2PairsProd() override; + + //! Create Trigger Units before starting event processing + void beginRun(edm::Run const& iRun, const edm::EventSetup& iEventSetup) override; + + //! Producer: process every event and generates trigger data + void produce(edm::Event& iEvent, const edm::EventSetup& iEventSetup) override; + + //! endRun: finish things + void endRun(edm::Run const& iRun, const edm::EventSetup& iEventSetup) override; + + // Methods + std::vector bestPairsPerChamber(const std::vector& phiDigis, + const std::vector& thetaDigis, + unsigned int maxPairs, + int wheel, + int sector, + int station); + float computeTimePosDistance( + const L1Phase2MuDTExtPhDigi& phiDigi, const L1Phase2MuDTExtThDigi& thetaDigi, int sector, int wheel, int station); + + // Setter-methods + + static void fillDescriptions(edm::ConfigurationDescriptions& descriptions); + + // data-members + + double shift_back; + +private: + // Debug Flag + bool debug_; + int scenario_; + int max_index_; + + // ParameterSet + edm::EDGetTokenT digiPhToken_; + edm::EDGetTokenT digiThToken_; +}; + +DTTrigPhase2PairsProd::DTTrigPhase2PairsProd(const edm::ParameterSet& pset) { + produces(); + + debug_ = pset.getUntrackedParameter("debug"); + scenario_ = pset.getParameter("scenario"); + max_index_ = 4; //Not configurable due to hardware capacities + + digiPhToken_ = consumes(pset.getParameter("digiPhTag")); + digiThToken_ = consumes(pset.getParameter("digiThTag")); + + double temp_shift = 0; + if (scenario_ == MC) + temp_shift = 400; // value used in standard CMSSW simulation + else if (scenario_ == DATA) + temp_shift = 0; + else if (scenario_ == SLICE_TEST) + temp_shift = 400; // slice test mimics simulation + + shift_back = temp_shift; +} + +DTTrigPhase2PairsProd::~DTTrigPhase2PairsProd() { + if (debug_) + LogDebug("DTTrigPhase2PairsProd") << "calling destructor" << std::endl; +} + +void DTTrigPhase2PairsProd::beginRun(edm::Run const& iRun, const edm::EventSetup& iEventSetup) { + if (debug_) + LogDebug("DTTrigPhase2PairsProd") << "beginRun " << iRun.id().run(); +} + +void DTTrigPhase2PairsProd::produce(edm::Event& iEvent, const edm::EventSetup& iEventSetup) { + if (debug_) + LogDebug("DTTrigPhase2PairsProd") << "produce"; + + edm::Handle thePhiDigis; + iEvent.getByToken(digiPhToken_, thePhiDigis); + + edm::Handle theThetaDigis; + iEvent.getByToken(digiThToken_, theThetaDigis); + + if (!thePhiDigis || !theThetaDigis) { + throw cms::Exception("DTTrigPhase2PairsProd") << "Phi or Theta container is null!"; + } + + if (debug_) + LogDebug("DTTrigPhase2PairsProd") << " Containers read"; + + using ChamberKey = std::tuple; // (wheel, sector, station) + + std::map> phiByChamber; + std::map> thetaByChamber; + + if (debug_) + LogDebug("DTTrigPhase2PairsProd") << "Variables declared"; + + // Group phi digis + for (auto phiIte = thePhiDigis->getContainer()->begin(); phiIte != thePhiDigis->getContainer()->end(); ++phiIte) { + ChamberKey key(phiIte->whNum(), phiIte->scNum(), phiIte->stNum()); + phiByChamber[key].push_back(*phiIte); + } + + // Group theta digis + for (auto thetaIte = theThetaDigis->getContainer()->begin(); thetaIte != theThetaDigis->getContainer()->end(); + ++thetaIte) { + ChamberKey key(thetaIte->whNum(), thetaIte->scNum(), thetaIte->stNum()); + thetaByChamber[key].push_back(*thetaIte); + } + + if (debug_) + LogDebug("DTTrigPhase2PairsProd") << "Grouping per chamber"; + + std::vector allPairs; + + // Process each chamber key from phi digis + for (const auto& [key, phiList] : phiByChamber) { + std::vector chamberPairs; + std::vector phiDigis; + std::vector thetaDigis; + + auto thetaListIt = thetaByChamber.find(key); + + for (const auto& phi : phiList) + phiDigis.emplace_back(phi); + + if (thetaListIt != thetaByChamber.end()) { // Both phi and theta exist + for (const auto& theta : thetaListIt->second) + thetaDigis.emplace_back(theta); + } + + if (debug_) + LogDebug("DTTrigPhase2PairsProd") << "Working on chamber:"; + + std::sort(phiDigis.begin(), phiDigis.end(), comparePhiDigis); + std::sort(thetaDigis.begin(), thetaDigis.end(), compareThetaDigis); + + if (debug_) + LogDebug("DTTrigPhase2PairsProd") << "Sorting"; + + auto [wheel, sector, station] = key; + chamberPairs = bestPairsPerChamber(phiDigis, thetaDigis, max_index_, wheel, sector, station); + + if (debug_) + LogDebug("DTTrigPhase2PairsProd") << "Saving top 4"; + + for (const auto& pair : chamberPairs) + allPairs.emplace_back(pair); + } + + if (debug_) + LogDebug("DTTrigPhase2PairsProd") << "Saving products"; + + // Storing results in the event + std::unique_ptr resultPhiThetaPair(new L1Phase2MuDTExtPhiThetaPairContainer); + resultPhiThetaPair->setContainer(allPairs); + iEvent.put(std::move(resultPhiThetaPair)); + if (debug_) + LogDebug("DTTrigPhase2PairsProd") << "Saved in the event"; + + allPairs.clear(); + allPairs.erase(allPairs.begin(), allPairs.end()); +} + +void DTTrigPhase2PairsProd::endRun(edm::Run const& iRun, const edm::EventSetup& iEventSetup) {}; + +void DTTrigPhase2PairsProd::fillDescriptions(edm::ConfigurationDescriptions& descriptions) { + // dtTriggerPhase2PrimitivePairDigis + edm::ParameterSetDescription desc; + desc.add("digiPhTag", edm::InputTag("dtTriggerPhase2PrimitiveDigis")); + desc.add("digiThTag", edm::InputTag("dtTriggerPhase2PrimitiveDigis")); + desc.add("scenario", 0); + desc.addUntracked("debug", false); + descriptions.add("dtTriggerPhase2PrimitivePairDigis", desc); +} + +DEFINE_FWK_MODULE(DTTrigPhase2PairsProd); + +std::vector DTTrigPhase2PairsProd::bestPairsPerChamber( + const std::vector& phiDigis, + const std::vector& thetaDigis, + unsigned int maxPairs, + int wheel, + int sector, + int station) { + std::vector pairs; + + if (station == 4 || thetaDigis.empty()) { // no theta digis in chamber + + L1Phase2MuDTExtThDigi emptyTheta; + for (const auto& phi : phiDigis) { + int phiQuality = phi.quality(); + pairs.emplace_back(phi, emptyTheta, phiQuality); + } + + } + + else if (phiDigis.empty() && !(thetaDigis.empty())) { // no phi digis in chamber + + L1Phase2MuDTExtPhDigi emptyPhi; + for (const auto& theta : thetaDigis) { + int thetaQuality = theta.quality(); + pairs.emplace_back(emptyPhi, theta, thetaQuality); + } + + } + + else { // phi and theta digis in chamber + + for (const auto& phi : phiDigis) { + float closestDistance = numeric_limits::infinity(); + const L1Phase2MuDTExtThDigi* closestTheta = nullptr; + + for (const auto& theta : thetaDigis) { + float currentDistance = computeTimePosDistance(phi, theta, sector, wheel, station); + if (closestDistance > currentDistance) { + closestDistance = currentDistance; + closestTheta = θ + } + } + int phiQuality = phi.quality(); + if (closestTheta) + pairs.emplace_back(phi, *closestTheta, phiQuality); + } + } + // Sort by quality descending + std::sort(pairs.begin(), pairs.end(), comparePairs); + + // Keep only top-N + if (pairs.size() > maxPairs) + pairs.resize(maxPairs); + + return pairs; +} + +float DTTrigPhase2PairsProd::computeTimePosDistance( + const L1Phase2MuDTExtPhDigi& phiDigi, const L1Phase2MuDTExtThDigi& thetaDigi, int sector, int wheel, int station) { + float t01 = ((int)round(thetaDigi.t0() / (float)LHC_CLK_FREQ)) - shift_back; + float posRefZ = zFE[wheel + 2]; + + if (wheel == 0 && (sector == 1 || sector == 4 || sector == 5 || sector == 8 || sector == 9 || sector == 12)) + posRefZ = -posRefZ; + + float posZ = abs(thetaDigi.z()); + + float t02 = ((int)round(phiDigi.t0() / (float)LHC_CLK_FREQ)) - shift_back; + + float tphi = t02 - abs(posZ / ZRES_CONV - posRefZ) / vwire; + + int LR = -1; + if (wheel == 0 && (sector == 3 || sector == 4 || sector == 7 || sector == 8 || sector == 11 || sector == 12)) + LR = +1; + else if (wheel > 0) + LR = pow(-1, wheel + sector + 1); + else if (wheel < 0) + LR = pow(-1, -wheel + sector); + + float posRefX = LR * xFE[station - 1]; + float ttheta = t01 - (phiDigi.xLocal() / 1000 - posRefX) / vwire; + + return abs(tphi - ttheta); +} diff --git a/L1Trigger/DTTriggerPhase2/plugins/DTTrigPhase2Prod.cc b/L1Trigger/DTTriggerPhase2/plugins/DTTrigPhase2Prod.cc index 5d31059221cba..da6d871bdd4ce 100644 --- a/L1Trigger/DTTriggerPhase2/plugins/DTTrigPhase2Prod.cc +++ b/L1Trigger/DTTriggerPhase2/plugins/DTTrigPhase2Prod.cc @@ -122,7 +122,6 @@ class DTTrigPhase2Prod : public edm::stream::EDProducer<> { // data-members const DTGeometry* dtGeo_; edm::ESGetToken dtGeomH; - std::vector> primitives_; private: // Trigger Configuration Manager CCB validity flag @@ -177,9 +176,9 @@ class DTTrigPhase2Prod : public edm::stream::EDProducer<> { bool activateBuffer_; int superCellhalfspacewidth_; float superCelltimewidth_; - std::vector distribDigis(std::queue>& inQ); + std::vector distribDigis(std::queue>& inQ); void processDigi(std::queue>& inQ, - std::vector>*>& vec); + std::vector>>& vec); // RPC std::unique_ptr rpc_integrator_; @@ -375,14 +374,14 @@ void DTTrigPhase2Prod::produce(Event& iEvent, const EventSetup& iEventSetup) { tmpvec.clear(); // Distribute the digis from the queue into supercells - std::vector superCells; + std::vector superCells; superCells = distribDigis(timequeue); // Process each supercell & collect the resulting muonpaths (as the muonpaths std::vector is only enlarged each time // the groupings access it, it's not needed to "collect" the final products). while (!superCells.empty()) { - grouping_obj_->run(iEvent, iEventSetup, *(superCells.back()), muonpaths[chid.rawId()]); + grouping_obj_->run(iEvent, iEventSetup, superCells.back(), muonpaths[chid.rawId()]); superCells.pop_back(); } } else { @@ -1247,35 +1246,36 @@ int DTTrigPhase2Prod::assignQualityOrder(const metaPrimitive& mP) const { return qmap_.find(mP.quality)->second; } -std::vector DTTrigPhase2Prod::distribDigis(std::queue>& inQ) { - std::vector>*> tmpVector; +std::vector DTTrigPhase2Prod::distribDigis(std::queue>& inQ) { + // Use value-based containers to avoid returning pointers to local variables. + std::vector>> tmpVector; tmpVector.clear(); - std::vector collVector; + std::vector collVector; collVector.clear(); while (!inQ.empty()) { processDigi(inQ, tmpVector); } for (auto& sQ : tmpVector) { DTDigiCollection tmpColl; - while (!sQ->empty()) { - tmpColl.insertDigi((sQ->front().first), (sQ->front().second)); - sQ->pop(); + while (!sQ.empty()) { + tmpColl.insertDigi((sQ.front().first), (sQ.front().second)); + sQ.pop(); } - collVector.push_back(&tmpColl); + collVector.push_back(std::move(tmpColl)); } return collVector; } void DTTrigPhase2Prod::processDigi(std::queue>& inQ, - std::vector>*>& vec) { + std::vector>>& vec) { bool classified = false; if (!vec.empty()) { for (auto& sC : vec) { // Conditions for entering a super cell. - if ((sC->front().second.time() + superCelltimewidth_) > inQ.front().second.time()) { + if ((sC.front().second.time() + superCelltimewidth_) > inQ.front().second.time()) { // Time requirement - if (std::abs(sC->front().second.wire() - inQ.front().second.wire()) <= superCellhalfspacewidth_) { + if (std::abs(sC.front().second.wire() - inQ.front().second.wire()) <= superCellhalfspacewidth_) { // Spatial requirement - sC->push(std::move(inQ.front())); + sC.push(std::move(inQ.front())); classified = true; } } @@ -1293,7 +1293,7 @@ void DTTrigPhase2Prod::processDigi(std::queue>& inQ newQueue.push(tmpPair); inQ.pop(); - vec.push_back(&newQueue); + vec.push_back(std::move(newQueue)); } void DTTrigPhase2Prod::fillDescriptions(edm::ConfigurationDescriptions& descriptions) { diff --git a/L1Trigger/DTTriggerPhase2/python/dtTriggerPhase2PrimitiveDigis_cfi.py b/L1Trigger/DTTriggerPhase2/python/dtTriggerPhase2PrimitiveDigis_cfi.py index b50d2fb012fb3..c0c1ae9bc3077 100644 --- a/L1Trigger/DTTriggerPhase2/python/dtTriggerPhase2PrimitiveDigis_cfi.py +++ b/L1Trigger/DTTriggerPhase2/python/dtTriggerPhase2PrimitiveDigis_cfi.py @@ -23,7 +23,7 @@ allow_confirmation = cms.bool(True), minx_match_2digis = cms.double(1.), scenario = cms.int32(0), #0 for mc, 1 for data, 2 for slice test - df_extended = cms.int32(0), # DF: 0 for standard, 1 for extended, 2 for both + df_extended = cms.int32(2), # DF: 0 for standard, 1 for extended, 2 for both co_option = cms.int32(1), # coincidence w.r.t. : -1 = off, 0 = co all, 1 = co phi, 2 = co theta co_quality = cms.int32(1), # quality cut (>X) for coincidence TP: request TPs to be above this cut co_wh2option = cms.int32(1),#0 (filter all stations in Wh2), 1(pass Wh2 St1), 2(pass Wh2 St1+2) diff --git a/L1Trigger/DTTriggerPhase2/python/dtTriggerPhase2PrimitivePairDigis_cfi.py b/L1Trigger/DTTriggerPhase2/python/dtTriggerPhase2PrimitivePairDigis_cfi.py new file mode 100644 index 0000000000000..27bb153d8dded --- /dev/null +++ b/L1Trigger/DTTriggerPhase2/python/dtTriggerPhase2PrimitivePairDigis_cfi.py @@ -0,0 +1,11 @@ + +import FWCore.ParameterSet.Config as cms + +dtTriggerPhase2PrimitivePairDigis = cms.EDProducer("DTTrigPhase2PairsProd", + scenario = cms.int32(0), #0 for mc, 1 for data, 2 for slice test + digiPhTag = cms.InputTag("dtTriggerPhase2PrimitiveDigis",""), + digiThTag = cms.InputTag("dtTriggerPhase2PrimitiveDigis",""), + + #debugging + debug = cms.untracked.bool(False), +) diff --git a/L1Trigger/DTTriggerPhase2/src/MPThetaMatching.cc b/L1Trigger/DTTriggerPhase2/src/MPThetaMatching.cc index 74e7439a19815..a01d569d453b2 100644 --- a/L1Trigger/DTTriggerPhase2/src/MPThetaMatching.cc +++ b/L1Trigger/DTTriggerPhase2/src/MPThetaMatching.cc @@ -8,10 +8,12 @@ namespace { struct { bool operator()(const metaPrimitive &mp1, const metaPrimitive &mp2) const { DTChamberId chId1(mp1.rawId); + DTSuperLayerId slId1(mp1.rawId); int sector1 = chId1.sector(); int wheel1 = chId1.wheel(); int station1 = chId1.station(); + int sl1 = slId1.superLayer(); DTChamberId chId2(mp2.rawId); DTSuperLayerId slId2(mp2.rawId); @@ -19,6 +21,7 @@ namespace { int sector2 = chId2.sector(); int wheel2 = chId2.wheel(); int station2 = chId2.station(); + int sl2 = slId2.superLayer(); // First, compare by chamber if (sector1 != sector2) @@ -27,11 +30,47 @@ namespace { return wheel1 < wheel2; if (station1 != station2) return station1 < station2; + if (sl1 != sl2) + return sl1 < sl2; - // If they are in the same category, sort by the value (4th index) + // If they are in the same chamber and SL, sort by the quality return mp1.quality > mp2.quality; } } const compareMPs; + + struct { + bool operator()(const metaPrimitive &mp1, const metaPrimitive &mp2) const { + // Use main characteristics to know if it is the same metaPrimitive + if (mp1.rawId != mp2.rawId) + return mp1.rawId < mp2.rawId; + + if (mp1.quality != mp2.quality) + return mp1.quality > mp2.quality; + + if (mp1.phi != mp2.phi) + return mp1.phi < mp2.phi; + + if (mp1.phiB != mp2.phiB) + return mp1.phiB < mp2.phiB; + + if (mp1.chi2 != mp2.chi2) + return mp1.chi2 < mp2.chi2; + + return mp1.t0 < mp2.t0; + } + } const deepCompareMPs; + + struct { + bool operator()(const metaPrimitive &mp1, const metaPrimitive &mp2) const { + // Use main characteristics to know if it is the same metaPrimitive + if (mp1.rawId != mp2.rawId || mp1.quality != mp2.quality || mp1.phi != mp2.phi || mp1.phiB != mp2.phiB || + mp1.chi2 != mp2.chi2 || mp1.t0 != mp2.t0) + return false; + else + return true; + } + } const sameMPs; + } //namespace // ============================================================================ @@ -80,6 +119,13 @@ void MPThetaMatching::run(edm::Event &iEvent, << std::endl; outMPaths = inMPaths; //no filter at all } + + /////////////////////////// + // Filter out duplicates + // Sort by features so that equal keys become adjacent + std::sort(outMPaths.begin(), outMPaths.end(), deepCompareMPs); + // Unique-erase adjacent duplicates + outMPaths.erase(std::unique(outMPaths.begin(), outMPaths.end(), sameMPs), outMPaths.end()); } void MPThetaMatching::finish() {}; @@ -298,7 +344,7 @@ void MPThetaMatching::orderAndSave(std::vector(p).t0 = std::get<1>(p).t0; //replace t0 by associated phi t0 + //std::get<0>(p).t0 = std::get<1>(p).t0; //replace t0 by associated phi t0 outMPs->push_back(std::get<1>(p)); //add PhiMP outMPs->push_back(std::get<0>(p)); //add ThetaMP savedThetaMPs->push_back(std::get<0>(p)); //for accounting @@ -312,9 +358,8 @@ void MPThetaMatching::orderAndSave(std::vector(p).rawId); if (count < th_option_ || (abs(chId.wheel()) == 2 && chId.station() < 3 && count < (th_option_ + 1))) { if (std::get<1>(p).quality > th_quality_) { - //if (abs(chId.wheel())!=0) - std::get<0>(p).t0 = std::get<1>(p).t0; //replace t0 by associated phi t0 - outMPs->push_back(std::get<0>(p)); //add ThetaMP + //std::get<0>(p).t0 = std::get<1>(p).t0; //replace t0 by associated phi t0 + outMPs->push_back(std::get<0>(p)); //add ThetaMP savedThetaMPs->push_back(std::get<0>(p)); count++; }