diff --git a/L1Trigger/DTTriggerPhase2/BuildFile.xml b/L1Trigger/DTTriggerPhase2/BuildFile.xml
new file mode 100644
index 0000000000000..61b5fb6050528
--- /dev/null
+++ b/L1Trigger/DTTriggerPhase2/BuildFile.xml
@@ -0,0 +1,44 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/L1Trigger/DTTriggerPhase2/doc/qualities.txt b/L1Trigger/DTTriggerPhase2/doc/qualities.txt
new file mode 100644
index 0000000000000..a28603daa7045
--- /dev/null
+++ b/L1Trigger/DTTriggerPhase2/doc/qualities.txt
@@ -0,0 +1,20 @@
+Just to keep track of the fast evolving quality definition
+#########################################################
+DT quality code
+---------------
+1, 2: 3-hit in a single SL
+3, 4: 4-hit in a single SL (3 means that there are other TP in this SL, 4 that it is the only one)
+5: 3-hit in a single SL + 1 or 2 hits in the other SL
+6: 3-hit in both SL
+7: 4-hit in a single SL + 1 or 2 hits in the other SL
+8: 4-hit in a SL + 3-hit in the other SL
+9: 4-hit in both SL
+
+RPC Flag (tells how RPC was used) #FIXME being implemented, not everything available yet
+---------------------------------
+0: segment that could not be matched to any RPC cluster (or 'useRPC' option is set to false)
+1: RPC used to overwrite TP timing info (both t0 and BX)
+2: RPC only segment
+3: RPC single hit not associated to any DT segment
+4: RPC used to confirm the presence of the TP, but not used to recompute any of its quantities
+5: RPC single hit associated with a DT segment (only kept if 'storeAllRPCHits' is set to True, which not the default)
diff --git a/L1Trigger/DTTriggerPhase2/interface/CandidateGroup.h b/L1Trigger/DTTriggerPhase2/interface/CandidateGroup.h
new file mode 100644
index 0000000000000..6195bb32b20b6
--- /dev/null
+++ b/L1Trigger/DTTriggerPhase2/interface/CandidateGroup.h
@@ -0,0 +1,62 @@
+#ifndef L1Trigger_DTTriggerPhase2_CandidateGroup_h
+#define L1Trigger_DTTriggerPhase2_CandidateGroup_h
+
+#include
+#include
+#include
+#include
+#include
+
+#include "L1Trigger/DTTriggerPhase2/interface/DTprimitive.h"
+#include "L1Trigger/DTTriggerPhase2/interface/DTPattern.h"
+
+namespace dtbayesam {
+
+ typedef std::bitset<8> qualitybits;
+
+ class CandidateGroup {
+ public:
+ //Constructors and destructors
+ CandidateGroup();
+ CandidateGroup(DTPattern* p);
+ ~CandidateGroup();
+
+ //Hit operation procedures
+ void addHit(DTPrimitive dthit, int lay, bool isGood);
+ void removeHit(DTPrimitive dthit);
+
+ //Get Methods
+ int candId() const { return candId_; };
+ int nhits() const { return nhits_; };
+ int nisGood() const { return nisGood_; };
+ int nLayerhits() const { return nLayerhits_; };
+ int nLayerUp() const { return nLayerUp_; };
+ int nLayerDown() const { return nLayerDown_; };
+ DTPrimitivePtrs candHits() const { return candHits_; };
+ qualitybits quality() const { return quality_; };
+ const DTPattern* pattern() const { return pattern_; };
+
+ //Set Methods
+ void setCandId(int cId) { candId_ = cId; };
+
+ //Pattern rankers
+ bool operator>(const CandidateGroup& cOther) const;
+ bool operator==(const CandidateGroup& cOther) const;
+
+ private:
+ DTPrimitivePtrs candHits_;
+ qualitybits quality_;
+ int nhits_;
+ int nLayerhits_;
+ int nLayerUp_;
+ int nLayerDown_;
+ int nisGood_;
+ DTPattern* pattern_;
+ int candId_;
+ };
+
+ typedef std::shared_ptr CandidateGroupPtr;
+ typedef std::vector CandidateGroupPtrs;
+}; // namespace dtbayesam
+
+#endif
diff --git a/L1Trigger/DTTriggerPhase2/interface/DTPattern.h b/L1Trigger/DTTriggerPhase2/interface/DTPattern.h
new file mode 100644
index 0000000000000..5841070e42775
--- /dev/null
+++ b/L1Trigger/DTTriggerPhase2/interface/DTPattern.h
@@ -0,0 +1,63 @@
+#ifndef L1Trigger_DTTriggerPhase2_DTPattern_h
+#define L1Trigger_DTTriggerPhase2_DTPattern_h
+
+#include
+#include
+#include
+
+// Typedef for refHits organized as [SL, Cell, Laterality]. Using integers is an
+// overkill for something that only needs 3, 7 and 2 bits.
+typedef std::tuple RefDTPatternHit;
+// Another overkill typing for the pattern identifier
+// [SLUp, SLDown, ChambedUp-ChamberDown], only need 3, 3 and 5 bits
+typedef std::tuple DTPatternIdentifier;
+
+class DTPattern {
+ // A pattern is a seed plus a set of hits. Translational simmetry is used to
+ // translate it across all posible recoHits in the lower (upper layer) and
+ // check for pattern hit matches of recohits.
+public:
+ //Constructors and destructors
+ DTPattern();
+ DTPattern(RefDTPatternHit seedUp, RefDTPatternHit seedDown);
+ DTPattern(int SL1, int SL2, int diff);
+ virtual ~DTPattern();
+
+ //Adding hits to the pattern
+ void addHit(RefDTPatternHit hit);
+ // Given the up and down seeding hits check if a given hit is in the pattern.
+ // Returns -1 for left laterality, +1 for right laterality, 0 if undecided
+ // and -999 if not in the pattern
+ int latHitIn(int slId, int chId, int allowedVariance) const;
+
+ // When comparing with a given set of hits we need to set up at least one of
+ // those two to compute the translation
+ void setHitUp(int chIdUp) { recoseedUp_ = chIdUp; }
+ void setHitDown(int chIdDown) { recoseedDown_ = chIdDown; }
+
+ //Get methods
+ DTPatternIdentifier id() const { return id_; }
+ int sl1() const { return std::get<0>(id_); }
+ int sl2() const { return std::get<1>(id_); }
+ int diff() const { return std::get<2>(id_); }
+ const std::vector &genHits() const { return genHits_; }
+
+ //Printing
+ friend std::ostream &operator<<(std::ostream &out, DTPattern &p);
+
+private:
+ //Generated seeds
+ RefDTPatternHit seedUp_;
+ RefDTPatternHit seedDown_;
+ // Generated hits
+ std::vector genHits_;
+ // Pattern is classified in terms of SL + chamber differences to profit from
+ // translational invariance
+ DTPatternIdentifier id_;
+ //Generated seeds + hits translated to a given seed pair
+ int recoseedUp_;
+ int recoseedDown_;
+ bool debug_ = false;
+};
+
+#endif
diff --git a/L1Trigger/DTTriggerPhase2/interface/DTprimitive.h b/L1Trigger/DTTriggerPhase2/interface/DTprimitive.h
new file mode 100644
index 0000000000000..cec71913409f8
--- /dev/null
+++ b/L1Trigger/DTTriggerPhase2/interface/DTprimitive.h
@@ -0,0 +1,57 @@
+#ifndef L1Trigger_DTTriggerPhase2_DTprimitive_h
+#define L1Trigger_DTTriggerPhase2_DTprimitive_h
+
+#include "L1Trigger/DTTriggerPhase2/interface/constants.h"
+#include
+#include
+#include
+
+class DTPrimitive {
+public:
+ DTPrimitive();
+ DTPrimitive(std::shared_ptr& ptr);
+ DTPrimitive(DTPrimitive* ptr);
+ virtual ~DTPrimitive();
+
+ bool isValidTime();
+ float wireHorizPos();
+
+ void setTimeCorrection(int time) { timeCorrection_ = time; };
+ void setTDCTimeStamp(int tstamp) { tdcTimeStamp_ = tstamp; };
+ void setOrbit(int orb) { orbit_ = orb; }
+ void setPayload(double hitTag, int idx) { this->payLoad_[idx] = hitTag; };
+ void setChannelId(int channel) { channelId_ = channel; };
+ void setLayerId(int layer) { layerId_ = layer; };
+ void setCameraId(int camera) { cameraId_ = camera; };
+ void setSuperLayerId(int lay) { superLayerId_ = lay; };
+ void setLaterality(cmsdt::LATERAL_CASES lat) { laterality_ = lat; };
+
+ const int timeCorrection() const { return timeCorrection_; };
+ const int tdcTimeStamp() const { return tdcTimeStamp_; };
+ const int orbit() const { return orbit_; };
+ const int tdcTimeStampNoOffset() const { return tdcTimeStamp_ - timeCorrection_; };
+ const double payLoad(int idx) const { return payLoad_[idx]; };
+ const int channelId() const { return channelId_; };
+ const int layerId() const { return layerId_; };
+ const int cameraId() const { return cameraId_; };
+ const int superLayerId() const { return superLayerId_; };
+ const cmsdt::LATERAL_CASES laterality() const { return laterality_; };
+
+private:
+ int cameraId_; // Chamber ID
+ int superLayerId_; // SL ID
+ int layerId_; // Layer ID
+ int channelId_; // Wire number
+ cmsdt::LATERAL_CASES laterality_; // LEFT, RIGHT, NONE
+
+ int timeCorrection_;
+ int tdcTimeStamp_;
+ int orbit_;
+ double payLoad_[cmsdt::PAYLOAD_ENTRIES];
+};
+
+typedef std::vector DTPrimitives;
+typedef std::shared_ptr DTPrimitivePtr;
+typedef std::vector DTPrimitivePtrs;
+
+#endif
diff --git a/L1Trigger/DTTriggerPhase2/interface/HoughGrouping.h b/L1Trigger/DTTriggerPhase2/interface/HoughGrouping.h
new file mode 100644
index 0000000000000..61d498d0d39ac
--- /dev/null
+++ b/L1Trigger/DTTriggerPhase2/interface/HoughGrouping.h
@@ -0,0 +1,106 @@
+#ifndef L1Trigger_DTTriggerPhase2_HoughGrouping_h
+#define L1Trigger_DTTriggerPhase2_HoughGrouping_h
+
+// System / std headers
+#include
+#include
+#include
+#include
+#include
+
+// Other headers
+#include "L1Trigger/DTTriggerPhase2/interface/MuonPath.h"
+#include "L1Trigger/DTTriggerPhase2/interface/DTprimitive.h"
+#include "L1Trigger/DTTriggerPhase2/interface/MotherGrouping.h"
+
+// ===============================================================================
+// Class declarations
+// ===============================================================================
+struct ProtoCand {
+ unsigned short int nLayersWithHits_; // 0: # of layers with hits.
+ std::vector isThereHitInLayer_; // 1: # of hits of high quality (the expected line crosses the cell).
+ std::vector
+ isThereNeighBourHitInLayer_; // 2: # of hits of low quality (the expected line is in a neighbouring cell).
+ unsigned short int nHitsDiff_; // 3: absolute diff. between the number of hits in SL1 and SL3.
+ std::vector xDistToPattern_; // 4: absolute distance to all hits of the segment.
+ DTPrimitives dtHits_; // 5: DTPrimitive of the candidate.
+};
+
+typedef std::pair PointInPlane;
+typedef std::vector PointsInPlane;
+typedef std::tuple PointTuple;
+typedef std::vector PointTuples;
+typedef std::map PointMap;
+
+class HoughGrouping : public MotherGrouping {
+public:
+ // Constructors and destructor
+ HoughGrouping(const edm::ParameterSet& pset, edm::ConsumesCollector& iC);
+ ~HoughGrouping() override;
+
+ // Main methods
+ void initialise(const edm::EventSetup& iEventSetup) override;
+ void run(edm::Event& iEvent,
+ const edm::EventSetup& iEventSetup,
+ const DTDigiCollection& digis,
+ MuonPathPtrs& outMpath) override;
+ void finish() override;
+
+ // Other public methods
+ // Public attributes
+
+private:
+ // Private methods
+ void resetAttributes();
+ void resetPosElementsOfLinespace();
+
+ void obtainGeometricalBorders(const DTLayer* lay);
+
+ void doHoughTransform();
+
+ PointsInPlane getMaximaVector();
+ PointsInPlane findTheMaxima(PointTuples& inputvec);
+
+ PointInPlane getTwoDelta(const PointTuple& pair1, const PointTuple& pair2);
+ PointInPlane getAveragePoint(const PointTuples& inputvec,
+ unsigned short int firstindex,
+ const std::vector& indexlist);
+ PointInPlane transformPair(const PointInPlane& inputpair);
+
+ ProtoCand associateHits(const DTChamber* thechamb, double m, double n);
+
+ void orderAndFilter(std::vector& invector, MuonPathPtrs& outMuonPath);
+
+ void setDifferenceBetweenSL(ProtoCand& tupl);
+ bool areThereEnoughHits(const ProtoCand& tupl);
+
+ // Private attributes
+ bool debug_, allowUncorrelatedPatterns_;
+ unsigned short int minNLayerHits_, minSingleSLHitsMax_, minSingleSLHitsMin_, minUncorrelatedHits_, upperNumber_,
+ lowerNumber_;
+ double angletan_, anglebinwidth_, posbinwidth_, maxdeltaAngDeg_, maxdeltaPos_, maxDistanceToWire_;
+
+ DTGeometry const* dtGeo_;
+ edm::ESGetToken dtGeomH;
+ DTChamberId TheChambId;
+
+ double maxrads_, minangle_, oneanglebin_;
+ double xlowlim_, xhighlim_, zlowlim_, zhighlim_;
+ double maxdeltaAng_;
+
+ unsigned short int anglebins_, halfanglebins_, spacebins_;
+ unsigned short int idigi_, nhits_;
+ unsigned short int thestation_, thesector_;
+ short int thewheel_;
+
+ std::vector> linespace_;
+
+ PointMap anglemap_;
+ PointMap posmap_;
+ std::map digimap_[8];
+
+ PointsInPlane maxima_;
+ PointsInPlane hitvec_;
+};
+
+#endif
diff --git a/L1Trigger/DTTriggerPhase2/interface/InitialGrouping.h b/L1Trigger/DTTriggerPhase2/interface/InitialGrouping.h
new file mode 100644
index 0000000000000..1a8bb034b83bb
--- /dev/null
+++ b/L1Trigger/DTTriggerPhase2/interface/InitialGrouping.h
@@ -0,0 +1,98 @@
+#ifndef Phase2L1Trigger_DTTrigger_InitialGrouping_h
+#define Phase2L1Trigger_DTTrigger_InitialGrouping_h
+
+#include "FWCore/ParameterSet/interface/ParameterSet.h"
+#include "FWCore/MessageLogger/interface/MessageLogger.h"
+
+#include "DataFormats/MuonDetId/interface/DTChamberId.h"
+#include "DataFormats/MuonDetId/interface/DTSuperLayerId.h"
+#include "DataFormats/MuonDetId/interface/DTLayerId.h"
+#include "DataFormats/MuonDetId/interface/DTWireId.h"
+#include "DataFormats/DTDigi/interface/DTDigiCollection.h"
+
+#include "L1Trigger/DTTriggerPhase2/interface/MuonPath.h"
+#include "L1Trigger/DTTriggerPhase2/interface/constants.h"
+
+#include "L1Trigger/DTTriggerPhase2/interface/MotherGrouping.h"
+
+#include
+#include
+
+// ===============================================================================
+// Previous definitions and declarations
+// ===============================================================================
+
+/*
+ Channels are labeled following next schema:
+ ---------------------------------
+ | 6 | 7 | 8 | 9 |
+ ---------------------------------
+ | 3 | 4 | 5 |
+ -------------------------
+ | 1 | 2 |
+ -----------------
+ | 0 |
+ ---------
+*/
+
+namespace dtamgrouping {
+ /* Cell's combination, following previous labeling, to obtain every possible muon's path.
+ Others cells combinations imply non straight paths */
+ constexpr int CHANNELS_PATH_ARRANGEMENTS[8][4] = {
+ {0, 1, 3, 6}, {0, 1, 3, 7}, {0, 1, 4, 7}, {0, 1, 4, 8}, {0, 2, 4, 7}, {0, 2, 4, 8}, {0, 2, 5, 8}, {0, 2, 5, 9}};
+
+ /* For each of the previous cell's combinations, this array stores the associated cell's
+ displacement, relative to lower layer cell, measured in semi-cell length units */
+
+ constexpr int CELL_HORIZONTAL_LAYOUTS[8][4] = {{0, -1, -2, -3},
+ {0, -1, -2, -1},
+ {0, -1, 0, -1},
+ {0, -1, 0, 1},
+ {0, 1, 0, -1},
+ {0, 1, 0, 1},
+ {0, 1, 2, 1},
+ {0, 1, 2, 3}};
+} // namespace dtamgrouping
+
+// ===============================================================================
+// Class declarations
+// ===============================================================================
+
+class InitialGrouping : public MotherGrouping {
+public:
+ // Constructors and destructor
+ InitialGrouping(const edm::ParameterSet& pset, edm::ConsumesCollector& iC);
+ ~InitialGrouping() override;
+
+ // Main methods
+ void initialise(const edm::EventSetup& iEventSetup) override;
+ void run(edm::Event& iEvent,
+ const edm::EventSetup& iEventSetup,
+ const DTDigiCollection& digis,
+ MuonPathPtrs& outMpath) override;
+ void finish() override;
+
+ // Other public methods
+
+ // Public attributes
+
+private:
+ // Private methods
+ void setInChannels(const DTDigiCollection* digi, int sl);
+ void selectInChannels(int baseCh);
+ void resetPrvTDCTStamp(void);
+ void mixChannels(int sl, int pathId, MuonPathPtrs& outMpath);
+ bool notEnoughDataInChannels(void);
+ bool isEqualComb2Previous(DTPrimitives& ptr);
+
+ // Private attributes
+ bool debug_;
+
+ DTPrimitives muxInChannels_[cmsdt::NUM_CELLS_PER_BLOCK];
+ DTPrimitives channelIn_[cmsdt::NUM_LAYERS][cmsdt::NUM_CH_PER_LAYER];
+ DTPrimitives chInDummy_;
+ int prevTDCTimeStamps_[4];
+ int currentBaseChannel_;
+};
+
+#endif
diff --git a/L1Trigger/DTTriggerPhase2/interface/MPFilter.h b/L1Trigger/DTTriggerPhase2/interface/MPFilter.h
new file mode 100644
index 0000000000000..95df42c84c4f5
--- /dev/null
+++ b/L1Trigger/DTTriggerPhase2/interface/MPFilter.h
@@ -0,0 +1,55 @@
+#ifndef Phase2L1Trigger_DTTrigger_MPFilter_h
+#define Phase2L1Trigger_DTTrigger_MPFilter_h
+
+#include "FWCore/Framework/interface/ESHandle.h"
+#include "FWCore/Framework/interface/Event.h"
+#include "FWCore/Framework/interface/Frameworkfwd.h"
+#include "FWCore/Framework/interface/EventSetup.h"
+#include "FWCore/ParameterSet/interface/ParameterSet.h"
+
+#include "L1Trigger/DTTriggerPhase2/interface/MuonPath.h"
+#include "L1Trigger/DTTriggerPhase2/interface/constants.h"
+#include "L1Trigger/DTTriggerPhase2/interface/MPFilter.h"
+#include "Geometry/Records/interface/MuonGeometryRecord.h"
+
+#include "Geometry/DTGeometry/interface/DTGeometry.h"
+#include "Geometry/DTGeometry/interface/DTLayer.h"
+
+#include
+#include
+
+// ===============================================================================
+// Previous definitions and declarations
+// ===============================================================================
+
+// ===============================================================================
+// Class declarations
+// ===============================================================================
+
+class MPFilter {
+public:
+ // Constructors and destructor
+ MPFilter(const edm::ParameterSet& pset);
+ virtual ~MPFilter();
+
+ // Main methods
+ virtual void initialise(const edm::EventSetup& iEventSetup) = 0;
+ virtual void run(edm::Event& iEvent,
+ const edm::EventSetup& iEventSetup,
+ std::vector& inMPath,
+ std::vector& outMPath) = 0;
+ virtual void run(edm::Event& iEvent,
+ const edm::EventSetup& iEventSetup,
+ MuonPathPtrs& inMPath,
+ MuonPathPtrs& outMPath) = 0;
+
+ virtual void finish() = 0;
+
+ // Other public methods
+
+private:
+ // Private attributes
+ bool debug_;
+};
+
+#endif
diff --git a/L1Trigger/DTTriggerPhase2/interface/MPQualityEnhancerFilter.h b/L1Trigger/DTTriggerPhase2/interface/MPQualityEnhancerFilter.h
new file mode 100644
index 0000000000000..11b5624769b93
--- /dev/null
+++ b/L1Trigger/DTTriggerPhase2/interface/MPQualityEnhancerFilter.h
@@ -0,0 +1,55 @@
+#ifndef Phase2L1Trigger_DTTrigger_MPQualityEnhancerFilter_h
+#define Phase2L1Trigger_DTTrigger_MPQualityEnhancerFilter_h
+
+#include "L1Trigger/DTTriggerPhase2/interface/MPFilter.h"
+
+#include
+#include
+
+// ===============================================================================
+// Previous definitions and declarations
+// ===============================================================================
+
+// ===============================================================================
+// Class declarations
+// ===============================================================================
+
+class MPQualityEnhancerFilter : public MPFilter {
+public:
+ // Constructors and destructor
+ MPQualityEnhancerFilter(const edm::ParameterSet &pset);
+ ~MPQualityEnhancerFilter() override;
+
+ // Main methods
+ void initialise(const edm::EventSetup &iEventSetup) override;
+ void run(edm::Event &iEvent,
+ const edm::EventSetup &iEventSetup,
+ std::vector &inMPath,
+ std::vector &outMPath) override;
+ void run(edm::Event &iEvent,
+ const edm::EventSetup &iEventSetup,
+ MuonPathPtrs &inMPath,
+ MuonPathPtrs &outMPath) override{};
+
+ void finish() override;
+
+ // Other public methods
+
+ // Public attributes
+ int areCousins(cmsdt::metaPrimitive mp1, cmsdt::metaPrimitive mp2);
+ int rango(cmsdt::metaPrimitive mp);
+ void printmP(cmsdt::metaPrimitive mP);
+
+private:
+ // Private methods
+ void filterCousins(std::vector &inMPath, std::vector &outMPath);
+ void refilteringCousins(std::vector &inMPath, std::vector &outMPath);
+ void filterTanPhi(std::vector &inMPath, std::vector &outMPath);
+ void filterUnique(std::vector &inMPath, std::vector &outMPath);
+
+ // Private attributes
+ bool debug_;
+ bool filter_cousins_;
+};
+
+#endif
diff --git a/L1Trigger/DTTriggerPhase2/interface/MPRedundantFilter.h b/L1Trigger/DTTriggerPhase2/interface/MPRedundantFilter.h
new file mode 100644
index 0000000000000..4ba9d7eab92e4
--- /dev/null
+++ b/L1Trigger/DTTriggerPhase2/interface/MPRedundantFilter.h
@@ -0,0 +1,48 @@
+#ifndef Phase2L1Trigger_DTTrigger_MPRedundantFilter_h
+#define Phase2L1Trigger_DTTrigger_MPRedundantFilter_h
+
+#include "L1Trigger/DTTriggerPhase2/interface/MPFilter.h"
+
+#include
+#include
+#include
+
+// ===============================================================================
+// Previous definitions and declarations
+// ===============================================================================
+
+// ===============================================================================
+// Class declarations
+// ===============================================================================
+
+class MPRedundantFilter : public MPFilter {
+public:
+ // Constructors and destructor
+ MPRedundantFilter(const edm::ParameterSet& pset);
+ ~MPRedundantFilter() override;
+
+ // Main methods
+ void initialise(const edm::EventSetup& iEventSetup) override;
+ void run(edm::Event& iEvent,
+ const edm::EventSetup& iEventSetup,
+ std::vector& inMPath,
+ std::vector& outMPath) override{};
+ void run(edm::Event& iEvent,
+ const edm::EventSetup& iEventSetup,
+ MuonPathPtrs& inMPath,
+ MuonPathPtrs& outMPath) override;
+ void finish() override { buffer_.clear(); };
+
+ // Other public methods
+
+private:
+ void filter(MuonPathPtr& mpath, MuonPathPtrs& outMPaths);
+ bool isInBuffer(MuonPathPtr& mpath);
+
+ // Private attributes
+ bool debug_;
+ unsigned int maxBufferSize_;
+ std::deque buffer_;
+};
+
+#endif
diff --git a/L1Trigger/DTTriggerPhase2/interface/MotherGrouping.h b/L1Trigger/DTTriggerPhase2/interface/MotherGrouping.h
new file mode 100644
index 0000000000000..fbab714a359c5
--- /dev/null
+++ b/L1Trigger/DTTriggerPhase2/interface/MotherGrouping.h
@@ -0,0 +1,54 @@
+#ifndef Phase2L1Trigger_DTTrigger_MotherGrouping_h
+#define Phase2L1Trigger_DTTrigger_MotherGrouping_h
+
+#include "FWCore/Framework/interface/ESHandle.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 "DataFormats/DTDigi/interface/DTDigiCollection.h"
+#include "L1Trigger/DTTriggerPhase2/interface/MuonPath.h"
+#include "L1Trigger/DTTriggerPhase2/interface/constants.h"
+
+#include "Geometry/Records/interface/MuonGeometryRecord.h"
+#include "Geometry/DTGeometry/interface/DTGeometry.h"
+#include "Geometry/DTGeometry/interface/DTLayer.h"
+
+#include
+#include
+
+// ===============================================================================
+// Previous definitions and declarations
+// ===============================================================================
+
+// ===============================================================================
+// Class declarations
+// ===============================================================================
+
+class MotherGrouping {
+public:
+ // Constructors and destructor
+ MotherGrouping(const edm::ParameterSet& pset, edm::ConsumesCollector& iC);
+ virtual ~MotherGrouping();
+
+ // Main methods
+ virtual void initialise(const edm::EventSetup& iEventSetup);
+ virtual void run(edm::Event& iEvent,
+ const edm::EventSetup& iEventSetup,
+ const DTDigiCollection& digis,
+ MuonPathPtrs& outMpath);
+ virtual void finish();
+
+ // Other public methods
+
+ // Public attributes
+
+private:
+ // Private methods
+
+ // Private attributes
+ bool debug_;
+};
+
+#endif
diff --git a/L1Trigger/DTTriggerPhase2/interface/MuonPath.h b/L1Trigger/DTTriggerPhase2/interface/MuonPath.h
new file mode 100644
index 0000000000000..cb5a268355628
--- /dev/null
+++ b/L1Trigger/DTTriggerPhase2/interface/MuonPath.h
@@ -0,0 +1,124 @@
+#ifndef L1Trigger_DTTriggerPhase2_MuonPath_h
+#define L1Trigger_DTTriggerPhase2_MuonPath_h
+#include
+#include
+
+#include "L1Trigger/DTTriggerPhase2/interface/DTprimitive.h"
+
+class MuonPath {
+public:
+ MuonPath();
+ MuonPath(DTPrimitivePtrs &ptrPrimitive, int prup = 0, int prdw = 0);
+ MuonPath(DTPrimitives &ptrPrimitive, int prup = 0, int prdw = 0);
+ MuonPath(std::shared_ptr &ptr);
+ virtual ~MuonPath() {}
+
+ // setter methods
+ void setPrimitive(DTPrimitivePtr &ptr, int layer);
+ void setNPrimitives(short nprim) { nprimitives_ = nprim; }
+ void setNPrimitivesUp(short nprim) { nprimitivesUp_ = nprim; }
+ void setNPrimitivesDown(short nprim) { nprimitivesDown_ = nprim; }
+ void setCellHorizontalLayout(int layout[4]);
+ void setCellHorizontalLayout(const int *layout);
+ void setBaseChannelId(int bch) { baseChannelId_ = bch; }
+ void setQuality(cmsdt::MP_QUALITY qty) { quality_ = qty; }
+ void setBxTimeValue(int time);
+ void setLateralComb(cmsdt::LATERAL_CASES latComb[4]);
+ void setLateralComb(const cmsdt::LATERAL_CASES *latComb);
+ void setLateralCombFromPrimitives(void);
+
+ void setHorizPos(float pos) { horizPos_ = pos; }
+ void setTanPhi(float tanPhi) { tanPhi_ = tanPhi; }
+ void setChiSquare(float chi) { chiSquare_ = chi; }
+ void setPhi(float phi) { phi_ = phi; }
+ void setPhiB(float phib) { phiB_ = phib; }
+ void setXCoorCell(float x, int cell) { xCoorCell_[cell] = x; }
+ void setDriftDistance(float dx, int cell) { xDriftDistance_[cell] = dx; }
+ void setXWirePos(float x, int cell) { xWirePos_[cell] = x; }
+ void setZWirePos(float z, int cell) { zWirePos_[cell] = z; }
+ void setTWireTDC(float t, int cell) { tWireTDC_[cell] = t; }
+ void setRawId(uint32_t id) { rawId_ = id; }
+
+ // getter methods
+ DTPrimitivePtr primitive(int layer) const { return prim_[layer]; }
+ short nprimitives() const { return nprimitives_; }
+ short nprimitivesDown() const { return nprimitivesDown_; }
+ short nprimitivesUp() const { return nprimitivesUp_; }
+ const int *cellLayout() const { return cellLayout_; }
+ int baseChannelId() const { return baseChannelId_; }
+ cmsdt::MP_QUALITY quality() const { return quality_; }
+ int bxTimeValue() const { return bxTimeValue_; }
+ int bxNumId() const { return bxNumId_; }
+ float tanPhi() const { return tanPhi_; }
+ const cmsdt::LATERAL_CASES *lateralComb() const { return (lateralComb_); }
+ float horizPos() const { return horizPos_; }
+ float chiSquare() const { return chiSquare_; }
+ float phi() const { return phi_; }
+ float phiB() const { return phiB_; }
+ float xCoorCell(int cell) const { return xCoorCell_[cell]; }
+ float xDriftDistance(int cell) const { return xDriftDistance_[cell]; }
+ float xWirePos(int cell) const { return xWirePos_[cell]; }
+ float zWirePos(int cell) const { return zWirePos_[cell]; }
+ float tWireTDC(int cell) const { return tWireTDC_[cell]; }
+ uint32_t rawId() const { return rawId_; }
+
+ // Other methods
+ bool isEqualTo(MuonPath *ptr);
+ bool isAnalyzable();
+ bool completeMP();
+
+private:
+ //------------------------------------------------------------------
+ //--- MuonPath's data
+ //------------------------------------------------------------------
+ /*
+ Primitives that make up the path. The 0th position holds the channel ID of
+ the lower layer. The order is critical.
+ */
+ DTPrimitivePtrs prim_; //ENSURE that there are no more than 4-8 prims
+ short nprimitives_;
+ short nprimitivesUp_;
+ short nprimitivesDown_;
+
+ /* Horizontal position of each cell (one per layer), in half-cell units,
+ with respect of the lower layer (layer 0).
+ */
+ int cellLayout_[cmsdt::NUM_LAYERS];
+ int baseChannelId_;
+
+ //------------------------------------------------------------------
+ //--- Fit results:
+ //------------------------------------------------------------------
+ /* path quality */
+ cmsdt::MP_QUALITY quality_;
+
+ /* Lateral combination */
+ cmsdt::LATERAL_CASES lateralComb_[cmsdt::NUM_LAYERS];
+
+ /* BX time value with respect to BX0 of the orbit */
+ int bxTimeValue_;
+
+ /* BX number in the orbit */
+ int bxNumId_;
+
+ /* Cell parameters */
+ float xCoorCell_[cmsdt::NUM_LAYERS_2SL]; // Horizontal position of the hit in each cell
+ float xDriftDistance_[cmsdt::NUM_LAYERS_2SL]; // Drift distance on the cell (absolute value)
+ float xWirePos_[cmsdt::NUM_LAYERS_2SL];
+ float zWirePos_[cmsdt::NUM_LAYERS_2SL];
+ float tWireTDC_[cmsdt::NUM_LAYERS_2SL];
+
+ float tanPhi_;
+ float horizPos_;
+ float chiSquare_;
+ float phi_;
+ float phiB_;
+
+ uint32_t rawId_;
+};
+
+typedef std::vector MuonPaths;
+typedef std::shared_ptr MuonPathPtr;
+typedef std::vector MuonPathPtrs;
+
+#endif
diff --git a/L1Trigger/DTTriggerPhase2/interface/MuonPathAnalyzer.h b/L1Trigger/DTTriggerPhase2/interface/MuonPathAnalyzer.h
new file mode 100644
index 0000000000000..159a6289273e0
--- /dev/null
+++ b/L1Trigger/DTTriggerPhase2/interface/MuonPathAnalyzer.h
@@ -0,0 +1,67 @@
+#ifndef Phase2L1Trigger_DTTrigger_MuonPathAnalyzer_h
+#define Phase2L1Trigger_DTTrigger_MuonPathAnalyzer_h
+
+#include "FWCore/Framework/interface/ESHandle.h"
+#include "FWCore/Utilities/interface/ESGetToken.h"
+#include "FWCore/Framework/interface/ConsumesCollector.h"
+#include "FWCore/Framework/interface/FrameworkfwdMostUsed.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 "DataFormats/MuonDetId/interface/DTChamberId.h"
+#include "DataFormats/MuonDetId/interface/DTSuperLayerId.h"
+#include "DataFormats/MuonDetId/interface/DTLayerId.h"
+#include "DataFormats/MuonDetId/interface/DTWireId.h"
+
+#include "L1Trigger/DTTriggerPhase2/interface/MuonPath.h"
+#include "L1Trigger/DTTriggerPhase2/interface/constants.h"
+
+#include "Geometry/Records/interface/MuonGeometryRecord.h"
+#include "Geometry/DTGeometry/interface/DTGeometry.h"
+
+#include
+#include
+
+// ===============================================================================
+// Previous definitions and declarations
+// ===============================================================================
+
+// ===============================================================================
+// Class declarations
+// ===============================================================================
+
+class MuonPathAnalyzer {
+public:
+ // Constructors and destructor
+ MuonPathAnalyzer(const edm::ParameterSet& pset, edm::ConsumesCollector& iC);
+ virtual ~MuonPathAnalyzer();
+
+ // Main methods
+ virtual void initialise(const edm::EventSetup& iEventSetup);
+ virtual void run(edm::Event& iEvent,
+ const edm::EventSetup& iEventSetup,
+ MuonPathPtrs& inMpath,
+ std::vector& metaPrimitives) = 0;
+ virtual void run(edm::Event& iEvent,
+ const edm::EventSetup& iEventSetup,
+ MuonPathPtrs& inMpath,
+ MuonPathPtrs& outMPath) = 0;
+
+ virtual void finish();
+
+ // Other public methods
+
+ // Public attributes
+
+private:
+ // Private methods
+
+ // Private attributes
+ bool debug_;
+};
+
+#endif
diff --git a/L1Trigger/DTTriggerPhase2/interface/MuonPathAnalyzerInChamber.h b/L1Trigger/DTTriggerPhase2/interface/MuonPathAnalyzerInChamber.h
new file mode 100644
index 0000000000000..3baf7556d7309
--- /dev/null
+++ b/L1Trigger/DTTriggerPhase2/interface/MuonPathAnalyzerInChamber.h
@@ -0,0 +1,83 @@
+#ifndef L1Trigger_DTTriggerPhase2_MuonPathAnalyzerInChamber_h
+#define L1Trigger_DTTriggerPhase2_MuonPathAnalyzerInChamber_h
+
+#include "L1Trigger/DTTriggerPhase2/interface/MuonPathAnalyzer.h"
+
+// ===============================================================================
+// Previous definitions and declarations
+// ===============================================================================
+namespace {
+ constexpr int NLayers = 8;
+ typedef std::array TLateralities;
+} // namespace
+// ===============================================================================
+// Class declarations
+// ===============================================================================
+
+class MuonPathAnalyzerInChamber : public MuonPathAnalyzer {
+public:
+ // Constructors and destructor
+ MuonPathAnalyzerInChamber(const edm::ParameterSet &pset, edm::ConsumesCollector &iC);
+ ~MuonPathAnalyzerInChamber() override;
+
+ // Main methods
+ void initialise(const edm::EventSetup &iEventSetup) override;
+ void run(edm::Event &iEvent,
+ const edm::EventSetup &iEventSetup,
+ MuonPathPtrs &inMpath,
+ std::vector &metaPrimitives) override {}
+ void run(edm::Event &iEvent,
+ const edm::EventSetup &iEventSetup,
+ MuonPathPtrs &inMpath,
+ MuonPathPtrs &outMPath) override;
+
+ void finish() override;
+
+ // Other public methods
+ void setBxTolerance(int t) { bxTolerance_ = t; };
+ void setMinHits4Fit(int h) { minHits4Fit_ = h; };
+ void setChiSquareThreshold(float ch2Thr) { chiSquareThreshold_ = ch2Thr; };
+ void setMinimumQuality(cmsdt::MP_QUALITY q) {
+ if (minQuality_ >= cmsdt::LOWQGHOST)
+ minQuality_ = q;
+ };
+
+ int bxTolerance(void) { return bxTolerance_; };
+ int minHits4Fit(void) { return minHits4Fit_; };
+ cmsdt::MP_QUALITY minQuality(void) { return minQuality_; };
+
+ bool hasPosRF(int wh, int sec) { return wh > 0 || (wh == 0 && sec % 4 > 1); };
+
+ // Public attributes
+ DTGeometry const *dtGeo_;
+ edm::ESGetToken dtGeomH;
+
+ //shift
+ std::map shiftinfo_;
+
+private:
+ // Private methods
+ void analyze(MuonPathPtr &inMPath, MuonPathPtrs &outMPaths);
+
+ void setCellLayout(MuonPathPtr &mpath);
+ void buildLateralities(MuonPathPtr &mpath);
+ void setLateralitiesInMP(MuonPathPtr &mpath, TLateralities lat);
+ void setWirePosAndTimeInMP(MuonPathPtr &mpath);
+ void calculateFitParameters(MuonPathPtr &mpath, TLateralities lat, int present_layer[NLayers]);
+
+ void evaluateQuality(MuonPathPtr &mPath);
+ int totalNumValLateralities_;
+ std::vector lateralities_;
+ std::vector latQuality_;
+
+ bool debug_;
+ double chi2Th_;
+ edm::FileInPath shift_filename_;
+ int bxTolerance_;
+ cmsdt::MP_QUALITY minQuality_;
+ float chiSquareThreshold_;
+ short minHits4Fit_;
+ int cellLayout_[NLayers];
+};
+
+#endif
diff --git a/L1Trigger/DTTriggerPhase2/interface/MuonPathAnalyzerPerSL.h b/L1Trigger/DTTriggerPhase2/interface/MuonPathAnalyzerPerSL.h
new file mode 100644
index 0000000000000..7352ea9677bdd
--- /dev/null
+++ b/L1Trigger/DTTriggerPhase2/interface/MuonPathAnalyzerPerSL.h
@@ -0,0 +1,103 @@
+#ifndef L1Trigger_DTTriggerPhase2_MuonPathAnalyzerPerSL_h
+#define L1Trigger_DTTriggerPhase2_MuonPathAnalyzerPerSL_h
+
+#include "L1Trigger/DTTriggerPhase2/interface/MuonPathAnalyzer.h"
+
+// ===============================================================================
+// Class declarations
+// ===============================================================================
+
+class MuonPathAnalyzerPerSL : public MuonPathAnalyzer {
+public:
+ // Constructors and destructor
+ MuonPathAnalyzerPerSL(const edm::ParameterSet &pset, edm::ConsumesCollector &iC);
+ ~MuonPathAnalyzerPerSL() override;
+
+ // Main methods
+ void initialise(const edm::EventSetup &iEventSetup) override;
+ void run(edm::Event &iEvent,
+ const edm::EventSetup &iEventSetup,
+ MuonPathPtrs &inMpath,
+ std::vector &metaPrimitives) override;
+ void run(edm::Event &iEvent,
+ const edm::EventSetup &iEventSetup,
+ MuonPathPtrs &inMpath,
+ MuonPathPtrs &outMPath) override{};
+
+ void finish() override;
+
+ // Other public methods
+ void setBXTolerance(int t) { bxTolerance_ = t; };
+ int bxTolerance(void) { return bxTolerance_; };
+
+ void setChiSquareThreshold(float ch2Thr) { chiSquareThreshold_ = ch2Thr; };
+
+ void setMinQuality(cmsdt::MP_QUALITY q) {
+ if (minQuality_ >= cmsdt::LOWQGHOST)
+ minQuality_ = q;
+ };
+ cmsdt::MP_QUALITY minQuality(void) { return minQuality_; };
+
+ bool hasPosRF(int wh, int sec) { return wh > 0 || (wh == 0 && sec % 4 > 1); };
+
+ // Public attributes
+ DTGeometry const *dtGeo_;
+ edm::ESGetToken dtGeomH;
+
+ //shift
+ edm::FileInPath shift_filename_;
+ std::map shiftinfo_;
+
+ int chosen_sl_;
+
+private:
+ // Private methods
+ void analyze(MuonPathPtr &inMPath, std::vector &metaPrimitives);
+
+ void setCellLayout(const int layout[cmsdt::NUM_LAYERS]);
+ void buildLateralities(void);
+ bool isStraightPath(cmsdt::LATERAL_CASES sideComb[cmsdt::NUM_LAYERS]);
+
+ void evaluatePathQuality(MuonPathPtr &mPath);
+ void evaluateLateralQuality(int latIdx, MuonPathPtr &mPath, cmsdt::LATQ_TYPE *latQuality);
+ void validate(cmsdt::LATERAL_CASES sideComb[3], int layerIndex[3], MuonPathPtr &mPath, cmsdt::PARTIAL_LATQ_TYPE *latq);
+
+ int eqMainBXTerm(cmsdt::LATERAL_CASES sideComb[2], int layerIdx[2], MuonPathPtr &mPath);
+
+ int eqMainTerm(cmsdt::LATERAL_CASES sideComb[2], int layerIdx[2], MuonPathPtr &mPath, int bxValue);
+
+ void lateralCoeficients(cmsdt::LATERAL_CASES sideComb[2], int *coefs);
+ bool sameBXValue(cmsdt::PARTIAL_LATQ_TYPE *latq);
+
+ void calculatePathParameters(MuonPathPtr &mPath);
+ void calcTanPhiXPosChamber(MuonPathPtr &mPath);
+ void calcCellDriftAndXcoor(MuonPathPtr &mPath);
+ void calcChiSquare(MuonPathPtr &mPath);
+
+ void calcTanPhiXPosChamber3Hits(MuonPathPtr &mPath);
+ void calcTanPhiXPosChamber4Hits(MuonPathPtr &mPath);
+
+ int omittedHit(int idx);
+
+ // Private attributes
+
+ static const int LAYER_ARRANGEMENTS_[cmsdt::NUM_LAYERS][cmsdt::NUM_CELL_COMB];
+ cmsdt::LATERAL_CASES lateralities_[cmsdt::NUM_LATERALITIES][cmsdt::NUM_LAYERS];
+ cmsdt::LATQ_TYPE latQuality_[cmsdt::NUM_LATERALITIES];
+
+ int totalNumValLateralities_;
+
+ int bxTolerance_;
+ cmsdt::MP_QUALITY minQuality_;
+ float chiSquareThreshold_;
+ bool debug_;
+ double chi2Th_;
+ double chi2corTh_;
+ double tanPhiTh_;
+ int cellLayout_[cmsdt::NUM_LAYERS];
+ bool use_LSB_;
+ double tanPsi_precision_;
+ double x_precision_;
+};
+
+#endif
diff --git a/L1Trigger/DTTriggerPhase2/interface/MuonPathAssociator.h b/L1Trigger/DTTriggerPhase2/interface/MuonPathAssociator.h
new file mode 100644
index 0000000000000..8586f54f3b96b
--- /dev/null
+++ b/L1Trigger/DTTriggerPhase2/interface/MuonPathAssociator.h
@@ -0,0 +1,92 @@
+#ifndef Phase2L1Trigger_DTTrigger_MuonPathAssociator_h
+#define Phase2L1Trigger_DTTrigger_MuonPathAssociator_h
+
+#include "FWCore/Framework/interface/Event.h"
+#include "FWCore/Framework/interface/EventSetup.h"
+#include "FWCore/Framework/interface/Run.h"
+#include "FWCore/ParameterSet/interface/ParameterSet.h"
+#include "FWCore/Framework/interface/FrameworkfwdMostUsed.h"
+
+#include "DataFormats/MuonDetId/interface/DTChamberId.h"
+#include "DataFormats/MuonDetId/interface/DTSuperLayerId.h"
+#include "DataFormats/MuonDetId/interface/DTLayerId.h"
+#include "DataFormats/MuonDetId/interface/DTWireId.h"
+#include "DataFormats/DTDigi/interface/DTDigiCollection.h"
+
+#include "L1Trigger/DTTriggerPhase2/interface/MuonPath.h"
+#include "L1Trigger/DTTriggerPhase2/interface/constants.h"
+
+#include "Geometry/Records/interface/MuonGeometryRecord.h"
+#include "Geometry/DTGeometry/interface/DTGeometry.h"
+#include "Geometry/DTGeometry/interface/DTLayer.h"
+
+#include
+#include
+
+// ===============================================================================
+// Previous definitions and declarations
+// ===============================================================================
+
+// ===============================================================================
+// Class declarations
+// ===============================================================================
+
+class MuonPathAssociator {
+public:
+ // Constructors and destructor
+ MuonPathAssociator(const edm::ParameterSet &pset, edm::ConsumesCollector &iC);
+ ~MuonPathAssociator();
+
+ // Main methods
+ void initialise(const edm::EventSetup &iEventSetup);
+ void run(edm::Event &iEvent,
+ const edm::EventSetup &iEventSetup,
+ edm::Handle digis,
+ std::vector &inMPaths,
+ std::vector &outMPaths);
+
+ void finish();
+
+ // Other public methods
+
+ bool shareFit(cmsdt::metaPrimitive first, cmsdt::metaPrimitive second);
+ bool isNotAPrimo(cmsdt::metaPrimitive first, cmsdt::metaPrimitive second);
+ void removeSharingFits(std::vector &chamberMPaths,
+ std::vector &allMPaths);
+ void removeSharingHits(std::vector &firstMPaths,
+ std::vector &secondMPaths,
+ std::vector &allMPaths);
+ void printmPC(cmsdt::metaPrimitive mP);
+
+ // Public attributes
+ DTGeometry const *dtGeo_;
+ edm::ESGetToken dtGeomH_;
+
+private:
+ // Private methods
+ void correlateMPaths(edm::Handle digis,
+ std::vector &inMPaths,
+ std::vector &outMPaths);
+
+ bool hasPosRF(int wh, int sec) { return wh > 0 || (wh == 0 && sec % 4 > 1); }
+
+ // Private attributes
+ bool debug_;
+ bool clean_chi2_correlation_;
+ bool useBX_correlation_;
+ bool allow_confirmation_;
+ double dT0_correlate_TP_;
+ double dBX_correlate_TP_;
+ double dTanPsi_correlate_TP_;
+ double minx_match_2digis_;
+ double chi2corTh_;
+ bool use_LSB_;
+ double tanPsi_precision_;
+ double x_precision_;
+
+ //shift
+ edm::FileInPath shift_filename_;
+ std::map shiftinfo_;
+};
+
+#endif
diff --git a/L1Trigger/DTTriggerPhase2/interface/PseudoBayesGrouping.h b/L1Trigger/DTTriggerPhase2/interface/PseudoBayesGrouping.h
new file mode 100644
index 0000000000000..82210d2af0acc
--- /dev/null
+++ b/L1Trigger/DTTriggerPhase2/interface/PseudoBayesGrouping.h
@@ -0,0 +1,118 @@
+#ifndef Phase2L1Trigger_DTTrigger_PseudoBayesGrouping_h
+#define Phase2L1Trigger_DTTrigger_PseudoBayesGrouping_h
+
+#include "L1Trigger/DTTriggerPhase2/interface/MotherGrouping.h"
+#include "L1Trigger/DTTriggerPhase2/interface/DTPattern.h"
+#include "L1Trigger/DTTriggerPhase2/interface/CandidateGroup.h"
+
+// ===============================================================================
+// Class declarations
+// ===============================================================================
+class PseudoBayesGrouping : public MotherGrouping {
+public:
+ // Constructors and destructor
+ PseudoBayesGrouping(const edm::ParameterSet& pset, edm::ConsumesCollector& iC);
+ ~PseudoBayesGrouping() override;
+
+ // Main methods
+ void initialise(const edm::EventSetup& iEventSetup) override;
+ void run(edm::Event& iEvent,
+ const edm::EventSetup& iEventSetup,
+ const DTDigiCollection& digis,
+ MuonPathPtrs& outMpath) override;
+ void finish() override;
+
+ // Other public methods
+
+ // Public attributes
+
+private:
+ // Private methods
+ void LoadPattern(std::vector>>::iterator itPattern);
+ void FillDigisByLayer(const DTDigiCollection* digis);
+ void CleanDigisByLayer();
+ void RecognisePatternsByLayerPairs();
+ void RecognisePatterns(std::vector digisinLDown,
+ std::vector digisinLUp,
+ std::vector patterns);
+ void ReCleanPatternsAndDigis();
+ void FillMuonPaths(MuonPathPtrs& mpaths);
+
+ //Comparator for pointer mode
+ struct CandPointGreat {
+ bool operator()(dtbayesam::CandidateGroupPtr c1, dtbayesam::CandidateGroupPtr c2) { return *c1 > *c2; }
+ };
+
+ // Private attributes
+ // Config variables
+ bool debug_;
+ std::string pattern_filename_;
+ int pidx_;
+ int minNLayerHits_;
+ int allowedVariance_;
+ bool allowDuplicates_;
+ bool allowUncorrelatedPatterns_;
+ bool setLateralities_;
+ bool saveOnPlace_;
+ int minSingleSLHitsMax_;
+ int minSingleSLHitsMin_;
+ int minUncorrelatedHits_;
+
+ //Classified digis
+ std::vector alldigis_;
+
+ std::vector digisinL0_;
+ std::vector digisinL1_;
+ std::vector digisinL2_;
+ std::vector digisinL3_;
+ std::vector digisinL4_;
+ std::vector digisinL5_;
+ std::vector digisinL6_;
+ std::vector digisinL7_;
+
+ //Preliminary matches, those can grow quite big so better not to rely on the stack
+ std::unique_ptr prelimMatches_;
+ std::unique_ptr allMatches_;
+ std::unique_ptr finalMatches_;
+
+ //Pattern related info
+ int nPatterns_;
+ std::vector allPatterns_;
+
+ std::vector L0L7Patterns_;
+ std::vector L1L7Patterns_;
+ std::vector L2L7Patterns_;
+ std::vector L3L7Patterns_;
+ std::vector L4L7Patterns_;
+ std::vector L5L7Patterns_;
+ std::vector L6L7Patterns_;
+
+ std::vector L0L6Patterns_;
+ std::vector L1L6Patterns_;
+ std::vector L2L6Patterns_;
+ std::vector L3L6Patterns_;
+ std::vector L4L6Patterns_;
+ std::vector L5L6Patterns_;
+
+ std::vector L0L5Patterns_;
+ std::vector L1L5Patterns_;
+ std::vector L2L5Patterns_;
+ std::vector L3L5Patterns_;
+ std::vector L4L5Patterns_;
+
+ std::vector L0L4Patterns_;
+ std::vector L1L4Patterns_;
+ std::vector L2L4Patterns_;
+ std::vector L3L4Patterns_;
+
+ std::vector L0L3Patterns_;
+ std::vector L1L3Patterns_;
+ std::vector L2L3Patterns_;
+
+ std::vector L0L2Patterns_;
+ std::vector L1L2Patterns_;
+
+ std::vector L0L1Patterns_;
+};
+
+#endif
diff --git a/L1Trigger/DTTriggerPhase2/interface/RPCIntegrator.h b/L1Trigger/DTTriggerPhase2/interface/RPCIntegrator.h
new file mode 100644
index 0000000000000..0e7b1ba0e9dc3
--- /dev/null
+++ b/L1Trigger/DTTriggerPhase2/interface/RPCIntegrator.h
@@ -0,0 +1,103 @@
+#ifndef Phase2L1Trigger_DTTrigger_RPCIntegrator_h
+#define Phase2L1Trigger_DTTrigger_RPCIntegrator_h
+
+#include "FWCore/Framework/interface/ESHandle.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/Framework/interface/ConsumesCollector.h"
+
+#include "DataFormats/MuonDetId/interface/DTChamberId.h"
+#include "DataFormats/MuonDetId/interface/DTSuperLayerId.h"
+#include "DataFormats/MuonDetId/interface/DTLayerId.h"
+#include "DataFormats/MuonDetId/interface/DTWireId.h"
+#include "DataFormats/DTDigi/interface/DTDigiCollection.h"
+#include "DataFormats/L1DTTrackFinder/interface/L1Phase2MuDTPhContainer.h"
+#include "DataFormats/L1DTTrackFinder/interface/L1Phase2MuDTPhDigi.h"
+
+#include "DataFormats/RPCRecHit/interface/RPCRecHitCollection.h"
+#include
+#include "Geometry/RPCGeometry/interface/RPCGeometry.h"
+
+//DT geometry
+#include
+#include "Geometry/DTGeometry/interface/DTGeometry.h"
+#include "Geometry/DTGeometry/interface/DTLayer.h"
+#include "DataFormats/MuonDetId/interface/DTWireId.h"
+#include "DQM/DTMonitorModule/interface/DTTrigGeomUtils.h"
+
+#include "L1Trigger/DTTriggerPhase2/interface/constants.h"
+
+struct RPCMetaprimitive {
+ RPCDetId rpc_id;
+ const RPCRecHit* rpc_cluster;
+ GlobalPoint global_position;
+ int rpcFlag;
+ int rpc_bx;
+ double rpc_t0;
+ RPCMetaprimitive(RPCDetId rpc_id_construct,
+ const RPCRecHit* rpc_cluster_construct,
+ GlobalPoint global_position_construct,
+ int rpcFlag_construct,
+ int rpc_bx_construct,
+ double rpc_t0_construct)
+ : rpc_id(rpc_id_construct),
+ rpc_cluster(rpc_cluster_construct),
+ global_position(global_position_construct),
+ rpcFlag(rpcFlag_construct),
+ rpc_bx(rpc_bx_construct),
+ rpc_t0(rpc_t0_construct) {}
+};
+
+class RPCIntegrator {
+public:
+ RPCIntegrator(const edm::ParameterSet& pset, edm::ConsumesCollector& iC);
+ ~RPCIntegrator();
+
+ void initialise(const edm::EventSetup& iEventSetup, double shift_back_fromDT);
+ void finish();
+
+ void prepareMetaPrimitives(edm::Handle rpcRecHits);
+ void matchWithDTAndUseRPCTime(std::vector& dt_metaprimitives);
+ void makeRPCOnlySegments();
+ void storeRPCSingleHits();
+ void removeRPCHitsUsed();
+
+ RPCMetaprimitive* matchDTwithRPC(cmsdt::metaPrimitive* dt_metaprimitive);
+ L1Phase2MuDTPhDigi createL1Phase2MuDTPhDigi(
+ RPCDetId rpcDetId, int rpc_bx, double rpc_time, double rpc_global_phi, double phiB, int rpc_flag);
+
+ double phiBending(RPCMetaprimitive* rpc_hit_1, RPCMetaprimitive* rpc_hit_2);
+ int phiInDTTPFormat(double rpc_global_phi, int rpcSector);
+ GlobalPoint RPCGlobalPosition(RPCDetId rpcId, const RPCRecHit& rpcIt) const;
+ double phi_DT_MP_conv(double rpc_global_phi, int rpcSector);
+ bool hasPosRF_rpc(int wh, int sec) const;
+
+ std::vector rpcRecHits_translated_;
+ std::vector RPCMetaprimitives_;
+
+private:
+ //RPCRecHitCollection m_rpcRecHits;
+ bool m_debug_;
+ int m_max_quality_to_overwrite_t0_;
+ int m_bx_window_;
+ double m_phi_window_;
+ bool m_storeAllRPCHits_;
+
+ DTGeometry const* dtGeo_;
+ RPCGeometry const* rpcGeo_;
+ edm::ESGetToken dtGeomH_;
+ edm::ESGetToken rpcGeomH_;
+
+ static constexpr double m_dt_phi_granularity_ = (65536. / 0.8); // 65536 different values per 0.8 radian
+ static constexpr double m_dt_phiB_granularity_ = (2048. / 1.4); // 2048. different values per 1.4 radian
+ // Constant geometry values
+ //R[stat][layer] - radius of rpc station/layer from center of CMS
+ static constexpr double R_[2][2] = {{410.0, 444.8}, {492.7, 527.3}};
+ static constexpr double distance_between_two_rpc_layers_ = 35; // in cm
+
+ double shift_back_;
+};
+#endif
diff --git a/L1Trigger/DTTriggerPhase2/interface/constants.h b/L1Trigger/DTTriggerPhase2/interface/constants.h
new file mode 100644
index 0000000000000..3c7e1b7756f78
--- /dev/null
+++ b/L1Trigger/DTTriggerPhase2/interface/constants.h
@@ -0,0 +1,254 @@
+/**
+ * Project:
+ * File name: constants.h
+ * Language: C++
+ *
+ * *********************************************************************
+ * Description:
+ *
+ *
+ * To Do:
+ *
+ * Author: Jose Manuel Cela
+ *
+ * *********************************************************************
+ * Copyright (c) 2015-08-07 Jose Manuel Cela
+ *
+ * For internal use, all rights reserved.
+ * *********************************************************************
+ */
+#ifndef L1Trigger_DTTriggerPhase2_constants_h
+#define L1Trigger_DTTriggerPhase2_constants_h
+#include
+
+// Compiler option to select program mode: PRUEBA_MEZCLADOR, PRUEBA_ANALIZADOR,
+// or NONE
+
+/* Quality of the trayectories:
+ NOPATH => Not valid trayectory
+ LOWQGHOST => 3h (multiple lateralities)
+ LOWQ => 3h
+ HIGHQGHOST => 4h (multiple lateralities)
+ HIGHQ => 4h
+ CLOWQ => 3h + 2h/1h
+ LOWLOWQ => 3h + 3h
+ CHIGHQ => 4h + 2h/1h
+ HIGHLOWQ => 4h + 3h
+ HIGHHIGHQ => 4h + 4h
+*/
+namespace cmsdt {
+
+ enum MP_QUALITY { NOPATH = 0, LOWQGHOST, LOWQ, HIGHQGHOST, HIGHQ, CLOWQ, LOWLOWQ, CHIGHQ, HIGHLOWQ, HIGHHIGHQ };
+
+ // Tipos de lateralidad de traza de partícula al pasar por una celda
+ enum LATERAL_CASES { LEFT = 0, RIGHT, NONE };
+
+ enum RPC_QUALITY { NORPC = 0, RPC_TIME, RPC_ONLY, RPC_HIT, RPC_CONFIRM, RPC_ASSOCIATE };
+
+ struct metaPrimitive {
+ metaPrimitive(uint32_t id,
+ double t,
+ double pos,
+ double tan,
+ double ph,
+ double phb,
+ double chi,
+ int q,
+ int w1,
+ int t1,
+ int l1,
+ int w2,
+ int t2,
+ int l2,
+ int w3,
+ int t3,
+ int l3,
+ int w4,
+ int t4,
+ int l4,
+ int w5 = 0,
+ int t5 = -1,
+ int l5 = 0,
+ int w6 = 0,
+ int t6 = -1,
+ int l6 = 0,
+ int w7 = 0,
+ int t7 = -1,
+ int l7 = 0,
+ int w8 = 0,
+ int t8 = -1,
+ int l8 = 0,
+ int idx = 0,
+ int rpc = 0)
+ : rawId(id),
+ t0(t),
+ x(pos),
+ tanPhi(tan),
+ phi(ph),
+ phiB(phb),
+ chi2(chi),
+ quality(q),
+ wi1(w1),
+ tdc1(t1),
+ lat1(l1),
+ wi2(w2),
+ tdc2(t2),
+ lat2(l2),
+ wi3(w3),
+ tdc3(t3),
+ lat3(l3),
+ wi4(w4),
+ tdc4(t4),
+ lat4(l4),
+ wi5(w5),
+ tdc5(t5),
+ lat5(l5),
+ wi6(w6),
+ tdc6(t6),
+ lat6(l6),
+ wi7(w7),
+ tdc7(t7),
+ lat7(l7),
+ wi8(w8),
+ tdc8(t8),
+ lat8(l8),
+ index(idx),
+ rpcFlag(rpc) {}
+
+ uint32_t rawId;
+ double t0;
+ double x;
+ double tanPhi;
+ double phi;
+ double phiB;
+ double chi2;
+ int quality;
+ int wi1;
+ int tdc1;
+ int lat1;
+ int wi2;
+ int tdc2;
+ int lat2;
+ int wi3;
+ int tdc3;
+ int lat3;
+ int wi4;
+ int tdc4;
+ int lat4;
+ int wi5;
+ int tdc5;
+ int lat5;
+ int wi6;
+ int tdc6;
+ int lat6;
+ int wi7;
+ int tdc7;
+ int lat7;
+ int wi8;
+ int tdc8;
+ int lat8;
+ int index;
+ int rpcFlag = 0;
+ };
+ struct PARTIAL_LATQ_TYPE {
+ bool latQValid;
+ int bxValue;
+ };
+ struct LATQ_TYPE {
+ bool valid;
+ int bxValue;
+ int invalidateHitIdx;
+ MP_QUALITY quality;
+ };
+
+ enum algo { Standard = 0, PseudoBayes = 1, HoughTrans = 2 };
+
+ enum scenario { MC = 0, DATA = 1, SLICE_TEST = 2 };
+
+ /* En nanosegundos */
+ constexpr int LHC_CLK_FREQ = 25;
+
+ /* Adimensional */
+ constexpr int MAX_BX_IDX = 3564;
+
+ // En nanosegundos (tiempo de deriva en la celda)
+ constexpr float MAXDRIFT = 386.75;
+ // En milímetros (dimensiones de la celda)
+ constexpr int CELL_HEIGHT = 13;
+ constexpr float CELL_SEMIHEIGHT = 6.5;
+ constexpr int CELL_LENGTH = 42;
+ constexpr int CELL_SEMILENGTH = 21;
+ // En milímetros / nanosegundo (velocidad de deriva)
+ constexpr float DRIFT_SPEED = 0.0542;
+ /*
+ This is the maximum value than internal time can take. This is because
+ internal time is cyclical due to the limited size of the time counters and
+ the limited value of the bunch crossing index.
+ It should be, approximately, the LHC's clock frequency multiplied by the
+ maximum BX index, plus an arbitrary amount for taking into account the
+ muon traveling time and muon's signal drift time.
+ */
+ constexpr int MAX_VALUE_OF_TIME = (LHC_CLK_FREQ * MAX_BX_IDX + 5000);
+
+ /*
+ * Total BTI number and total channel number must be coordinated. One BTI
+ * works over 10 channels, but 2 consecutive BTI's overlap many of their
+ * channels.
+ */
+ constexpr int TOTAL_BTI = 100; // Should be the same value as NUM_CH_PER_LAYER
+ constexpr int NUM_CH_PER_LAYER = 100; // Should be the same value as TOTAL_BTI
+ constexpr int NUM_LAYERS = 4;
+ constexpr int NUM_LATERALITIES = 16;
+ constexpr int NUM_CELL_COMB = 3;
+ constexpr int TOTAL_CHANNELS = (NUM_LAYERS * NUM_CH_PER_LAYER);
+ constexpr int NUM_SUPERLAYERS = 3;
+ constexpr float PHIRES_CONV = 65536. / 0.8;
+ constexpr float PHIBRES_CONV = 2048. / 1.4;
+ constexpr int CHI2RES_CONV = 1000000;
+
+ constexpr int DIVISION_HELPER1 = 43691;
+ constexpr int DIVISION_HELPER2 = 65536;
+ constexpr int DIVISION_HELPER3 = 131072;
+ constexpr int DENOM_TYPE1 = 6;
+ constexpr int DENOM_TYPE2 = 4;
+ constexpr int DENOM_TYPE3 = 2;
+ constexpr int NBITS = 18;
+ /*
+ * Size of pre-mixer buffers for DTPrimitives
+ *
+ * As first approach, this value should be evaluated in order to allow storing
+ * enough elements to avoid saturating its size. It will be dependent on the
+ * noise level, the number of good data injected in the system, as well as on
+ * the processing speed of the final analyzer.
+ */
+ constexpr int SIZE_SEEKT_BUFFER = 32;
+
+ // Number of cells for a analysis block (BTI)
+ constexpr int NUM_CELLS_PER_BLOCK = 10;
+
+ /*
+ * Number of entries for the payload inside DTPrimitive.
+ * This value is also used in other code places to manage reading and writing
+ * from/to files
+ */
+ constexpr int PAYLOAD_ENTRIES = 9;
+
+ /*
+ * Size of muon primitive
+ */
+ constexpr int NUM_LAYERS_2SL = 8;
+ constexpr double PHI_CONV = 0.5235988;
+
+ constexpr int BX_SHIFT = 20;
+ constexpr float Z_SHIFT_MB4 = -1.8;
+ constexpr float Z_POS_SL = 11.75;
+ constexpr double X_POS_L3 = 0.65;
+ constexpr double X_POS_L4 = 1.95;
+
+ constexpr int MEANTIME_2LAT = 16384;
+ constexpr int MEANTIME_3LAT = 10923;
+ constexpr int MEANTIME_4LAT = 8192;
+
+} // namespace cmsdt
+
+#endif
diff --git a/L1Trigger/DTTriggerPhase2/plugins/BuildFile.xml b/L1Trigger/DTTriggerPhase2/plugins/BuildFile.xml
new file mode 100644
index 0000000000000..202f0d6fa28d7
--- /dev/null
+++ b/L1Trigger/DTTriggerPhase2/plugins/BuildFile.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/L1Trigger/DTTriggerPhase2/plugins/CalibratedDigis.cc b/L1Trigger/DTTriggerPhase2/plugins/CalibratedDigis.cc
new file mode 100644
index 0000000000000..b27cfaf6edf69
--- /dev/null
+++ b/L1Trigger/DTTriggerPhase2/plugins/CalibratedDigis.cc
@@ -0,0 +1,149 @@
+// -*- C++ -*-
+//
+// Package: UserCode/CalibratedDigis
+// Class: CalibratedDigis
+//
+/**\class CalibratedDigis CalibratedDigis.cc UserCode/CalibratedDigis/plugins/CalibratedDigis.cc
+
+ Description: [one line class summary]
+
+ Implementation:
+ [Notes on implementation]
+*/
+//
+// Original Author: Luigi Guiducci
+// Created: Fri, 11 Jan 2019 12:49:12 GMT
+//
+//
+
+// system include files
+#include
+
+// user include files
+#include "FWCore/Framework/interface/Frameworkfwd.h"
+#include "FWCore/Framework/interface/stream/EDProducer.h"
+
+#include "FWCore/Framework/interface/Event.h"
+#include "FWCore/Framework/interface/MakerMacros.h"
+
+#include "FWCore/ParameterSet/interface/ParameterSet.h"
+#include "FWCore/Utilities/interface/StreamID.h"
+#include "CalibMuon/DTDigiSync/interface/DTTTrigBaseSync.h"
+#include "FWCore/Framework/interface/ConsumesCollector.h"
+#include "DataFormats/Common/interface/Handle.h"
+#include "FWCore/Framework/interface/ESHandle.h"
+
+#include "CalibMuon/DTDigiSync/interface/DTTTrigSyncFactory.h"
+
+#include "Geometry/DTGeometry/interface/DTGeometry.h"
+#include "FWCore/Framework/interface/EventSetup.h"
+#include "DataFormats/DTDigi/interface/DTDigiCollection.h"
+#include "DataFormats/MuonDetId/interface/DTLayerId.h"
+#include "DataFormats/MuonDetId/interface/DTWireId.h"
+#include "Geometry/Records/interface/MuonGeometryRecord.h"
+#include "FWCore/ParameterSet/interface/ParameterSet.h"
+
+#include "L1Trigger/DTTriggerPhase2/interface/constants.h"
+
+namespace edm {
+ class ParameterSet;
+ class EventSetup;
+} // namespace edm
+
+using namespace std;
+using namespace edm;
+using namespace cmsdt;
+//
+// class declaration
+//
+
+class CalibratedDigis : public edm::stream::EDProducer<> {
+public:
+ explicit CalibratedDigis(const edm::ParameterSet&);
+ ~CalibratedDigis() override;
+
+private:
+ int timeOffset_;
+ int flat_calib_;
+ int scenario;
+
+ void produce(edm::Event&, const edm::EventSetup&) override;
+
+ std::unique_ptr theSync;
+
+ // ----------member data ---------------------------
+ edm::EDGetTokenT dtDigisToken;
+ edm::Handle DTDigiHandle;
+ edm::InputTag dtDigiTag;
+
+ static constexpr float bxspacing = 25.0;
+ static constexpr float timeshift = 400.0;
+ static constexpr float flatcalib = 325.0;
+};
+
+//
+// constructors and destructor
+//
+CalibratedDigis::CalibratedDigis(const edm::ParameterSet& iConfig) {
+ //register your products
+ dtDigiTag = iConfig.getParameter("dtDigiTag");
+ dtDigisToken = consumes(dtDigiTag);
+
+ theSync = DTTTrigSyncFactory::get()->create(iConfig.getParameter("tTrigMode"),
+ iConfig.getParameter("tTrigModeConfig"));
+
+ flat_calib_ = iConfig.getParameter("flat_calib");
+ timeOffset_ = iConfig.getParameter("timeOffset");
+
+ scenario = iConfig.getUntrackedParameter("scenario");
+
+ produces();
+ //now do what ever other initialization is needed
+}
+
+CalibratedDigis::~CalibratedDigis() {
+ // do anything here that needs to be done at destruction time
+ // (e.g. close files, deallocate resources etc.)
+}
+
+//
+// member functions
+//
+
+// ------------ method called to produce the data ------------
+void CalibratedDigis::produce(edm::Event& iEvent, const edm::EventSetup& iSetup) {
+ using namespace edm;
+ theSync->setES(iSetup);
+ iEvent.getByToken(dtDigisToken, DTDigiHandle);
+ DTDigiCollection mydigis;
+
+ for (const auto& dtLayerIt : *DTDigiHandle) {
+ const DTLayerId& layerId = dtLayerIt.first;
+ for (DTDigiCollection::const_iterator digiIt = dtLayerIt.second.first; digiIt != dtLayerIt.second.second;
+ ++digiIt) {
+ DTWireId wireId(layerId, (*digiIt).wire());
+ float digiTime = (*digiIt).time();
+ int wire = (*digiIt).wire();
+ int number = (*digiIt).number();
+ float newTime = 0;
+ if (flat_calib_ != 0)
+ newTime = digiTime - flatcalib + bxspacing * iEvent.eventAuxiliary().bunchCrossing() + float(timeOffset_);
+ else {
+ if (scenario == MC) //FIX MC
+ newTime = digiTime + bxspacing * timeshift;
+ else if (scenario == SLICE_TEST) //FIX SliceTest
+ newTime = digiTime;
+ else
+ newTime = digiTime - theSync->offset(wireId) + bxspacing * iEvent.eventAuxiliary().bunchCrossing() +
+ float(timeOffset_);
+ }
+ DTDigi newDigi(wire, newTime, number);
+ mydigis.insertDigi(layerId, newDigi);
+ }
+ }
+ auto CorrectedDTDigiCollection = std::make_unique(mydigis);
+ iEvent.put(std::move(CorrectedDTDigiCollection));
+}
+
+//define this as a plug-in
+DEFINE_FWK_MODULE(CalibratedDigis);
diff --git a/L1Trigger/DTTriggerPhase2/plugins/DTTrigPhase2Prod.cc b/L1Trigger/DTTriggerPhase2/plugins/DTTrigPhase2Prod.cc
new file mode 100644
index 0000000000000..4dcedadba8e37
--- /dev/null
+++ b/L1Trigger/DTTriggerPhase2/plugins/DTTrigPhase2Prod.cc
@@ -0,0 +1,711 @@
+#include "FWCore/Framework/interface/MakerMacros.h"
+#include "FWCore/Framework/interface/stream/EDProducer.h"
+#include "FWCore/Framework/interface/ESHandle.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/MuonPath.h"
+#include "L1Trigger/DTTriggerPhase2/interface/constants.h"
+
+#include "L1Trigger/DTTriggerPhase2/interface/MotherGrouping.h"
+#include "L1Trigger/DTTriggerPhase2/interface/InitialGrouping.h"
+#include "L1Trigger/DTTriggerPhase2/interface/HoughGrouping.h"
+#include "L1Trigger/DTTriggerPhase2/interface/PseudoBayesGrouping.h"
+#include "L1Trigger/DTTriggerPhase2/interface/MuonPathAnalyzer.h"
+#include "L1Trigger/DTTriggerPhase2/interface/MuonPathAnalyzerPerSL.h"
+#include "L1Trigger/DTTriggerPhase2/interface/MuonPathAnalyzerInChamber.h"
+#include "L1Trigger/DTTriggerPhase2/interface/MuonPathAssociator.h"
+#include "L1Trigger/DTTriggerPhase2/interface/MPFilter.h"
+#include "L1Trigger/DTTriggerPhase2/interface/MPQualityEnhancerFilter.h"
+#include "L1Trigger/DTTriggerPhase2/interface/MPRedundantFilter.h"
+
+#include "DataFormats/MuonDetId/interface/DTChamberId.h"
+#include "DataFormats/MuonDetId/interface/DTSuperLayerId.h"
+#include "DataFormats/MuonDetId/interface/DTLayerId.h"
+#include "DataFormats/MuonDetId/interface/DTWireId.h"
+#include "DataFormats/DTDigi/interface/DTDigiCollection.h"
+#include "DataFormats/L1DTTrackFinder/interface/L1Phase2MuDTPhContainer.h"
+#include "DataFormats/L1DTTrackFinder/interface/L1Phase2MuDTPhDigi.h"
+
+// DT trigger GeomUtils
+#include "DQM/DTMonitorModule/interface/DTTrigGeomUtils.h"
+
+//RPC TP
+#include "DataFormats/RPCRecHit/interface/RPCRecHitCollection.h"
+#include
+#include "Geometry/RPCGeometry/interface/RPCGeometry.h"
+#include "L1Trigger/DTTriggerPhase2/interface/RPCIntegrator.h"
+
+#include
+#include
+#include
+#include
+
+using namespace edm;
+using namespace std;
+using namespace cmsdt;
+
+class DTTrigPhase2Prod : public edm::stream::EDProducer<> {
+ typedef std::map> DTDigiMap;
+ typedef DTDigiMap::iterator DTDigiMap_iterator;
+ typedef DTDigiMap::const_iterator DTDigiMap_const_iterator;
+
+public:
+ //! Constructor
+ DTTrigPhase2Prod(const edm::ParameterSet& pset);
+
+ //! Destructor
+ ~DTTrigPhase2Prod() 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
+ int rango(const metaPrimitive& mp) const;
+ bool outer(const metaPrimitive& mp) const;
+ bool inner(const metaPrimitive& mp) const;
+ void printmP(const std::string& ss, const metaPrimitive& mP) const;
+ void printmPC(const std::string& ss, const metaPrimitive& mP) const;
+ bool hasPosRF(int wh, int sec) const;
+
+ // Getter-methods
+ MP_QUALITY getMinimumQuality(void);
+
+ // Setter-methods
+ void setChiSquareThreshold(float ch2Thr);
+ void setMinimumQuality(MP_QUALITY q);
+
+ // data-members
+ DTGeometry const* dtGeo_;
+ edm::ESGetToken dtGeomH;
+ std::vector> primitives_;
+
+private:
+ // Trigger Configuration Manager CCB validity flag
+ bool my_CCBValid_;
+
+ // BX offset used to correct DTTPG output
+ int my_BXoffset_;
+
+ // Debug Flag
+ bool debug_;
+ bool dump_;
+ double dT0_correlate_TP_;
+ bool do_correlation_;
+ int scenario_;
+
+ // shift
+ edm::FileInPath shift_filename_;
+ std::map shiftinfo_;
+
+ // ParameterSet
+ edm::EDGetTokenT dtDigisToken_;
+ edm::EDGetTokenT rpcRecHitsLabel_;
+
+ // Grouping attributes and methods
+ int algo_; // Grouping code
+ std::unique_ptr grouping_obj_;
+ std::unique_ptr mpathanalyzer_;
+ std::unique_ptr mpathqualityenhancer_;
+ std::unique_ptr mpathredundantfilter_;
+ std::unique_ptr mpathassociator_;
+
+ // Buffering
+ bool activateBuffer_;
+ int superCellhalfspacewidth_;
+ float superCelltimewidth_;
+ std::vector distribDigis(std::queue>& inQ);
+ void processDigi(std::queue>& inQ,
+ std::vector>*>& vec);
+
+ // RPC
+ std::unique_ptr rpc_integrator_;
+ bool useRPC_;
+
+ void assignIndex(std::vector& inMPaths);
+ void assignIndexPerBX(std::vector& inMPaths);
+ int assignQualityOrder(const metaPrimitive& mP) const;
+
+ const std::unordered_map qmap_;
+};
+
+namespace {
+ struct {
+ bool operator()(std::pair a, std::pair b) const {
+ return (a.second.time() < b.second.time());
+ }
+ } DigiTimeOrdering;
+} // namespace
+
+DTTrigPhase2Prod::DTTrigPhase2Prod(const ParameterSet& pset)
+ : qmap_({{9, 9}, {8, 8}, {7, 6}, {6, 7}, {5, 3}, {4, 5}, {3, 4}, {2, 2}, {1, 1}}) {
+ produces();
+
+ debug_ = pset.getUntrackedParameter("debug");
+ dump_ = pset.getUntrackedParameter("dump");
+
+ do_correlation_ = pset.getParameter("do_correlation");
+ scenario_ = pset.getParameter("scenario");
+
+ dtDigisToken_ = consumes(pset.getParameter("digiTag"));
+
+ rpcRecHitsLabel_ = consumes(pset.getParameter("rpcRecHits"));
+ useRPC_ = pset.getParameter("useRPC");
+
+ // Choosing grouping scheme:
+ algo_ = pset.getParameter("algo");
+
+ edm::ConsumesCollector consumesColl(consumesCollector());
+
+ if (algo_ == PseudoBayes) {
+ grouping_obj_ =
+ std::make_unique(pset.getParameter("PseudoBayesPattern"), consumesColl);
+ } else if (algo_ == HoughTrans) {
+ grouping_obj_ =
+ std::make_unique(pset.getParameter("HoughGrouping"), consumesColl);
+ } else {
+ grouping_obj_ = std::make_unique(pset, consumesColl);
+ }
+
+ if (algo_ == Standard) {
+ if (debug_)
+ LogDebug("DTTrigPhase2Prod") << "DTp2:constructor: JM analyzer";
+ mpathanalyzer_ = std::make_unique(pset, consumesColl);
+ } else {
+ if (debug_)
+ LogDebug("DTTrigPhase2Prod") << "DTp2:constructor: Full chamber analyzer";
+ mpathanalyzer_ = std::make_unique(pset, consumesColl);
+ }
+
+ // Getting buffer option
+ activateBuffer_ = pset.getParameter("activateBuffer");
+ superCellhalfspacewidth_ = pset.getParameter("superCellspacewidth") / 2;
+ superCelltimewidth_ = pset.getParameter("superCelltimewidth");
+
+ mpathqualityenhancer_ = std::make_unique(pset);
+ mpathredundantfilter_ = std::make_unique(pset);
+ mpathassociator_ = std::make_unique(pset, consumesColl);
+ rpc_integrator_ = std::make_unique(pset, consumesColl);
+
+ dtGeomH = esConsumes();
+}
+
+DTTrigPhase2Prod::~DTTrigPhase2Prod() {
+ if (debug_)
+ LogDebug("DTTrigPhase2Prod") << "DTp2: calling destructor" << std::endl;
+}
+
+void DTTrigPhase2Prod::beginRun(edm::Run const& iRun, const edm::EventSetup& iEventSetup) {
+ if (debug_)
+ LogDebug("DTTrigPhase2Prod") << "beginRun " << iRun.id().run();
+ if (debug_)
+ LogDebug("DTTrigPhase2Prod") << "beginRun: getting DT geometry";
+
+ grouping_obj_->initialise(iEventSetup); // Grouping object initialisation
+ mpathanalyzer_->initialise(iEventSetup); // Analyzer object initialisation
+ mpathqualityenhancer_->initialise(iEventSetup); // Filter object initialisation
+ mpathredundantfilter_->initialise(iEventSetup); // Filter object initialisation
+ mpathassociator_->initialise(iEventSetup); // Associator object initialisation
+
+ const MuonGeometryRecord& geom = iEventSetup.get();
+ dtGeo_ = &geom.get(dtGeomH);
+}
+
+void DTTrigPhase2Prod::produce(Event& iEvent, const EventSetup& iEventSetup) {
+ if (debug_)
+ LogDebug("DTTrigPhase2Prod") << "produce";
+ edm::Handle dtdigis;
+ iEvent.getByToken(dtDigisToken_, dtdigis);
+
+ if (debug_)
+ LogDebug("DTTrigPhase2Prod") << "\t Getting the RPC RecHits" << std::endl;
+ edm::Handle rpcRecHits;
+ iEvent.getByToken(rpcRecHitsLabel_, rpcRecHits);
+
+ ////////////////////////////////
+ // GROUPING CODE:
+ ////////////////////////////////
+ DTDigiMap digiMap;
+ DTDigiCollection::DigiRangeIterator detUnitIt;
+ for (const auto& detUnitIt : *dtdigis) {
+ const DTLayerId& layId = detUnitIt.first;
+ const DTChamberId chambId = layId.superlayerId().chamberId();
+ const DTDigiCollection::Range& range = detUnitIt.second;
+ digiMap[chambId].put(range, layId);
+ }
+
+ // generate a list muon paths for each event!!!
+ if (debug_ && activateBuffer_)
+ LogDebug("DTTrigPhase2Prod") << "produce - Getting and grouping digis per chamber using a buffer and super cells.";
+ else if (debug_)
+ LogDebug("DTTrigPhase2Prod") << "produce - Getting and grouping digis per chamber.";
+
+ MuonPathPtrs muonpaths;
+ for (const auto& ich : dtGeo_->chambers()) {
+ // The code inside this for loop would ideally later fit inside a trigger unit (in principle, a DT station) of the future Phase 2 DT Trigger.
+ const DTChamber* chamb = ich;
+ DTChamberId chid = chamb->id();
+ DTDigiMap_iterator dmit = digiMap.find(chid);
+
+ if (dmit == digiMap.end())
+ continue;
+
+ if (activateBuffer_) { // Use buffering (per chamber) or not
+ // Import digis from the station
+ std::vector> tmpvec;
+ tmpvec.clear();
+
+ for (const auto& dtLayerIdIt : (*dmit).second) {
+ for (DTDigiCollection::const_iterator digiIt = (dtLayerIdIt.second).first;
+ digiIt != (dtLayerIdIt.second).second;
+ digiIt++) {
+ tmpvec.emplace_back(dtLayerIdIt.first, *digiIt);
+ }
+ }
+
+ // Check to enhance CPU time usage
+ if (tmpvec.empty())
+ continue;
+
+ // Order digis depending on TDC time and insert them into a queue (FIFO buffer). TODO: adapt for MC simulations.
+ std::sort(tmpvec.begin(), tmpvec.end(), DigiTimeOrdering);
+ std::queue> timequeue;
+
+ for (const auto& elem : tmpvec)
+ timequeue.emplace(std::move(elem));
+ tmpvec.clear();
+
+ // Distribute the digis from the queue into 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);
+ superCells.pop_back();
+ }
+ } else {
+ grouping_obj_->run(iEvent, iEventSetup, (*dmit).second, muonpaths);
+ }
+ }
+ digiMap.clear();
+
+ if (dump_) {
+ for (unsigned int i = 0; i < muonpaths.size(); i++) {
+ stringstream ss;
+ ss << iEvent.id().event() << " mpath " << i << ": ";
+ for (int lay = 0; lay < muonpaths.at(i)->nprimitives(); lay++)
+ ss << muonpaths.at(i)->primitive(lay)->channelId() << " ";
+ for (int lay = 0; lay < muonpaths.at(i)->nprimitives(); lay++)
+ ss << muonpaths.at(i)->primitive(lay)->tdcTimeStamp() << " ";
+ for (int lay = 0; lay < muonpaths.at(i)->nprimitives(); lay++)
+ ss << muonpaths.at(i)->primitive(lay)->laterality() << " ";
+ LogInfo("DTTrigPhase2Prod") << ss.str();
+ }
+ }
+
+ // FILTER GROUPING
+ MuonPathPtrs filteredmuonpaths;
+ if (algo_ == Standard) {
+ mpathredundantfilter_->run(iEvent, iEventSetup, muonpaths, filteredmuonpaths);
+ }
+
+ if (dump_) {
+ for (unsigned int i = 0; i < filteredmuonpaths.size(); i++) {
+ stringstream ss;
+ ss << iEvent.id().event() << " filt. mpath " << i << ": ";
+ for (int lay = 0; lay < filteredmuonpaths.at(i)->nprimitives(); lay++)
+ ss << filteredmuonpaths.at(i)->primitive(lay)->channelId() << " ";
+ for (int lay = 0; lay < filteredmuonpaths.at(i)->nprimitives(); lay++)
+ ss << filteredmuonpaths.at(i)->primitive(lay)->tdcTimeStamp() << " ";
+ LogInfo("DTTrigPhase2Prod") << ss.str();
+ }
+ }
+
+ ///////////////////////////////////////////
+ /// FITTING SECTION;
+ ///////////////////////////////////////////
+ if (debug_)
+ LogDebug("DTTrigPhase2Prod") << "MUON PATHS found: " << muonpaths.size() << " (" << filteredmuonpaths.size()
+ << ") in event " << iEvent.id().event();
+ if (debug_)
+ LogDebug("DTTrigPhase2Prod") << "filling NmetaPrimtives" << std::endl;
+ std::vector metaPrimitives;
+ MuonPathPtrs outmpaths;
+ if (algo_ == Standard) {
+ if (debug_)
+ LogDebug("DTTrigPhase2Prod") << "Fitting 1SL ";
+ mpathanalyzer_->run(iEvent, iEventSetup, filteredmuonpaths, metaPrimitives);
+ } else {
+ // implementation for advanced (2SL) grouping, no filter required..
+ if (debug_)
+ LogDebug("DTTrigPhase2Prod") << "Fitting 2SL at once ";
+ mpathanalyzer_->run(iEvent, iEventSetup, muonpaths, outmpaths);
+ }
+
+ if (dump_) {
+ for (unsigned int i = 0; i < outmpaths.size(); i++) {
+ LogInfo("DTTrigPhase2Prod") << iEvent.id().event() << " mp " << i << ": " << outmpaths.at(i)->bxTimeValue() << " "
+ << outmpaths.at(i)->horizPos() << " " << outmpaths.at(i)->tanPhi() << " "
+ << outmpaths.at(i)->phi() << " " << outmpaths.at(i)->phiB() << " "
+ << outmpaths.at(i)->quality() << " " << outmpaths.at(i)->chiSquare();
+ }
+ for (unsigned int i = 0; i < metaPrimitives.size(); i++) {
+ stringstream ss;
+ ss << iEvent.id().event() << " mp " << i << ": ";
+ printmP(ss.str(), metaPrimitives.at(i));
+ }
+ }
+
+ muonpaths.clear();
+ filteredmuonpaths.clear();
+
+ /////////////////////////////////////
+ // FILTER SECTIONS:
+ ////////////////////////////////////
+ if (debug_)
+ LogDebug("DTTrigPhase2Prod") << "declaring new vector for filtered" << std::endl;
+
+ std::vector filteredMetaPrimitives;
+ if (algo_ == Standard)
+ mpathqualityenhancer_->run(iEvent, iEventSetup, metaPrimitives, filteredMetaPrimitives);
+
+ if (dump_) {
+ for (unsigned int i = 0; i < filteredMetaPrimitives.size(); i++) {
+ stringstream ss;
+ ss << iEvent.id().event() << " filtered mp " << i << ": ";
+ printmP(ss.str(), filteredMetaPrimitives.at(i));
+ }
+ }
+
+ metaPrimitives.clear();
+ metaPrimitives.erase(metaPrimitives.begin(), metaPrimitives.end());
+
+ if (debug_)
+ LogDebug("DTTrigPhase2Prod") << "DTp2 in event:" << iEvent.id().event() << " we found "
+ << filteredMetaPrimitives.size() << " filteredMetaPrimitives (superlayer)"
+ << std::endl;
+ if (debug_)
+ LogDebug("DTTrigPhase2Prod") << "filteredMetaPrimitives: starting correlations" << std::endl;
+
+ /////////////////////////////////////
+ //// CORRELATION:
+ /////////////////////////////////////
+ std::vector correlatedMetaPrimitives;
+ if (algo_ == Standard)
+ mpathassociator_->run(iEvent, iEventSetup, dtdigis, filteredMetaPrimitives, correlatedMetaPrimitives);
+ else {
+ for (const auto& muonpath : outmpaths) {
+ correlatedMetaPrimitives.emplace_back(muonpath->rawId(),
+ (double)muonpath->bxTimeValue(),
+ muonpath->horizPos(),
+ muonpath->tanPhi(),
+ muonpath->phi(),
+ muonpath->phiB(),
+ muonpath->chiSquare(),
+ (int)muonpath->quality(),
+ muonpath->primitive(0)->channelId(),
+ muonpath->primitive(0)->tdcTimeStamp(),
+ muonpath->primitive(0)->laterality(),
+ muonpath->primitive(1)->channelId(),
+ muonpath->primitive(1)->tdcTimeStamp(),
+ muonpath->primitive(1)->laterality(),
+ muonpath->primitive(2)->channelId(),
+ muonpath->primitive(2)->tdcTimeStamp(),
+ muonpath->primitive(2)->laterality(),
+ muonpath->primitive(3)->channelId(),
+ muonpath->primitive(3)->tdcTimeStamp(),
+ muonpath->primitive(3)->laterality(),
+ muonpath->primitive(4)->channelId(),
+ muonpath->primitive(4)->tdcTimeStamp(),
+ muonpath->primitive(4)->laterality(),
+ muonpath->primitive(5)->channelId(),
+ muonpath->primitive(5)->tdcTimeStamp(),
+ muonpath->primitive(5)->laterality(),
+ muonpath->primitive(6)->channelId(),
+ muonpath->primitive(6)->tdcTimeStamp(),
+ muonpath->primitive(6)->laterality(),
+ muonpath->primitive(7)->channelId(),
+ muonpath->primitive(7)->tdcTimeStamp(),
+ muonpath->primitive(7)->laterality());
+ }
+ }
+ filteredMetaPrimitives.clear();
+
+ if (debug_)
+ LogDebug("DTTrigPhase2Prod") << "DTp2 in event:" << iEvent.id().event() << " we found "
+ << correlatedMetaPrimitives.size() << " correlatedMetPrimitives (chamber)";
+
+ if (dump_) {
+ LogInfo("DTTrigPhase2Prod") << "DTp2 in event:" << iEvent.id().event() << " we found "
+ << correlatedMetaPrimitives.size() << " correlatedMetPrimitives (chamber)";
+
+ for (unsigned int i = 0; i < correlatedMetaPrimitives.size(); i++) {
+ stringstream ss;
+ ss << iEvent.id().event() << " correlated mp " << i << ": ";
+ printmPC(ss.str(), correlatedMetaPrimitives.at(i));
+ }
+ }
+
+ double shift_back = 0;
+ if (scenario_ == MC) //scope for MC
+ shift_back = 400;
+ else if (scenario_ == DATA) //scope for data
+ shift_back = 0;
+ else if (scenario_ == SLICE_TEST) //scope for slice test
+ shift_back = 0;
+
+ // RPC integration
+ if (useRPC_) {
+ rpc_integrator_->initialise(iEventSetup, shift_back);
+ rpc_integrator_->prepareMetaPrimitives(rpcRecHits);
+ rpc_integrator_->matchWithDTAndUseRPCTime(correlatedMetaPrimitives);
+ rpc_integrator_->makeRPCOnlySegments();
+ rpc_integrator_->storeRPCSingleHits();
+ rpc_integrator_->removeRPCHitsUsed();
+ }
+
+ /// STORING RESULTs
+ vector outP2Ph;
+
+ // Assigning index value
+ assignIndex(correlatedMetaPrimitives);
+ for (const auto& metaPrimitiveIt : correlatedMetaPrimitives) {
+ DTChamberId chId(metaPrimitiveIt.rawId);
+ if (debug_)
+ LogDebug("DTTrigPhase2Prod") << "looping in final vector: SuperLayerId" << chId << " x=" << metaPrimitiveIt.x
+ << " quality=" << metaPrimitiveIt.quality
+ << " BX=" << round(metaPrimitiveIt.t0 / 25.) << " index=" << metaPrimitiveIt.index;
+
+ int sectorTP = chId.sector();
+ //sectors 13 and 14 exist only for the outermost stations for sectors 4 and 10 respectively
+ //due to the larger MB4 that are divided into two.
+ if (sectorTP == 13)
+ sectorTP = 4;
+ if (sectorTP == 14)
+ sectorTP = 10;
+ sectorTP = sectorTP - 1;
+ int sl = 0;
+ if (metaPrimitiveIt.quality < LOWLOWQ || metaPrimitiveIt.quality == CHIGHQ) {
+ if (inner(metaPrimitiveIt))
+ sl = 1;
+ else
+ sl = 3;
+ }
+
+ if (debug_)
+ LogDebug("DTTrigPhase2Prod") << "pushing back phase-2 dataformat carlo-federica dataformat";
+ outP2Ph.push_back(L1Phase2MuDTPhDigi(
+ (int)round(metaPrimitiveIt.t0 / (float)LHC_CLK_FREQ) - shift_back,
+ chId.wheel(), // uwh (m_wheel)
+ sectorTP, // usc (m_sector)
+ chId.station(), // ust (m_station)
+ sl, // ust (m_station)
+ (int)round(metaPrimitiveIt.phi * PHIRES_CONV), // uphi (_phiAngle)
+ (int)round(metaPrimitiveIt.phiB * PHIBRES_CONV), // uphib (m_phiBending)
+ metaPrimitiveIt.quality, // uqua (m_qualityCode)
+ metaPrimitiveIt.index, // uind (m_segmentIndex)
+ (int)round(metaPrimitiveIt.t0) - shift_back * LHC_CLK_FREQ, // ut0 (m_t0Segment)
+ (int)round(metaPrimitiveIt.chi2 * CHI2RES_CONV), // uchi2 (m_chi2Segment)
+ metaPrimitiveIt.rpcFlag // urpc (m_rpcFlag)
+ ));
+ }
+
+ // Storing RPC hits that were not used elsewhere
+ if (useRPC_) {
+ for (auto rpc_dt_digi = rpc_integrator_->rpcRecHits_translated_.begin();
+ rpc_dt_digi != rpc_integrator_->rpcRecHits_translated_.end();
+ rpc_dt_digi++) {
+ outP2Ph.push_back(*rpc_dt_digi);
+ }
+ }
+
+ auto resultP2Ph = std::make_unique();
+ resultP2Ph->setContainer(outP2Ph);
+ iEvent.put(std::move(resultP2Ph));
+ outP2Ph.clear();
+ outP2Ph.erase(outP2Ph.begin(), outP2Ph.end());
+}
+
+void DTTrigPhase2Prod::endRun(edm::Run const& iRun, const edm::EventSetup& iEventSetup) {
+ grouping_obj_->finish();
+ mpathanalyzer_->finish();
+ mpathqualityenhancer_->finish();
+ mpathredundantfilter_->finish();
+ mpathassociator_->finish();
+ rpc_integrator_->finish();
+};
+
+bool DTTrigPhase2Prod::outer(const metaPrimitive& mp) const {
+ int counter = (mp.wi5 != -1) + (mp.wi6 != -1) + (mp.wi7 != -1) + (mp.wi8 != -1);
+ return (counter > 2);
+}
+
+bool DTTrigPhase2Prod::inner(const metaPrimitive& mp) const {
+ int counter = (mp.wi1 != -1) + (mp.wi2 != -1) + (mp.wi3 != -1) + (mp.wi4 != -1);
+ return (counter > 2);
+}
+
+bool DTTrigPhase2Prod::hasPosRF(int wh, int sec) const { return wh > 0 || (wh == 0 && sec % 4 > 1); }
+
+void DTTrigPhase2Prod::printmP(const string& ss, const metaPrimitive& mP) const {
+ DTSuperLayerId slId(mP.rawId);
+ LogInfo("DTTrigPhase2Prod") << ss << (int)slId << "\t " << setw(2) << left << mP.wi1 << " " << setw(2) << left
+ << mP.wi2 << " " << setw(2) << left << mP.wi3 << " " << setw(2) << left << mP.wi4 << " "
+ << setw(5) << left << mP.tdc1 << " " << setw(5) << left << mP.tdc2 << " " << setw(5)
+ << left << mP.tdc3 << " " << setw(5) << left << mP.tdc4 << " " << setw(10) << right
+ << mP.x << " " << setw(9) << left << mP.tanPhi << " " << setw(5) << left << mP.t0 << " "
+ << setw(13) << left << mP.chi2 << " r:" << rango(mP);
+}
+
+void DTTrigPhase2Prod::printmPC(const string& ss, const metaPrimitive& mP) const {
+ DTChamberId ChId(mP.rawId);
+ LogInfo("DTTrigPhase2Prod") << ss << (int)ChId << "\t " << setw(2) << left << mP.wi1 << " " << setw(2) << left
+ << mP.wi2 << " " << setw(2) << left << mP.wi3 << " " << setw(2) << left << mP.wi4 << " "
+ << setw(2) << left << mP.wi5 << " " << setw(2) << left << mP.wi6 << " " << setw(2) << left
+ << mP.wi7 << " " << setw(2) << left << mP.wi8 << " " << setw(5) << left << mP.tdc1 << " "
+ << setw(5) << left << mP.tdc2 << " " << setw(5) << left << mP.tdc3 << " " << setw(5)
+ << left << mP.tdc4 << " " << setw(5) << left << mP.tdc5 << " " << setw(5) << left
+ << mP.tdc6 << " " << setw(5) << left << mP.tdc7 << " " << setw(5) << left << mP.tdc8
+ << " " << setw(2) << left << mP.lat1 << " " << setw(2) << left << mP.lat2 << " "
+ << setw(2) << left << mP.lat3 << " " << setw(2) << left << mP.lat4 << " " << setw(2)
+ << left << mP.lat5 << " " << setw(2) << left << mP.lat6 << " " << setw(2) << left
+ << mP.lat7 << " " << setw(2) << left << mP.lat8 << " " << setw(10) << right << mP.x << " "
+ << setw(9) << left << mP.tanPhi << " " << setw(5) << left << mP.t0 << " " << setw(13)
+ << left << mP.chi2 << " r:" << rango(mP);
+}
+
+int DTTrigPhase2Prod::rango(const metaPrimitive& mp) const {
+ if (mp.quality == 1 or mp.quality == 2)
+ return 3;
+ if (mp.quality == 3 or mp.quality == 4)
+ return 4;
+ return mp.quality;
+}
+
+void DTTrigPhase2Prod::assignIndex(std::vector& inMPaths) {
+ std::map> primsPerBX;
+ for (const auto& metaPrimitive : inMPaths) {
+ int BX = round(metaPrimitive.t0 / 25.);
+ primsPerBX[BX].push_back(metaPrimitive);
+ }
+ inMPaths.clear();
+ for (auto& prims : primsPerBX) {
+ assignIndexPerBX(prims.second);
+ for (const auto& primitive : prims.second)
+ inMPaths.push_back(primitive);
+ }
+}
+
+void DTTrigPhase2Prod::assignIndexPerBX(std::vector& inMPaths) {
+ // First we asociate a new index to the metaprimitive depending on quality or phiB;
+ uint32_t rawId = -1;
+ int numP = -1;
+ for (auto& metaPrimitiveIt : inMPaths) {
+ numP++;
+ rawId = metaPrimitiveIt.rawId;
+ int iOrder = assignQualityOrder(metaPrimitiveIt);
+ int inf = 0;
+ int numP2 = -1;
+ for (auto& metaPrimitiveItN : inMPaths) {
+ int nOrder = assignQualityOrder(metaPrimitiveItN);
+ numP2++;
+ if (rawId != metaPrimitiveItN.rawId)
+ continue;
+ if (numP2 == numP) {
+ metaPrimitiveIt.index = inf;
+ break;
+ } else if (iOrder < nOrder) {
+ inf++;
+ } else if (iOrder > nOrder) {
+ metaPrimitiveItN.index++;
+ } else if (iOrder == nOrder) {
+ if (std::abs(metaPrimitiveIt.phiB) >= std::abs(metaPrimitiveItN.phiB)) {
+ inf++;
+ } else if (std::abs(metaPrimitiveIt.phiB) < std::abs(metaPrimitiveItN.phiB)) {
+ metaPrimitiveItN.index++;
+ }
+ }
+ } // ending second for
+ } // ending first for
+}
+
+int DTTrigPhase2Prod::assignQualityOrder(const metaPrimitive& mP) const {
+ if (mP.quality > 9 || mP.quality < 1)
+ return -1;
+
+ return qmap_.find(mP.quality)->second;
+}
+
+std::vector DTTrigPhase2Prod::distribDigis(std::queue>& inQ) {
+ std::vector>*> tmpVector;
+ tmpVector.clear();
+ 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();
+ }
+ collVector.push_back(&tmpColl);
+ }
+ return collVector;
+}
+
+void DTTrigPhase2Prod::processDigi(std::queue>& inQ,
+ 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()) {
+ // Time requirement
+ if (TMath::Abs(sC->front().second.wire() - inQ.front().second.wire()) <= superCellhalfspacewidth_) {
+ // Spatial requirement
+ sC->push(std::move(inQ.front()));
+ classified = true;
+ }
+ }
+ }
+ }
+ if (classified) {
+ inQ.pop();
+ return;
+ }
+
+ std::queue> newQueue;
+
+ std::pair tmpPair;
+ tmpPair = std::move(inQ.front());
+ newQueue.push(tmpPair);
+ inQ.pop();
+
+ vec.push_back(&newQueue);
+}
+
+DEFINE_FWK_MODULE(DTTrigPhase2Prod);
diff --git a/L1Trigger/DTTriggerPhase2/python/CalibratedDigis_cfi.py b/L1Trigger/DTTriggerPhase2/python/CalibratedDigis_cfi.py
new file mode 100644
index 0000000000000..8fd4400f161b5
--- /dev/null
+++ b/L1Trigger/DTTriggerPhase2/python/CalibratedDigis_cfi.py
@@ -0,0 +1,30 @@
+import FWCore.ParameterSet.Config as cms
+
+# The reconstruction algo and its parameter set
+# constant vdrift from DB (and ttrig from DB)
+
+CalibratedDigis = cms.EDProducer("CalibratedDigis",
+ tTrigModeConfig = cms.PSet(
+ # The velocity of signal propagation along the wire (cm/ns)
+ vPropWire = cms.double(24.4),
+ # Switch on/off the TOF correction for particles
+ doTOFCorrection = cms.bool(True),
+ tofCorrType = cms.int32(0),
+ wirePropCorrType = cms.int32(0),
+ # Switch on/off the correction for the signal propagation along the wire
+ doWirePropCorrection = cms.bool(True),
+ # Switch on/off the TOF correction from pulses
+ doT0Correction = cms.bool(True),
+ debug = cms.untracked.bool(False),
+ tTrigLabel = cms.string(''),
+ ),
+ tTrigMode = cms.string('DTTTrigSyncFromDB'),
+ timeOffset = cms.int32(0),
+ flat_calib = cms.int32(0),
+ scenario = cms.untracked.int32(0),
+ dtDigiTag = cms.InputTag("muonDTDigis")
+ )
+
+
+
+
diff --git a/L1Trigger/DTTriggerPhase2/python/CalibratedDigishlt_cfi.py b/L1Trigger/DTTriggerPhase2/python/CalibratedDigishlt_cfi.py
new file mode 100644
index 0000000000000..85592d4af6f85
--- /dev/null
+++ b/L1Trigger/DTTriggerPhase2/python/CalibratedDigishlt_cfi.py
@@ -0,0 +1,29 @@
+import FWCore.ParameterSet.Config as cms
+
+# The reconstruction algo and its parameter set
+# constant vdrift from DB (and ttrig from DB)
+
+CalibratedDigis = cms.EDProducer("CalibratedDigis",
+ tTrigModeConfig = cms.PSet(
+ # The velocity of signal propagation along the wire (cm/ns)
+ vPropWire = cms.double(24.4),
+ # Switch on/off the TOF correction for particles
+ doTOFCorrection = cms.bool(True),
+ tofCorrType = cms.int32(0),
+ wirePropCorrType = cms.int32(0),
+ # Switch on/off the correction for the signal propagation along the wire
+ doWirePropCorrection = cms.bool(True),
+ # Switch on/off the TOF correction from pulses
+ doT0Correction = cms.bool(True),
+ debug = cms.untracked.bool(False),
+ tTrigLabel = cms.string(''),
+ ),
+ tTrigMode = cms.string('DTTTrigSyncFromDB'),
+ timeOffset = cms.int32(0),
+ flat_calib = cms.int32(0),
+ dtDigiTag = cms.InputTag("hltMuonDTDigis")
+ )
+
+
+
+
diff --git a/L1Trigger/DTTriggerPhase2/python/HoughGrouping_cfi.py b/L1Trigger/DTTriggerPhase2/python/HoughGrouping_cfi.py
new file mode 100644
index 0000000000000..727deda514b87
--- /dev/null
+++ b/L1Trigger/DTTriggerPhase2/python/HoughGrouping_cfi.py
@@ -0,0 +1,42 @@
+import FWCore.ParameterSet.Config as cms
+
+HoughGrouping = cms.PSet(debug = cms.untracked.bool(False),
+ # HOUGH TRANSFORM CONFIGURATION
+ # Tangent of the angle that puts a limit to the maximum inclination of a
+ # muon. Then, the maximum number of radians of inclination of the muon
+ # is derived as pi/2 - arctan(angletan).
+ angletan = cms.untracked.double(0.3),
+ # Width (in sexageseimal degrees) of the angle bins of the line space.
+ anglebinwidth = cms.untracked.double(1.0),
+ # Width (in centimetres) of the position bins of the line space.
+ posbinwidth = cms.untracked.double(2.1),
+
+ # MAXIMA SEARCH CONFIGURATION
+ # Maximum distance (in sexageseimal degrees) used to derive maxima.
+ maxdeltaAngDeg = cms.untracked.double(10),
+ # Maximum distance (in centimetres) used to derive maxima.
+ maxdeltaPos = cms.untracked.double(10),
+ # Upper number of entries of a line space bin that are needed to be
+ # considered for maxima search.
+ UpperNumber = cms.untracked.int32(6),
+ # Lower number of entries of a line space bin that are needed to be
+ # considered for maxima search.
+ LowerNumber = cms.untracked.int32(4),
+
+ # HITS ASSOCIATION CONFIGURATION
+ # Distance to the wire (in centimetres) from a candidate line below
+ # which no laterality is assumed.
+ MaxDistanceToWire = cms.untracked.double(0.03),
+
+ # CANDIDATE QUALITY CONFIGURATION
+ # Minimum number of layers on which the candidate has a hit (maximum 8).
+ minNLayerHits = cms.untracked.int32(6),
+ # Minimum number of hits in the superlayer with more hits.
+ minSingleSLHitsMax = cms.untracked.int32(3),
+ # Minimum number of hits in the superlayer with less hits.
+ minSingleSLHitsMin = cms.untracked.int32(3),
+ # Allow the algorithm to give you back uncorrelated candidates.
+ allowUncorrelatedPatterns = cms.untracked.bool(True),
+ # Minimum number of hits that uncorrelated candidates can have.
+ minUncorrelatedHits = cms.untracked.int32(3),
+ )
diff --git a/L1Trigger/DTTriggerPhase2/python/PseudoBayesGrouping_cfi.py b/L1Trigger/DTTriggerPhase2/python/PseudoBayesGrouping_cfi.py
new file mode 100644
index 0000000000000..bbe30f1ed6be0
--- /dev/null
+++ b/L1Trigger/DTTriggerPhase2/python/PseudoBayesGrouping_cfi.py
@@ -0,0 +1,23 @@
+import FWCore.ParameterSet.Config as cms
+
+PseudoBayesPattern = cms.PSet(pattern_filename = cms.untracked.FileInPath("L1Trigger/DTTriggerPhase2/data/PseudoBayesPatterns_uncorrelated_v0.root"),
+ debug = cms.untracked.bool(False),
+ #Minimum number of layers hit (total). Together with the two parameters under this it means 4+4, 4+3 or 3+3
+ minNLayerHits = cms.untracked.int32(4),
+ #Minimum number of hits in the most hit superlayer
+ minSingleSLHitsMax = cms.untracked.int32(2),
+ #Minimum number of hits in the less hit superlayer
+ minSingleSLHitsMin = cms.untracked.int32(2),
+ #By default pattern width is 1, 0 can be considered (harder fits but, lower efficiency of high quality), 2 is the absolute limit unless we have extremely bent muons somehow
+ allowedVariance = cms.untracked.int32(0),
+ #If true, it will provide all candidate sets with the same hits of the same quality (with lateralities defined). If false only the leading one (with its lateralities).
+ allowDuplicates = cms.untracked.bool(False),
+ #Also provide best estimates for the lateralities
+ setLateralities = cms.untracked.bool(True),
+ #Allow for uncorrelated patterns searching
+ allowUncorrelatedPatterns = cms.untracked.bool(True),
+ #If uncorrelated, minimum hits
+ minUncorrelatedHits = cms.untracked.int32(3),
+ #DTPrimitives are saved in the appropriate element of the muonPath array
+ saveOnPlace = cms.untracked.bool(True),
+ )
diff --git a/L1Trigger/DTTriggerPhase2/python/dtTriggerPhase2PrimitiveDigis_cfi.py b/L1Trigger/DTTriggerPhase2/python/dtTriggerPhase2PrimitiveDigis_cfi.py
new file mode 100644
index 0000000000000..f1c65d71868e2
--- /dev/null
+++ b/L1Trigger/DTTriggerPhase2/python/dtTriggerPhase2PrimitiveDigis_cfi.py
@@ -0,0 +1,51 @@
+import FWCore.ParameterSet.Config as cms
+
+from L1TriggerConfig.DTTPGConfigProducers.L1DTTPGConfigFromDB_cff import *
+from L1Trigger.DTTriggerPhase2.HoughGrouping_cfi import HoughGrouping
+from L1Trigger.DTTriggerPhase2.PseudoBayesGrouping_cfi import PseudoBayesPattern
+
+dtTriggerPhase2PrimitiveDigis = cms.EDProducer("DTTrigPhase2Prod",
+ digiTag = cms.InputTag("CalibratedDigis"),
+ trigger_with_sl = cms.untracked.int32(4),
+ tanPhiTh = cms.untracked.double(1.),
+ chi2Th = cms.untracked.double(0.01), #in cm^2
+ chi2corTh = cms.untracked.double(0.1), #in cm^2
+ do_correlation = cms.bool(True),
+ useBX_correlation = cms.untracked.bool(False),
+ dT0_correlate_TP = cms.untracked.double(25.),
+ dBX_correlate_TP = cms.untracked.int32(0),
+ dTanPsi_correlate_TP = cms.untracked.double(99999.),
+ clean_chi2_correlation = cms.untracked.bool(True),
+ allow_confirmation = cms.untracked.bool(True),
+ use_LSB = cms.untracked.bool(True),
+ tanPsi_precision = cms.untracked.double(1./4096.),
+ x_precision = cms.untracked.double(1./160.),
+ minx_match_2digis = cms.untracked.double(1.),
+ scenario = cms.int32(0), #0 for mc, 1 for data, 2 for slice test
+ filter_cousins = cms.untracked.bool(True),
+
+ ttrig_filename = cms.FileInPath('L1Trigger/DTTriggerPhase2/data/wire_rawId_ttrig.txt'),
+ z_filename = cms.FileInPath('L1Trigger/DTTriggerPhase2/data/wire_rawId_z.txt'),
+ shift_filename = cms.FileInPath('L1Trigger/DTTriggerPhase2/data/wire_rawId_x.txt'),
+ algo = cms.int32(0), # 0 = STD gr., 2 = Hough transform, 1 = PseudoBayes Approach
+
+ minHits4Fit = cms.untracked.int32(4),
+
+ #debugging
+ debug = cms.untracked.bool(False),
+ dump = cms.untracked.bool(False),
+
+ #RPC
+ rpcRecHits = cms.InputTag("rpcRecHits"),
+ useRPC = cms.bool(False),
+ bx_window = cms.untracked.int32(1), # will look for RPC cluster within a bunch crossing window of 'dt.BX +- bx_window'
+ phi_window = cms.untracked.double(50.), # will look for RPC cluster within a phi window of +- phi_window in arbitrary coordinates (plot the value we cut on in RPCIntergator to fine tune it)
+ max_quality_to_overwrite_t0 = cms.untracked.int32(9), # will use RPC to set 't0' for TP with quality < 'max_quality_to_overwrite_t0'
+ storeAllRPCHits = cms.untracked.bool(False),
+ activateBuffer = cms.bool(False),
+ superCelltimewidth = cms.double(400), # in nanoseconds
+ superCellspacewidth = cms.int32(20), # in number of cells: IT MUST BE AN EVEN NUMBER
+ )
+
+dtTriggerPhase2PrimitiveDigis.HoughGrouping = HoughGrouping
+dtTriggerPhase2PrimitiveDigis.PseudoBayesPattern = PseudoBayesPattern
diff --git a/L1Trigger/DTTriggerPhase2/src/CandidateGroup.cc b/L1Trigger/DTTriggerPhase2/src/CandidateGroup.cc
new file mode 100644
index 0000000000000..2875ae71b10f5
--- /dev/null
+++ b/L1Trigger/DTTriggerPhase2/src/CandidateGroup.cc
@@ -0,0 +1,118 @@
+#include "L1Trigger/DTTriggerPhase2/interface/CandidateGroup.h"
+
+#include
+#include
+
+using namespace dtbayesam;
+
+//------------------------------------------------------------------
+//--- Constructores y destructores
+//------------------------------------------------------------------
+CandidateGroup::CandidateGroup(DTPattern* p) {
+ nhits_ = 0;
+ nLayerhits_ = 0;
+ nisGood_ = 0;
+ nLayerDown_ = 0;
+ nLayerUp_ = 0;
+ pattern_ = p;
+}
+
+CandidateGroup::CandidateGroup() {}
+
+CandidateGroup::~CandidateGroup() {}
+
+void CandidateGroup::addHit(DTPrimitive dthit, int lay, bool isGood) {
+ //Add a hit, check if the hits layer was fired and if it wasn't add it to the fired layers
+ candHits_.push_back(std::make_shared(dthit));
+ if (quality_ != (quality_ | qualitybits(std::pow(2, lay))))
+ nLayerhits_++;
+ if (isGood)
+ nisGood_++;
+ quality_ = quality_ | qualitybits(std::pow(2, lay));
+ nhits_++;
+ if (lay <= 3)
+ nLayerDown_++;
+ if (lay >= 4)
+ nLayerUp_++;
+}
+
+void CandidateGroup::removeHit(DTPrimitive dthit) {
+ //Add a hit, check if the hits layer was fired and if it wasn't add it to the fired layers
+ DTPrimitivePtrs tempHits;
+ nhits_ = 0;
+ nLayerDown_ = 0;
+ nLayerUp_ = 0;
+ nLayerhits_ = 0;
+ nisGood_ = 0;
+ quality_ = qualitybits("00000000");
+ for (auto dt_it = candHits_.begin(); dt_it != candHits_.end(); dt_it++) {
+ if (dthit.layerId() == (*dt_it)->layerId() && dthit.channelId() == (*dt_it)->channelId()) {
+ } else {
+ if (pattern_->latHitIn((*dt_it)->layerId(), (*dt_it)->channelId(), 0) > -5)
+ nisGood_++;
+ if (quality_ != (quality_ | qualitybits(std::pow(2, (*dt_it)->layerId()))))
+ nLayerhits_++;
+ quality_ = quality_ | qualitybits(std::pow(2, (*dt_it)->layerId()));
+ nhits_++;
+ if ((*dt_it)->layerId() <= 3)
+ nLayerDown_++;
+ else if ((*dt_it)->layerId() >= 4)
+ nLayerUp_++;
+ tempHits.push_back(*dt_it);
+ }
+ }
+ candHits_ = tempHits;
+}
+
+bool CandidateGroup::operator>(const CandidateGroup& cOther) const {
+ //First number of good (in pattern) matched hits
+ if (nisGood_ > cOther.nisGood())
+ return true;
+ else if (nisGood_ < cOther.nisGood())
+ return false;
+ //Tehn quality_ is number of layers fired
+ else if (nLayerhits_ > cOther.nLayerhits())
+ return true;
+ else if (nLayerhits_ < cOther.nLayerhits())
+ return false;
+ //Then number of matched hits (if multiple hits in a layer is better)
+ else if (nhits_ > cOther.nhits())
+ return true;
+ else if (nhits_ < cOther.nhits())
+ return false;
+ //Balanced quality_, prefer 3+2 over 4+1 for example
+ else if ((nLayerUp_ - nLayerDown_) > (cOther.nLayerUp() - cOther.nLayerDown()))
+ return true;
+ else if ((nLayerUp_ - nLayerDown_) < (cOther.nLayerUp() - cOther.nLayerDown()))
+ return false;
+ //Last, patterns with less gen hits are better matched
+ else if (pattern_->genHits().size() < (cOther.pattern()->genHits().size()))
+ return true;
+ else if (pattern_->genHits().size() > (cOther.pattern()->genHits().size()))
+ return false;
+ //For a total order relation we need this additional dummy
+ else if (candId_ < cOther.candId())
+ return true;
+ else if (candId_ > cOther.candId())
+ return false;
+
+ //If we are here, they are basically equal so it doesn't matter who goes first
+ return true;
+}
+
+bool CandidateGroup::operator==(const CandidateGroup& cOther) const {
+ //First number of good hits
+ if (nisGood_ != cOther.nisGood())
+ return false;
+ //First quality_ is number of layers fired
+ else if (nLayerhits_ != cOther.nLayerhits())
+ return false;
+ //Then number of matched hits (if multiple hits in a layer is better)
+ else if (nhits_ != cOther.nhits())
+ return false;
+ //Balanced quality_, prefer 3+2 over 4+1 for example
+ else if ((nLayerUp_ - nLayerDown_) != (cOther.nLayerUp() - cOther.nLayerDown()))
+ return false;
+ //Last, patterns with less gen hits are better matched
+ return true;
+}
diff --git a/L1Trigger/DTTriggerPhase2/src/DTPattern.cc b/L1Trigger/DTTriggerPhase2/src/DTPattern.cc
new file mode 100644
index 0000000000000..9902df6e41dc2
--- /dev/null
+++ b/L1Trigger/DTTriggerPhase2/src/DTPattern.cc
@@ -0,0 +1,69 @@
+#include "L1Trigger/DTTriggerPhase2/interface/DTPattern.h"
+#include "L1Trigger/DTTriggerPhase2/interface/constants.h"
+#include "FWCore/MessageLogger/interface/MessageLogger.h"
+
+#include
+
+//------------------------------------------------------------------
+//--- Constructores y destructores
+//------------------------------------------------------------------
+DTPattern::DTPattern() {}
+
+DTPattern::DTPattern(RefDTPatternHit seedUp, RefDTPatternHit seedDown) : seedUp_(seedUp), seedDown_(seedDown) {
+ //On creation, pattern is based on seeds, with no hits. Due to traslational simmetry we only need the superlayer indexes as well as the cell index difference
+ id_ = std::make_tuple(std::get<0>(seedUp), std::get<0>(seedDown), std::get<1>(seedUp) - std::get<1>(seedDown));
+ if (debug_)
+ LogDebug("DTPattern") << "Pattern id: " << std::get<0>(id_) << " , " << std::get<1>(id_) << " , "
+ << std::get<2>(id_);
+}
+
+DTPattern::DTPattern(int SL1, int SL2, int diff) {
+ //On creation, pattern is based on seeds, with no hits. Due to traslational simmetry we only need the superlayer indexes as well as the cell index difference
+ seedUp_ = std::make_tuple(SL1, 0, 0);
+ seedDown_ = std::make_tuple(SL2, diff, 0);
+ id_ = std::make_tuple(SL1, SL2, diff);
+ if (debug_)
+ LogDebug("DTPattern") << "Pattern id: " << std::get<0>(id_) << " , " << std::get<1>(id_) << " , "
+ << std::get<2>(id_);
+}
+
+void DTPattern::addHit(RefDTPatternHit hit) {
+ //Add additional gen level hits in the gen pattern coordinates (untranslated)
+ genHits_.push_back(hit);
+ if (debug_)
+ LogDebug("DTPattern") << "Added gen hit: " << std::get<0>(hit) << " , " << std::get<1>(hit) << " , "
+ << std::get<2>(hit);
+}
+
+int DTPattern::latHitIn(int slId, int chId, int allowedVariance) const {
+ //Check if a hit is inside of the pattern for a given pattern width
+ int temp = -999;
+ for (auto it = this->genHits_.begin(); it != this->genHits_.end(); ++it) {
+ if (slId == (std::get<0>(*it) - 1)) {
+ if (chId == (std::get<1>(*it) + recoseedDown_)) {
+ return std::get<2>(*it);
+ }
+ //This is equivalent to an allowed discrete width of the pattern (configured)
+ else if ((chId <= (std::get<1>(*it) + recoseedDown_ + allowedVariance)) &&
+ (chId >= (std::get<1>(*it) + recoseedDown_ - allowedVariance))) {
+ temp = -10;
+ }
+ }
+ }
+ return temp;
+}
+
+std::ostream &operator<<(std::ostream &out, DTPattern &p) {
+ //Friend for printing pattern information trough iostream
+ out << "Pattern id: " << std::get<0>(p.id()) << " , " << std::get<1>(p.id()) << " , " << std::get<2>(p.id())
+ << std::endl;
+ std::vector thegenHits = p.genHits();
+ out << "Pattern hits: " << std::endl;
+
+ for (std::vector::iterator itHit = thegenHits.begin(); itHit != thegenHits.end(); itHit++) {
+ out << "[" << std::get<0>(*itHit) << " , " << std::get<1>(*itHit) << " , " << std::get<2>(*itHit) << "]";
+ }
+ return out;
+}
+
+DTPattern::~DTPattern() {}
diff --git a/L1Trigger/DTTriggerPhase2/src/DTprimitive.cc b/L1Trigger/DTTriggerPhase2/src/DTprimitive.cc
new file mode 100644
index 0000000000000..173f692562461
--- /dev/null
+++ b/L1Trigger/DTTriggerPhase2/src/DTprimitive.cc
@@ -0,0 +1,66 @@
+#include "L1Trigger/DTTriggerPhase2/interface/DTprimitive.h"
+#include "L1Trigger/DTTriggerPhase2/interface/constants.h"
+#include
+#include
+
+using namespace cmsdt;
+//------------------------------------------------------------------
+//--- Constructores y destructores
+//------------------------------------------------------------------
+DTPrimitive::DTPrimitive() {
+ cameraId_ = -1;
+ superLayerId_ = -1;
+ layerId_ = -1;
+ channelId_ = -1;
+ tdcTimeStamp_ = -1;
+ orbit_ = -1;
+ timeCorrection_ = 0;
+ laterality_ = NONE;
+
+ for (int i = 0; i < PAYLOAD_ENTRIES; i++)
+ setPayload(0.0, i);
+}
+
+DTPrimitive::DTPrimitive(DTPrimitivePtr& ptr) {
+ setTimeCorrection(ptr->timeCorrection());
+ setTDCTimeStamp(ptr->tdcTimeStamp());
+ setOrbit(ptr->orbit());
+ setChannelId(ptr->channelId());
+ setLayerId(ptr->layerId());
+ setCameraId(ptr->cameraId());
+ setSuperLayerId(ptr->superLayerId());
+ setLaterality(ptr->laterality());
+
+ for (int i = 0; i < PAYLOAD_ENTRIES; i++)
+ setPayload(ptr->payLoad(i), i);
+}
+
+DTPrimitive::DTPrimitive(DTPrimitive* ptr) {
+ setTimeCorrection(ptr->timeCorrection());
+ setTDCTimeStamp(ptr->tdcTimeStamp());
+ setOrbit(ptr->orbit());
+ setChannelId(ptr->channelId());
+ setLayerId(ptr->layerId());
+ setCameraId(ptr->cameraId());
+ setSuperLayerId(ptr->superLayerId());
+ setLaterality(ptr->laterality());
+
+ for (int i = 0; i < PAYLOAD_ENTRIES; i++)
+ setPayload(ptr->payLoad(i), i);
+}
+
+DTPrimitive::~DTPrimitive() {}
+
+//------------------------------------------------------------------
+//--- Public Methods
+//------------------------------------------------------------------
+bool DTPrimitive::isValidTime(void) { return (tdcTimeStamp_ >= 0 ? true : false); }
+
+float DTPrimitive::wireHorizPos(void) {
+ // For layers with odd-number
+ float wireHorizPos = CELL_LENGTH * channelId();
+ // If layer is even, you must correct by half a cell
+ if (layerId() == 0 || layerId() == 2)
+ wireHorizPos += CELL_SEMILENGTH;
+ return wireHorizPos;
+}
diff --git a/L1Trigger/DTTriggerPhase2/src/HoughGrouping.cc b/L1Trigger/DTTriggerPhase2/src/HoughGrouping.cc
new file mode 100644
index 0000000000000..d4cdccb1ad514
--- /dev/null
+++ b/L1Trigger/DTTriggerPhase2/src/HoughGrouping.cc
@@ -0,0 +1,905 @@
+#include "L1Trigger/DTTriggerPhase2/interface/HoughGrouping.h"
+
+#include "FWCore/Framework/interface/ConsumesCollector.h"
+#include "FWCore/ParameterSet/interface/ParameterSet.h"
+#include "FWCore/MessageLogger/interface/MessageLogger.h"
+
+#include "DataFormats/Math/interface/CMSUnits.h"
+
+#include
+#include
+
+#include "TMath.h"
+
+using namespace std;
+using namespace edm;
+using namespace cmsdt;
+using namespace cms_units::operators;
+
+namespace {
+ struct {
+ bool operator()(ProtoCand a, ProtoCand b) const {
+ unsigned short int sumhqa = 0;
+ unsigned short int sumhqb = 0;
+ unsigned short int sumlqa = 0;
+ unsigned short int sumlqb = 0;
+ double sumdista = 0;
+ double sumdistb = 0;
+
+ for (unsigned short int lay = 0; lay < 8; lay++) {
+ sumhqa += (unsigned short int)a.isThereHitInLayer_[lay];
+ sumhqb += (unsigned short int)b.isThereHitInLayer_[lay];
+ sumlqa += (unsigned short int)a.isThereNeighBourHitInLayer_[lay];
+ sumlqb += (unsigned short int)b.isThereNeighBourHitInLayer_[lay];
+ sumdista += a.xDistToPattern_[lay];
+ sumdistb += b.xDistToPattern_[lay];
+ }
+
+ if (a.nLayersWithHits_ != b.nLayersWithHits_)
+ return (a.nLayersWithHits_ > b.nLayersWithHits_); // number of layers with hits
+ else if (sumhqa != sumhqb)
+ return (sumhqa > sumhqb); // number of hq hits
+ else if (sumlqa != sumlqb)
+ return (sumlqa > sumlqb); // number of lq hits
+ else if (a.nHitsDiff_ != b.nHitsDiff_)
+ return (a.nHitsDiff_ < b.nHitsDiff_); // abs. diff. between SL1 & SL3 hits
+ else
+ return (sumdista < sumdistb); // abs. dist. to digis
+ }
+ } HoughOrdering;
+} // namespace
+// ============================================================================
+// Constructors and destructor
+// ============================================================================
+HoughGrouping::HoughGrouping(const ParameterSet& pset, edm::ConsumesCollector& iC) : MotherGrouping(pset, iC) {
+ // Obtention of parameters
+ debug_ = pset.getUntrackedParameter("debug");
+ if (debug_)
+ LogDebug("HoughGrouping") << "HoughGrouping: constructor";
+
+ // HOUGH TRANSFORM CONFIGURATION
+ angletan_ = pset.getUntrackedParameter("angletan");
+ anglebinwidth_ = pset.getUntrackedParameter